summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /src
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/CHANGELOG.md1
-rw-r--r--src/bootstrap/Cargo.lock125
-rw-r--r--src/bootstrap/Cargo.toml11
-rw-r--r--src/bootstrap/bin/main.rs6
-rw-r--r--src/bootstrap/bin/rustc.rs11
-rw-r--r--src/bootstrap/bin/rustdoc.rs9
-rw-r--r--src/bootstrap/bolt.rs2
-rw-r--r--src/bootstrap/bootstrap.py350
-rw-r--r--src/bootstrap/bootstrap_test.py16
-rw-r--r--src/bootstrap/builder.rs88
-rw-r--r--src/bootstrap/builder/tests.rs36
-rw-r--r--src/bootstrap/channel.rs2
-rw-r--r--src/bootstrap/check.rs100
-rw-r--r--src/bootstrap/clean.rs2
-rw-r--r--src/bootstrap/compile.rs121
-rw-r--r--src/bootstrap/config.rs262
-rw-r--r--src/bootstrap/config/tests.rs83
-rwxr-xr-xsrc/bootstrap/configure.py28
-rw-r--r--src/bootstrap/dist.rs19
-rw-r--r--src/bootstrap/doc.rs7
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/download.rs55
-rw-r--r--src/bootstrap/flags.rs1033
-rw-r--r--src/bootstrap/format.rs6
-rw-r--r--src/bootstrap/install.rs4
-rw-r--r--src/bootstrap/lib.rs133
-rw-r--r--src/bootstrap/llvm.rs15
-rw-r--r--src/bootstrap/metadata.rs75
-rw-r--r--src/bootstrap/metrics.rs142
-rw-r--r--src/bootstrap/render_tests.rs12
-rw-r--r--src/bootstrap/run.rs61
-rw-r--r--src/bootstrap/sanity.rs2
-rw-r--r--src/bootstrap/test.rs787
-rw-r--r--src/bootstrap/tool.rs245
-rw-r--r--src/bootstrap/util.rs2
-rw-r--r--src/ci/docker/README.md127
-rw-r--r--src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch2
-rw-r--r--src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile14
-rw-r--r--src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config754
-rw-r--r--src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig12
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh27
-rw-r--r--src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile24
-rw-r--r--src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config748
-rw-r--r--src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig13
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh29
-rw-r--r--src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile14
-rw-r--r--src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config749
-rw-r--r--src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.defconfig14
-rw-r--r--src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile14
-rw-r--r--src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config746
-rw-r--r--src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.defconfig16
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh29
-rw-r--r--src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile12
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config726
-rw-r--r--src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.defconfig14
-rw-r--r--src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile30
-rw-r--r--src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig14
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile9
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config740
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig16
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile9
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config741
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig16
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile9
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config741
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig17
-rw-r--r--src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile9
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config740
-rw-r--r--src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig17
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile14
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config736
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.defconfig12
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile14
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-powerpc64-linux/build-powerpc64-toolchain.sh11
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config736
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig14
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh16
-rw-r--r--src/ci/docker/host-x86_64/dist-riscv64-linux/Dockerfile14
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh27
-rw-r--r--src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config907
-rw-r--r--src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.defconfig16
-rw-r--r--src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile14
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config732
-rw-r--r--src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.defconfig13
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile5
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh3
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile1
-rwxr-xr-xsrc/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh2
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile10
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile64
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rwxr-xr-xsrc/ci/docker/run.sh1
-rw-r--r--src/ci/docker/scripts/cross-apt-packages.sh1
-rw-r--r--src/ci/docker/scripts/crosstool-ng-1.24.sh13
-rwxr-xr-xsrc/ci/docker/scripts/crosstool-ng-build.sh (renamed from src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh)9
-rw-r--r--src/ci/docker/scripts/crosstool-ng-git.sh17
-rw-r--r--src/ci/docker/scripts/crosstool-ng.sh13
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py137
-rw-r--r--src/ci/docker/scripts/musl-toolchain.sh18
-rw-r--r--src/ci/docker/scripts/musl.sh2
-rw-r--r--src/ci/docker/scripts/qemu-bare-bones-rcS2
-rw-r--r--src/ci/github-actions/ci.yml38
-rwxr-xr-xsrc/ci/run.sh6
-rwxr-xr-xsrc/ci/scripts/install-awscli.sh38
-rw-r--r--src/ci/stage-build.py92
-rw-r--r--src/doc/book/LICENSE-APACHE2
-rw-r--r--src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md2
-rw-r--r--src/doc/embedded-book/src/interoperability/c-with-rust.md6
-rw-r--r--src/doc/embedded-book/src/interoperability/index.md51
-rw-r--r--src/doc/embedded-book/src/intro/index.md1
-rw-r--r--src/doc/embedded-book/src/start/exceptions.md4
-rw-r--r--src/doc/embedded-book/src/start/registers.md2
-rw-r--r--src/doc/nomicon/book.toml2
-rw-r--r--src/doc/nomicon/src/intro.md2
-rw-r--r--src/doc/nomicon/src/unbounded-lifetimes.md40
-rw-r--r--src/doc/reference/src/SUMMARY.md1
-rw-r--r--src/doc/reference/src/attributes.md3
-rw-r--r--src/doc/reference/src/attributes/codegen.md2
-rw-r--r--src/doc/reference/src/attributes/debugger.md141
-rw-r--r--src/doc/reference/src/inline-assembly.md2
-rw-r--r--src/doc/reference/src/items/external-blocks.md36
-rw-r--r--src/doc/reference/src/keywords.md1
-rw-r--r--src/doc/reference/src/macros-by-example.md2
-rw-r--r--src/doc/reference/src/procedural-macros.md2
-rw-r--r--src/doc/reference/src/types/impl-trait.md18
-rw-r--r--src/doc/rust-by-example/README.md10
-rw-r--r--src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md2
-rw-r--r--src/doc/rust-by-example/src/hello/print.md5
-rw-r--r--src/doc/rust-by-example/src/primitives/array.md4
-rw-r--r--src/doc/rustc-dev-guide/src/SUMMARY.md1
-rw-r--r--src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md6
-rw-r--r--src/doc/rustc-dev-guide/src/building/suggested.md27
-rw-r--r--src/doc/rustc-dev-guide/src/getting-started.md4
-rw-r--r--src/doc/rustc-dev-guide/src/hir-debugging.md2
-rw-r--r--src/doc/rustc-dev-guide/src/mir/optimizations.md2
-rw-r--r--src/doc/rustc-dev-guide/src/solve/trait-solving.md4
-rw-r--r--src/doc/rustc-dev-guide/src/tests/headers.md5
-rw-r--r--src/doc/rustc-dev-guide/src/tests/suggest-tests.md55
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ui.md3
-rw-r--r--src/doc/rustc/src/SUMMARY.md2
-rw-r--r--src/doc/rustc/src/codegen-options/index.md15
-rw-r--r--src/doc/rustc/src/command-line-arguments.md6
-rw-r--r--src/doc/rustc/src/exploit-mitigations.md17
-rw-r--r--src/doc/rustc/src/images/image3.pngbin72412 -> 19069 bytes
-rw-r--r--src/doc/rustc/src/instrument-coverage.md2
-rw-r--r--src/doc/rustc/src/json.md2
-rw-r--r--src/doc/rustc/src/platform-support.md5
-rw-r--r--src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md (renamed from src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md)97
-rw-r--r--src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md2
-rw-r--r--src/doc/rustc/src/platform-support/esp-idf.md41
-rw-r--r--src/doc/rustc/src/platform-support/loongarch-linux.md4
-rw-r--r--src/doc/rustc/src/platform-support/unknown-uefi.md2
-rw-r--r--src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md57
-rw-r--r--src/doc/rustdoc/src/SUMMARY.md1
-rw-r--r--src/doc/rustdoc/src/how-to-read-rustdoc.md9
-rw-r--r--src/doc/rustdoc/src/how-to-write-documentation.md6
-rw-r--r--src/doc/rustdoc/src/images/collapsed-long-item.pngbin0 -> 17017 bytes
-rw-r--r--src/doc/rustdoc/src/images/collapsed-trait-impls.pngbin0 -> 44225 bytes
-rw-r--r--src/doc/rustdoc/src/lints.md38
-rw-r--r--src/doc/rustdoc/src/read-documentation/in-doc-settings.md64
-rw-r--r--src/doc/rustdoc/src/references.md8
-rw-r--r--src/doc/rustdoc/src/scraped-examples.md4
-rw-r--r--src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md9
-rw-r--r--src/doc/style-guide/src/principles.md2
-rw-r--r--src/doc/style-guide/src/statements.md37
-rw-r--r--src/doc/style-guide/src/types.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/check-cfg.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/extern-options.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/move-size-limit.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md118
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md28
-rw-r--r--src/doc/unstable-book/src/language-features/cfi-encoding.md25
-rw-r--r--src/doc/unstable-book/src/language-features/debugger-visualizer.md27
-rw-r--r--src/doc/unstable-book/src/language-features/intrinsics.md2
-rw-r--r--src/doc/unstable-book/src/language-features/raw-dylib.md34
-rw-r--r--src/doc/unstable-book/src/language-features/transparent-unions.md2
-rw-r--r--src/doc/unstable-book/src/library-features/libstd-thread-internals.md5
-rw-r--r--src/etc/completions/x.py.fish490
-rw-r--r--src/etc/completions/x.py.ps1622
-rw-r--r--src/etc/completions/x.py.sh1704
-rw-r--r--src/etc/installer/pkg/Distribution.xml2
-rw-r--r--src/etc/lldb_lookup.py2
-rw-r--r--src/etc/lldb_providers.py6
-rw-r--r--src/librustdoc/clean/auto_trait.rs22
-rw-r--r--src/librustdoc/clean/blanket_impl.rs2
-rw-r--r--src/librustdoc/clean/inline.rs16
-rw-r--r--src/librustdoc/clean/mod.rs229
-rw-r--r--src/librustdoc/clean/types.rs152
-rw-r--r--src/librustdoc/clean/types/tests.rs5
-rw-r--r--src/librustdoc/clean/utils.rs9
-rw-r--r--src/librustdoc/config.rs25
-rw-r--r--src/librustdoc/core.rs22
-rw-r--r--src/librustdoc/doctest.rs11
-rw-r--r--src/librustdoc/doctest/tests.rs4
-rw-r--r--src/librustdoc/externalfiles.rs4
-rw-r--r--src/librustdoc/formats/cache.rs22
-rw-r--r--src/librustdoc/html/format.rs49
-rw-r--r--src/librustdoc/html/highlight.rs14
-rw-r--r--src/librustdoc/html/markdown.rs136
-rw-r--r--src/librustdoc/html/render/context.rs19
-rw-r--r--src/librustdoc/html/render/mod.rs77
-rw-r--r--src/librustdoc/html/render/print_item.rs269
-rw-r--r--src/librustdoc/html/render/search_index.rs40
-rw-r--r--src/librustdoc/html/render/type_layout.rs86
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css4
-rw-r--r--src/librustdoc/html/static/css/settings.css10
-rw-r--r--src/librustdoc/html/static/js/externs.js5
-rw-r--r--src/librustdoc/html/static/js/main.js15
-rw-r--r--src/librustdoc/html/static/js/search.js424
-rw-r--r--src/librustdoc/html/static/js/settings.js19
-rw-r--r--src/librustdoc/html/static/js/source-script.js2
-rw-r--r--src/librustdoc/html/templates/item_union.html8
-rw-r--r--src/librustdoc/html/templates/type_layout.html58
-rw-r--r--src/librustdoc/html/templates/type_layout_size.html12
-rw-r--r--src/librustdoc/json/conversions.rs19
-rw-r--r--src/librustdoc/json/mod.rs5
-rw-r--r--src/librustdoc/lib.rs60
-rw-r--r--src/librustdoc/lint.rs12
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs8
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs6
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs289
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs34
-rw-r--r--src/librustdoc/passes/lint.rs2
-rw-r--r--src/librustdoc/passes/lint/bare_urls.rs2
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs8
-rw-r--r--src/librustdoc/passes/lint/html_tags.rs2
-rw-r--r--src/librustdoc/passes/lint/unescaped_backticks.rs416
-rw-r--r--src/librustdoc/passes/strip_hidden.rs30
-rw-r--r--src/librustdoc/passes/stripper.rs2
-rw-r--r--src/librustdoc/scrape_examples.rs6
-rw-r--r--src/librustdoc/theme.rs2
-rw-r--r--src/librustdoc/theme/tests.rs4
-rw-r--r--src/librustdoc/visit_ast.rs152
-rw-r--r--src/rustdoc-json-types/Cargo.toml1
-rw-r--r--src/rustdoc-json-types/lib.rs12
-rw-r--r--src/rustdoc-json-types/tests.rs16
-rw-r--r--src/stage0.json580
-rw-r--r--src/tools/build-manifest/Cargo.toml1
-rw-r--r--src/tools/build-manifest/src/main.rs2
-rw-r--r--src/tools/build-manifest/src/versions.rs28
-rw-r--r--src/tools/build_helper/src/ci.rs24
-rw-r--r--src/tools/cargo/.cargo/config.toml4
-rw-r--r--src/tools/cargo/.github/ISSUE_TEMPLATE/bug_report.yml2
-rw-r--r--src/tools/cargo/.github/ISSUE_TEMPLATE/feature_request.yml2
-rw-r--r--src/tools/cargo/.github/workflows/main.yml119
-rw-r--r--src/tools/cargo/CHANGELOG.md159
-rw-r--r--src/tools/cargo/Cargo.lock3755
-rw-r--r--src/tools/cargo/Cargo.toml196
-rw-r--r--src/tools/cargo/benches/benchsuite/Cargo.toml15
-rw-r--r--src/tools/cargo/benches/capture/Cargo.toml9
-rwxr-xr-xsrc/tools/cargo/ci/validate-man.sh15
-rwxr-xr-xsrc/tools/cargo/ci/validate-version-bump.sh61
-rw-r--r--src/tools/cargo/crates/cargo-platform/Cargo.toml4
-rw-r--r--src/tools/cargo/crates/cargo-test-macro/Cargo.toml1
-rw-r--r--src/tools/cargo/crates/cargo-test-support/Cargo.toml41
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/install.rs6
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/lib.rs33
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/publish.rs4
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/registry.rs15
-rw-r--r--src/tools/cargo/crates/cargo-util/Cargo.toml28
-rw-r--r--src/tools/cargo/crates/crates-io/Cargo.toml14
-rw-r--r--src/tools/cargo/crates/crates-io/lib.rs3
-rw-r--r--src/tools/cargo/crates/credential/cargo-credential-macos-keychain/src/main.rs50
-rw-r--r--src/tools/cargo/crates/credential/cargo-credential-wincred/src/main.rs111
-rw-r--r--src/tools/cargo/crates/home/CHANGELOG.md11
-rw-r--r--src/tools/cargo/crates/home/Cargo.toml4
-rw-r--r--src/tools/cargo/crates/home/src/env.rs2
-rw-r--r--src/tools/cargo/crates/home/src/lib.rs42
-rw-r--r--src/tools/cargo/crates/mdman/Cargo.lock459
-rw-r--r--src/tools/cargo/crates/mdman/Cargo.toml17
-rwxr-xr-xsrc/tools/cargo/crates/mdman/build-man.sh7
-rw-r--r--src/tools/cargo/crates/mdman/doc/mdman.md2
-rw-r--r--src/tools/cargo/crates/mdman/doc/out/mdman.18
-rw-r--r--src/tools/cargo/crates/mdman/doc/out/mdman.md6
-rw-r--r--src/tools/cargo/crates/mdman/doc/out/mdman.txt8
-rw-r--r--src/tools/cargo/crates/resolver-tests/Cargo.toml15
-rw-r--r--src/tools/cargo/crates/resolver-tests/src/lib.rs4
-rw-r--r--src/tools/cargo/crates/semver-check/Cargo.toml (renamed from src/tools/cargo/src/doc/semver-check/Cargo.toml)5
-rw-r--r--src/tools/cargo/crates/semver-check/src/main.rs (renamed from src/tools/cargo/src/doc/semver-check/src/main.rs)10
-rw-r--r--src/tools/cargo/crates/xtask-build-man/Cargo.toml7
-rw-r--r--src/tools/cargo/crates/xtask-build-man/src/main.rs108
-rw-r--r--src/tools/cargo/crates/xtask-stale-label/Cargo.toml8
-rw-r--r--src/tools/cargo/crates/xtask-stale-label/src/main.rs91
-rw-r--r--src/tools/cargo/crates/xtask-unpublished/Cargo.toml12
-rw-r--r--src/tools/cargo/crates/xtask-unpublished/src/main.rs15
-rw-r--r--src/tools/cargo/crates/xtask-unpublished/src/xtask.rs200
-rw-r--r--src/tools/cargo/credential/README.md (renamed from src/tools/cargo/crates/credential/README.md)0
-rw-r--r--src/tools/cargo/credential/cargo-credential-1password/Cargo.toml (renamed from src/tools/cargo/crates/credential/cargo-credential-1password/Cargo.toml)6
-rw-r--r--src/tools/cargo/credential/cargo-credential-1password/src/main.rs (renamed from src/tools/cargo/crates/credential/cargo-credential-1password/src/main.rs)0
-rw-r--r--src/tools/cargo/credential/cargo-credential-gnome-secret/Cargo.toml (renamed from src/tools/cargo/crates/credential/cargo-credential-gnome-secret/Cargo.toml)4
-rw-r--r--src/tools/cargo/credential/cargo-credential-gnome-secret/build.rs (renamed from src/tools/cargo/crates/credential/cargo-credential-gnome-secret/build.rs)0
-rw-r--r--src/tools/cargo/credential/cargo-credential-gnome-secret/src/main.rs (renamed from src/tools/cargo/crates/credential/cargo-credential-gnome-secret/src/main.rs)0
-rw-r--r--src/tools/cargo/credential/cargo-credential-macos-keychain/Cargo.toml (renamed from src/tools/cargo/crates/credential/cargo-credential-macos-keychain/Cargo.toml)6
-rw-r--r--src/tools/cargo/credential/cargo-credential-macos-keychain/src/main.rs58
-rw-r--r--src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml (renamed from src/tools/cargo/crates/credential/cargo-credential-wincred/Cargo.toml)7
-rw-r--r--src/tools/cargo/credential/cargo-credential-wincred/src/main.rs122
-rw-r--r--src/tools/cargo/credential/cargo-credential/Cargo.toml (renamed from src/tools/cargo/crates/credential/cargo-credential/Cargo.toml)0
-rw-r--r--src/tools/cargo/credential/cargo-credential/README.md (renamed from src/tools/cargo/crates/credential/cargo-credential/README.md)2
-rw-r--r--src/tools/cargo/credential/cargo-credential/src/lib.rs (renamed from src/tools/cargo/crates/credential/cargo-credential/src/lib.rs)20
-rw-r--r--src/tools/cargo/src/bin/cargo/cli.rs3
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/add.rs16
-rw-r--r--src/tools/cargo/src/bin/cargo/main.rs4
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs4
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/compilation.rs15
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/custom_build.rs101
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs4
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs24
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/mod.rs38
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/standard_lib.rs14
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs2
-rw-r--r--src/tools/cargo/src/cargo/core/features.rs31
-rw-r--r--src/tools/cargo/src/cargo/core/manifest.rs9
-rw-r--r--src/tools/cargo/src/cargo/core/package_id_spec.rs6
-rw-r--r--src/tools/cargo/src/cargo/core/profiles.rs54
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/dep_cache.rs7
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/errors.rs5
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/features.rs10
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/version_prefs.rs10
-rw-r--r--src/tools/cargo/src/cargo/core/shell.rs2
-rw-r--r--src/tools/cargo/src/cargo/core/source/mod.rs91
-rw-r--r--src/tools/cargo/src/cargo/core/source/source_id.rs164
-rw-r--r--src/tools/cargo/src/cargo/core/summary.rs7
-rw-r--r--src/tools/cargo/src/cargo/core/workspace.rs23
-rw-r--r--src/tools/cargo/src/cargo/lib.rs4
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_add/mod.rs130
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_clean.rs4
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_install.rs25
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_new.rs141
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs2
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_package.rs46
-rw-r--r--src/tools/cargo/src/cargo/ops/registry.rs63
-rw-r--r--src/tools/cargo/src/cargo/ops/tree/graph.rs4
-rw-r--r--src/tools/cargo/src/cargo/ops/tree/mod.rs18
-rw-r--r--src/tools/cargo/src/cargo/sources/config.rs16
-rw-r--r--src/tools/cargo/src/cargo/sources/directory.rs47
-rw-r--r--src/tools/cargo/src/cargo/sources/git/mod.rs41
-rw-r--r--src/tools/cargo/src/cargo/sources/git/oxide.rs57
-rw-r--r--src/tools/cargo/src/cargo/sources/git/source.rs36
-rw-r--r--src/tools/cargo/src/cargo/sources/git/utils.rs99
-rw-r--r--src/tools/cargo/src/cargo/sources/mod.rs21
-rw-r--r--src/tools/cargo/src/cargo/sources/path.rs46
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/index.rs88
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/mod.rs185
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/remote.rs11
-rw-r--r--src/tools/cargo/src/cargo/sources/replaced.rs11
-rw-r--r--src/tools/cargo/src/cargo/util/command_prelude.rs8
-rw-r--r--src/tools/cargo/src/cargo/util/config/mod.rs185
-rw-r--r--src/tools/cargo/src/cargo/util/diagnostic_server.rs64
-rw-r--r--src/tools/cargo/src/cargo/util/edit_distance.rs143
-rw-r--r--src/tools/cargo/src/cargo/util/lev_distance.rs93
-rw-r--r--src/tools/cargo/src/cargo/util/machine_message.rs10
-rw-r--r--src/tools/cargo/src/cargo/util/mod.rs22
-rw-r--r--src/tools/cargo/src/cargo/util/network/mod.rs1
-rw-r--r--src/tools/cargo/src/cargo/util/network/proxy.rs42
-rw-r--r--src/tools/cargo/src/cargo/util/toml/mod.rs327
-rw-r--r--src/tools/cargo/src/cargo/util/toml_mut/dependency.rs100
-rw-r--r--src/tools/cargo/src/doc/README.md14
-rwxr-xr-xsrc/tools/cargo/src/doc/build-man.sh31
-rw-r--r--src/tools/cargo/src/doc/contrib/src/SUMMARY.md1
-rw-r--r--src/tools/cargo/src/doc/contrib/src/implementation/console.md2
-rw-r--r--src/tools/cargo/src/doc/contrib/src/implementation/filesystem.md2
-rw-r--r--src/tools/cargo/src/doc/contrib/src/index.md7
-rw-r--r--src/tools/cargo/src/doc/contrib/src/issues.md209
-rw-r--r--src/tools/cargo/src/doc/contrib/src/process/index.md70
-rw-r--r--src/tools/cargo/src/doc/contrib/src/process/unstable.md22
-rw-r--r--src/tools/cargo/src/doc/contrib/src/team.md157
-rw-r--r--src/tools/cargo/src/doc/man/cargo-add.md9
-rw-r--r--src/tools/cargo/src/doc/man/cargo-bench.md12
-rw-r--r--src/tools/cargo/src/doc/man/cargo-install.md2
-rw-r--r--src/tools/cargo/src/doc/man/cargo-metadata.md6
-rw-r--r--src/tools/cargo/src/doc/man/cargo-test.md11
-rw-r--r--src/tools/cargo/src/doc/man/cargo-yank.md56
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-add.txt9
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt15
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt4
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt6
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt17
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-yank.txt62
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-add.md8
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-bench.md12
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-install.md2
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-metadata.md6
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-test.md11
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-yank.md56
-rw-r--r--src/tools/cargo/src/doc/src/faq.md4
-rw-r--r--src/tools/cargo/src/doc/src/reference/manifest.md5
-rw-r--r--src/tools/cargo/src/doc/src/reference/profiles.md12
-rw-r--r--src/tools/cargo/src/doc/src/reference/publishing.md8
-rw-r--r--src/tools/cargo/src/doc/src/reference/registry-index.md5
-rw-r--r--src/tools/cargo/src/doc/src/reference/registry-web-api.md7
-rw-r--r--src/tools/cargo/src/doc/src/reference/semver.md134
-rw-r--r--src/tools/cargo/src/doc/src/reference/unstable.md240
-rw-r--r--src/tools/cargo/src/etc/man/cargo-add.110
-rw-r--r--src/tools/cargo/src/etc/man/cargo-bench.112
-rw-r--r--src/tools/cargo/src/etc/man/cargo-install.12
-rw-r--r--src/tools/cargo/src/etc/man/cargo-metadata.16
-rw-r--r--src/tools/cargo/src/etc/man/cargo-test.111
-rw-r--r--src/tools/cargo/src/etc/man/cargo-yank.185
-rw-r--r--src/tools/cargo/tests/testsuite/alt_registry.rs12
-rw-r--r--src/tools/cargo/tests/testsuite/artifact_dep.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/bad_config.rs38
-rw-r--r--src/tools/cargo/tests/testsuite/build.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/in/Cargo.toml8
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/in/src/lib.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/mod.rs25
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/out/Cargo.toml8
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/mod.rs5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/in/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs36
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/out/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/in/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs38
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/out/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/out/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/stderr.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/in/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/mod.rs35
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/out/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/in/Cargo.toml6
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/mod.rs35
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/out/Cargo.toml9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/out/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/stderr.log3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_env_config.rs100
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/README.md0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/src/lib.rs14
l---------src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/in1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/src/main.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/stdout.log0
l---------src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/in1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/src/main.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stdout.log0
l---------src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/in1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/src/main.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/Cargo.toml20
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/README.md0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/Cargo.toml20
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/src/main.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/mod.rs5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/Cargo.toml15
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/README.md0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/mod.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/Cargo.toml15
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/src/main.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stderr.log9
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/check.rs26
-rw-r--r--src/tools/cargo/tests/testsuite/config.rs67
-rw-r--r--src/tools/cargo/tests/testsuite/features_namespaced.rs81
-rw-r--r--src/tools/cargo/tests/testsuite/fix.rs61
-rw-r--r--src/tools/cargo/tests/testsuite/git.rs89
-rw-r--r--src/tools/cargo/tests/testsuite/git_shallow.rs831
-rw-r--r--src/tools/cargo/tests/testsuite/https.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs13
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/README.md0
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/crates/foo/src/main.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/mod.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml21
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/src/main.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/src/lib.rs14
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/init/mod.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/install.rs121
-rw-r--r--src/tools/cargo/tests/testsuite/lints.rs639
-rw-r--r--src/tools/cargo/tests/testsuite/main.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/metadata.rs58
-rw-r--r--src/tools/cargo/tests/testsuite/mock-std/library/sysroot/Cargo.toml15
-rw-r--r--src/tools/cargo/tests/testsuite/mock-std/library/sysroot/src/lib.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/mock-std/library/test/Cargo.toml7
-rw-r--r--src/tools/cargo/tests/testsuite/offline.rs38
-rw-r--r--src/tools/cargo/tests/testsuite/package.rs221
-rw-r--r--src/tools/cargo/tests/testsuite/patch.rs19
-rw-r--r--src/tools/cargo/tests/testsuite/profile_config.rs7
-rw-r--r--src/tools/cargo/tests/testsuite/profile_targets.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/publish.rs12
-rw-r--r--src/tools/cargo/tests/testsuite/registry.rs137
-rw-r--r--src/tools/cargo/tests/testsuite/registry_auth.rs73
-rw-r--r--src/tools/cargo/tests/testsuite/rustup.rs262
-rw-r--r--src/tools/cargo/tests/testsuite/tree.rs55
-rw-r--r--src/tools/cargo/tests/testsuite/update.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/vendor.rs5
-rw-r--r--src/tools/cargo/tests/testsuite/weak_dep_features.rs1
-rw-r--r--src/tools/cargo/triagebot.toml25
-rw-r--r--src/tools/clippy/.github/workflows/clippy.yml2
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml10
-rw-r--r--src/tools/clippy/.github/workflows/clippy_dev.yml2
-rw-r--r--src/tools/clippy/.github/workflows/deploy.yml4
-rw-r--r--src/tools/clippy/.github/workflows/remark.yml10
-rw-r--r--src/tools/clippy/CHANGELOG.md127
-rw-r--r--src/tools/clippy/Cargo.toml7
-rw-r--r--src/tools/clippy/README.md5
-rw-r--r--src/tools/clippy/book/src/SUMMARY.md2
-rw-r--r--src/tools/clippy/book/src/development/README.md22
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md2
-rw-r--r--src/tools/clippy/book/src/development/lint_passes.md114
-rw-r--r--src/tools/clippy/book/src/development/macro_expansions.md158
-rw-r--r--src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md2
-rw-r--r--src/tools/clippy/book/src/development/type_checking.md31
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md27
-rw-r--r--src/tools/clippy/book/src/usage.md3
-rw-r--r--src/tools/clippy/clippy_dev/src/dogfood.rs8
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs13
-rw-r--r--src/tools/clippy/clippy_dev/src/lint.rs17
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs56
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml4
-rw-r--r--src/tools/clippy/clippy_lints/src/allow_attributes.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs144
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs84
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs117
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/float_literal.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs47
-rw-r--r--src/tools/clippy/clippy_lints/src/fn_null_check.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/formatting.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/items_after_test_module.rs85
-rw-r--r--src/tools/clippy/clippy_lints/src/large_futures.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs110
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs35
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_bits.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs63
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_bool.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs233
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs101
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/open_options.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/repeat_once.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_trait_methods.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs74
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_multiply.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/octal_escapes.rs94
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs56
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/bit_mask.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/float_cmp.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark_used.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ref_patterns.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_block.rs125
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/unicode.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs111
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs140
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs2
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/attrs.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs117
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs217
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs101
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs52
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs23
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs16
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs1
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml4
-rw-r--r--src/tools/clippy/declare_clippy_lint/src/lib.rs8
-rw-r--r--src/tools/clippy/lintcheck/README.md4
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs2
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/src/driver.rs73
-rw-r--r--src/tools/clippy/src/main.rs2
-rw-r--r--src/tools/clippy/tests/compile-test.rs3
-rw-r--r--src/tools/clippy/tests/dogfood.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.rs13
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr8
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/outer_expn_data.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/outer_expn_data.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed4
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs4
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed2
-rw-r--r--src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs4
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed4
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs4
-rw-r--r--src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/both.fixed86
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/both.rs86
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/both.stderr55
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/clippy.toml2
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed85
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.rs85
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr18
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed85
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.rs85
-rw-r--r--src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr39
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs4
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr3
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs2
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes.fixed2
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes.rs2
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes_false_positive.rs5
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.fixed6
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.rs6
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs37
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr268
-rw-r--r--src/tools/clippy/tests/ui/as_conversions.rs2
-rw-r--r--src/tools/clippy/tests/ui/as_underscore.fixed2
-rw-r--r--src/tools/clippy/tests/ui/as_underscore.rs2
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax.rs4
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_result_states.fixed2
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_result_states.rs2
-rw-r--r--src/tools/clippy/tests/ui/assign_ops.fixed2
-rw-r--r--src/tools/clippy/tests/ui/assign_ops.rs2
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.fixed2
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.rs2
-rw-r--r--src/tools/clippy/tests/ui/author/blocks.rs2
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/macro_rules.rs7
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs10
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs77
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs4
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs4
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macros.rs4
-rw-r--r--src/tools/clippy/tests/ui/bind_instead_of_map.fixed2
-rw-r--r--src/tools/clippy/tests/ui/bind_instead_of_map.rs2
-rw-r--r--src/tools/clippy/tests/ui/bind_instead_of_map_multipart.fixed2
-rw-r--r--src/tools/clippy/tests/ui/bind_instead_of_map_multipart.rs2
-rw-r--r--src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs2
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed2
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_if_conditions.rs2
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.fixed2
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.rs2
-rw-r--r--src/tools/clippy/tests/ui/bool_comparison.fixed2
-rw-r--r--src/tools/clippy/tests/ui/bool_comparison.rs2
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.fixed11
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.rs11
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.stderr2
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr.fixed2
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr.rs2
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed2
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs2
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.fixed17
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.rs17
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.stderr6
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs2
-rw-r--r--src/tools/clippy/tests/ui/box_default.fixed10
-rw-r--r--src/tools/clippy/tests/ui/box_default.rs10
-rw-r--r--src/tools/clippy/tests/ui/box_default.stderr32
-rw-r--r--src/tools/clippy/tests/ui/bytes_count_to_len.fixed2
-rw-r--r--src/tools/clippy/tests/ui/bytes_count_to_len.rs2
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.fixed2
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.rs2
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed2
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_bool.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_bool.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_float.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_float.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_integer.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_integer.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_size.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_size_32bit.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_size_32bit.stderr53
-rw-r--r--src/tools/clippy/tests/ui/cast_slice_different_sizes.rs2
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs2
-rw-r--r--src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.fixed2
-rw-r--r--src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.rs2
-rw-r--r--src/tools/clippy/tests/ui/checked_conversions.fixed2
-rw-r--r--src/tools/clippy/tests/ui/checked_conversions.rs2
-rw-r--r--src/tools/clippy/tests/ui/clear_with_drain.fixed2
-rw-r--r--src/tools/clippy/tests/ui/clear_with_drain.rs2
-rw-r--r--src/tools/clippy/tests/ui/clone_on_copy.fixed2
-rw-r--r--src/tools/clippy/tests/ui/clone_on_copy.rs2
-rw-r--r--src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cloned_instead_of_copied.rs2
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs2
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/comparison_flip.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/comparison_flip.rs2
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs2
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.fixed2
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.rs2
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.fixed9
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.rs9
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.stderr18
-rw-r--r--src/tools/clippy/tests/ui/collapsible_str_replace.fixed2
-rw-r--r--src/tools/clippy/tests/ui/collapsible_str_replace.rs2
-rw-r--r--src/tools/clippy/tests/ui/collection_is_never_read.rs49
-rw-r--r--src/tools/clippy/tests/ui/collection_is_never_read.stderr62
-rw-r--r--src/tools/clippy/tests/ui/comparison_to_empty.fixed2
-rw-r--r--src/tools/clippy/tests/ui/comparison_to_empty.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10148.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10645.rs7
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10645.stderr16
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3741.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-4968.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-5207.rs1
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7272.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7410.rs6
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-8681.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice_exact_size.rs (renamed from src/tools/clippy/tests/ui/crashes/ice_exacte_size.rs)0
-rw-r--r--src/tools/clippy/tests/ui/crate_in_macro_def.fixed2
-rw-r--r--src/tools/clippy/tests/ui/crate_in_macro_def.rs2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs4
-rw-r--r--src/tools/clippy/tests/ui/create_dir.fixed2
-rw-r--r--src/tools/clippy/tests/ui/create_dir.rs2
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.rs29
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.stderr82
-rw-r--r--src/tools/clippy/tests/ui/decimal_literal_representation.fixed2
-rw-r--r--src/tools/clippy/tests/ui/decimal_literal_representation.rs2
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.rs2
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed159
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.rs159
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr40
-rw-r--r--src/tools/clippy/tests/ui/default_instead_of_iter_empty.fixed2
-rw-r--r--src/tools/clippy/tests/ui/default_instead_of_iter_empty.rs2
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed4
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs4
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed4
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs4
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.fixed4
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.rs4
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.fixed4
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.rs4
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui/deref_by_slicing.fixed2
-rw-r--r--src/tools/clippy/tests/ui/deref_by_slicing.rs2
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.fixed2
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.rs2
-rw-r--r--src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed2
-rw-r--r--src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs2
-rw-r--r--src/tools/clippy/tests/ui/diverging_sub_expression.stderr10
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/doc_unsafe.rs2
-rw-r--r--src/tools/clippy/tests/ui/double_comparison.fixed2
-rw-r--r--src/tools/clippy/tests/ui/double_comparison.rs2
-rw-r--r--src/tools/clippy/tests/ui/drop_forget_copy.rs86
-rw-r--r--src/tools/clippy/tests/ui/drop_forget_copy.stderr112
-rw-r--r--src/tools/clippy/tests/ui/drop_ref.rs97
-rw-r--r--src/tools/clippy/tests/ui/drop_ref.stderr147
-rw-r--r--src/tools/clippy/tests/ui/duration_subsec.fixed2
-rw-r--r--src/tools/clippy/tests/ui/duration_subsec.rs2
-rw-r--r--src/tools/clippy/tests/ui/empty_drop.fixed2
-rw-r--r--src/tools/clippy/tests/ui/empty_drop.rs2
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs132
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr36
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs2
-rw-r--r--src/tools/clippy/tests/ui/empty_loop.rs2
-rw-r--r--src/tools/clippy/tests/ui/empty_loop_no_std.rs4
-rw-r--r--src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed2
-rw-r--r--src/tools/clippy/tests/ui/empty_structs_with_brackets.rs2
-rw-r--r--src/tools/clippy/tests/ui/entry.fixed4
-rw-r--r--src/tools/clippy/tests/ui/entry.rs4
-rw-r--r--src/tools/clippy/tests/ui/entry_btree.fixed2
-rw-r--r--src/tools/clippy/tests/ui/entry_btree.rs2
-rw-r--r--src/tools/clippy/tests/ui/entry_with_else.fixed2
-rw-r--r--src/tools/clippy/tests/ui/entry_with_else.rs2
-rw-r--r--src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs2
-rw-r--r--src/tools/clippy/tests/ui/enum_glob_use.fixed2
-rw-r--r--src/tools/clippy/tests/ui/enum_glob_use.rs2
-rw-r--r--src/tools/clippy/tests/ui/enum_variants.rs10
-rw-r--r--src/tools/clippy/tests/ui/eq_op.rs2
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.fixed4
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.rs4
-rw-r--r--src/tools/clippy/tests/ui/err_expect.fixed2
-rw-r--r--src/tools/clippy/tests/ui/err_expect.rs2
-rw-r--r--src/tools/clippy/tests/ui/eta.fixed2
-rw-r--r--src/tools/clippy/tests/ui/eta.rs2
-rw-r--r--src/tools/clippy/tests/ui/excessive_precision.fixed2
-rw-r--r--src/tools/clippy/tests/ui/excessive_precision.rs2
-rw-r--r--src/tools/clippy/tests/ui/exhaustive_items.fixed2
-rw-r--r--src/tools/clippy/tests/ui/exhaustive_items.rs2
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.fixed2
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.rs2
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.rs2
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.fixed4
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.rs4
-rw-r--r--src/tools/clippy/tests/ui/explicit_write.fixed2
-rw-r--r--src/tools/clippy/tests/ui/explicit_write.rs2
-rw-r--r--src/tools/clippy/tests/ui/extend_with_drain.fixed2
-rw-r--r--src/tools/clippy/tests/ui/extend_with_drain.rs2
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_lifetimes.rs2
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed2
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.rs2
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.rs4
-rw-r--r--src/tools/clippy/tests/ui/filter_map_identity.fixed2
-rw-r--r--src/tools/clippy/tests/ui/filter_map_identity.rs2
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/flat_map_identity.fixed2
-rw-r--r--src/tools/clippy/tests/ui/flat_map_identity.rs2
-rw-r--r--src/tools/clippy/tests/ui/flat_map_option.fixed2
-rw-r--r--src/tools/clippy/tests/ui/flat_map_option.rs2
-rw-r--r--src/tools/clippy/tests/ui/float_arithmetic.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_abs.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_abs.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs31
-rw-r--r--src/tools/clippy/tests/ui/floating_point_exp.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_exp.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_hypot.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_hypot.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_log.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_log.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_logbase.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_logbase.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_mul_add.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_mul_add.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powf.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powf.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powi.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powi.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_rad.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_rad.rs2
-rw-r--r--src/tools/clippy/tests/ui/fn_to_numeric_cast.rs2
-rw-r--r--src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.rs2
-rw-r--r--src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.stderr14
-rw-r--r--src/tools/clippy/tests/ui/for_loop_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/for_loop_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/forget_ref.rs50
-rw-r--r--src/tools/clippy/tests/ui/forget_ref.stderr111
-rw-r--r--src/tools/clippy/tests/ui/format.fixed2
-rw-r--r--src/tools/clippy/tests/ui/format.rs2
-rw-r--r--src/tools/clippy/tests/ui/format_args.fixed2
-rw-r--r--src/tools/clippy/tests/ui/format_args.rs2
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed2
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs2
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.fixed4
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.rs4
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.stderr12
-rw-r--r--src/tools/clippy/tests/ui/from_over_into_unfixable.stderr6
-rw-r--r--src/tools/clippy/tests/ui/future_not_send.stderr24
-rw-r--r--src/tools/clippy/tests/ui/get_first.fixed2
-rw-r--r--src/tools/clippy/tests/ui/get_first.rs2
-rw-r--r--src/tools/clippy/tests/ui/get_last_with_len.fixed2
-rw-r--r--src/tools/clippy/tests/ui/get_last_with_len.rs2
-rw-r--r--src/tools/clippy/tests/ui/get_unwrap.fixed2
-rw-r--r--src/tools/clippy/tests/ui/get_unwrap.rs2
-rw-r--r--src/tools/clippy/tests/ui/identity_op.fixed2
-rw-r--r--src/tools/clippy/tests/ui/identity_op.rs2
-rw-r--r--src/tools/clippy/tests/ui/implicit_clone.fixed2
-rw-r--r--src/tools/clippy/tests/ui/implicit_clone.rs2
-rw-r--r--src/tools/clippy/tests/ui/implicit_hasher.rs2
-rw-r--r--src/tools/clippy/tests/ui/implicit_return.fixed2
-rw-r--r--src/tools/clippy/tests/ui/implicit_return.rs2
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_add.fixed2
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_add.rs2
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.fixed2
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.rs2
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_digit_grouping.fixed2
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_digit_grouping.rs2
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed4
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs4
-rw-r--r--src/tools/clippy/tests/ui/inefficient_to_string.fixed2
-rw-r--r--src/tools/clippy/tests/ui/inefficient_to_string.rs2
-rw-r--r--src/tools/clippy/tests/ui/infallible_destructuring_match.fixed2
-rw-r--r--src/tools/clippy/tests/ui/infallible_destructuring_match.rs2
-rw-r--r--src/tools/clippy/tests/ui/inline_fn_without_body.fixed2
-rw-r--r--src/tools/clippy/tests/ui/inline_fn_without_body.rs2
-rw-r--r--src/tools/clippy/tests/ui/int_plus_one.fixed2
-rw-r--r--src/tools/clippy/tests/ui/int_plus_one.rs2
-rw-r--r--src/tools/clippy/tests/ui/integer_arithmetic.rs102
-rw-r--r--src/tools/clippy/tests/ui/integer_arithmetic.stderr169
-rw-r--r--src/tools/clippy/tests/ui/into_iter_on_ref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/into_iter_on_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed2
-rw-r--r--src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs2
-rw-r--r--src/tools/clippy/tests/ui/is_digit_ascii_radix.fixed2
-rw-r--r--src/tools/clippy/tests/ui/is_digit_ascii_radix.rs2
-rw-r--r--src/tools/clippy/tests/ui/issue-111399.rs13
-rw-r--r--src/tools/clippy/tests/ui/issue_2356.fixed2
-rw-r--r--src/tools/clippy/tests/ui/issue_2356.rs2
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/auxiliary/tests.rs1
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/block_module.rs23
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr17
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/imported_module.rs20
-rw-r--r--src/tools/clippy/tests/ui/iter_cloned_collect.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_cloned_collect.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_count.fixed4
-rw-r--r--src/tools/clippy/tests/ui/iter_count.rs4
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_next_slice.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_next_slice.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_nth.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_nth_zero.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_nth_zero.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_on_empty_collections.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_on_empty_collections.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_on_single_items.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_on_single_items.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_overeager_cloned.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_overeager_cloned.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_skip_next.fixed4
-rw-r--r--src/tools/clippy/tests/ui/iter_skip_next.rs4
-rw-r--r--src/tools/clippy/tests/ui/iter_with_drain.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_with_drain.rs2
-rw-r--r--src/tools/clippy/tests/ui/large_const_arrays.fixed2
-rw-r--r--src/tools/clippy/tests/ui/large_const_arrays.rs2
-rw-r--r--src/tools/clippy/tests/ui/large_digit_groups.fixed2
-rw-r--r--src/tools/clippy/tests/ui/large_digit_groups.rs2
-rw-r--r--src/tools/clippy/tests/ui/large_enum_variant.rs2
-rw-r--r--src/tools/clippy/tests/ui/large_types_passed_by_value.rs4
-rw-r--r--src/tools/clippy/tests/ui/len_zero.fixed6
-rw-r--r--src/tools/clippy/tests/ui/len_zero.rs6
-rw-r--r--src/tools/clippy/tests/ui/len_zero.stderr16
-rw-r--r--src/tools/clippy/tests/ui/len_zero_ranges.fixed2
-rw-r--r--src/tools/clippy/tests/ui/len_zero_ranges.rs2
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.rs20
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.stderr48
-rw-r--r--src/tools/clippy/tests/ui/let_unit.fixed2
-rw-r--r--src/tools/clippy/tests/ui/let_unit.rs2
-rw-r--r--src/tools/clippy/tests/ui/let_with_type_underscore.rs27
-rw-r--r--src/tools/clippy/tests/ui/let_with_type_underscore.stderr38
-rw-r--r--src/tools/clippy/tests/ui/lines_filter_map_ok.fixed2
-rw-r--r--src/tools/clippy/tests/ui/lines_filter_map_ok.rs2
-rw-r--r--src/tools/clippy/tests/ui/lossy_float_literal.fixed2
-rw-r--r--src/tools/clippy/tests/ui/lossy_float_literal.rs2
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.fixed10
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.rs10
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports_expect.rs8
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.fixed8
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.fixed8
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.rs8
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_bits.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_bits.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_filter_map.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_filter_map.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_find_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_find_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_find_map.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_find_map.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_instant_elapsed.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_instant_elapsed.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.rs15
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.stderr82
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_main_separator_str.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_main_separator_str.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option_2.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option_2.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.fixed36
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.rs36
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.stderr16
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_or.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_or.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_rem_euclid.fixed4
-rw-r--r--src/tools/clippy/tests/ui/manual_rem_euclid.rs4
-rw-r--r--src/tools/clippy/tests/ui/manual_retain.fixed6
-rw-r--r--src/tools/clippy/tests/ui/manual_retain.rs6
-rw-r--r--src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed46
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_size_calculation.rs10
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr41
-rw-r--r--src/tools/clippy/tests/ui/manual_split_once.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_split_once.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_str_repeat.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_str_repeat.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_string_new.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_string_new.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_while_let_some.fixed93
-rw-r--r--src/tools/clippy/tests/ui/manual_while_let_some.rs93
-rw-r--r--src/tools/clippy/tests/ui/manual_while_let_some.stderr87
-rw-r--r--src/tools/clippy/tests/ui/map_clone.fixed2
-rw-r--r--src/tools/clippy/tests/ui/map_clone.rs2
-rw-r--r--src/tools/clippy/tests/ui/map_collect_result_unit.fixed2
-rw-r--r--src/tools/clippy/tests/ui/map_collect_result_unit.rs2
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/map_identity.fixed2
-rw-r--r--src/tools/clippy/tests/ui/map_identity.rs2
-rw-r--r--src/tools/clippy/tests/ui/map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed4
-rw-r--r--src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs4
-rw-r--r--src/tools/clippy/tests/ui/match_as_ref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_as_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed4
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr8
-rw-r--r--src/tools/clippy/tests/ui/match_ref_pats.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_ref_pats.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_result_ok.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_result_ok.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms.rs82
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs6
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr17
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding2.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding2.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_str_case_mismatch.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_str_case_mismatch.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs2
-rw-r--r--src/tools/clippy/tests/ui/mem_forget.rs2
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.fixed2
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.rs2
-rw-r--r--src/tools/clippy/tests/ui/mem_replace_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui/methods.rs2
-rw-r--r--src/tools/clippy/tests/ui/methods_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/methods_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed2
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs2
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed2
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_unix.rs2
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs4
-rw-r--r--src/tools/clippy/tests/ui/missing_doc.rs4
-rw-r--r--src/tools/clippy/tests/ui/missing_doc_impl.rs2
-rw-r--r--src/tools/clippy/tests/ui/missing_spin_loop.fixed2
-rw-r--r--src/tools/clippy/tests/ui/missing_spin_loop.rs2
-rw-r--r--src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed2
-rw-r--r--src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs2
-rw-r--r--src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed4
-rw-r--r--src/tools/clippy/tests/ui/mistyped_literal_suffix.rs4
-rw-r--r--src/tools/clippy/tests/ui/module_name_repetitions.rs2
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs4
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.fixed2
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.rs2
-rw-r--r--src/tools/clippy/tests/ui/must_use_unit.fixed4
-rw-r--r--src/tools/clippy/tests/ui/must_use_unit.rs4
-rw-r--r--src/tools/clippy/tests/ui/mut_mut.rs2
-rw-r--r--src/tools/clippy/tests/ui/mut_mutex_lock.fixed2
-rw-r--r--src/tools/clippy/tests/ui/mut_mutex_lock.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_arbitrary_self_type.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_arbitrary_self_type.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr2
-rw-r--r--src/tools/clippy/tests/ui/needless_bitwise_bool.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_bitwise_bool.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.fixed9
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.rs9
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.stderr24
-rw-r--r--src/tools/clippy/tests/ui/needless_bool_assign.fixed33
-rw-r--r--src/tools/clippy/tests/ui/needless_bool_assign.rs45
-rw-r--r--src/tools/clippy/tests/ui/needless_bool_assign.stderr53
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.fixed14
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.rs14
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.stderr26
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_fixable.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_fixable.rs4
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.rs4
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.rs4
-rw-r--r--src/tools/clippy/tests/ui/needless_match.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_match.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_option_take.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_option_take.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs4
-rw-r--r--src/tools/clippy/tests/ui/needless_question_mark.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_question_mark.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed7
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs7
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr26
-rw-r--r--src/tools/clippy/tests/ui/needless_splitn.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_splitn.rs4
-rw-r--r--src/tools/clippy/tests/ui/neg_multiply.fixed2
-rw-r--r--src/tools/clippy/tests/ui/neg_multiply.rs2
-rw-r--r--src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs2
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.fixed17
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.rs17
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.stderr28
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg2.rs6
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg2.stderr10
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed4
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.rs4
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed2
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool_methods.rs2
-rw-r--r--src/tools/clippy/tests/ui/numbered_fields.fixed2
-rw-r--r--src/tools/clippy/tests/ui/numbered_fields.rs2
-rw-r--r--src/tools/clippy/tests/ui/obfuscated_if_else.fixed2
-rw-r--r--src/tools/clippy/tests/ui/obfuscated_if_else.rs2
-rw-r--r--src/tools/clippy/tests/ui/octal_escapes.rs1
-rw-r--r--src/tools/clippy/tests/ui/octal_escapes.stderr18
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_deref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_deref.rs2
-rw-r--r--src/tools/clippy/tests/ui/option_env_unwrap.rs2
-rw-r--r--src/tools/clippy/tests/ui/option_filter_map.fixed2
-rw-r--r--src/tools/clippy/tests/ui/option_filter_map.rs2
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed18
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs18
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr47
-rw-r--r--src/tools/clippy/tests/ui/option_map_or_none.fixed2
-rw-r--r--src/tools/clippy/tests/ui/option_map_or_none.rs2
-rw-r--r--src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed2
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.rs2
-rw-r--r--src/tools/clippy/tests/ui/or_then_unwrap.fixed2
-rw-r--r--src/tools/clippy/tests/ui/or_then_unwrap.rs2
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.fixed3
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.rs3
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.stderr30
-rw-r--r--src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed2
-rw-r--r--src/tools/clippy/tests/ui/path_buf_push_overwrite.rs2
-rw-r--r--src/tools/clippy/tests/ui/patterns.fixed2
-rw-r--r--src/tools/clippy/tests/ui/patterns.rs2
-rw-r--r--src/tools/clippy/tests/ui/precedence.fixed2
-rw-r--r--src/tools/clippy/tests/ui/precedence.rs2
-rw-r--r--src/tools/clippy/tests/ui/print_stdout_build_script.rs2
-rw-r--r--src/tools/clippy/tests/ui/print_with_newline.rs2
-rw-r--r--src/tools/clippy/tests/ui/println_empty_string.fixed2
-rw-r--r--src/tools/clippy/tests/ui/println_empty_string.rs2
-rw-r--r--src/tools/clippy/tests/ui/ptr_as_ptr.fixed4
-rw-r--r--src/tools/clippy/tests/ui/ptr_as_ptr.rs4
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.fixed2
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.rs2
-rw-r--r--src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed2
-rw-r--r--src/tools/clippy/tests/ui/ptr_offset_with_cast.rs2
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed2
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs2
-rw-r--r--src/tools/clippy/tests/ui/range_contains.fixed2
-rw-r--r--src/tools/clippy/tests/ui/range_contains.rs2
-rw-r--r--src/tools/clippy/tests/ui/range_plus_minus_one.fixed2
-rw-r--r--src/tools/clippy/tests/ui/range_plus_minus_one.rs2
-rw-r--r--src/tools/clippy/tests/ui/rc_buffer.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rc_buffer.rs2
-rw-r--r--src/tools/clippy/tests/ui/rc_buffer_arc.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rc_buffer_arc.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_async_block.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_async_block.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.fixed3
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.rs3
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.stderr60
-rw-r--r--src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed23
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs35
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr64
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed28
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs40
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr62
-rw-r--r--src/tools/clippy/tests/ui/redundant_pub_crate.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pub_crate.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_slicing.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_slicing.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.rs2
-rw-r--r--src/tools/clippy/tests/ui/ref_patterns.rs19
-rw-r--r--src/tools/clippy/tests/ui/ref_patterns.stderr27
-rw-r--r--src/tools/clippy/tests/ui/regex.rs2
-rw-r--r--src/tools/clippy/tests/ui/regex.stderr40
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed15
-rw-r--r--src/tools/clippy/tests/ui/rename.rs15
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr122
-rw-r--r--src/tools/clippy/tests/ui/renamed_builtin_attr.fixed2
-rw-r--r--src/tools/clippy/tests/ui/renamed_builtin_attr.rs2
-rw-r--r--src/tools/clippy/tests/ui/repeat_once.fixed2
-rw-r--r--src/tools/clippy/tests/ui/repeat_once.rs2
-rw-r--r--src/tools/clippy/tests/ui/result_map_or_into_option.fixed2
-rw-r--r--src/tools/clippy/tests/ui/result_map_or_into_option.rs2
-rw-r--r--src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/same_functions_in_if_condition.rs2
-rw-r--r--src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr6
-rw-r--r--src/tools/clippy/tests/ui/same_name_method.rs2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.rs2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none.rs2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.rs2
-rw-r--r--src/tools/clippy/tests/ui/seek_from_current.fixed2
-rw-r--r--src/tools/clippy/tests/ui/seek_from_current.rs2
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed2
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs2
-rw-r--r--src/tools/clippy/tests/ui/semicolon_inside_block.fixed2
-rw-r--r--src/tools/clippy/tests/ui/semicolon_inside_block.rs2
-rw-r--r--src/tools/clippy/tests/ui/semicolon_outside_block.fixed2
-rw-r--r--src/tools/clippy/tests/ui/semicolon_outside_block.rs2
-rw-r--r--src/tools/clippy/tests/ui/shadow.rs19
-rw-r--r--src/tools/clippy/tests/ui/shadow.stderr92
-rw-r--r--src/tools/clippy/tests/ui/short_circuit_statement.fixed2
-rw-r--r--src/tools/clippy/tests/ui/short_circuit_statement.rs2
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs2
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.fixed2
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_char_add_str.fixed2
-rw-r--r--src/tools/clippy/tests/ui/single_char_add_str.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.fixed2
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.fixed2
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.fixed2
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.rs2
-rw-r--r--src/tools/clippy/tests/ui/skip_while_next.rs2
-rw-r--r--src/tools/clippy/tests/ui/stable_sort_primitive.fixed2
-rw-r--r--src/tools/clippy/tests/ui/stable_sort_primitive.rs2
-rw-r--r--src/tools/clippy/tests/ui/starts_ends_with.fixed2
-rw-r--r--src/tools/clippy/tests/ui/starts_ends_with.rs2
-rw-r--r--src/tools/clippy/tests/ui/string_add.rs2
-rw-r--r--src/tools/clippy/tests/ui/string_add_assign.fixed2
-rw-r--r--src/tools/clippy/tests/ui/string_add_assign.rs2
-rw-r--r--src/tools/clippy/tests/ui/string_extend.fixed2
-rw-r--r--src/tools/clippy/tests/ui/string_extend.rs2
-rw-r--r--src/tools/clippy/tests/ui/string_from_utf8_as_bytes.fixed2
-rw-r--r--src/tools/clippy/tests/ui/string_from_utf8_as_bytes.rs2
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.fixed16
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.rs16
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.stderr25
-rw-r--r--src/tools/clippy/tests/ui/strlen_on_c_strings.fixed2
-rw-r--r--src/tools/clippy/tests/ui/strlen_on_c_strings.rs2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments.fixed2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments.rs2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_else_formatting.rs2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_operation_groupings.rs2
-rw-r--r--src/tools/clippy/tests/ui/swap.fixed4
-rw-r--r--src/tools/clippy/tests/ui/swap.rs4
-rw-r--r--src/tools/clippy/tests/ui/swap_ptr_to_ref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/swap_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed2
-rw-r--r--src/tools/clippy/tests/ui/tabs_in_doc_comments.rs2
-rw-r--r--src/tools/clippy/tests/ui/tests_outside_test_module.rs2
-rw-r--r--src/tools/clippy/tests/ui/to_digit_is_some.fixed2
-rw-r--r--src/tools/clippy/tests/ui/to_digit_is_some.rs2
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg.fixed4
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg.rs4
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs2
-rw-r--r--src/tools/clippy/tests/ui/track-diagnostics.rs5
-rw-r--r--src/tools/clippy/tests/ui/trailing_empty_array.rs2
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed12
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs12
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr24
-rw-r--r--src/tools/clippy/tests/ui/transmute_32bit.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_32bit.stderr29
-rw-r--r--src/tools/clippy/tests/ui/transmute_64bit.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs2
-rw-r--r--src/tools/clippy/tests/ui/trim_split_whitespace.fixed2
-rw-r--r--src/tools/clippy/tests/ui/trim_split_whitespace.rs2
-rw-r--r--src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs4
-rw-r--r--src/tools/clippy/tests/ui/try_err.fixed4
-rw-r--r--src/tools/clippy/tests/ui/try_err.rs4
-rw-r--r--src/tools/clippy/tests/ui/types.fixed2
-rw-r--r--src/tools/clippy/tests/ui/types.rs2
-rw-r--r--src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs2
-rw-r--r--src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs2
-rw-r--r--src/tools/clippy/tests/ui/unicode.fixed4
-rw-r--r--src/tools/clippy/tests/ui/unicode.rs4
-rw-r--r--src/tools/clippy/tests/ui/uninit.rs4
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.fixed4
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.rs4
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed8
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed8
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.rs8
-rw-r--r--src/tools/clippy/tests/ui/unit_arg.rs2
-rw-r--r--src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs2
-rw-r--r--src/tools/clippy/tests/ui/unknown_clippy_lints.fixed4
-rw-r--r--src/tools/clippy/tests/ui/unknown_clippy_lints.rs2
-rw-r--r--src/tools/clippy/tests/ui/unknown_clippy_lints.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_box_returns.rs10
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clone.rs13
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clone.stderr52
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_fold.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_fold.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_join.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_join.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_operation.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_operation.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_self_imports.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_self_imports.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_sort_by.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_sort_by.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.fixed4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.rs4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs2
-rw-r--r--src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns2.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns2.rs2
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.rs2
-rw-r--r--src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed4
-rw-r--r--src/tools/clippy/tests/ui/unseparated_prefix_literals.rs4
-rw-r--r--src/tools/clippy/tests/ui/unused_rounding.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unused_rounding.rs2
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.rs2
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or_else_default.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or_else_default.rs2
-rw-r--r--src/tools/clippy/tests/ui/use_self.fixed4
-rw-r--r--src/tools/clippy/tests/ui/use_self.rs4
-rw-r--r--src/tools/clippy/tests/ui/use_self_trait.fixed6
-rw-r--r--src/tools/clippy/tests/ui/use_self_trait.rs6
-rw-r--r--src/tools/clippy/tests/ui/use_self_trait.stderr2
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_binding.rs2
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.rs2
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.fixed4
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.rs4
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed8
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs8
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr32
-rw-r--r--src/tools/clippy/tests/ui/vec.fixed2
-rw-r--r--src/tools/clippy/tests/ui/vec.rs2
-rw-r--r--src/tools/clippy/tests/ui/vec_box_sized.fixed2
-rw-r--r--src/tools/clippy/tests/ui/vec_box_sized.rs2
-rw-r--r--src/tools/clippy/tests/ui/while_let_on_iterator.fixed2
-rw-r--r--src/tools/clippy/tests/ui/while_let_on_iterator.rs2
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed4
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs4
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.fixed6
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.rs6
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed10
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed10
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.rs10
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.stderr132
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs19
-rw-r--r--src/tools/clippy/tests/ui/write_with_newline.rs4
-rw-r--r--src/tools/clippy/tests/ui/write_with_newline.stderr6
-rw-r--r--src/tools/clippy/tests/ui/writeln_empty_string.fixed2
-rw-r--r--src/tools/clippy/tests/ui/writeln_empty_string.rs2
-rw-r--r--src/tools/clippy/tests/ui/zero_ptr.fixed2
-rw-r--r--src/tools/clippy/tests/ui/zero_ptr.rs2
-rw-r--r--src/tools/clippy/tests/ui/zero_ptr_no_std.fixed2
-rw-r--r--src/tools/clippy/tests/ui/zero_ptr_no_std.rs2
-rw-r--r--src/tools/clippy/triagebot.toml2
-rw-r--r--src/tools/compiletest/Cargo.toml6
-rw-r--r--src/tools/compiletest/src/common.rs127
-rw-r--r--src/tools/compiletest/src/header.rs326
-rw-r--r--src/tools/compiletest/src/header/cfg.rs52
-rw-r--r--src/tools/compiletest/src/header/needs.rs267
-rw-r--r--src/tools/compiletest/src/header/tests.rs30
-rw-r--r--src/tools/compiletest/src/lib.rs1136
-rw-r--r--src/tools/compiletest/src/main.rs1115
-rw-r--r--src/tools/compiletest/src/runtest.rs169
-rw-r--r--src/tools/generate-windows-sys/Cargo.toml7
-rw-r--r--src/tools/generate-windows-sys/src/main.rs37
-rw-r--r--src/tools/jsondoclint/src/validator.rs4
-rwxr-xr-xsrc/tools/linkchecker/linkcheck.sh26
-rw-r--r--src/tools/linkchecker/main.rs35
-rw-r--r--src/tools/lint-docs/src/groups.rs2
-rw-r--r--src/tools/lint-docs/src/lib.rs3
-rw-r--r--src/tools/miropt-test-tools/src/lib.rs19
-rw-r--r--src/tools/replace-version-placeholder/src/main.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs6
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs6
-rw-r--r--src/tools/rustc-workspace-hack/Cargo.toml102
-rw-r--r--src/tools/rustc-workspace-hack/README.md25
-rw-r--r--src/tools/rustc-workspace-hack/lib.rs1
-rw-r--r--src/tools/rustdoc-gui-test/Cargo.toml9
-rw-r--r--src/tools/rustdoc-gui-test/src/config.rs62
-rw-r--r--src/tools/rustdoc-gui-test/src/main.rs162
-rw-r--r--src/tools/rustdoc-gui/tester.js13
-rw-r--r--src/tools/rustdoc-js/tester.js54
-rw-r--r--src/tools/rustfmt/src/bin/main.rs9
-rw-r--r--src/tools/rustfmt/src/chains.rs4
-rw-r--r--src/tools/rustfmt/src/expr.rs8
-rw-r--r--src/tools/rustfmt/src/types.rs6
-rw-r--r--src/tools/rustfmt/src/utils.rs1
-rw-r--r--src/tools/rustfmt/tests/source/type-ascription.rs10
-rw-r--r--src/tools/rustfmt/tests/target/configs/format_macro_bodies/true.rs8
-rw-r--r--src/tools/rustfmt/tests/target/configs/format_macro_matchers/false.rs8
-rw-r--r--src/tools/rustfmt/tests/target/configs/format_macro_matchers/true.rs8
-rw-r--r--src/tools/rustfmt/tests/target/macros.rs22
-rw-r--r--src/tools/rustfmt/tests/target/negative-bounds.rs11
-rw-r--r--src/tools/rustfmt/tests/target/type-ascription.rs12
-rw-r--r--src/tools/rustfmt/tests/target/type.rs2
-rw-r--r--src/tools/suggest-tests/src/static_suggestions.rs2
-rw-r--r--src/tools/suggest-tests/src/tests.rs2
-rw-r--r--src/tools/tidy/src/deps.rs202
-rw-r--r--src/tools/tidy/src/fluent_alphabetical.rs72
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs1
-rw-r--r--src/tools/tidy/src/style.rs12
-rw-r--r--src/tools/tidy/src/ui_tests.rs44
-rw-r--r--src/version2
1593 files changed, 30514 insertions, 21230 deletions
diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md
index 74dd22df9..d6924cf2c 100644
--- a/src/bootstrap/CHANGELOG.md
+++ b/src/bootstrap/CHANGELOG.md
@@ -27,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
from the default rust toolchain. [#78513](https://github.com/rust-lang/rust/pull/78513)
- Add options for enabling overflow checks, one for std (`overflow-checks-std`) and one for everything else (`overflow-checks`). Both default to false.
- Add llvm option `enable-warnings` to have control on llvm compilation warnings. Default to false.
+- Add `rpath` option in `target` section to support set rpath option for each target independently. [#111242](https://github.com/rust-lang/rust/pull/111242)
## [Version 2] - 2020-09-25
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index a158d1f71..8f8778efe 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -12,6 +12,12 @@ dependencies = [
]
[[package]]
+name = "anstyle"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+
+[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -38,10 +44,11 @@ version = "0.0.0"
dependencies = [
"build_helper",
"cc",
+ "clap",
+ "clap_complete",
"cmake",
"fd-lock",
"filetime",
- "getopts",
"hex",
"ignore",
"is-terminal",
@@ -51,6 +58,7 @@ dependencies = [
"once_cell",
"opener",
"pretty_assertions",
+ "semver",
"serde",
"serde_derive",
"serde_json",
@@ -92,6 +100,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+name = "clap"
+version = "4.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+ "once_cell",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749"
+dependencies = [
+ "anstyle",
+ "bitflags",
+ "clap_lex",
+]
+
+[[package]]
+name = "clap_complete"
+version = "4.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36774babb166352bb4f7b9cb16f781ffa3439d2a8f12cd31bea85a38c888fea3"
+dependencies = [
+ "clap",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.8",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
+
+[[package]]
name = "cmake"
version = "0.1.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -175,7 +232,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
dependencies = [
"quote",
- "syn",
+ "syn 1.0.102",
]
[[package]]
@@ -261,15 +318,6 @@ dependencies = [
]
[[package]]
-name = "getopts"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
name = "globset"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -283,6 +331,12 @@ dependencies = [
]
[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -374,9 +428,9 @@ checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]]
name = "linux-raw-sys"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
+checksum = "3f508063cc7bb32987c71511216bd5a32be15bccb6a80b52df8b9d7f01fc3aa2"
[[package]]
name = "log"
@@ -434,9 +488,9 @@ dependencies = [
[[package]]
name = "object"
-version = "0.29.0"
+version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
dependencies = [
"memchr",
]
@@ -486,18 +540,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.46"
+version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.18"
+version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
@@ -593,20 +647,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
+name = "semver"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+
+[[package]]
name = "serde"
-version = "1.0.137"
+version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
[[package]]
name = "serde_derive"
-version = "1.0.137"
+version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.8",
]
[[package]]
@@ -643,6 +703,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "2.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "sysinfo"
version = "0.26.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -708,12 +779,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
[[package]]
-name = "unicode-width"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
-
-[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index eeda6d7c1..367c61909 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -34,11 +34,10 @@ is-terminal = "0.4"
build_helper = { path = "../tools/build_helper" }
cmake = "0.1.38"
filetime = "0.2"
-getopts = "0.2.19"
cc = "1.0.69"
libc = "0.2"
hex = "0.4"
-object = { version = "0.29.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
+object = { version = "0.31.1", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
serde = "1.0.137"
# Directly use serde_derive rather than through the derive feature of serde to allow building both
# in parallel and to allow serde_json and toml to start building as soon as serde has been built.
@@ -56,6 +55,9 @@ walkdir = "2"
# Dependencies needed by the build-metrics feature
sysinfo = { version = "0.26.0", optional = true }
+clap = { version = "4.2.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
+clap_complete = "4.2.2"
+semver = "1.0.17"
# Solaris doesn't support flock() and thus fd-lock is not option now
[target.'cfg(not(target_os = "solaris"))'.dependencies]
@@ -69,13 +71,9 @@ version = "0.46.0"
features = [
"Win32_Foundation",
"Win32_Security",
- "Win32_Storage_FileSystem",
"Win32_System_Diagnostics_Debug",
- "Win32_System_IO",
- "Win32_System_Ioctl",
"Win32_System_JobObjects",
"Win32_System_ProcessStatus",
- "Win32_System_SystemServices",
"Win32_System_Threading",
"Win32_System_Time",
]
@@ -90,6 +88,7 @@ build-metrics = ["sysinfo"]
# dependencies, only bootstrap itself.
[profile.dev]
debug = 0
+
[profile.dev.package]
# Only use debuginfo=1 to further reduce compile times.
bootstrap.debug = 1
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index 912d875e4..a80379e85 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -16,9 +16,11 @@ fn main() {
let config = Config::parse(&args);
#[cfg(all(any(unix, windows), not(target_os = "solaris")))]
+ let mut build_lock;
+ #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
+ let _build_lock_guard;
+ #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
{
- let mut build_lock;
- let _build_lock_guard;
let path = config.out.join("lock");
build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path)));
_build_lock_guard = match build_lock.try_write() {
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 040fec361..e87125a49 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -19,7 +19,7 @@ include!("../dylib_util.rs");
use std::env;
use std::path::PathBuf;
-use std::process::{Child, Command};
+use std::process::{exit, Child, Command};
use std::str::FromStr;
use std::time::Instant;
@@ -47,7 +47,12 @@ fn main() {
} else {
("RUSTC_REAL", "RUSTC_LIBDIR")
};
- let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
+ let stage = env::var("RUSTC_STAGE").unwrap_or_else(|_| {
+ // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
+ eprintln!("rustc shim: fatal: RUSTC_STAGE was not set");
+ eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap");
+ exit(101);
+ });
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new);
@@ -150,7 +155,7 @@ fn main() {
// allow the `rustc_private` feature to link to other unstable crates
// also in the sysroot. We also do this for host crates, since those
// may be proc macros, in which case we might ship them.
- if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
+ if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
cmd.arg("-Z").arg("force-unstable-if-unmarked");
}
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs
index 23828f475..d2b85f7a6 100644
--- a/src/bootstrap/bin/rustdoc.rs
+++ b/src/bootstrap/bin/rustdoc.rs
@@ -5,13 +5,18 @@
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
-use std::process::Command;
+use std::process::{exit, Command};
include!("../dylib_util.rs");
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
- let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
+ let stage = env::var("RUSTC_STAGE").unwrap_or_else(|_| {
+ // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
+ eprintln!("rustc shim: fatal: RUSTC_STAGE was not set");
+ eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap");
+ exit(101);
+ });
let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set");
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
diff --git a/src/bootstrap/bolt.rs b/src/bootstrap/bolt.rs
index 10e6d2e7d..5384181ea 100644
--- a/src/bootstrap/bolt.rs
+++ b/src/bootstrap/bolt.rs
@@ -40,7 +40,7 @@ pub fn optimize_with_bolt(path: &Path, profile_path: &Path, output_path: &Path)
// Reorder functions within the binary
.arg("-reorder-functions=hfsort+")
// Split function code into hot and code regions
- .arg("-split-functions=2")
+ .arg("-split-functions")
// Split as many basic blocks as possible
.arg("-split-all-cold")
// Move jump tables to a separate section
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 025145244..58d1926ad 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -13,17 +13,35 @@ import tarfile
import tempfile
from time import time
+from multiprocessing import Pool, cpu_count
try:
import lzma
except ImportError:
lzma = None
-if sys.platform == 'win32':
+def platform_is_win32():
+ return sys.platform == 'win32'
+
+if platform_is_win32():
EXE_SUFFIX = ".exe"
else:
EXE_SUFFIX = ""
+def get_cpus():
+ if hasattr(os, "sched_getaffinity"):
+ return len(os.sched_getaffinity(0))
+ if hasattr(os, "cpu_count"):
+ cpus = os.cpu_count()
+ if cpus is not None:
+ return cpus
+ try:
+ return cpu_count()
+ except NotImplementedError:
+ return 1
+
+
+
def get(base, url, path, checksums, verbose=False):
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
temp_path = temp_file.name
@@ -39,23 +57,23 @@ def get(base, url, path, checksums, verbose=False):
if os.path.exists(path):
if verify(path, sha256, False):
if verbose:
- print("using already-download file", path)
+ print("using already-download file", path, file=sys.stderr)
return
else:
if verbose:
print("ignoring already-download file",
- path, "due to failed verification")
+ path, "due to failed verification", file=sys.stderr)
os.unlink(path)
download(temp_path, "{}/{}".format(base, url), True, verbose)
if not verify(temp_path, sha256, verbose):
raise RuntimeError("failed verification")
if verbose:
- print("moving {} to {}".format(temp_path, path))
+ print("moving {} to {}".format(temp_path, path), file=sys.stderr)
shutil.move(temp_path, path)
finally:
if os.path.isfile(temp_path):
if verbose:
- print("removing", temp_path)
+ print("removing", temp_path, file=sys.stderr)
os.unlink(temp_path)
@@ -65,7 +83,7 @@ def download(path, url, probably_big, verbose):
_download(path, url, probably_big, verbose, True)
return
except RuntimeError:
- print("\nspurious failure, trying again")
+ print("\nspurious failure, trying again", file=sys.stderr)
_download(path, url, probably_big, verbose, False)
@@ -76,9 +94,8 @@ def _download(path, url, probably_big, verbose, exception):
# - If we are on win32 fallback to powershell
# - Otherwise raise the error if appropriate
if probably_big or verbose:
- print("downloading {}".format(url))
+ print("downloading {}".format(url), file=sys.stderr)
- platform_is_win32 = sys.platform == 'win32'
try:
if probably_big or verbose:
option = "-#"
@@ -86,21 +103,21 @@ def _download(path, url, probably_big, verbose, exception):
option = "-s"
# If curl is not present on Win32, we should not sys.exit
# but raise `CalledProcessError` or `OSError` instead
- require(["curl", "--version"], exception=platform_is_win32)
+ require(["curl", "--version"], exception=platform_is_win32())
with open(path, "wb") as outfile:
run(["curl", option,
"-L", # Follow redirect.
"-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds
"--connect-timeout", "30", # timeout if cannot connect within 30 seconds
- "--retry", "3", "-Sf", url],
+ "--retry", "3", "-SRf", url],
stdout=outfile, #Implements cli redirect operator '>'
verbose=verbose,
exception=True, # Will raise RuntimeError on failure
)
except (subprocess.CalledProcessError, OSError, RuntimeError):
# see http://serverfault.com/questions/301128/how-to-download
- if platform_is_win32:
- run(["PowerShell.exe", "/nologo", "-Command",
+ if platform_is_win32():
+ run_powershell([
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)],
verbose=verbose,
@@ -113,20 +130,20 @@ def _download(path, url, probably_big, verbose, exception):
def verify(path, expected, verbose):
"""Check if the sha256 sum of the given path is valid"""
if verbose:
- print("verifying", path)
+ print("verifying", path, file=sys.stderr)
with open(path, "rb") as source:
found = hashlib.sha256(source.read()).hexdigest()
verified = found == expected
if not verified:
print("invalid checksum:\n"
" found: {}\n"
- " expected: {}".format(found, expected))
+ " expected: {}".format(found, expected), file=sys.stderr)
return verified
def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
"""Unpack the given tarball file"""
- print("extracting", tarball)
+ print("extracting", tarball, file=sys.stderr)
fname = os.path.basename(tarball).replace(tarball_suffix, "")
with contextlib.closing(tarfile.open(tarball)) as tar:
for member in tar.getnames():
@@ -139,7 +156,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
dst_path = os.path.join(dst, name)
if verbose:
- print(" extracting", member)
+ print(" extracting", member, file=sys.stderr)
tar.extract(member, dst)
src_path = os.path.join(dst, member)
if os.path.isdir(src_path) and os.path.exists(dst_path):
@@ -151,7 +168,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
"""Run a child program in a new process"""
if verbose:
- print("running: " + ' '.join(args))
+ print("running: " + ' '.join(args), file=sys.stderr)
sys.stdout.flush()
# Ensure that the .exe is used on Windows just in case a Linux ELF has been
# compiled in the same directory.
@@ -174,6 +191,10 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
else:
sys.exit(err)
+def run_powershell(script, *args, **kwargs):
+ """Run a powershell script"""
+ run(["PowerShell.exe", "/nologo", "-Command"] + script, *args, **kwargs)
+
def require(cmd, exit=True, exception=False):
'''Run a command, returning its output.
@@ -187,8 +208,8 @@ def require(cmd, exit=True, exception=False):
if exception:
raise
elif exit:
- print("error: unable to run `{}`: {}".format(' '.join(cmd), exc))
- print("Please make sure it's installed and in the path.")
+ print("error: unable to run `{}`: {}".format(' '.join(cmd), exc), file=sys.stderr)
+ print("Please make sure it's installed and in the path.", file=sys.stderr)
sys.exit(1)
return None
@@ -205,38 +226,41 @@ def format_build_time(duration):
def default_build_triple(verbose):
"""Build triple as in LLVM"""
- # If the user already has a host build triple with an existing `rustc`
- # install, use their preference. This fixes most issues with Windows builds
- # being detected as GNU instead of MSVC.
+ # If we're on Windows and have an existing `rustc` toolchain, use `rustc --version --verbose`
+ # to find our host target triple. This fixes an issue with Windows builds being detected
+ # as GNU instead of MSVC.
+ # Otherwise, detect it via `uname`
default_encoding = sys.getdefaultencoding()
- try:
- version = subprocess.check_output(["rustc", "--version", "--verbose"],
- stderr=subprocess.DEVNULL)
- version = version.decode(default_encoding)
- host = next(x for x in version.split('\n') if x.startswith("host: "))
- triple = host.split("host: ")[1]
- if verbose:
- print("detected default triple {} from pre-installed rustc".format(triple))
- return triple
- except Exception as e:
- if verbose:
- print("pre-installed rustc not detected: {}".format(e))
- print("falling back to auto-detect")
- required = sys.platform != 'win32'
- ostype = require(["uname", "-s"], exit=required)
- cputype = require(['uname', '-m'], exit=required)
+ if platform_is_win32():
+ try:
+ version = subprocess.check_output(["rustc", "--version", "--verbose"],
+ stderr=subprocess.DEVNULL)
+ version = version.decode(default_encoding)
+ host = next(x for x in version.split('\n') if x.startswith("host: "))
+ triple = host.split("host: ")[1]
+ if verbose:
+ print("detected default triple {} from pre-installed rustc".format(triple),
+ file=sys.stderr)
+ return triple
+ except Exception as e:
+ if verbose:
+ print("pre-installed rustc not detected: {}".format(e),
+ file=sys.stderr)
+ print("falling back to auto-detect", file=sys.stderr)
+
+ required = not platform_is_win32()
+ uname = require(["uname", "-smp"], exit=required)
# If we do not have `uname`, assume Windows.
- if ostype is None or cputype is None:
+ if uname is None:
return 'x86_64-pc-windows-msvc'
- ostype = ostype.decode(default_encoding)
- cputype = cputype.decode(default_encoding)
+ kernel, cputype, processor = uname.decode(default_encoding).split()
# The goal here is to come up with the same triple as LLVM would,
# at least for the subset of platforms we're willing to target.
- ostype_mapper = {
+ kerneltype_mapper = {
'Darwin': 'apple-darwin',
'DragonFly': 'unknown-dragonfly',
'FreeBSD': 'unknown-freebsd',
@@ -246,17 +270,18 @@ def default_build_triple(verbose):
}
# Consider the direct transformation first and then the special cases
- if ostype in ostype_mapper:
- ostype = ostype_mapper[ostype]
- elif ostype == 'Linux':
- os_from_sp = subprocess.check_output(
- ['uname', '-o']).strip().decode(default_encoding)
- if os_from_sp == 'Android':
- ostype = 'linux-android'
+ if kernel in kerneltype_mapper:
+ kernel = kerneltype_mapper[kernel]
+ elif kernel == 'Linux':
+ # Apple doesn't support `-o` so this can't be used in the combined
+ # uname invocation above
+ ostype = require(["uname", "-o"], exit=required).decode(default_encoding)
+ if ostype == 'Android':
+ kernel = 'linux-android'
else:
- ostype = 'unknown-linux-gnu'
- elif ostype == 'SunOS':
- ostype = 'pc-solaris'
+ kernel = 'unknown-linux-gnu'
+ elif kernel == 'SunOS':
+ kernel = 'pc-solaris'
# On Solaris, uname -m will return a machine classification instead
# of a cpu type, so uname -p is recommended instead. However, the
# output from that option is too generic for our purposes (it will
@@ -265,34 +290,34 @@ def default_build_triple(verbose):
cputype = require(['isainfo', '-k']).decode(default_encoding)
# sparc cpus have sun as a target vendor
if 'sparc' in cputype:
- ostype = 'sun-solaris'
- elif ostype.startswith('MINGW'):
+ kernel = 'sun-solaris'
+ elif kernel.startswith('MINGW'):
# msys' `uname` does not print gcc configuration, but prints msys
# configuration. so we cannot believe `uname -m`:
# msys1 is always i686 and msys2 is always x86_64.
# instead, msys defines $MSYSTEM which is MINGW32 on i686 and
# MINGW64 on x86_64.
- ostype = 'pc-windows-gnu'
+ kernel = 'pc-windows-gnu'
cputype = 'i686'
if os.environ.get('MSYSTEM') == 'MINGW64':
cputype = 'x86_64'
- elif ostype.startswith('MSYS'):
- ostype = 'pc-windows-gnu'
- elif ostype.startswith('CYGWIN_NT'):
+ elif kernel.startswith('MSYS'):
+ kernel = 'pc-windows-gnu'
+ elif kernel.startswith('CYGWIN_NT'):
cputype = 'i686'
- if ostype.endswith('WOW64'):
+ if kernel.endswith('WOW64'):
cputype = 'x86_64'
- ostype = 'pc-windows-gnu'
- elif sys.platform == 'win32':
+ kernel = 'pc-windows-gnu'
+ elif platform_is_win32():
# Some Windows platforms might have a `uname` command that returns a
# non-standard string (e.g. gnuwin32 tools returns `windows32`). In
# these cases, fall back to using sys.platform.
return 'x86_64-pc-windows-msvc'
else:
- err = "unknown OS type: {}".format(ostype)
+ err = "unknown OS type: {}".format(kernel)
sys.exit(err)
- if cputype in ['powerpc', 'riscv'] and ostype == 'unknown-freebsd':
+ if cputype in ['powerpc', 'riscv'] and kernel == 'unknown-freebsd':
cputype = subprocess.check_output(
['uname', '-p']).strip().decode(default_encoding)
cputype_mapper = {
@@ -325,24 +350,23 @@ def default_build_triple(verbose):
cputype = cputype_mapper[cputype]
elif cputype in {'xscale', 'arm'}:
cputype = 'arm'
- if ostype == 'linux-android':
- ostype = 'linux-androideabi'
- elif ostype == 'unknown-freebsd':
- cputype = subprocess.check_output(
- ['uname', '-p']).strip().decode(default_encoding)
- ostype = 'unknown-freebsd'
+ if kernel == 'linux-android':
+ kernel = 'linux-androideabi'
+ elif kernel == 'unknown-freebsd':
+ cputype = processor
+ kernel = 'unknown-freebsd'
elif cputype == 'armv6l':
cputype = 'arm'
- if ostype == 'linux-android':
- ostype = 'linux-androideabi'
+ if kernel == 'linux-android':
+ kernel = 'linux-androideabi'
else:
- ostype += 'eabihf'
+ kernel += 'eabihf'
elif cputype in {'armv7l', 'armv8l'}:
cputype = 'armv7'
- if ostype == 'linux-android':
- ostype = 'linux-androideabi'
+ if kernel == 'linux-android':
+ kernel = 'linux-androideabi'
else:
- ostype += 'eabihf'
+ kernel += 'eabihf'
elif cputype == 'mips':
if sys.byteorder == 'big':
cputype = 'mips'
@@ -358,14 +382,14 @@ def default_build_triple(verbose):
else:
raise ValueError('unknown byteorder: {}'.format(sys.byteorder))
# only the n64 ABI is supported, indicate it
- ostype += 'abi64'
+ kernel += 'abi64'
elif cputype == 'sparc' or cputype == 'sparcv9' or cputype == 'sparc64':
pass
else:
err = "unknown cpu type: {}".format(cputype)
sys.exit(err)
- return "{}-{}".format(cputype, ostype)
+ return "{}-{}".format(cputype, kernel)
@contextlib.contextmanager
@@ -392,6 +416,48 @@ class Stage0Toolchain:
return self.version + "-" + self.date
+class DownloadInfo:
+ """A helper class that can be pickled into a parallel subprocess"""
+
+ def __init__(
+ self,
+ base_download_url,
+ download_path,
+ bin_root,
+ tarball_path,
+ tarball_suffix,
+ checksums_sha256,
+ pattern,
+ verbose,
+ ):
+ self.base_download_url = base_download_url
+ self.download_path = download_path
+ self.bin_root = bin_root
+ self.tarball_path = tarball_path
+ self.tarball_suffix = tarball_suffix
+ self.checksums_sha256 = checksums_sha256
+ self.pattern = pattern
+ self.verbose = verbose
+
+def download_component(download_info):
+ if not os.path.exists(download_info.tarball_path):
+ get(
+ download_info.base_download_url,
+ download_info.download_path,
+ download_info.tarball_path,
+ download_info.checksums_sha256,
+ verbose=download_info.verbose,
+ )
+
+def unpack_component(download_info):
+ unpack(
+ download_info.tarball_path,
+ download_info.tarball_suffix,
+ download_info.bin_root,
+ match=download_info.pattern,
+ verbose=download_info.verbose,
+ )
+
class RustBuild(object):
"""Provide all the methods required to build Rust"""
def __init__(self):
@@ -428,18 +494,71 @@ class RustBuild(object):
(not os.path.exists(self.rustc()) or
self.program_out_of_date(self.rustc_stamp(), key)):
if os.path.exists(bin_root):
+ # HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's
+ # running. Kill it.
+ if platform_is_win32():
+ print("Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain")
+ regex = '{}\\\\(host|{})\\\\stage0\\\\libexec'.format(
+ os.path.basename(self.build_dir),
+ self.build
+ )
+ script = (
+ # NOTE: can't use `taskkill` or `Get-Process -Name` because they error if
+ # the server isn't running.
+ 'Get-Process | ' +
+ 'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |' +
+ 'Where-Object {{$_.Path -match "{}"}} |'.format(regex) +
+ 'Stop-Process'
+ )
+ run_powershell([script])
shutil.rmtree(bin_root)
+
+ key = self.stage0_compiler.date
+ cache_dst = os.path.join(self.build_dir, "cache")
+ rustc_cache = os.path.join(cache_dst, key)
+ if not os.path.exists(rustc_cache):
+ os.makedirs(rustc_cache)
+
tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz'
- filename = "rust-std-{}-{}{}".format(
- rustc_channel, self.build, tarball_suffix)
- pattern = "rust-std-{}".format(self.build)
- self._download_component_helper(filename, pattern, tarball_suffix)
- filename = "rustc-{}-{}{}".format(rustc_channel, self.build,
- tarball_suffix)
- self._download_component_helper(filename, "rustc", tarball_suffix)
- filename = "cargo-{}-{}{}".format(rustc_channel, self.build,
- tarball_suffix)
- self._download_component_helper(filename, "cargo", tarball_suffix)
+
+ toolchain_suffix = "{}-{}{}".format(rustc_channel, self.build, tarball_suffix)
+
+ tarballs_to_download = [
+ ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)),
+ ("rustc-{}".format(toolchain_suffix), "rustc"),
+ ("cargo-{}".format(toolchain_suffix), "cargo"),
+ ]
+
+ tarballs_download_info = [
+ DownloadInfo(
+ base_download_url=self.download_url,
+ download_path="dist/{}/{}".format(self.stage0_compiler.date, filename),
+ bin_root=self.bin_root(),
+ tarball_path=os.path.join(rustc_cache, filename),
+ tarball_suffix=tarball_suffix,
+ checksums_sha256=self.checksums_sha256,
+ pattern=pattern,
+ verbose=self.verbose,
+ )
+ for filename, pattern in tarballs_to_download
+ ]
+
+ # Download the components serially to show the progress bars properly.
+ for download_info in tarballs_download_info:
+ download_component(download_info)
+
+ # Unpack the tarballs in parallle.
+ # In Python 2.7, Pool cannot be used as a context manager.
+ pool_size = min(len(tarballs_download_info), get_cpus())
+ if self.verbose:
+ print('Choosing a pool size of', pool_size, 'for the unpacking of the tarballs')
+ p = Pool(pool_size)
+ try:
+ p.map(unpack_component, tarballs_download_info)
+ finally:
+ p.close()
+ p.join()
+
if self.should_fix_bins_and_dylibs():
self.fix_bin_or_dylib("{}/bin/cargo".format(bin_root))
@@ -455,13 +574,9 @@ class RustBuild(object):
rust_stamp.write(key)
def _download_component_helper(
- self, filename, pattern, tarball_suffix,
+ self, filename, pattern, tarball_suffix, rustc_cache,
):
key = self.stage0_compiler.date
- cache_dst = os.path.join(self.build_dir, "cache")
- rustc_cache = os.path.join(cache_dst, key)
- if not os.path.exists(rustc_cache):
- os.makedirs(rustc_cache)
tarball = os.path.join(rustc_cache, filename)
if not os.path.exists(tarball):
@@ -516,7 +631,7 @@ class RustBuild(object):
answer = self._should_fix_bins_and_dylibs = get_answer()
if answer:
- print("info: You seem to be using Nix.")
+ print("info: You seem to be using Nix.", file=sys.stderr)
return answer
def fix_bin_or_dylib(self, fname):
@@ -529,7 +644,7 @@ class RustBuild(object):
Please see https://nixos.org/patchelf.html for more information
"""
assert self._should_fix_bins_and_dylibs is True
- print("attempting to patch", fname)
+ print("attempting to patch", fname, file=sys.stderr)
# Only build `.nix-deps` once.
nix_deps_dir = self.nix_deps_dir
@@ -562,7 +677,7 @@ class RustBuild(object):
"nix-build", "-E", nix_expr, "-o", nix_deps_dir,
])
except subprocess.CalledProcessError as reason:
- print("warning: failed to call nix-build:", reason)
+ print("warning: failed to call nix-build:", reason, file=sys.stderr)
return
self.nix_deps_dir = nix_deps_dir
@@ -575,14 +690,14 @@ class RustBuild(object):
]
patchelf_args = ["--set-rpath", ":".join(rpath_entries)]
if not fname.endswith(".so"):
- # Finally, set the corret .interp for binaries
+ # Finally, set the correct .interp for binaries
with open("{}/nix-support/dynamic-linker".format(nix_deps_dir)) as dynamic_linker:
patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()]
try:
subprocess.check_output([patchelf] + patchelf_args + [fname])
except subprocess.CalledProcessError as reason:
- print("warning: failed to call patchelf:", reason)
+ print("warning: failed to call patchelf:", reason, file=sys.stderr)
return
def rustc_stamp(self):
@@ -722,11 +837,14 @@ class RustBuild(object):
def build_bootstrap(self, color, verbose_count):
"""Build bootstrap"""
- print("Building bootstrap")
+ env = os.environ.copy()
+ if "GITHUB_ACTIONS" in env:
+ print("::group::Building bootstrap")
+ else:
+ print("Building bootstrap", file=sys.stderr)
build_dir = os.path.join(self.build_dir, "bootstrap")
if self.clean and os.path.exists(build_dir):
shutil.rmtree(build_dir)
- env = os.environ.copy()
# `CARGO_BUILD_TARGET` breaks bootstrap build.
# See also: <https://github.com/rust-lang/rust/issues/70208>.
if "CARGO_BUILD_TARGET" in env:
@@ -798,6 +916,9 @@ class RustBuild(object):
# Run this from the source directory so cargo finds .cargo/config
run(args, env=env, verbose=self.verbose, cwd=self.rust_root)
+ if "GITHUB_ACTIONS" in env:
+ print("::endgroup::")
+
def build_triple(self):
"""Build triple as in LLVM
@@ -814,25 +935,33 @@ class RustBuild(object):
if 'SUDO_USER' in os.environ and not self.use_vendored_sources:
if os.getuid() == 0:
self.use_vendored_sources = True
- print('info: looks like you\'re trying to run this command as root')
- print(' and so in order to preserve your $HOME this will now')
- print(' use vendored sources by default.')
+ print('info: looks like you\'re trying to run this command as root',
+ file=sys.stderr)
+ print(' and so in order to preserve your $HOME this will now',
+ file=sys.stderr)
+ print(' use vendored sources by default.',
+ file=sys.stderr)
cargo_dir = os.path.join(self.rust_root, '.cargo')
if self.use_vendored_sources:
vendor_dir = os.path.join(self.rust_root, 'vendor')
if not os.path.exists(vendor_dir):
- sync_dirs = "--sync ./src/tools/rust-analyzer/Cargo.toml " \
+ sync_dirs = "--sync ./src/tools/cargo/Cargo.toml " \
+ "--sync ./src/tools/rust-analyzer/Cargo.toml " \
"--sync ./compiler/rustc_codegen_cranelift/Cargo.toml " \
"--sync ./src/bootstrap/Cargo.toml "
- print('error: vendoring required, but vendor directory does not exist.')
+ print('error: vendoring required, but vendor directory does not exist.',
+ file=sys.stderr)
print(' Run `cargo vendor {}` to initialize the '
- 'vendor directory.'.format(sync_dirs))
- print('Alternatively, use the pre-vendored `rustc-src` dist component.')
+ 'vendor directory.'.format(sync_dirs),
+ file=sys.stderr)
+ print('Alternatively, use the pre-vendored `rustc-src` dist component.',
+ file=sys.stderr)
raise Exception("{} not found".format(vendor_dir))
if not os.path.exists(cargo_dir):
- print('error: vendoring required, but .cargo/config does not exist.')
+ print('error: vendoring required, but .cargo/config does not exist.',
+ file=sys.stderr)
raise Exception("{} not found".format(cargo_dir))
else:
if os.path.exists(cargo_dir):
@@ -942,7 +1071,7 @@ def main():
print(
"info: Downloading and building bootstrap before processing --help command.\n"
" See src/bootstrap/README.md for help with common commands."
- )
+ , file=sys.stderr)
exit_code = 0
success_word = "successfully"
@@ -953,11 +1082,12 @@ def main():
exit_code = error.code
else:
exit_code = 1
- print(error)
+ print(error, file=sys.stderr)
success_word = "unsuccessfully"
if not help_triggered:
- print("Build completed", success_word, "in", format_build_time(time() - start_time))
+ print("Build completed", success_word, "in", format_build_time(time() - start_time),
+ file=sys.stderr)
sys.exit(exit_code)
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index 20bd71f06..5ecda83ee 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -97,6 +97,7 @@ class GenerateAndParseConfig(unittest.TestCase):
def test_no_args(self):
build = self.serialize_and_parse([])
self.assertEqual(build.get_toml("changelog-seen"), '2')
+ self.assertEqual(build.get_toml("profile"), 'user')
self.assertIsNone(build.get_toml("llvm.download-ci-llvm"))
def test_set_section(self):
@@ -107,10 +108,17 @@ class GenerateAndParseConfig(unittest.TestCase):
build = self.serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"])
self.assertEqual(build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), 'gcc')
- # Uncomment when #108928 is fixed.
- # def test_set_top_level(self):
- # build = self.serialize_and_parse(["--set", "profile=compiler"])
- # self.assertEqual(build.get_toml("profile"), 'compiler')
+ def test_set_top_level(self):
+ build = self.serialize_and_parse(["--set", "profile=compiler"])
+ self.assertEqual(build.get_toml("profile"), 'compiler')
+
+ def test_set_codegen_backends(self):
+ build = self.serialize_and_parse(["--set", "rust.codegen-backends=cranelift"])
+ self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift']"), -1)
+ build = self.serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"])
+ self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1)
+ build = self.serialize_and_parse(["--enable-full-tools"])
+ self.assertNotEqual(build.config_toml.find("codegen-backends = ['llvm']"), -1)
if __name__ == '__main__':
SUITE = unittest.TestSuite()
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index e959ea06f..2fa445506 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -33,6 +33,7 @@ pub use crate::Compiler;
// - use std::lazy for `Lazy`
// - use std::cell for `OnceCell`
// Once they get stabilized and reach beta.
+use clap::ValueEnum;
use once_cell::sync::{Lazy, OnceCell};
pub struct Builder<'a> {
@@ -263,7 +264,7 @@ impl PathSet {
/// A convenience wrapper for Steps which know they have no aliases and all their sets contain only a single path.
///
- /// This can be used with [`ShouldRun::krate`], [`ShouldRun::path`], or [`ShouldRun::alias`].
+ /// This can be used with [`ShouldRun::crate_or_deps`], [`ShouldRun::path`], or [`ShouldRun::alias`].
#[track_caller]
pub fn assert_single_path(&self) -> &TaskPath {
match self {
@@ -576,19 +577,24 @@ impl<'a> ShouldRun<'a> {
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, ValueEnum)]
pub enum Kind {
+ #[clap(alias = "b")]
Build,
+ #[clap(alias = "c")]
Check,
Clippy,
Fix,
Format,
+ #[clap(alias = "t")]
Test,
Bench,
+ #[clap(alias = "d")]
Doc,
Clean,
Dist,
Install,
+ #[clap(alias = "r")]
Run,
Setup,
Suggest,
@@ -634,6 +640,14 @@ impl Kind {
Kind::Suggest => "suggest",
}
}
+
+ pub fn test_description(&self) -> &'static str {
+ match self {
+ Kind::Test => "Testing",
+ Kind::Bench => "Benchmarking",
+ _ => panic!("not a test command: {}!", self.as_str()),
+ }
+ }
}
impl<'a> Builder<'a> {
@@ -675,7 +689,8 @@ impl<'a> Builder<'a> {
tool::Miri,
tool::CargoMiri,
llvm::Lld,
- llvm::CrtBeginEnd
+ llvm::CrtBeginEnd,
+ tool::RustdocGUITest,
),
Kind::Check | Kind::Clippy | Kind::Fix => describe!(
check::Std,
@@ -695,7 +710,6 @@ impl<'a> Builder<'a> {
crate::toolstate::ToolStateCheck,
test::ExpandYamlAnchors,
test::Tidy,
- test::TidySelfTest,
test::Ui,
test::RunPassValgrind,
test::MirOpt,
@@ -711,11 +725,9 @@ impl<'a> Builder<'a> {
test::CrateLibrustc,
test::CrateRustdoc,
test::CrateRustdocJsonTypes,
- test::CrateJsonDocLint,
- test::SuggestTestsCrate,
+ test::CrateBootstrap,
test::Linkcheck,
test::TierCheck,
- test::ReplacePlaceholderTest,
test::Cargotest,
test::Cargo,
test::RustAnalyzer,
@@ -776,6 +788,7 @@ impl<'a> Builder<'a> {
doc::EditionGuide,
doc::StyleGuide,
doc::Tidy,
+ doc::Bootstrap,
),
Kind::Dist => describe!(
dist::Docs,
@@ -827,6 +840,8 @@ impl<'a> Builder<'a> {
run::Miri,
run::CollectLicenseMetadata,
run::GenerateCopyright,
+ run::GenerateWindowsSys,
+ run::GenerateCompletions,
),
Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode),
Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
@@ -882,18 +897,19 @@ impl<'a> Builder<'a> {
}
pub fn new(build: &Build) -> Builder<'_> {
+ let paths = &build.config.paths;
let (kind, paths) = match build.config.cmd {
- Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
- Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
- Subcommand::Clippy { ref paths, .. } => (Kind::Clippy, &paths[..]),
- Subcommand::Fix { ref paths } => (Kind::Fix, &paths[..]),
- Subcommand::Doc { ref paths, .. } => (Kind::Doc, &paths[..]),
- Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]),
- Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
- Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
- Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
- Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]),
- Subcommand::Clean { ref paths, .. } => (Kind::Clean, &paths[..]),
+ Subcommand::Build => (Kind::Build, &paths[..]),
+ Subcommand::Check { .. } => (Kind::Check, &paths[..]),
+ Subcommand::Clippy { .. } => (Kind::Clippy, &paths[..]),
+ Subcommand::Fix => (Kind::Fix, &paths[..]),
+ Subcommand::Doc { .. } => (Kind::Doc, &paths[..]),
+ Subcommand::Test { .. } => (Kind::Test, &paths[..]),
+ Subcommand::Bench { .. } => (Kind::Bench, &paths[..]),
+ Subcommand::Dist => (Kind::Dist, &paths[..]),
+ Subcommand::Install => (Kind::Install, &paths[..]),
+ Subcommand::Run { .. } => (Kind::Run, &paths[..]),
+ Subcommand::Clean { .. } => (Kind::Clean, &paths[..]),
Subcommand::Format { .. } => (Kind::Format, &[][..]),
Subcommand::Suggest { .. } => (Kind::Suggest, &[][..]),
Subcommand::Setup { profile: ref path } => (
@@ -928,7 +944,6 @@ impl<'a> Builder<'a> {
self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
}
- /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable.
pub fn doc_rust_lang_org_channel(&self) -> String {
let channel = match &*self.config.channel {
"stable" => &self.version,
@@ -1008,9 +1023,24 @@ impl<'a> Builder<'a> {
// Avoid deleting the rustlib/ directory we just copied
// (in `impl Step for Sysroot`).
if !builder.download_rustc() {
+ builder.verbose(&format!(
+ "Removing sysroot {} to avoid caching bugs",
+ sysroot.display()
+ ));
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
}
+
+ if self.compiler.stage == 0 {
+ // The stage 0 compiler for the build triple is always pre-built.
+ // Ensure that `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use it when run.
+ dist::maybe_install_llvm_target(
+ builder,
+ self.compiler.host,
+ &builder.sysroot(self.compiler),
+ );
+ }
+
INTERNER.intern_path(sysroot)
}
}
@@ -1384,7 +1414,7 @@ impl<'a> Builder<'a> {
// Add extra cfg not defined in/by rustc
//
- // Note: Altrough it would seems that "-Zunstable-options" to `rustflags` is useless as
+ // Note: Although it would seems that "-Zunstable-options" to `rustflags` is useless as
// cargo would implicitly add it, it was discover that sometimes bootstrap only use
// `rustflags` without `cargo` making it required.
rustflags.arg("-Zunstable-options");
@@ -1574,8 +1604,8 @@ impl<'a> Builder<'a> {
// which adds to the runtime dynamic loader path when looking for
// 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, of course, but basically that's why
- // we're gated on RUSTC_RPATH here.
+ // of the box. This can be disabled by setting `rpath = false` in `[rust]`
+ // table of `config.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
@@ -1595,7 +1625,7 @@ impl<'a> Builder<'a> {
// argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it
// fun to pass a flag to a tool to pass a flag to pass a flag to a tool
// to change a flag in a binary?
- if self.config.rust_rpath && util::use_host_linker(target) {
+ if self.config.rpath_enabled(target) && util::use_host_linker(target) {
let rpath = if target.contains("apple") {
// Note that we need to take one extra step on macOS to also pass
// `-Wl,-instal_name,@rpath/...` to get things to work right. To
@@ -1887,10 +1917,10 @@ impl<'a> Builder<'a> {
}
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
- // This replaces spaces with newlines because RUSTDOCFLAGS does not
+ // This replaces spaces with tabs because RUSTDOCFLAGS does not
// support arguments with regular spaces. Hopefully someday Cargo will
// have space support.
- let rust_version = self.rust_version().replace(' ', "\n");
+ let rust_version = self.rust_version().replace(' ', "\t");
rustdocflags.arg("--crate-version").arg(&rust_version);
// Environment variables *required* throughout the build
@@ -2030,7 +2060,7 @@ impl<'a> Builder<'a> {
}
#[cfg(feature = "build-metrics")]
- self.metrics.enter_step(&step);
+ self.metrics.enter_step(&step, self);
let (out, dur) = {
let start = Instant::now();
@@ -2056,7 +2086,7 @@ impl<'a> Builder<'a> {
}
#[cfg(feature = "build-metrics")]
- self.metrics.exit_step();
+ self.metrics.exit_step(self);
{
let mut stack = self.stack.borrow_mut();
@@ -2131,6 +2161,10 @@ impl<'a> Builder<'a> {
#[cfg(test)]
mod tests;
+/// Represents flag values in `String` form with whitespace delimiter to pass it to the compiler later.
+///
+/// `-Z crate-attr` flags will be applied recursively on the target code using the `rustc_parse::parser::Parser`.
+/// See `rustc_builtin_macros::cmdline_attrs::inject` for more information.
#[derive(Debug, Clone)]
struct Rustflags(String, TargetSelection);
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 3574f1118..edca8fe9b 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -146,6 +146,22 @@ fn alias_and_path_for_library() {
);
}
+#[test]
+fn test_beta_rev_parsing() {
+ use crate::extract_beta_rev;
+
+ // single digit revision
+ assert_eq!(extract_beta_rev("1.99.9-beta.7 (xxxxxx)"), Some("7".to_string()));
+ // multiple digits
+ assert_eq!(extract_beta_rev("1.99.9-beta.777 (xxxxxx)"), Some("777".to_string()));
+ // nightly channel (no beta revision)
+ assert_eq!(extract_beta_rev("1.99.9-nightly (xxxxxx)"), None);
+ // stable channel (no beta revision)
+ assert_eq!(extract_beta_rev("1.99.9 (xxxxxxx)"), None);
+ // invalid string
+ assert_eq!(extract_beta_rev("invalid"), None);
+}
+
mod defaults {
use super::{configure, first, run_build};
use crate::builder::*;
@@ -236,7 +252,7 @@ mod defaults {
fn doc_default() {
let mut config = configure("doc", &["A"], &["A"]);
config.compiler_docs = true;
- config.cmd = Subcommand::Doc { paths: Vec::new(), open: false, json: false };
+ config.cmd = Subcommand::Doc { open: false, json: false };
let mut cache = run_build(&[], config);
let a = TargetSelection::from_user("A");
@@ -545,12 +561,13 @@ mod dist {
fn test_with_no_doc_stage0() {
let mut config = configure(&["A"], &["A"]);
config.stage = 0;
+ config.paths = vec!["library/std".into()];
config.cmd = Subcommand::Test {
- paths: vec!["library/std".into()],
test_args: vec![],
rustc_args: vec![],
- fail_fast: true,
- doc_tests: DocTests::No,
+ no_fail_fast: false,
+ no_doc: true,
+ doc: false,
bless: false,
force_rerun: false,
compare_mode: None,
@@ -558,6 +575,7 @@ mod dist {
pass: None,
run: None,
only_modified: false,
+ skip: vec![],
};
let build = Build::new(config);
@@ -578,7 +596,6 @@ mod dist {
compiler: Compiler { host, stage: 0 },
target: host,
mode: Mode::Std,
- test_kind: test::TestKind::Test,
crates: vec![INTERNER.intern_str("std")],
},]
);
@@ -588,7 +605,7 @@ mod dist {
fn doc_ci() {
let mut config = configure(&["A"], &["A"]);
config.compiler_docs = true;
- config.cmd = Subcommand::Doc { paths: Vec::new(), open: false, json: false };
+ config.cmd = Subcommand::Doc { open: false, json: false };
let build = Build::new(config);
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
@@ -617,11 +634,12 @@ mod dist {
// Behavior of `x.py test` doing various documentation tests.
let mut config = configure(&["A"], &["A"]);
config.cmd = Subcommand::Test {
- paths: vec![],
test_args: vec![],
rustc_args: vec![],
- fail_fast: true,
- doc_tests: DocTests::Yes,
+ no_fail_fast: false,
+ doc: true,
+ no_doc: false,
+ skip: vec![],
bless: false,
force_rerun: false,
compare_mode: None,
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index c3e3fa009..870185740 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -22,7 +22,7 @@ pub enum GitInfo {
/// If the info should be used (`omit_git_hash` is false), this will be
/// `Some`, otherwise it will be `None`.
Present(Option<Info>),
- /// This is not a git repostory, but the info can be fetched from the
+ /// This is not a git repository, but the info can be fetched from the
/// `git-commit-info` file.
RecordedForTarball(Info),
}
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index fcaa69831..b11be96ce 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -20,15 +20,7 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
arr.iter().copied().map(String::from)
}
- if let Subcommand::Clippy {
- fix,
- clippy_lint_allow,
- clippy_lint_deny,
- clippy_lint_warn,
- clippy_lint_forbid,
- ..
- } = &builder.config.cmd
- {
+ if let Subcommand::Clippy { fix, allow, deny, warn, forbid, .. } = &builder.config.cmd {
// disable the most spammy clippy lints
let ignored_lints = vec![
"many_single_char_names", // there are a lot in stdarch
@@ -53,10 +45,10 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
args.extend(strings(&["--", "--cap-lints", "warn"]));
args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
let mut clippy_lint_levels: Vec<String> = Vec::new();
- clippy_lint_allow.iter().for_each(|v| clippy_lint_levels.push(format!("-A{}", v)));
- clippy_lint_deny.iter().for_each(|v| clippy_lint_levels.push(format!("-D{}", v)));
- clippy_lint_warn.iter().for_each(|v| clippy_lint_levels.push(format!("-W{}", v)));
- clippy_lint_forbid.iter().for_each(|v| clippy_lint_levels.push(format!("-F{}", v)));
+ allow.iter().for_each(|v| clippy_lint_levels.push(format!("-A{}", v)));
+ deny.iter().for_each(|v| clippy_lint_levels.push(format!("-D{}", v)));
+ warn.iter().for_each(|v| clippy_lint_levels.push(format!("-W{}", v)));
+ forbid.iter().for_each(|v| clippy_lint_levels.push(format!("-F{}", v)));
args.extend(clippy_lint_levels);
args.extend(builder.config.free_args.clone());
args
@@ -79,7 +71,7 @@ impl Step for Std {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.all_krates("test").path("library")
+ run.all_krates("sysroot").path("library")
}
fn make_run(run: RunConfig<'_>) {
@@ -105,15 +97,7 @@ impl Step for Std {
cargo.arg("--lib");
}
- let msg = if compiler.host == target {
- format!("Checking stage{} library artifacts ({target})", builder.top_stage)
- } else {
- format!(
- "Checking stage{} library artifacts ({} -> {})",
- builder.top_stage, &compiler.host, target
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg_check("library artifacts", target);
run_cargo(
builder,
cargo,
@@ -167,18 +151,7 @@ impl Step for Std {
cargo.arg("-p").arg(krate.name);
}
- let msg = if compiler.host == target {
- format!(
- "Checking stage{} library test/bench/example targets ({target})",
- builder.top_stage
- )
- } else {
- format!(
- "Checking stage{} library test/bench/example targets ({} -> {})",
- builder.top_stage, &compiler.host, target
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg_check("library test/bench/example targets", target);
run_cargo(
builder,
cargo,
@@ -252,15 +225,7 @@ impl Step for Rustc {
cargo.arg("-p").arg(krate.name);
}
- let msg = if compiler.host == target {
- format!("Checking stage{} compiler artifacts ({target})", builder.top_stage)
- } else {
- format!(
- "Checking stage{} compiler artifacts ({} -> {})",
- builder.top_stage, &compiler.host, target
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg_check("compiler artifacts", target);
run_cargo(
builder,
cargo,
@@ -271,17 +236,9 @@ impl Step for Rustc {
false,
);
- // HACK: This avoids putting the newly built artifacts in the sysroot if we're using
- // `download-rustc`, to avoid "multiple candidates for `rmeta`" errors. Technically, that's
- // not quite right: people can set `download-rustc = true` to download even if there are
- // changes to the compiler, and in that case ideally we would put the *new* artifacts in the
- // sysroot, in case there are API changes that should be used by tools. In practice,
- // though, that should be very uncommon, and people can still disable download-rustc.
- if !builder.download_rustc() {
- let libdir = builder.sysroot_libdir(compiler, target);
- let hostdir = builder.sysroot_libdir(compiler, compiler.host);
- add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
- }
+ let libdir = builder.sysroot_libdir(compiler, target);
+ let hostdir = builder.sysroot_libdir(compiler, compiler.host);
+ add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
}
}
@@ -325,15 +282,7 @@ impl Step for CodegenBackend {
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
- let msg = if compiler.host == target {
- format!("Checking stage{} {} artifacts ({target})", builder.top_stage, backend)
- } else {
- format!(
- "Checking stage{} {} library ({} -> {})",
- builder.top_stage, backend, &compiler.host.triple, target.triple
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg_check(&backend, target);
run_cargo(
builder,
@@ -393,15 +342,7 @@ impl Step for RustAnalyzer {
cargo.arg("--benches");
}
- let msg = if compiler.host == target {
- format!("Checking stage{} {} artifacts ({target})", compiler.stage, "rust-analyzer")
- } else {
- format!(
- "Checking stage{} {} artifacts ({} -> {})",
- compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg_check("rust-analyzer artifacts", target);
run_cargo(
builder,
cargo,
@@ -468,18 +409,7 @@ macro_rules! tool_check_step {
// NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
// See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776
cargo.rustflag("-Zunstable-options");
- let msg = if compiler.host == target {
- format!("Checking stage{} {} artifacts ({target})", builder.top_stage, stringify!($name).to_lowercase())
- } else {
- format!(
- "Checking stage{} {} artifacts ({} -> {})",
- builder.top_stage,
- stringify!($name).to_lowercase(),
- &compiler.host.triple,
- target.triple
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg_check(&concat!(stringify!($name), " artifacts").to_lowercase(), target);
run_cargo(
builder,
cargo,
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 7ebd0a8f2..0d9fd56b0 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -81,7 +81,7 @@ macro_rules! clean_crate_tree {
clean_crate_tree! {
Rustc, Mode::Rustc, "rustc-main";
- Std, Mode::Std, "test";
+ Std, Mode::Std, "sysroot";
}
fn clean_default(build: &Build, all: bool) {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 4a4e7adcb..33addb90d 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -9,6 +9,7 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::env;
+use std::ffi::OsStr;
use std::fs;
use std::io::prelude::*;
use std::io::BufReader;
@@ -55,7 +56,7 @@ impl Step for Std {
// When downloading stage1, the standard library has already been copied to the sysroot, so
// there's no need to rebuild it.
let builder = run.builder;
- run.crate_or_deps("test")
+ run.crate_or_deps("sysroot")
.path("library")
.lazy_default_condition(Box::new(|| !builder.download_rustc()))
}
@@ -142,23 +143,13 @@ impl Step for Std {
cargo.arg("-p").arg(krate);
}
- let msg = if compiler.host == target {
- format!(
- "Building{} stage{} library artifacts ({}) ",
- crate_description(&self.crates),
- compiler.stage,
- compiler.host
- )
- } else {
- format!(
- "Building{} stage{} library artifacts ({} -> {})",
- crate_description(&self.crates),
- compiler.stage,
- compiler.host,
- target,
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg(
+ Kind::Build,
+ compiler.stage,
+ format_args!("library artifacts{}", crate_description(&self.crates)),
+ compiler.host,
+ target,
+ );
run_cargo(
builder,
cargo,
@@ -373,7 +364,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
.arg("--features")
.arg(features)
.arg("--manifest-path")
- .arg(builder.src.join("library/test/Cargo.toml"));
+ .arg(builder.src.join("library/sysroot/Cargo.toml"));
// Help the libc crate compile by assisting it in finding various
// sysroot native libraries.
@@ -421,6 +412,8 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
cargo.rustflag(&html_root);
cargo.rustdocflag(&html_root);
+
+ cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -652,8 +645,19 @@ impl Step for Rustc {
// so its artifacts can't be reused.
if builder.download_rustc() && compiler.stage != 0 {
// Copy the existing artifacts instead of rebuilding them.
- // NOTE: this path is only taken for tools linking to rustc-dev.
- builder.ensure(Sysroot { compiler });
+ // NOTE: this path is only taken for tools linking to rustc-dev (including ui-fulldeps tests).
+ let sysroot = builder.ensure(Sysroot { compiler });
+
+ let ci_rustc_dir = builder.out.join(&*builder.build.build.triple).join("ci-rustc");
+ for file in builder.config.rustc_dev_contents() {
+ let src = ci_rustc_dir.join(&file);
+ let dst = sysroot.join(file);
+ if src.is_dir() {
+ t!(fs::create_dir_all(dst));
+ } else {
+ builder.copy(&src, &dst);
+ }
+ }
return;
}
@@ -778,24 +782,13 @@ impl Step for Rustc {
cargo.arg("-p").arg(krate);
}
- let msg = if compiler.host == target {
- format!(
- "Building{} compiler artifacts (stage{} -> stage{})",
- crate_description(&self.crates),
- compiler.stage,
- compiler.stage + 1
- )
- } else {
- format!(
- "Building{} compiler artifacts (stage{}:{} -> stage{}:{})",
- crate_description(&self.crates),
- compiler.stage,
- compiler.host,
- compiler.stage + 1,
- target,
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg_sysroot_tool(
+ Kind::Build,
+ compiler.stage,
+ format_args!("compiler artifacts{}", crate_description(&self.crates)),
+ compiler.host,
+ target,
+ );
run_cargo(
builder,
cargo,
@@ -819,6 +812,9 @@ pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelec
.arg(builder.rustc_features(builder.kind))
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc/Cargo.toml"));
+
+ cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
+
rustc_cargo_env(builder, cargo, target, stage);
}
@@ -1102,15 +1098,7 @@ impl Step for CodegenBackend {
let tmp_stamp = out_dir.join(".tmp.stamp");
- let msg = if compiler.host == target {
- format!("Building stage{} codegen backend {}", compiler.stage, backend)
- } else {
- format!(
- "Building stage{} codegen backend {} ({} -> {})",
- compiler.stage, backend, compiler.host, target
- )
- };
- builder.info(&msg);
+ let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
if builder.config.dry_run() {
return;
@@ -1260,6 +1248,7 @@ impl Step for Sysroot {
};
let sysroot = sysroot_dir(compiler.stage);
+ builder.verbose(&format!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
@@ -1281,8 +1270,40 @@ impl Step for Sysroot {
}
// Copy the compiler into the correct sysroot.
- builder.cp_r(&builder.ci_rustc_dir(builder.build.build), &sysroot);
- return INTERNER.intern_path(sysroot);
+ // NOTE(#108767): We intentionally don't copy `rustc-dev` artifacts until they're requested with `builder.ensure(Rustc)`.
+ // This fixes an issue where we'd have multiple copies of libc in the sysroot with no way to tell which to load.
+ // There are a few quirks of bootstrap that interact to make this reliable:
+ // 1. The order `Step`s are run is hard-coded in `builder.rs` and not configurable. This
+ // avoids e.g. reordering `test::UiFulldeps` before `test::Ui` and causing the latter to
+ // fail because of duplicate metadata.
+ // 2. The sysroot is deleted and recreated between each invocation, so running `x test
+ // ui-fulldeps && x test ui` can't cause failures.
+ let mut filtered_files = Vec::new();
+ // Don't trim directories or files that aren't loaded per-target; they can't cause conflicts.
+ let suffix = format!("lib/rustlib/{}/lib", compiler.host);
+ for path in builder.config.rustc_dev_contents() {
+ let path = Path::new(&path);
+ if path.parent().map_or(false, |parent| parent.ends_with(&suffix)) {
+ filtered_files.push(path.file_name().unwrap().to_owned());
+ }
+ }
+
+ let filtered_extensions = [OsStr::new("rmeta"), OsStr::new("rlib"), OsStr::new("so")];
+ let ci_rustc_dir = builder.ci_rustc_dir(builder.config.build);
+ builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| {
+ if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) {
+ return true;
+ }
+ if !path.parent().map_or(true, |p| p.ends_with(&suffix)) {
+ return true;
+ }
+ if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
+ builder.verbose_than(1, &format!("ignoring {}", path.display()));
+ false
+ } else {
+ true
+ }
+ });
}
// Symlink the source root into the same location inside the sysroot,
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index cc3b3bc25..e192cda9a 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -21,9 +21,10 @@ use crate::cache::{Interned, INTERNER};
use crate::cc_detect::{ndk_compiler, Language};
use crate::channel::{self, GitInfo};
pub use crate::flags::Subcommand;
-use crate::flags::{Color, Flags};
+use crate::flags::{Color, Flags, Warnings};
use crate::util::{exe, output, t};
use once_cell::sync::OnceCell;
+use semver::Version;
use serde::{Deserialize, Deserializer};
use serde_derive::Deserialize;
@@ -237,6 +238,8 @@ pub struct Config {
initial_rustfmt: RefCell<RustfmtState>,
#[cfg(test)]
pub initial_rustfmt: RefCell<RustfmtState>,
+
+ pub paths: Vec<PathBuf>,
}
#[derive(Default, Deserialize, Clone)]
@@ -347,7 +350,7 @@ impl SplitDebuginfo {
}
/// LTO mode used for compiling rustc itself.
-#[derive(Default, Clone, PartialEq)]
+#[derive(Default, Clone, PartialEq, Debug)]
pub enum RustcLto {
Off,
#[default]
@@ -376,6 +379,16 @@ pub struct TargetSelection {
file: Option<Interned<String>>,
}
+/// Newtype over `Vec<TargetSelection>` so we can implement custom parsing logic
+#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+pub struct TargetSelectionList(Vec<TargetSelection>);
+
+pub fn target_selection_list(s: &str) -> Result<TargetSelectionList, String> {
+ Ok(TargetSelectionList(
+ s.split(",").filter(|s| !s.is_empty()).map(TargetSelection::from_user).collect(),
+ ))
+}
+
impl TargetSelection {
pub fn from_user(selection: &str) -> Self {
let path = Path::new(selection);
@@ -455,6 +468,7 @@ pub struct Target {
pub ndk: Option<PathBuf>,
pub sanitizers: Option<bool>,
pub profiler: Option<bool>,
+ pub rpath: Option<bool>,
pub crt_static: Option<bool>,
pub musl_root: Option<PathBuf>,
pub musl_libdir: Option<PathBuf>,
@@ -494,29 +508,42 @@ struct TomlConfig {
profile: Option<String>,
}
+/// Describes how to handle conflicts in merging two [`TomlConfig`]
+#[derive(Copy, Clone, Debug)]
+enum ReplaceOpt {
+ /// Silently ignore a duplicated value
+ IgnoreDuplicate,
+ /// Override the current value, even if it's `Some`
+ Override,
+ /// Exit with an error on duplicate values
+ ErrorOnDuplicate,
+}
+
trait Merge {
- fn merge(&mut self, other: Self);
+ fn merge(&mut self, other: Self, replace: ReplaceOpt);
}
impl Merge for TomlConfig {
fn merge(
&mut self,
- TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen: _ }: Self,
+ TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen }: Self,
+ replace: ReplaceOpt,
) {
- fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>) {
+ fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
if let Some(new) = y {
if let Some(original) = x {
- original.merge(new);
+ original.merge(new, replace);
} else {
*x = Some(new);
}
}
}
- do_merge(&mut self.build, build);
- do_merge(&mut self.install, install);
- do_merge(&mut self.llvm, llvm);
- do_merge(&mut self.rust, rust);
- do_merge(&mut self.dist, dist);
+ self.changelog_seen.merge(changelog_seen, replace);
+ do_merge(&mut self.build, build, replace);
+ do_merge(&mut self.install, install, replace);
+ do_merge(&mut self.llvm, llvm, replace);
+ do_merge(&mut self.rust, rust, replace);
+ do_merge(&mut self.dist, dist, replace);
assert!(target.is_none(), "merging target-specific config is not currently supported");
}
}
@@ -533,10 +560,33 @@ macro_rules! define_config {
}
impl Merge for $name {
- fn merge(&mut self, other: Self) {
+ fn merge(&mut self, other: Self, replace: ReplaceOpt) {
$(
- if !self.$field.is_some() {
- self.$field = other.$field;
+ match replace {
+ ReplaceOpt::IgnoreDuplicate => {
+ if self.$field.is_none() {
+ self.$field = other.$field;
+ }
+ },
+ ReplaceOpt::Override => {
+ if other.$field.is_some() {
+ self.$field = other.$field;
+ }
+ }
+ ReplaceOpt::ErrorOnDuplicate => {
+ if other.$field.is_some() {
+ if self.$field.is_some() {
+ if cfg!(test) {
+ panic!("overriding existing option")
+ } else {
+ eprintln!("overriding existing option: `{}`", stringify!($field));
+ crate::detail_exit(2);
+ }
+ } else {
+ self.$field = other.$field;
+ }
+ }
+ }
}
)*
}
@@ -609,6 +659,37 @@ macro_rules! define_config {
}
}
+impl<T> Merge for Option<T> {
+ fn merge(&mut self, other: Self, replace: ReplaceOpt) {
+ match replace {
+ ReplaceOpt::IgnoreDuplicate => {
+ if self.is_none() {
+ *self = other;
+ }
+ }
+ ReplaceOpt::Override => {
+ if other.is_some() {
+ *self = other;
+ }
+ }
+ ReplaceOpt::ErrorOnDuplicate => {
+ if other.is_some() {
+ if self.is_some() {
+ if cfg!(test) {
+ panic!("overriding existing option")
+ } else {
+ eprintln!("overriding existing option");
+ crate::detail_exit(2);
+ }
+ } else {
+ *self = other;
+ }
+ }
+ }
+ }
+ }
+}
+
define_config! {
/// TOML representation of various global build decisions.
#[derive(Default)]
@@ -800,6 +881,7 @@ define_config! {
android_ndk: Option<String> = "android-ndk",
sanitizers: Option<bool> = "sanitizers",
profiler: Option<bool> = "profiler",
+ rpath: Option<bool> = "rpath",
crt_static: Option<bool> = "crt-static",
musl_root: Option<String> = "musl-root",
musl_libdir: Option<String> = "musl-libdir",
@@ -849,48 +931,45 @@ impl Config {
pub fn parse(args: &[String]) -> Config {
#[cfg(test)]
- let get_toml = |_: &_| TomlConfig::default();
+ fn get_toml(_: &Path) -> TomlConfig {
+ TomlConfig::default()
+ }
+
#[cfg(not(test))]
- let get_toml = |file: &Path| {
+ fn get_toml(file: &Path) -> TomlConfig {
let contents =
t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
// Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
// TomlConfig and sub types to be monomorphized 5x by toml.
- match toml::from_str(&contents)
+ toml::from_str(&contents)
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
- {
- Ok(table) => table,
- Err(err) => {
- eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
+ .unwrap_or_else(|err| {
+ eprintln!("failed to parse TOML configuration '{}': {err}", file.display());
crate::detail_exit(2);
- }
- }
- };
-
+ })
+ }
Self::parse_inner(args, get_toml)
}
- fn parse_inner<'a>(args: &[String], get_toml: impl 'a + Fn(&Path) -> TomlConfig) -> Config {
- let flags = Flags::parse(&args);
+ fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config {
+ let mut flags = Flags::parse(&args);
let mut config = Config::default_opts();
// Set flags.
+ config.paths = std::mem::take(&mut flags.paths);
config.exclude = flags.exclude.into_iter().map(|path| TaskPath::parse(path)).collect();
config.include_default_paths = flags.include_default_paths;
config.rustc_error_format = flags.rustc_error_format;
config.json_output = flags.json_output;
config.on_fail = flags.on_fail;
- config.jobs = flags.jobs.map(threads_from_config);
+ config.jobs = Some(threads_from_config(flags.jobs as u32));
config.cmd = flags.cmd;
config.incremental = flags.incremental;
config.dry_run = if flags.dry_run { DryRun::UserSelected } else { DryRun::Disabled };
config.keep_stage = flags.keep_stage;
config.keep_stage_std = flags.keep_stage_std;
config.color = flags.color;
- config.free_args = flags.free_args.clone().unwrap_or_default();
- if let Some(value) = flags.deny_warnings {
- config.deny_warnings = value;
- }
+ config.free_args = std::mem::take(&mut flags.free_args);
config.llvm_profile_use = flags.llvm_profile_use;
config.llvm_profile_generate = flags.llvm_profile_generate;
config.llvm_bolt_profile_generate = flags.llvm_bolt_profile_generate;
@@ -985,9 +1064,41 @@ impl Config {
include_path.push("defaults");
include_path.push(format!("config.{}.toml", include));
let included_toml = get_toml(&include_path);
- toml.merge(included_toml);
+ toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate);
}
+ let mut override_toml = TomlConfig::default();
+ for option in flags.set.iter() {
+ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
+ toml::from_str(&option)
+ .and_then(|table: toml::Value| TomlConfig::deserialize(table))
+ }
+
+ let mut err = match get_table(option) {
+ Ok(v) => {
+ override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
+ continue;
+ }
+ Err(e) => e,
+ };
+ // We want to be able to set string values without quotes,
+ // like in `configure.py`. Try adding quotes around the right hand side
+ if let Some((key, value)) = option.split_once("=") {
+ if !value.contains('"') {
+ match get_table(&format!(r#"{key}="{value}""#)) {
+ Ok(v) => {
+ override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
+ continue;
+ }
+ Err(e) => err = e,
+ }
+ }
+ }
+ eprintln!("failed to parse override `{option}`: `{err}");
+ crate::detail_exit(2)
+ }
+ toml.merge(override_toml, ReplaceOpt::Override);
+
config.changelog_seen = toml.changelog_seen;
let build = toml.build.unwrap_or_default();
@@ -1007,9 +1118,12 @@ impl Config {
config.download_beta_toolchain();
config.out.join(config.build.triple).join("stage0/bin/rustc")
});
+
config.initial_cargo = build
.cargo
- .map(PathBuf::from)
+ .map(|cargo| {
+ t!(PathBuf::from(cargo).canonicalize(), "`initial_cargo` not found on disk")
+ })
.unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/cargo"));
// NOTE: it's important this comes *after* we set `initial_rustc` just above.
@@ -1019,14 +1133,14 @@ impl Config {
config.out = dir;
}
- config.hosts = if let Some(arg_host) = flags.host {
+ config.hosts = if let Some(TargetSelectionList(arg_host)) = flags.host {
arg_host
} else if let Some(file_host) = build.host {
file_host.iter().map(|h| TargetSelection::from_user(h)).collect()
} else {
vec![config.build]
};
- config.targets = if let Some(arg_target) = flags.target {
+ config.targets = if let Some(TargetSelectionList(arg_target)) = flags.target {
arg_target
} else if let Some(file_target) = build.target {
file_target.iter().map(|h| TargetSelection::from_user(h)).collect()
@@ -1062,7 +1176,7 @@ impl Config {
set(&mut config.print_step_rusage, build.print_step_rusage);
set(&mut config.patch_binaries_for_nix, build.patch_binaries_for_nix);
- config.verbose = cmp::max(config.verbose, flags.verbose);
+ config.verbose = cmp::max(config.verbose, flags.verbose as usize);
if let Some(install) = toml.install {
config.prefix = install.prefix.map(PathBuf::from);
@@ -1135,7 +1249,14 @@ impl Config {
config.rustc_default_linker = rust.default_linker;
config.musl_root = rust.musl_root.map(PathBuf::from);
config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
- set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
+ set(
+ &mut config.deny_warnings,
+ match flags.warnings {
+ Warnings::Deny => Some(true),
+ Warnings::Warn => Some(false),
+ Warnings::Default => rust.deny_warnings,
+ },
+ );
set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
@@ -1299,6 +1420,7 @@ impl Config {
target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
target.sanitizers = cfg.sanitizers;
target.profiler = cfg.profiler;
+ target.rpath = cfg.rpath;
config.target_config.insert(TargetSelection::from_user(&triple), target);
}
@@ -1307,7 +1429,7 @@ impl Config {
if config.llvm_from_ci {
let triple = &config.build.triple;
let ci_llvm_bin = config.ci_llvm_root().join("bin");
- let mut build_target = config
+ let build_target = config
.target_config
.entry(config.build)
.or_insert_with(|| Target::from_triple(&triple));
@@ -1440,6 +1562,28 @@ impl Config {
git
}
+ pub(crate) fn test_args(&self) -> Vec<&str> {
+ let mut test_args = match self.cmd {
+ Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
+ test_args.iter().flat_map(|s| s.split_whitespace()).collect()
+ }
+ _ => vec![],
+ };
+ test_args.extend(self.free_args.iter().map(|s| s.as_str()));
+ test_args
+ }
+
+ pub(crate) fn args(&self) -> Vec<&str> {
+ let mut args = match self.cmd {
+ Subcommand::Run { ref args, .. } => {
+ args.iter().flat_map(|s| s.split_whitespace()).collect()
+ }
+ _ => vec![],
+ };
+ args.extend(self.free_args.iter().map(|s| s.as_str()));
+ args
+ }
+
/// Bootstrap embeds a version number into the name of shared libraries it uploads in CI.
/// Return the version it would have used for the given commit.
pub(crate) fn artifact_version_part(&self, commit: &str) -> String {
@@ -1608,6 +1752,10 @@ impl Config {
self.target_config.values().any(|t| t.profiler == Some(true)) || self.profiler
}
+ pub fn rpath_enabled(&self, target: TargetSelection) -> bool {
+ self.target_config.get(&target).map(|t| t.rpath).flatten().unwrap_or(self.rust_rpath)
+ }
+
pub fn llvm_enabled(&self) -> bool {
self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
}
@@ -1632,6 +1780,42 @@ impl Config {
self.rust_codegen_backends.get(0).cloned()
}
+ pub fn check_build_rustc_version(&self) {
+ if self.dry_run() {
+ return;
+ }
+
+ // check rustc version is same or lower with 1 apart from the building one
+ let mut cmd = Command::new(&self.initial_rustc);
+ cmd.arg("--version");
+ let rustc_output = output(&mut cmd)
+ .lines()
+ .next()
+ .unwrap()
+ .split(' ')
+ .nth(1)
+ .unwrap()
+ .split('-')
+ .next()
+ .unwrap()
+ .to_owned();
+ let rustc_version = Version::parse(&rustc_output.trim()).unwrap();
+ let source_version =
+ Version::parse(&fs::read_to_string(self.src.join("src/version")).unwrap().trim())
+ .unwrap();
+ if !(source_version == rustc_version
+ || (source_version.major == rustc_version.major
+ && source_version.minor == rustc_version.minor + 1))
+ {
+ let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
+ eprintln!(
+ "Unexpected rustc version: {}, we should use {}/{} to build source with {}",
+ rustc_version, prev_version, source_version, source_version
+ );
+ crate::detail_exit(1);
+ }
+ }
+
/// Returns the commit to download, or `None` if we shouldn't download CI artifacts.
fn download_ci_rustc_commit(&self, download_rustc: Option<StringOrBool>) -> Option<String> {
// If `download-rustc` is not set, default to rebuilding.
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 50569eb4f..4de84b543 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -1,12 +1,11 @@
-use super::{Config, TomlConfig};
+use super::{Config, Flags};
+use clap::CommandFactory;
use std::{env, path::Path};
-fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
- |&_| toml::from_str(config).unwrap()
-}
-
fn parse(config: &str) -> Config {
- Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], toml(config))
+ Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], |&_| {
+ toml::from_str(config).unwrap()
+ })
}
#[test]
@@ -88,3 +87,75 @@ fn detect_src_and_out() {
test(parse("build.build-dir = \"/tmp\""), build_dir);
}
}
+
+#[test]
+fn clap_verify() {
+ Flags::command().debug_assert();
+}
+
+#[test]
+fn override_toml() {
+ let config = Config::parse_inner(
+ &[
+ "check".to_owned(),
+ "--config=/does/not/exist".to_owned(),
+ "--set=changelog-seen=1".to_owned(),
+ "--set=rust.lto=fat".to_owned(),
+ "--set=rust.deny-warnings=false".to_owned(),
+ "--set=build.gdb=\"bar\"".to_owned(),
+ "--set=build.tools=[\"cargo\"]".to_owned(),
+ "--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(),
+ ],
+ |&_| {
+ toml::from_str(
+ r#"
+changelog-seen = 0
+[rust]
+lto = "off"
+deny-warnings = true
+
+[build]
+gdb = "foo"
+tools = []
+
+[llvm]
+download-ci-llvm = false
+build-config = {}
+ "#,
+ )
+ .unwrap()
+ },
+ );
+ assert_eq!(config.changelog_seen, Some(1), "setting top-level value");
+ assert_eq!(
+ config.rust_lto,
+ crate::config::RustcLto::Fat,
+ "setting string value without quotes"
+ );
+ assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
+ assert_eq!(config.deny_warnings, false, "setting boolean value");
+ assert_eq!(
+ config.tools,
+ Some(["cargo".to_string()].into_iter().collect()),
+ "setting list value"
+ );
+ assert_eq!(
+ config.llvm_build_config,
+ [("foo".to_string(), "bar".to_string())].into_iter().collect(),
+ "setting dictionary value"
+ );
+}
+
+#[test]
+#[should_panic]
+fn override_toml_duplicate() {
+ Config::parse_inner(
+ &[
+ "check".to_owned(),
+ "--config=/does/not/exist".to_owned(),
+ "--set=changelog-seen=1".to_owned(),
+ "--set=changelog-seen=2".to_owned(),
+ ],
+ |&_| toml::from_str("changelog-seen = 0").unwrap(),
+ );
+}
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index abd28b400..571062a3a 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -139,6 +139,10 @@ v("musl-root-mips64", "target.mips64-unknown-linux-muslabi64.musl-root",
"mips64-unknown-linux-muslabi64 install directory")
v("musl-root-mips64el", "target.mips64el-unknown-linux-muslabi64.musl-root",
"mips64el-unknown-linux-muslabi64 install directory")
+v("musl-root-riscv32gc", "target.riscv32gc-unknown-linux-musl.musl-root",
+ "riscv32gc-unknown-linux-musl install directory")
+v("musl-root-riscv64gc", "target.riscv64gc-unknown-linux-musl.musl-root",
+ "riscv64gc-unknown-linux-musl install directory")
v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
"rootfs in qemu testing, you probably don't want to use this")
v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
@@ -149,8 +153,7 @@ v("experimental-targets", "llvm.experimental-targets",
"experimental LLVM targets to build")
v("release-channel", "rust.channel", "the name of the release channel to build")
v("release-description", "rust.description", "optional descriptive string for version output")
-v("dist-compression-formats", None,
- "comma-separated list of compression formats to use")
+v("dist-compression-formats", None, "List of compression formats to use")
# Used on systems where "cc" is unavailable
v("default-linker", "rust.default-linker", "the default linker")
@@ -164,8 +167,8 @@ o("extended", "build.extended", "build an extended rust tool set")
v("tools", None, "List of extended tools will be installed")
v("codegen-backends", None, "List of codegen backends to build")
v("build", "build.build", "GNUs ./configure syntax LLVM build triple")
-v("host", None, "GNUs ./configure syntax LLVM host triples")
-v("target", None, "GNUs ./configure syntax LLVM target triples")
+v("host", None, "List of GNUs ./configure syntax LLVM host triples")
+v("target", None, "List of GNUs ./configure syntax LLVM target triples")
v("set", None, "set arbitrary key/value pairs in TOML configuration")
@@ -178,6 +181,11 @@ def err(msg):
print("configure: error: " + msg)
sys.exit(1)
+def is_value_list(key):
+ for option in options:
+ if option.name == key and option.desc.startswith('List of'):
+ return True
+ return False
if '--help' in sys.argv or '-h' in sys.argv:
print('Usage: ./configure [options]')
@@ -291,6 +299,8 @@ def set(key, value, config):
parts = key.split('.')
for i, part in enumerate(parts):
if i == len(parts) - 1:
+ if is_value_list(part) and isinstance(value, str):
+ value = value.split(',')
arr[part] = value
else:
if part not in arr:
@@ -417,6 +427,8 @@ def parse_example_config(known_args, config):
# Avoid using quotes unless it's necessary.
targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target)
+ if 'profile' not in config:
+ set('profile', 'user', config)
configure_file(sections, top_level_keys, targets, config)
return section_order, sections, targets
@@ -475,7 +487,7 @@ def configure_section(lines, config):
def configure_top_level_key(lines, top_level_key, value):
for i, line in enumerate(lines):
if line.startswith('#' + top_level_key + ' = ') or line.startswith(top_level_key + ' = '):
- lines[i] = "{} = {}".format(top_level_key, value)
+ lines[i] = "{} = {}".format(top_level_key, to_toml(value))
return
raise RuntimeError("failed to find config line for {}".format(top_level_key))
@@ -521,8 +533,14 @@ def write_config_toml(writer, section_order, targets, sections):
else:
writer = write_uncommented(sections[section], writer)
+def quit_if_file_exists(file):
+ if os.path.isfile(file):
+ err("Existing '" + file + "' detected.")
if __name__ == "__main__":
+ # If 'config.toml' already exists, exit the script at this point
+ quit_if_file_exists('config.toml')
+
p("processing command line")
# Parse all known arguments into a configuration structure that reflects the
# TOML we're going to write out
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 76aad16c1..9cead7adc 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -822,6 +822,8 @@ fn copy_src_dirs(
"llvm-project\\compiler-rt",
"llvm-project/cmake",
"llvm-project\\cmake",
+ "llvm-project/runtimes",
+ "llvm-project\\runtimes",
];
if spath.contains("llvm-project")
&& !spath.ends_with("llvm-project")
@@ -997,12 +999,15 @@ impl Step for PlainSourceTarball {
// If we're building from git sources, we need to vendor a complete distribution.
if builder.rust_info().is_managed_git_subrepository() {
// Ensure we have the submodules checked out.
+ builder.update_submodule(Path::new("src/tools/cargo"));
builder.update_submodule(Path::new("src/tools/rust-analyzer"));
// Vendor all Cargo dependencies
let mut cmd = Command::new(&builder.initial_cargo);
cmd.arg("vendor")
.arg("--sync")
+ .arg(builder.src.join("./src/tools/cargo/Cargo.toml"))
+ .arg("--sync")
.arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
.arg("--sync")
.arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
@@ -1963,20 +1968,6 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
}
}
- // FIXME: for reasons I don't understand, the LLVM so in the `rustc` component is different than the one in `rust-dev`.
- // Only the one in `rustc` works with the downloaded compiler.
- if builder.download_rustc() && target == builder.build.build {
- let src_libdir = builder.ci_rustc_dir(target).join("lib");
- for entry in t!(std::fs::read_dir(&src_libdir)) {
- let entry = t!(entry);
- if entry.file_name().to_str().unwrap().starts_with("libLLVM-") {
- install_llvm_file(builder, &entry.path(), dst_libdir);
- return !builder.config.dry_run();
- }
- }
- panic!("libLLVM.so not found in src_libdir {}!", src_libdir.display());
- }
-
// On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
// instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
// clear why this is the case, though. llvm-config will emit the versioned
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 9ad98eb57..b52c3b68c 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -438,7 +438,7 @@ impl Step for Std {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.all_krates("test").path("library").default_condition(builder.config.docs)
+ run.all_krates("sysroot").path("library").default_condition(builder.config.docs)
}
fn make_run(run: RunConfig<'_>) {
@@ -839,6 +839,8 @@ macro_rules! tool_doc {
)+
cargo.rustdocflag("--document-private-items");
+ // Since we always pass --document-private-items, there's no need to warn about linking to private items.
+ cargo.rustdocflag("-Arustdoc::private-intra-doc-links");
cargo.rustdocflag("--enable-index-page");
cargo.rustdocflag("--show-type-layout");
cargo.rustdocflag("--generate-link-to-definition");
@@ -882,7 +884,8 @@ tool_doc!(
// "cargo-credential-wincred",
]
);
-tool_doc!(Tidy, "tidy", "src/tools/tidy", ["tidy"]);
+tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["tidy"]);
+tool_doc!(Bootstrap, "bootstrap", "src/bootstrap", rustc_tool = false, ["bootstrap"]);
#[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ErrorIndex {
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index 36f9aaa59..4111b7cc0 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
-Last change is for: https://github.com/rust-lang/rust/pull/109373
+Last change is for: https://github.com/rust-lang/rust/pull/96971
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 242515565..c7969d2a2 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -2,7 +2,7 @@ use std::{
env,
ffi::{OsStr, OsString},
fs::{self, File},
- io::{BufRead, BufReader, ErrorKind},
+ io::{BufRead, BufReader, BufWriter, ErrorKind, Write},
path::{Path, PathBuf},
process::{Command, Stdio},
};
@@ -112,7 +112,7 @@ impl Config {
is_nixos && !Path::new("/lib").exists()
});
if val {
- println!("info: You seem to be using Nix.");
+ eprintln!("info: You seem to be using Nix.");
}
val
}
@@ -123,7 +123,7 @@ impl Config {
/// This is only required on NixOS and uses the PatchELF utility to
/// change the interpreter/RPATH of ELF executables.
///
- /// Please see https://nixos.org/patchelf.html for more information
+ /// Please see <https://nixos.org/patchelf.html> for more information
fn fix_bin_or_dylib(&self, fname: &Path) {
assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
println!("attempting to patch {}", fname.display());
@@ -219,14 +219,14 @@ impl Config {
"30", // timeout if cannot connect within 30 seconds
"--retry",
"3",
- "-Sf",
+ "-SRf",
]);
curl.arg(url);
let f = File::create(tempfile).unwrap();
curl.stdout(Stdio::from(f));
if !self.check_run(&mut curl) {
if self.build.contains("windows-msvc") {
- println!("Fallback to PowerShell");
+ eprintln!("Fallback to PowerShell");
for _ in 0..3 {
if self.try_run(Command::new("PowerShell.exe").args(&[
"/nologo",
@@ -239,7 +239,7 @@ impl Config {
])) {
return;
}
- println!("\nspurious failure, trying again");
+ eprintln!("\nspurious failure, trying again");
}
}
if !help_on_error.is_empty() {
@@ -250,7 +250,7 @@ impl Config {
}
fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
- println!("extracting {} to {}", tarball.display(), dst.display());
+ eprintln!("extracting {} to {}", tarball.display(), dst.display());
if !dst.exists() {
t!(fs::create_dir_all(dst));
}
@@ -262,10 +262,20 @@ impl Config {
let directory_prefix = Path::new(Path::new(uncompressed_filename).file_stem().unwrap());
// decompress the file
- let data = t!(File::open(tarball));
+ let data = t!(File::open(tarball), format!("file {} not found", tarball.display()));
let decompressor = XzDecoder::new(BufReader::new(data));
let mut tar = tar::Archive::new(decompressor);
+
+ // `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding
+ // it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow.
+ // Cache the entries when we extract it so we only have to read it once.
+ let mut recorded_entries = if dst.ends_with("ci-rustc") && pattern == "rustc-dev" {
+ Some(BufWriter::new(t!(File::create(dst.join(".rustc-dev-contents")))))
+ } else {
+ None
+ };
+
for member in t!(tar.entries()) {
let mut member = t!(member);
let original_path = t!(member.path()).into_owned();
@@ -283,13 +293,19 @@ impl Config {
if !t!(member.unpack_in(dst)) {
panic!("path traversal attack ??");
}
+ if let Some(record) = &mut recorded_entries {
+ t!(writeln!(record, "{}", short_path.to_str().unwrap()));
+ }
let src_path = dst.join(original_path);
if src_path.is_dir() && dst_path.exists() {
continue;
}
t!(fs::rename(src_path, dst_path));
}
- t!(fs::remove_dir_all(dst.join(directory_prefix)));
+ let dst_dir = dst.join(directory_prefix);
+ if dst_dir.exists() {
+ t!(fs::remove_dir_all(&dst_dir), format!("failed to remove {}", dst_dir.display()));
+ }
}
/// Returns whether the SHA256 checksum of `path` matches `expected`.
@@ -365,6 +381,13 @@ impl Config {
Some(rustfmt_path)
}
+ pub(crate) fn rustc_dev_contents(&self) -> Vec<String> {
+ assert!(self.download_rustc());
+ let ci_rustc_dir = self.out.join(&*self.build.triple).join("ci-rustc");
+ let rustc_dev_contents_file = t!(File::open(ci_rustc_dir.join(".rustc-dev-contents")));
+ t!(BufReader::new(rustc_dev_contents_file).lines().collect())
+ }
+
pub(crate) fn download_ci_rustc(&self, commit: &str) {
self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})"));
@@ -404,7 +427,6 @@ impl Config {
fn download_toolchain(
&self,
- // FIXME(ozkanonur) use CompilerMetadata instead of `version: &str`
version: &str,
sysroot: &str,
stamp_key: &str,
@@ -518,7 +540,18 @@ impl Config {
None
};
- self.download_file(&format!("{base_url}/{url}"), &tarball, "");
+ let mut help_on_error = "";
+ if destination == "ci-rustc" {
+ 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:
+
+[rust]
+download-rustc = false
+";
+ }
+ self.download_file(&format!("{base_url}/{url}"), &tarball, help_on_error);
if let Some(sha256) = checksum {
if !self.verify(&tarball, sha256) {
panic!("failed to verify {}", tarball.display());
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index b6f5f3103..80e715777 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -3,726 +3,415 @@
//! This module implements the command-line parsing of the build system which
//! has various flags to configure how it's run.
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
-use getopts::Options;
+use clap::{CommandFactory, Parser, ValueEnum};
use crate::builder::{Builder, Kind};
-use crate::config::{Config, TargetSelection};
+use crate::config::{target_selection_list, Config, TargetSelectionList};
use crate::setup::Profile;
-use crate::util::t;
use crate::{Build, DocTests};
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Default, Debug, ValueEnum)]
pub enum Color {
Always,
Never,
+ #[default]
Auto,
}
-impl Default for Color {
- fn default() -> Self {
- Self::Auto
- }
-}
-
-impl std::str::FromStr for Color {
- type Err = ();
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- match s.to_lowercase().as_str() {
- "always" => Ok(Self::Always),
- "never" => Ok(Self::Never),
- "auto" => Ok(Self::Auto),
- _ => Err(()),
- }
- }
+/// Whether to deny warnings, emit them as warnings, or use the default behavior
+#[derive(Copy, Clone, Default, Debug, ValueEnum)]
+pub enum Warnings {
+ Deny,
+ Warn,
+ #[default]
+ Default,
}
/// Deserialized version of all flags for this compile.
+#[derive(Debug, Parser)]
+#[clap(
+ override_usage = "x.py <subcommand> [options] [<paths>...]",
+ disable_help_subcommand(true),
+ about = "",
+ next_line_help(false)
+)]
pub struct Flags {
- pub verbose: usize, // number of -v args; each extra -v after the first is passed to Cargo
- pub on_fail: Option<String>,
- pub stage: Option<u32>,
- pub keep_stage: Vec<u32>,
- pub keep_stage_std: Vec<u32>,
+ #[command(subcommand)]
+ pub cmd: Subcommand,
- pub host: Option<Vec<TargetSelection>>,
- pub target: Option<Vec<TargetSelection>>,
+ #[arg(global(true), short, long, action = clap::ArgAction::Count)]
+ /// use verbose output (-vv for very verbose)
+ pub verbose: u8, // each extra -v after the first is passed to Cargo
+ #[arg(global(true), short, long)]
+ /// use incremental compilation
+ pub incremental: bool,
+ #[arg(global(true), long, value_hint = clap::ValueHint::FilePath, value_name = "FILE")]
+ /// 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`
pub build_dir: Option<PathBuf>,
- pub jobs: Option<u32>,
- pub cmd: Subcommand,
- pub incremental: bool,
+
+ #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "BUILD")]
+ /// build target of the stage0 compiler
+ pub build: Option<String>,
+
+ #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "HOST", value_parser = target_selection_list)]
+ /// host targets to build
+ pub host: Option<TargetSelectionList>,
+
+ #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "TARGET", value_parser = target_selection_list)]
+ /// target targets to build
+ pub target: Option<TargetSelectionList>,
+
+ #[arg(global(true), long, value_name = "PATH")]
+ /// build paths to exclude
pub exclude: Vec<PathBuf>,
+ #[arg(global(true), long)]
+ /// include default paths in addition to the provided ones
pub include_default_paths: bool,
+
+ #[arg(global(true), value_hint = clap::ValueHint::Other, long)]
pub rustc_error_format: Option<String>,
- pub json_output: bool,
+
+ #[arg(global(true), long, value_hint = clap::ValueHint::CommandString, value_name = "CMD")]
+ /// command to run on failure
+ pub on_fail: Option<String>,
+ #[arg(global(true), long)]
+ /// dry run; don't build anything
pub dry_run: bool,
- pub color: Color,
+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
+ /// stage to build (indicates compiler to use/test, e.g., stage 0 uses the
+ /// bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)
+ pub stage: Option<u32>,
+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
+ /// stage(s) to keep without recompiling
+ /// (pass multiple times to keep e.g., both stages 0 and 1)
+ pub keep_stage: Vec<u32>,
+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
+ /// stage(s) of the standard library to keep without recompiling
+ /// (pass multiple times to keep e.g., both stages 0 and 1)
+ pub keep_stage_std: Vec<u32>,
+ #[arg(global(true), long, value_hint = clap::ValueHint::DirPath, value_name = "DIR")]
+ /// path to the root of the rust checkout
+ pub src: Option<PathBuf>,
+
+ #[arg(
+ global(true),
+ short,
+ long,
+ value_hint = clap::ValueHint::Other,
+ default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get),
+ value_name = "JOBS"
+ )]
+ /// number of jobs to run in parallel
+ pub jobs: usize,
// This overrides the deny-warnings configuration option,
// which passes -Dwarnings to the compiler invocations.
- //
- // true => deny, false => warn
- pub deny_warnings: Option<bool>,
+ #[arg(global(true), long)]
+ #[clap(value_enum, default_value_t=Warnings::Default, value_name = "deny|warn")]
+ /// if value is deny, will deny warnings
+ /// if value is warn, will emit warnings
+ /// otherwise, use the default configured behaviour
+ pub warnings: Warnings,
+
+ #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "FORMAT")]
+ /// rustc error format
+ pub error_format: Option<String>,
+ #[arg(global(true), long)]
+ /// use message-format=json
+ pub json_output: bool,
- pub rust_profile_use: Option<String>,
- pub rust_profile_generate: Option<String>,
+ #[arg(global(true), long, value_name = "STYLE")]
+ #[clap(value_enum, default_value_t = Color::Auto)]
+ /// whether to use color in cargo and rustc output
+ pub color: Color,
+ /// whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml
+ #[arg(global(true), long, value_name = "VALUE")]
+ pub llvm_skip_rebuild: Option<bool>,
+ /// generate PGO profile with rustc build
+ #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
+ pub rust_profile_generate: Option<String>,
+ /// use PGO profile for rustc build
+ #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
+ pub rust_profile_use: Option<String>,
+ /// use PGO profile for LLVM build
+ #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
pub llvm_profile_use: Option<String>,
// LLVM doesn't support a custom location for generating profile
// information.
//
// llvm_out/build/profiles/ is the location this writes to.
+ /// generate PGO profile with llvm built for rustc
+ #[arg(global(true), long)]
pub llvm_profile_generate: bool,
+ /// generate BOLT profile for LLVM build
+ #[arg(global(true), long)]
pub llvm_bolt_profile_generate: bool,
+ /// use BOLT profile for LLVM build
+ #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
pub llvm_bolt_profile_use: Option<String>,
+ #[arg(global(true))]
+ /// paths for the subcommand
+ pub paths: Vec<PathBuf>,
+ /// override options in config.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>,
+}
+
+impl Flags {
+ pub fn parse(args: &[String]) -> Self {
+ let first = String::from("x.py");
+ let it = std::iter::once(&first).chain(args.iter());
+ // We need to check for `<cmd> -h -v`, in which case we list the paths
+ #[derive(Parser)]
+ #[clap(disable_help_flag(true))]
+ struct HelpVerboseOnly {
+ #[arg(short, long)]
+ help: bool,
+ #[arg(global(true), short, long, action = clap::ArgAction::Count)]
+ pub verbose: u8,
+ #[arg(value_enum)]
+ cmd: Kind,
+ }
+ if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) =
+ HelpVerboseOnly::try_parse_from(it.clone())
+ {
+ println!("note: updating submodules before printing available paths");
+ let config = Config::parse(&[String::from("build")]);
+ let build = Build::new(config);
+ let paths = Builder::get_help(&build, subcommand);
+ if let Some(s) = paths {
+ println!("{}", s);
+ } else {
+ panic!("No paths available for subcommand `{}`", subcommand.as_str());
+ }
+ crate::detail_exit(0);
+ }
- /// Arguments appearing after `--` to be forwarded to tools,
- /// e.g. `--fix-broken` or test arguments.
- pub free_args: Option<Vec<String>>,
+ Flags::parse_from(it)
+ }
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Default, clap::Subcommand)]
pub enum Subcommand {
- Build {
- paths: Vec<PathBuf>,
- },
+ #[clap(aliases = ["b"], long_about = "\n
+ Arguments:
+ This subcommand accepts a number of paths to directories to the crates
+ and/or artifacts to compile. For example, for a quick build of a usable
+ compiler:
+ ./x.py build --stage 1 library/std
+ This will build a compiler and standard library from the local source code.
+ Once this is done, build/$ARCH/stage1 contains a usable compiler.
+ If no arguments are passed then the default artifacts for that stage are
+ compiled. For example:
+ ./x.py build --stage 0
+ ./x.py build ")]
+ /// Compile either the compiler or libraries
+ #[default]
+ Build,
+ #[clap(aliases = ["c"], long_about = "\n
+ Arguments:
+ This subcommand accepts a number of paths to directories to the crates
+ and/or artifacts to compile. For example:
+ ./x.py check library/std
+ If no arguments are passed then many artifacts are checked.")]
+ /// Compile either the compiler or libraries, using cargo check
Check {
- paths: Vec<PathBuf>,
+ #[arg(long)]
+ /// Check all targets
+ all_targets: bool,
},
+ /// Run Clippy (uses rustup/cargo-installed clippy binary)
+ #[clap(long_about = "\n
+ Arguments:
+ This subcommand accepts a number of paths to directories to the crates
+ and/or artifacts to run clippy against. For example:
+ ./x.py clippy library/core
+ ./x.py clippy library/core library/proc_macro")]
Clippy {
+ #[arg(long)]
fix: bool,
- paths: Vec<PathBuf>,
- clippy_lint_allow: Vec<String>,
- clippy_lint_deny: Vec<String>,
- clippy_lint_warn: Vec<String>,
- clippy_lint_forbid: Vec<String>,
- },
- Fix {
- paths: Vec<PathBuf>,
+ /// clippy lints to allow
+ #[arg(global(true), short = 'A', action = clap::ArgAction::Append, value_name = "LINT")]
+ allow: Vec<String>,
+ /// clippy lints to deny
+ #[arg(global(true), short = 'D', action = clap::ArgAction::Append, value_name = "LINT")]
+ deny: Vec<String>,
+ /// clippy lints to warn on
+ #[arg(global(true), short = 'W', action = clap::ArgAction::Append, value_name = "LINT")]
+ warn: Vec<String>,
+ /// clippy lints to forbid
+ #[arg(global(true), short = 'F', action = clap::ArgAction::Append, value_name = "LINT")]
+ forbid: Vec<String>,
},
+ /// Run cargo fix
+ #[clap(long_about = "\n
+ Arguments:
+ This subcommand accepts a number of paths to directories to the crates
+ and/or artifacts to run `cargo fix` against. For example:
+ ./x.py fix library/core
+ ./x.py fix library/core library/proc_macro")]
+ Fix,
+ #[clap(
+ name = "fmt",
+ long_about = "\n
+ Arguments:
+ This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and
+ fails if it is not. For example:
+ ./x.py fmt
+ ./x.py fmt --check"
+ )]
+ /// Run rustfmt
Format {
- paths: Vec<PathBuf>,
+ /// check formatting instead of applying
+ #[arg(long)]
check: bool,
},
+ #[clap(aliases = ["d"], long_about = "\n
+ Arguments:
+ This subcommand accepts a number of paths to directories of documentation
+ to build. For example:
+ ./x.py doc src/doc/book
+ ./x.py doc src/doc/nomicon
+ ./x.py doc src/doc/book library/std
+ ./x.py doc library/std --json
+ ./x.py doc library/std --open
+ If no arguments are passed then everything is documented:
+ ./x.py doc
+ ./x.py doc --stage 1")]
+ /// Build documentation
Doc {
- paths: Vec<PathBuf>,
+ #[arg(long)]
+ /// open the docs in a browser
open: bool,
+ #[arg(long)]
+ /// render the documentation in JSON format in addition to the usual HTML format
json: bool,
},
+ #[clap(aliases = ["t"], long_about = "\n
+ Arguments:
+ This subcommand accepts a number of paths to test directories that
+ should be compiled and run. For example:
+ ./x.py test tests/ui
+ ./x.py test library/std --test-args hash_map
+ ./x.py test library/std --stage 0 --no-doc
+ ./x.py test tests/ui --bless
+ ./x.py test tests/ui --compare-mode chalk
+ Note that `test tests/* --stage N` does NOT depend on `build compiler/rustc --stage N`;
+ just like `build library/std --stage N` it tests the compiler produced by the previous
+ stage.
+ Execute tool tests with a tool name argument:
+ ./x.py test tidy
+ If no arguments are passed then the complete artifacts for that stage are
+ compiled and tested.
+ ./x.py test
+ ./x.py test --stage 1")]
+ /// Build and run some test suites
Test {
- paths: Vec<PathBuf>,
- /// Whether to automatically update stderr/stdout files
+ #[arg(long)]
+ /// run all tests regardless of failure
+ no_fail_fast: bool,
+ #[arg(long, value_name = "SUBSTRING")]
+ /// skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times
+ skip: Vec<String>,
+ #[arg(long, value_name = "ARGS", allow_hyphen_values(true))]
+ /// extra arguments to be passed for the test tool being used
+ /// (e.g. libtest, compiletest or rustdoc)
+ test_args: Vec<String>,
+ /// extra options to pass the compiler when running tests
+ #[arg(long, value_name = "ARGS", allow_hyphen_values(true))]
+ rustc_args: Vec<String>,
+ #[arg(long)]
+ /// do not run doc tests
+ no_doc: bool,
+ #[arg(long)]
+ /// only run doc tests
+ doc: bool,
+ #[arg(long)]
+ /// whether to automatically update stderr/stdout files
bless: bool,
+ #[arg(long)]
+ /// rerun tests even if the inputs are unchanged
force_rerun: bool,
+ #[arg(long)]
+ /// only run tests that result has been changed
+ only_modified: bool,
+ #[arg(long, value_name = "COMPARE MODE")]
+ /// mode describing what file the actual ui output will be compared to
compare_mode: Option<String>,
+ #[arg(long, value_name = "check | build | run")]
+ /// force {check,build,run}-pass tests to this mode.
pass: Option<String>,
+ #[arg(long, value_name = "auto | always | never")]
+ /// whether to execute run-* tests
run: Option<String>,
- test_args: Vec<String>,
- rustc_args: Vec<String>,
- fail_fast: bool,
- doc_tests: DocTests,
+ #[arg(long)]
+ /// enable this to generate a Rustfix coverage file, which is saved in
+ /// `/<build_base>/rustfix_missing_coverage.txt`
rustfix_coverage: bool,
- only_modified: bool,
},
+ /// Build and run some benchmarks
Bench {
- paths: Vec<PathBuf>,
+ #[arg(long, allow_hyphen_values(true))]
test_args: Vec<String>,
},
+ /// Clean out build directories
Clean {
- paths: Vec<PathBuf>,
+ #[arg(long)]
all: bool,
},
- Dist {
- paths: Vec<PathBuf>,
- },
- Install {
- paths: Vec<PathBuf>,
- },
+ /// Build distribution artifacts
+ Dist,
+ /// Install distribution artifacts
+ Install,
+ #[clap(aliases = ["r"], long_about = "\n
+ Arguments:
+ This subcommand accepts a number of paths to tools to build and run. For
+ example:
+ ./x.py run src/tools/expand-yaml-anchors
+ At least a tool needs to be called.")]
+ /// Run tools contained in this repository
Run {
- paths: Vec<PathBuf>,
+ /// arguments for the tool
+ #[arg(long, allow_hyphen_values(true))]
args: Vec<String>,
},
- Setup {
- profile: Option<PathBuf>,
- },
- Suggest {
- run: bool,
- },
-}
-
-impl Default for Subcommand {
- fn default() -> Subcommand {
- Subcommand::Build { paths: vec![PathBuf::from("nowhere")] }
- }
-}
-
-impl Flags {
- pub fn parse(args: &[String]) -> Flags {
- let (args, free_args) = if let Some(pos) = args.iter().position(|s| s == "--") {
- let (args, free) = args.split_at(pos);
- (args, Some(free[1..].to_vec()))
- } else {
- (args, None)
- };
- let mut subcommand_help = String::from(
- "\
-Usage: x.py <subcommand> [options] [<paths>...]
-
-Subcommands:
- build, b Compile either the compiler or libraries
- check, c Compile either the compiler or libraries, using cargo check
- clippy Run clippy (uses rustup/cargo-installed clippy binary)
- fix Run cargo fix
- fmt Run rustfmt
- test, t Build and run some test suites
- bench Build and run some benchmarks
- doc, d Build documentation
- clean Clean out build directories
- dist Build distribution artifacts
- install Install distribution artifacts
- run, r Run tools contained in this repository
- setup Create a config.toml (making it easier to use `x.py` itself)
- suggest Suggest a subset of tests to run, based on modified files
-
-To learn more about a subcommand, run `./x.py <subcommand> -h`",
- );
-
- let mut opts = Options::new();
- // Options common to all subcommands
- opts.optflagmulti("v", "verbose", "use verbose output (-vv for very verbose)");
- opts.optflag("i", "incremental", "use incremental compilation");
- opts.optopt("", "config", "TOML configuration file for build", "FILE");
- opts.optopt(
- "",
- "build-dir",
- "Build directory, overrides `build.build-dir` in `config.toml`",
- "DIR",
- );
- opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
- opts.optmulti("", "host", "host targets to build", "HOST");
- opts.optmulti("", "target", "target targets to build", "TARGET");
- opts.optmulti("", "exclude", "build paths to exclude", "PATH");
- opts.optflag(
- "",
- "include-default-paths",
- "include default paths in addition to the provided ones",
- );
- opts.optopt("", "on-fail", "command to run on failure", "CMD");
- opts.optflag("", "dry-run", "dry run; don't build anything");
- opts.optopt(
- "",
- "stage",
- "stage to build (indicates compiler to use/test, e.g., stage 0 uses the \
- bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)",
- "N",
- );
- opts.optmulti(
- "",
- "keep-stage",
- "stage(s) to keep without recompiling \
- (pass multiple times to keep e.g., both stages 0 and 1)",
- "N",
- );
- opts.optmulti(
- "",
- "keep-stage-std",
- "stage(s) of the standard library to keep without recompiling \
- (pass multiple times to keep e.g., both stages 0 and 1)",
- "N",
- );
- opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
- let j_msg = format!(
- "number of jobs to run in parallel; \
- defaults to {} (this host's logical CPU count)",
- std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
- );
- opts.optopt("j", "jobs", &j_msg, "JOBS");
- opts.optflag("h", "help", "print this help message");
- opts.optopt(
- "",
- "warnings",
- "if value is deny, will deny warnings, otherwise use default",
- "VALUE",
- );
- opts.optopt("", "error-format", "rustc error format", "FORMAT");
- opts.optflag("", "json-output", "use message-format=json");
- opts.optopt("", "color", "whether to use color in cargo and rustc output", "STYLE");
- opts.optopt(
- "",
- "rust-profile-generate",
- "generate PGO profile with rustc build",
- "PROFILE",
- );
- opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "PROFILE");
- opts.optflag("", "llvm-profile-generate", "generate PGO profile with llvm built for rustc");
- opts.optopt("", "llvm-profile-use", "use PGO profile for llvm build", "PROFILE");
- opts.optmulti("A", "", "allow certain clippy lints", "OPT");
- opts.optmulti("D", "", "deny certain clippy lints", "OPT");
- opts.optmulti("W", "", "warn about certain clippy lints", "OPT");
- opts.optmulti("F", "", "forbid certain clippy lints", "OPT");
- opts.optflag("", "llvm-bolt-profile-generate", "generate BOLT profile for LLVM build");
- opts.optopt("", "llvm-bolt-profile-use", "use BOLT profile for LLVM build", "PROFILE");
-
- // We can't use getopt to parse the options until we have completed specifying which
- // options are valid, but under the current implementation, some options are conditional on
- // the subcommand. Therefore we must manually identify the subcommand first, so that we can
- // complete the definition of the options. Then we can use the getopt::Matches object from
- // there on out.
- let subcommand = match args.iter().find_map(|s| Kind::parse(&s)) {
- Some(s) => s,
- None => {
- // No or an invalid subcommand -- show the general usage and subcommand help
- // An exit code will be 0 when no subcommand is given, and 1 in case of an invalid
- // subcommand.
- println!("{}\n", subcommand_help);
- let exit_code = if args.is_empty() { 0 } else { 1 };
- crate::detail_exit(exit_code);
- }
- };
-
- // Some subcommands get extra options
- match subcommand {
- Kind::Test => {
- opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
- opts.optmulti("", "skip", "skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times", "SUBSTRING");
- opts.optmulti(
- "",
- "test-args",
- "extra arguments to be passed for the test tool being used \
- (e.g. libtest, compiletest or rustdoc)",
- "ARGS",
- );
- opts.optmulti(
- "",
- "rustc-args",
- "extra options to pass the compiler when running tests",
- "ARGS",
- );
- opts.optflag("", "no-doc", "do not run doc tests");
- opts.optflag("", "doc", "only run doc tests");
- opts.optflag("", "bless", "update all stderr/stdout files of failing ui tests");
- opts.optflag("", "force-rerun", "rerun tests even if the inputs are unchanged");
- opts.optflag("", "only-modified", "only run tests that result has been changed");
- opts.optopt(
- "",
- "compare-mode",
- "mode describing what file the actual ui output will be compared to",
- "COMPARE MODE",
- );
- opts.optopt(
- "",
- "pass",
- "force {check,build,run}-pass tests to this mode.",
- "check | build | run",
- );
- opts.optopt("", "run", "whether to execute run-* tests", "auto | always | never");
- opts.optflag(
- "",
- "rustfix-coverage",
- "enable this to generate a Rustfix coverage file, which is saved in \
- `/<build_base>/rustfix_missing_coverage.txt`",
- );
- }
- Kind::Check => {
- opts.optflag("", "all-targets", "Check all targets");
- }
- Kind::Bench => {
- opts.optmulti("", "test-args", "extra arguments", "ARGS");
- }
- Kind::Clippy => {
- opts.optflag("", "fix", "automatically apply lint suggestions");
- }
- Kind::Doc => {
- opts.optflag("", "open", "open the docs in a browser");
- opts.optflag(
- "",
- "json",
- "render the documentation in JSON format in addition to the usual HTML format",
- );
- }
- Kind::Clean => {
- opts.optflag("", "all", "clean all build artifacts");
- }
- Kind::Format => {
- opts.optflag("", "check", "check formatting instead of applying.");
- }
- Kind::Run => {
- opts.optmulti("", "args", "arguments for the tool", "ARGS");
- }
- Kind::Suggest => {
- opts.optflag("", "run", "run suggested tests");
- }
- _ => {}
- };
-
- // fn usage()
- let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! {
- println!("{}", opts.usage(subcommand_help));
- if verbose {
- // We have an unfortunate situation here: some Steps use `builder.in_tree_crates` to determine their paths.
- // To determine those crates, we need to run `cargo metadata`, which means we need all submodules to be checked out.
- // That takes a while to run, so only do it when paths were explicitly requested, not on all CLI errors.
- // `Build::new` won't load submodules for the `setup` command.
- let cmd = if verbose {
- println!("note: updating submodules before printing available paths");
- "build"
- } else {
- "setup"
- };
- let config = Config::parse(&[cmd.to_string()]);
- let build = Build::new(config);
- let paths = Builder::get_help(&build, subcommand);
-
- if let Some(s) = paths {
- println!("{}", s);
- } else {
- panic!("No paths available for subcommand `{}`", subcommand.as_str());
- }
- } else {
- println!(
- "Run `./x.py {} -h -v` to see a list of available paths.",
- subcommand.as_str()
- );
- }
- crate::detail_exit(exit_code);
- };
-
- // Done specifying what options are possible, so do the getopts parsing
- let matches = opts.parse(args).unwrap_or_else(|e| {
- // Invalid argument/option format
- println!("\n{}\n", e);
- usage(1, &opts, false, &subcommand_help);
- });
-
- // Extra sanity check to make sure we didn't hit this crazy corner case:
- //
- // ./x.py --frobulate clean build
- // ^-- option ^ ^- actual subcommand
- // \_ arg to option could be mistaken as subcommand
- let mut pass_sanity_check = true;
- match matches.free.get(0).and_then(|s| Kind::parse(&s)) {
- Some(check_subcommand) => {
- if check_subcommand != subcommand {
- pass_sanity_check = false;
- }
- }
- None => {
- pass_sanity_check = false;
- }
- }
- if !pass_sanity_check {
- eprintln!("{}\n", subcommand_help);
- eprintln!(
- "Sorry, I couldn't figure out which subcommand you were trying to specify.\n\
- You may need to move some options to after the subcommand.\n"
- );
- crate::detail_exit(1);
- }
- // Extra help text for some commands
- match subcommand {
- Kind::Build => {
- subcommand_help.push_str(
- "\n
-Arguments:
- This subcommand accepts a number of paths to directories to the crates
- and/or artifacts to compile. For example, for a quick build of a usable
- compiler:
-
- ./x.py build --stage 1 library/std
-
- This will build a compiler and standard library from the local source code.
- Once this is done, build/$ARCH/stage1 contains a usable compiler.
-
- If no arguments are passed then the default artifacts for that stage are
- compiled. For example:
-
- ./x.py build --stage 0
- ./x.py build ",
- );
- }
- Kind::Check => {
- subcommand_help.push_str(
- "\n
-Arguments:
- This subcommand accepts a number of paths to directories to the crates
- and/or artifacts to compile. For example:
-
- ./x.py check library/std
-
- If no arguments are passed then many artifacts are checked.",
- );
- }
- Kind::Clippy => {
- subcommand_help.push_str(
- "\n
-Arguments:
- This subcommand accepts a number of paths to directories to the crates
- and/or artifacts to run clippy against. For example:
-
- ./x.py clippy library/core
- ./x.py clippy library/core library/proc_macro",
- );
- }
- Kind::Fix => {
- subcommand_help.push_str(
- "\n
-Arguments:
- This subcommand accepts a number of paths to directories to the crates
- and/or artifacts to run `cargo fix` against. For example:
-
- ./x.py fix library/core
- ./x.py fix library/core library/proc_macro",
- );
- }
- Kind::Format => {
- subcommand_help.push_str(
- "\n
-Arguments:
- This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and
- fails if it is not. For example:
-
- ./x.py fmt
- ./x.py fmt --check",
- );
- }
- Kind::Test => {
- subcommand_help.push_str(
- "\n
-Arguments:
- This subcommand accepts a number of paths to test directories that
- should be compiled and run. For example:
-
- ./x.py test tests/ui
- ./x.py test library/std --test-args hash_map
- ./x.py test library/std --stage 0 --no-doc
- ./x.py test tests/ui --bless
- ./x.py test tests/ui --compare-mode chalk
-
- Note that `test tests/* --stage N` does NOT depend on `build compiler/rustc --stage N`;
- just like `build library/std --stage N` it tests the compiler produced by the previous
- stage.
-
- Execute tool tests with a tool name argument:
-
- ./x.py test tidy
-
- If no arguments are passed then the complete artifacts for that stage are
- compiled and tested.
-
- ./x.py test
- ./x.py test --stage 1",
- );
- }
- Kind::Doc => {
- subcommand_help.push_str(
- "\n
-Arguments:
- This subcommand accepts a number of paths to directories of documentation
- to build. For example:
-
- ./x.py doc src/doc/book
- ./x.py doc src/doc/nomicon
- ./x.py doc src/doc/book library/std
- ./x.py doc library/std --json
- ./x.py doc library/std --open
-
- If no arguments are passed then everything is documented:
-
- ./x.py doc
- ./x.py doc --stage 1",
- );
- }
- Kind::Run => {
- subcommand_help.push_str(
- "\n
-Arguments:
- This subcommand accepts a number of paths to tools to build and run. For
- example:
-
- ./x.py run src/tools/expand-yaml-anchors
-
- At least a tool needs to be called.",
- );
- }
- Kind::Setup => {
- subcommand_help.push_str(&format!(
- "\n
+ /// Set up the environment for development
+ #[clap(long_about = format!(
+ "\n
x.py setup creates a `config.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.
-
+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:
-
./x.py setup library
-
The profile is optional and you will be prompted interactively if it is not given.
The following profiles are available:
-
{}
-
- To only set up the git hook, VS code or toolchain link, you may use
+ To only set up the git hook, VS Code config or toolchain link, you may use
./x.py setup hook
./x.py setup vscode
- ./x.py setup link
-",
- Profile::all_for_help(" ").trim_end()
- ));
- }
- Kind::Bench | Kind::Clean | Kind::Dist | Kind::Install | Kind::Suggest => {}
- };
- // Get any optional paths which occur after the subcommand
- let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
-
- let verbose = matches.opt_present("verbose");
-
- // User passed in -h/--help?
- if matches.opt_present("help") {
- usage(0, &opts, verbose, &subcommand_help);
- }
-
- let cmd = match subcommand {
- Kind::Build => Subcommand::Build { paths },
- Kind::Check => {
- if matches.opt_present("all-targets") {
- println!(
- "Warning: --all-targets is now on by default and does not need to be passed explicitly."
- );
- }
- Subcommand::Check { paths }
- }
- Kind::Clippy => Subcommand::Clippy {
- paths,
- fix: matches.opt_present("fix"),
- clippy_lint_allow: matches.opt_strs("A"),
- clippy_lint_warn: matches.opt_strs("W"),
- clippy_lint_deny: matches.opt_strs("D"),
- clippy_lint_forbid: matches.opt_strs("F"),
- },
- Kind::Fix => Subcommand::Fix { paths },
- Kind::Test => Subcommand::Test {
- paths,
- bless: matches.opt_present("bless"),
- force_rerun: matches.opt_present("force-rerun"),
- compare_mode: matches.opt_str("compare-mode"),
- pass: matches.opt_str("pass"),
- run: matches.opt_str("run"),
- test_args: matches.opt_strs("test-args"),
- rustc_args: matches.opt_strs("rustc-args"),
- fail_fast: !matches.opt_present("no-fail-fast"),
- rustfix_coverage: matches.opt_present("rustfix-coverage"),
- only_modified: matches.opt_present("only-modified"),
- doc_tests: if matches.opt_present("doc") {
- DocTests::Only
- } else if matches.opt_present("no-doc") {
- DocTests::No
- } else {
- DocTests::Yes
- },
- },
- Kind::Bench => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
- Kind::Doc => Subcommand::Doc {
- paths,
- open: matches.opt_present("open"),
- json: matches.opt_present("json"),
- },
- Kind::Clean => Subcommand::Clean { all: matches.opt_present("all"), paths },
- Kind::Format => Subcommand::Format { check: matches.opt_present("check"), paths },
- Kind::Dist => Subcommand::Dist { paths },
- Kind::Install => Subcommand::Install { paths },
- Kind::Suggest => Subcommand::Suggest { run: matches.opt_present("run") },
- Kind::Run => {
- if paths.is_empty() {
- println!("\nrun requires at least a path!\n");
- usage(1, &opts, verbose, &subcommand_help);
- }
- Subcommand::Run { paths, args: matches.opt_strs("args") }
- }
- Kind::Setup => {
- let profile = if paths.len() > 1 {
- eprintln!("\nerror: At most one option can be passed to setup\n");
- usage(1, &opts, verbose, &subcommand_help)
- } else if let Some(path) = paths.pop() {
- let profile_string = t!(path.into_os_string().into_string().map_err(
- |path| format!("{} is not a valid UTF8 string", path.to_string_lossy())
- ));
-
- let profile = profile_string.parse().unwrap_or_else(|err| {
- eprintln!("error: {}", err);
- eprintln!("help: the available profiles are:");
- eprint!("{}", Profile::all_for_help("- "));
- crate::detail_exit(1);
- });
- Some(profile)
- } else {
- None
- };
- Subcommand::Setup { profile }
- }
- };
-
- Flags {
- verbose: matches.opt_count("verbose"),
- stage: matches.opt_str("stage").map(|j| j.parse().expect("`stage` should be a number")),
- dry_run: matches.opt_present("dry-run"),
- on_fail: matches.opt_str("on-fail"),
- rustc_error_format: matches.opt_str("error-format"),
- json_output: matches.opt_present("json-output"),
- keep_stage: matches
- .opt_strs("keep-stage")
- .into_iter()
- .map(|j| j.parse().expect("`keep-stage` should be a number"))
- .collect(),
- keep_stage_std: matches
- .opt_strs("keep-stage-std")
- .into_iter()
- .map(|j| j.parse().expect("`keep-stage-std` should be a number"))
- .collect(),
- host: if matches.opt_present("host") {
- Some(
- split(&matches.opt_strs("host"))
- .into_iter()
- .map(|x| TargetSelection::from_user(&x))
- .collect::<Vec<_>>(),
- )
- } else {
- None
- },
- target: if matches.opt_present("target") {
- Some(
- split(&matches.opt_strs("target"))
- .into_iter()
- .map(|x| TargetSelection::from_user(&x))
- .collect::<Vec<_>>(),
- )
- } else {
- None
- },
- config: matches.opt_str("config").map(PathBuf::from),
- build_dir: matches.opt_str("build-dir").map(PathBuf::from),
- jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")),
- cmd,
- incremental: matches.opt_present("incremental"),
- exclude: split(&matches.opt_strs("exclude"))
- .into_iter()
- .map(|p| p.into())
- .collect::<Vec<_>>(),
- include_default_paths: matches.opt_present("include-default-paths"),
- deny_warnings: parse_deny_warnings(&matches),
- color: matches
- .opt_get_default("color", Color::Auto)
- .expect("`color` should be `always`, `never`, or `auto`"),
- rust_profile_use: matches.opt_str("rust-profile-use"),
- rust_profile_generate: matches.opt_str("rust-profile-generate"),
- llvm_profile_use: matches.opt_str("llvm-profile-use"),
- llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
- llvm_bolt_profile_generate: matches.opt_present("llvm-bolt-profile-generate"),
- llvm_bolt_profile_use: matches.opt_str("llvm-bolt-profile-use"),
- free_args,
- }
- }
+ ./x.py setup link", Profile::all_for_help(" ").trim_end()))]
+ Setup {
+ /// Either the profile for `config.toml` or another setup action.
+ /// May be omitted to set up interactively
+ #[arg(value_name = "<PROFILE>|hook|vscode|link")]
+ profile: Option<PathBuf>,
+ },
+ /// Suggest a subset of tests to run, based on modified files
+ #[clap(long_about = "\n")]
+ Suggest {
+ /// run suggested tests
+ #[arg(long)]
+ run: bool,
+ },
}
impl Subcommand {
@@ -745,15 +434,6 @@ impl Subcommand {
}
}
- pub fn test_args(&self) -> Vec<&str> {
- match *self {
- Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
- test_args.iter().flat_map(|s| s.split_whitespace()).collect()
- }
- _ => vec![],
- }
- }
-
pub fn rustc_args(&self) -> Vec<&str> {
match *self {
Subcommand::Test { ref rustc_args, .. } => {
@@ -763,25 +443,24 @@ impl Subcommand {
}
}
- pub fn args(&self) -> Vec<&str> {
- match *self {
- Subcommand::Run { ref args, .. } => {
- args.iter().flat_map(|s| s.split_whitespace()).collect()
- }
- _ => vec![],
- }
- }
-
pub fn fail_fast(&self) -> bool {
match *self {
- Subcommand::Test { fail_fast, .. } => fail_fast,
+ Subcommand::Test { no_fail_fast, .. } => !no_fail_fast,
_ => false,
}
}
pub fn doc_tests(&self) -> DocTests {
match *self {
- Subcommand::Test { doc_tests, .. } => doc_tests,
+ Subcommand::Test { doc, no_doc, .. } => {
+ if doc {
+ DocTests::Only
+ } else if no_doc {
+ DocTests::No
+ } else {
+ DocTests::Yes
+ }
+ }
_ => DocTests::Yes,
}
}
@@ -850,18 +529,22 @@ impl Subcommand {
}
}
-fn split(s: &[String]) -> Vec<String> {
- s.iter().flat_map(|s| s.split(',')).filter(|s| !s.is_empty()).map(|s| s.to_string()).collect()
-}
-
-fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
- match matches.opt_str("warnings").as_deref() {
- Some("deny") => Some(true),
- Some("warn") => Some(false),
- Some(value) => {
- eprintln!(r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value,);
- crate::detail_exit(1);
- }
- None => None,
+/// Returns the shell completion for a given shell, if the result differs from the current
+/// content of `path`. If `path` does not exist, always returns `Some`.
+pub fn get_completion<G: clap_complete::Generator>(shell: G, path: &Path) -> Option<String> {
+ let mut cmd = Flags::command();
+ let current = if !path.exists() {
+ String::new()
+ } else {
+ std::fs::read_to_string(path).unwrap_or_else(|_| {
+ eprintln!("couldn't read {}", path.display());
+ crate::detail_exit(1)
+ })
+ };
+ let mut buf = Vec::new();
+ clap_complete::generate(shell, &mut cmd, "x.py", &mut buf);
+ if buf == current.as_bytes() {
+ return None;
}
+ Some(String::from_utf8(buf).expect("completion script should be UTF-8"))
}
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index b79969663..d8d3f300a 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -145,10 +145,8 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
let untracked_paths = untracked_paths_output
.lines()
.filter(|entry| entry.starts_with("??"))
- .filter_map(|entry| {
- let path =
- entry.split(' ').nth(1).expect("every git status entry should list a path");
- path.ends_with(".rs").then_some(path)
+ .map(|entry| {
+ entry.split(' ').nth(1).expect("every git status entry should list a path")
});
for untracked_path in untracked_paths {
println!("skip untracked path {} during rustfmt invocations", untracked_path);
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 42d895a34..b62aa9992 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -12,7 +12,7 @@ use crate::util::t;
use crate::dist;
use crate::tarball::GeneratedTarball;
-use crate::Compiler;
+use crate::{Compiler, Kind};
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::config::{Config, TargetSelection};
@@ -52,7 +52,7 @@ fn install_sh(
host: Option<TargetSelection>,
tarball: &GeneratedTarball,
) {
- builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));
+ let _guard = builder.msg(Kind::Install, stage, package, host, host);
let prefix = default_path(&builder.config.prefix, "/usr/local");
let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 419bcbc63..943f51341 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -19,13 +19,14 @@
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use std::env;
+use std::fmt::Display;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str;
-use build_helper::ci::CiEnv;
+use build_helper::ci::{gha, CiEnv};
use channel::GitInfo;
use config::{DryRun, Target};
use filetime::FileTime;
@@ -130,8 +131,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
/* Extra values not defined in the built-in targets yet, but used in std */
(Some(Mode::Std), "target_env", Some(&["libnx"])),
// (Some(Mode::Std), "target_os", Some(&[])),
- // #[cfg(bootstrap)] loongarch64
- (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa", "loongarch64"])),
+ (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])),
/* Extra names used by dependencies */
// FIXME: Used by serde_json, but we should not be triggering on external dependencies.
(Some(Mode::Rustc), "no_btreemap_remove_entry", None),
@@ -151,8 +151,6 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
// Needed to avoid the need to copy windows.lib into the sysroot.
(Some(Mode::Rustc), "windows_raw_dylib", None),
(Some(Mode::ToolRustc), "windows_raw_dylib", None),
- // #[cfg(bootstrap)] ohos
- (Some(Mode::Std), "target_env", Some(&["ohos"])),
];
/// A structure representing a Rust compiler.
@@ -238,8 +236,6 @@ pub struct Build {
ci_env: CiEnv,
delayed_failures: RefCell<Vec<String>>,
prerelease_version: Cell<Option<u32>>,
- tool_artifacts:
- RefCell<HashMap<TargetSelection, HashMap<String, (&'static str, PathBuf, Vec<String>)>>>,
#[cfg(feature = "build-metrics")]
metrics: metrics::BuildMetrics,
@@ -250,6 +246,7 @@ struct Crate {
name: Interned<String>,
deps: HashSet<Interned<String>>,
path: PathBuf,
+ has_lib: bool,
}
impl Crate {
@@ -417,6 +414,7 @@ impl Build {
bootstrap_out.display()
)
}
+ config.check_build_rustc_version();
if rust_info.is_from_tarball() && config.description.is_none() {
config.description = Some("built from a source tarball".to_owned());
@@ -458,7 +456,6 @@ impl Build {
ci_env: CiEnv::current(),
delayed_failures: RefCell::new(Vec::new()),
prerelease_version: Cell::new(None),
- tool_artifacts: Default::default(),
#[cfg(feature = "build-metrics")]
metrics: metrics::BuildMetrics::init(),
@@ -664,8 +661,8 @@ impl Build {
// hardcoded subcommands
match &self.config.cmd {
- Subcommand::Format { check, paths } => {
- return format::format(&builder::Builder::new(&self), *check, &paths);
+ Subcommand::Format { check } => {
+ return format::format(&builder::Builder::new(&self), *check, &self.config.paths);
}
Subcommand::Suggest { run } => {
return suggest::suggest(&builder::Builder::new(&self), *run);
@@ -996,6 +993,89 @@ impl Build {
}
}
+ fn msg_check(
+ &self,
+ what: impl Display,
+ target: impl Into<Option<TargetSelection>>,
+ ) -> Option<gha::Group> {
+ self.msg(Kind::Check, self.config.stage, what, self.config.build, target)
+ }
+
+ fn msg_build(
+ &self,
+ compiler: Compiler,
+ what: impl Display,
+ target: impl Into<Option<TargetSelection>>,
+ ) -> Option<gha::Group> {
+ self.msg(Kind::Build, compiler.stage, what, compiler.host, target)
+ }
+
+ /// Return a `Group` guard for a [`Step`] that is built for each `--stage`.
+ ///
+ /// [`Step`]: crate::builder::Step
+ fn msg(
+ &self,
+ action: impl Into<Kind>,
+ stage: u32,
+ what: impl Display,
+ host: impl Into<Option<TargetSelection>>,
+ target: impl Into<Option<TargetSelection>>,
+ ) -> Option<gha::Group> {
+ let action = action.into();
+ let msg = |fmt| format!("{action:?}ing stage{stage} {what}{fmt}");
+ let msg = if let Some(target) = target.into() {
+ let host = host.into().unwrap();
+ if host == target {
+ msg(format_args!(" ({target})"))
+ } else {
+ msg(format_args!(" ({host} -> {target})"))
+ }
+ } else {
+ msg(format_args!(""))
+ };
+ self.group(&msg)
+ }
+
+ /// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`.
+ ///
+ /// [`Step`]: crate::builder::Step
+ fn msg_unstaged(
+ &self,
+ action: impl Into<Kind>,
+ what: impl Display,
+ target: TargetSelection,
+ ) -> Option<gha::Group> {
+ let action = action.into();
+ let msg = format!("{action:?}ing {what} for {target}");
+ self.group(&msg)
+ }
+
+ fn msg_sysroot_tool(
+ &self,
+ action: impl Into<Kind>,
+ stage: u32,
+ what: impl Display,
+ host: TargetSelection,
+ target: TargetSelection,
+ ) -> Option<gha::Group> {
+ let action = action.into();
+ let msg = |fmt| format!("{action:?}ing {what} {fmt}");
+ let msg = if host == target {
+ msg(format_args!("(stage{stage} -> stage{}, {target})", stage + 1))
+ } else {
+ msg(format_args!("(stage{stage}:{host} -> stage{}:{target})", stage + 1))
+ };
+ self.group(&msg)
+ }
+
+ fn group(&self, msg: &str) -> Option<gha::Group> {
+ self.info(&msg);
+ match self.config.dry_run {
+ DryRun::SelfCheck => None,
+ DryRun::Disabled | DryRun::UserSelected => Some(gha::group(&msg)),
+ }
+ }
+
/// Returns the number of parallel jobs that have been configured for this
/// build.
fn jobs(&self) -> u32 {
@@ -1248,7 +1328,7 @@ impl Build {
match &self.config.channel[..] {
"stable" => num.to_string(),
"beta" => {
- if self.rust_info().is_managed_git_subrepository() && !self.config.omit_git_hash {
+ if !self.config.omit_git_hash {
format!("{}-beta.{}", num, self.beta_prerelease_version())
} else {
format!("{}-beta", num)
@@ -1260,18 +1340,28 @@ impl Build {
}
fn beta_prerelease_version(&self) -> u32 {
+ fn extract_beta_rev_from_file<P: AsRef<Path>>(version_file: P) -> Option<String> {
+ let version = fs::read_to_string(version_file).ok()?;
+
+ extract_beta_rev(&version)
+ }
+
if let Some(s) = self.prerelease_version.get() {
return s;
}
- // Figure out how many merge commits happened since we branched off master.
- // That's our beta number!
- // (Note that we use a `..` range, not the `...` symmetric difference.)
- let count =
+ // First check if there is a version file available.
+ // If available, we read the beta revision from that file.
+ // This only happens when building from a source tarball when Git should not be used.
+ let count = extract_beta_rev_from_file(self.src.join("version")).unwrap_or_else(|| {
+ // Figure out how many merge commits happened since we branched off master.
+ // That's our beta number!
+ // (Note that we use a `..` range, not the `...` symmetric difference.)
output(self.config.git().arg("rev-list").arg("--count").arg("--merges").arg(format!(
"refs/remotes/origin/{}..HEAD",
self.config.stage0_metadata.config.nightly_branch
- )));
+ )))
+ });
let n = count.trim().parse().unwrap();
self.prerelease_version.set(Some(n));
n
@@ -1631,6 +1721,17 @@ to download LLVM rather than building it.
}
}
+/// Extract the beta revision from the full version string.
+///
+/// The full version string looks like "a.b.c-beta.y". And we need to extract
+/// the "y" part from the string.
+pub fn extract_beta_rev(version: &str) -> Option<String> {
+ let parts = version.splitn(2, "-beta.").collect::<Vec<_>>();
+ let count = parts.get(1).and_then(|s| s.find(' ').map(|p| (&s[..p]).to_string()));
+
+ count
+}
+
#[cfg(unix)]
fn chmod(path: &Path, perms: u32) {
use std::os::unix::fs::*;
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs
index a893c3a47..040a12f5d 100644
--- a/src/bootstrap/llvm.rs
+++ b/src/bootstrap/llvm.rs
@@ -21,7 +21,7 @@ use crate::channel;
use crate::config::{Config, TargetSelection};
use crate::util::get_clang_cl_resource_dir;
use crate::util::{self, exe, output, t, up_to_date};
-use crate::{CLang, GitRepo};
+use crate::{CLang, GitRepo, Kind};
use build_helper::ci::CiEnv;
@@ -185,6 +185,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
("arm-unknown-linux-gnueabi", false),
("arm-unknown-linux-gnueabihf", false),
("armv7-unknown-linux-gnueabihf", false),
+ ("loongarch64-unknown-linux-gnu", false),
("mips-unknown-linux-gnu", false),
("mips64-unknown-linux-gnuabi64", false),
("mips64el-unknown-linux-gnuabi64", false),
@@ -271,7 +272,7 @@ impl Step for Llvm {
panic!("shared linking to LLVM is not currently supported on {}", target.triple);
}
- builder.info(&format!("Building LLVM for {}", target));
+ let _guard = builder.msg_unstaged(Kind::Build, "LLVM", target);
t!(stamp.remove());
let _time = util::timeit(&builder);
t!(fs::create_dir_all(&out_dir));
@@ -813,7 +814,7 @@ impl Step for Lld {
return out_dir;
}
- builder.info(&format!("Building LLD for {}", target));
+ let _guard = builder.msg_unstaged(Kind::Build, "LLD", target);
let _time = util::timeit(&builder);
t!(fs::create_dir_all(&out_dir));
@@ -911,7 +912,7 @@ impl Step for Sanitizers {
return runtimes;
}
- builder.info(&format!("Building sanitizers for {}", self.target));
+ let _guard = builder.msg_unstaged(Kind::Build, "sanitizers", self.target);
t!(stamp.remove());
let _time = util::timeit(&builder);
@@ -1103,7 +1104,7 @@ impl Step for CrtBeginEnd {
return out_dir;
}
- builder.info("Building crtbegin.o and crtend.o");
+ let _guard = builder.msg_unstaged(Kind::Build, "crtbegin.o and crtend.o", self.target);
t!(fs::create_dir_all(&out_dir));
let mut cfg = cc::Build::new();
@@ -1153,7 +1154,7 @@ impl Step for Libunwind {
run.builder.ensure(Libunwind { target: run.target });
}
- /// Build linunwind.a
+ /// Build libunwind.a
fn run(self, builder: &Builder<'_>) -> Self::Output {
builder.update_submodule(&Path::new("src/llvm-project"));
@@ -1168,7 +1169,7 @@ impl Step for Libunwind {
return out_dir;
}
- builder.info(&format!("Building libunwind.a for {}", self.target.triple));
+ let _guard = builder.msg_unstaged(Kind::Build, "libunwind.a", self.target);
t!(fs::create_dir_all(&out_dir));
let mut cc_cfg = cc::Build::new();
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index bba4d65e8..8f2c3faca 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -5,40 +5,43 @@ use serde_derive::Deserialize;
use crate::cache::INTERNER;
use crate::util::output;
-use crate::{Build, Crate};
+use crate::{t, Build, Crate};
-#[derive(Deserialize)]
+/// For more information, see the output of
+/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
+#[derive(Debug, Deserialize)]
struct Output {
packages: Vec<Package>,
}
-#[derive(Deserialize)]
+/// For more information, see the output of
+/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
+#[derive(Debug, Deserialize)]
struct Package {
name: String,
source: Option<String>,
manifest_path: String,
dependencies: Vec<Dependency>,
+ targets: Vec<Target>,
}
-#[derive(Deserialize)]
+/// For more information, see the output of
+/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
+#[derive(Debug, Deserialize)]
struct Dependency {
name: String,
source: Option<String>,
}
+#[derive(Debug, Deserialize)]
+struct Target {
+ kind: Vec<String>,
+}
+
+/// Collects and stores package metadata of each workspace members into `build`,
+/// by executing `cargo metadata` commands.
pub fn build(build: &mut Build) {
- // Run `cargo metadata` to figure out what crates we're testing.
- let mut cargo = Command::new(&build.initial_cargo);
- cargo
- .arg("metadata")
- .arg("--format-version")
- .arg("1")
- .arg("--no-deps")
- .arg("--manifest-path")
- .arg(build.src.join("Cargo.toml"));
- let output = output(&mut cargo);
- let output: Output = serde_json::from_str(&output).unwrap();
- for package in output.packages {
+ for package in workspace_members(build) {
if package.source.is_none() {
let name = INTERNER.intern_string(package.name);
let mut path = PathBuf::from(package.manifest_path);
@@ -49,11 +52,47 @@ pub fn build(build: &mut Build) {
.filter(|dep| dep.source.is_none())
.map(|dep| INTERNER.intern_string(dep.name))
.collect();
- let krate = Crate { name, deps, path };
+ let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib"));
+ let krate = Crate { name, deps, path, has_lib };
let relative_path = krate.local_path(build);
build.crates.insert(name, krate);
let existing_path = build.crate_paths.insert(relative_path, name);
- assert!(existing_path.is_none(), "multiple crates with the same path");
+ assert!(
+ existing_path.is_none(),
+ "multiple crates with the same path: {}",
+ existing_path.unwrap()
+ );
}
}
}
+
+/// Invokes `cargo metadata` to get package metadata of each workspace member.
+///
+/// Note that `src/tools/cargo` is no longer a workspace member but we still
+/// treat it as one here, by invoking an additional `cargo metadata` command.
+fn workspace_members(build: &Build) -> impl Iterator<Item = Package> {
+ let collect_metadata = |manifest_path| {
+ let mut cargo = Command::new(&build.initial_cargo);
+ cargo
+ .arg("metadata")
+ .arg("--format-version")
+ .arg("1")
+ .arg("--no-deps")
+ .arg("--manifest-path")
+ .arg(build.src.join(manifest_path));
+ let metadata_output = output(&mut cargo);
+ let Output { packages, .. } = t!(serde_json::from_str(&metadata_output));
+ packages
+ };
+
+ // Collects `metadata.packages` from all workspaces.
+ let packages = collect_metadata("Cargo.toml");
+ let cargo_packages = collect_metadata("src/tools/cargo/Cargo.toml");
+ let ra_packages = collect_metadata("src/tools/rust-analyzer/Cargo.toml");
+ let bootstrap_packages = collect_metadata("src/bootstrap/Cargo.toml");
+
+ // We only care about the root package from `src/tool/cargo` workspace.
+ let cargo_package = cargo_packages.into_iter().find(|pkg| pkg.name == "cargo").into_iter();
+
+ packages.into_iter().chain(cargo_package).chain(ra_packages).chain(bootstrap_packages)
+}
diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs
index 82b123ec8..5990f33b9 100644
--- a/src/bootstrap/metrics.rs
+++ b/src/bootstrap/metrics.rs
@@ -4,7 +4,7 @@
//! As this module requires additional dependencies not present during local builds, it's cfg'd
//! away whenever the `build.metrics` config option is not set to `true`.
-use crate::builder::Step;
+use crate::builder::{Builder, Step};
use crate::util::t;
use crate::Build;
use serde_derive::{Deserialize, Serialize};
@@ -14,6 +14,25 @@ use std::io::BufWriter;
use std::time::{Duration, Instant, SystemTime};
use sysinfo::{CpuExt, System, SystemExt};
+// Update this number whenever a breaking change is made to the build metrics.
+//
+// The output format is versioned for two reasons:
+//
+// - The metadata is intended to be consumed by external tooling, and exposing a format version
+// helps the tools determine whether they're compatible with a metrics file.
+//
+// - If a developer enables build metrics in their local checkout, making a breaking change to the
+// metrics format would result in a hard-to-diagnose error message when an existing metrics file
+// is not compatible with the new changes. With a format version number, bootstrap can discard
+// incompatible metrics files instead of appending metrics to them.
+//
+// Version changelog:
+//
+// - v0: initial version
+// - v1: replaced JsonNode::Test with JsonNode::TestSuite
+//
+const CURRENT_FORMAT_VERSION: usize = 1;
+
pub(crate) struct BuildMetrics {
state: RefCell<MetricsState>,
}
@@ -33,7 +52,12 @@ impl BuildMetrics {
BuildMetrics { state }
}
- pub(crate) fn enter_step<S: Step>(&self, step: &S) {
+ pub(crate) fn enter_step<S: Step>(&self, step: &S, builder: &Builder<'_>) {
+ // Do not record dry runs, as they'd be duplicates of the actual steps.
+ if builder.config.dry_run() {
+ return;
+ }
+
let mut state = self.state.borrow_mut();
// Consider all the stats gathered so far as the parent's.
@@ -52,11 +76,16 @@ impl BuildMetrics {
duration_excluding_children_sec: Duration::ZERO,
children: Vec::new(),
- tests: Vec::new(),
+ test_suites: Vec::new(),
});
}
- pub(crate) fn exit_step(&self) {
+ pub(crate) fn exit_step(&self, builder: &Builder<'_>) {
+ // Do not record dry runs, as they'd be duplicates of the actual steps.
+ if builder.config.dry_run() {
+ return;
+ }
+
let mut state = self.state.borrow_mut();
self.collect_stats(&mut *state);
@@ -74,14 +103,31 @@ impl BuildMetrics {
}
}
- pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome) {
+ pub(crate) fn begin_test_suite(&self, metadata: TestSuiteMetadata, builder: &Builder<'_>) {
+ // Do not record dry runs, as they'd be duplicates of the actual steps.
+ if builder.config.dry_run() {
+ return;
+ }
+
+ let mut state = self.state.borrow_mut();
+ let step = state.running_steps.last_mut().unwrap();
+ step.test_suites.push(TestSuite { metadata, tests: Vec::new() });
+ }
+
+ pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome, builder: &Builder<'_>) {
+ // Do not record dry runs, as they'd be duplicates of the actual steps.
+ if builder.config.dry_run() {
+ return;
+ }
+
let mut state = self.state.borrow_mut();
- state
- .running_steps
- .last_mut()
- .unwrap()
- .tests
- .push(Test { name: name.to_string(), outcome });
+ let step = state.running_steps.last_mut().unwrap();
+
+ if let Some(test_suite) = step.test_suites.last_mut() {
+ test_suite.tests.push(Test { name: name.to_string(), outcome });
+ } else {
+ panic!("metrics.record_test() called without calling metrics.begin_test_suite() first");
+ }
}
fn collect_stats(&self, state: &mut MetricsState) {
@@ -116,7 +162,20 @@ impl BuildMetrics {
// Some of our CI builds consist of multiple independent CI invocations. Ensure all the
// previous invocations are still present in the resulting file.
let mut invocations = match std::fs::read(&dest) {
- Ok(contents) => t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations,
+ Ok(contents) => {
+ // We first parse just the format_version field to have the check succeed even if
+ // the rest of the contents are not valid anymore.
+ let version: OnlyFormatVersion = t!(serde_json::from_slice(&contents));
+ if version.format_version == CURRENT_FORMAT_VERSION {
+ t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations
+ } else {
+ println!(
+ "warning: overriding existing build/metrics.json, as it's not \
+ compatible with build metrics format version {CURRENT_FORMAT_VERSION}."
+ );
+ Vec::new()
+ }
+ }
Err(err) => {
if err.kind() != std::io::ErrorKind::NotFound {
panic!("failed to open existing metrics file at {}: {err}", dest.display());
@@ -134,7 +193,7 @@ impl BuildMetrics {
children: steps.into_iter().map(|step| self.prepare_json_step(step)).collect(),
});
- let json = JsonRoot { system_stats, invocations };
+ let json = JsonRoot { format_version: CURRENT_FORMAT_VERSION, system_stats, invocations };
t!(std::fs::create_dir_all(dest.parent().unwrap()));
let mut file = BufWriter::new(t!(File::create(&dest)));
@@ -144,11 +203,7 @@ impl BuildMetrics {
fn prepare_json_step(&self, step: StepMetrics) -> JsonNode {
let mut children = Vec::new();
children.extend(step.children.into_iter().map(|child| self.prepare_json_step(child)));
- children.extend(
- step.tests
- .into_iter()
- .map(|test| JsonNode::Test { name: test.name, outcome: test.outcome }),
- );
+ children.extend(step.test_suites.into_iter().map(JsonNode::TestSuite));
JsonNode::RustbuildStep {
type_: step.type_,
@@ -183,17 +238,14 @@ struct StepMetrics {
duration_excluding_children_sec: Duration,
children: Vec<StepMetrics>,
- tests: Vec<Test>,
-}
-
-struct Test {
- name: String,
- outcome: TestOutcome,
+ test_suites: Vec<TestSuite>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
struct JsonRoot {
+ #[serde(default)] // For version 0 the field was not present.
+ format_version: usize,
system_stats: JsonInvocationSystemStats,
invocations: Vec<JsonInvocation>,
}
@@ -222,14 +274,42 @@ enum JsonNode {
children: Vec<JsonNode>,
},
- Test {
- name: String,
- #[serde(flatten)]
- outcome: TestOutcome,
+ TestSuite(TestSuite),
+}
+
+#[derive(Serialize, Deserialize)]
+struct TestSuite {
+ metadata: TestSuiteMetadata,
+ tests: Vec<Test>,
+}
+
+#[derive(Serialize, Deserialize)]
+#[serde(tag = "kind", rename_all = "snake_case")]
+pub(crate) enum TestSuiteMetadata {
+ CargoPackage {
+ crates: Vec<String>,
+ target: String,
+ host: String,
+ stage: u32,
+ },
+ Compiletest {
+ suite: String,
+ mode: String,
+ compare_mode: Option<String>,
+ target: String,
+ host: String,
+ stage: u32,
},
}
#[derive(Serialize, Deserialize)]
+pub(crate) struct Test {
+ name: String,
+ #[serde(flatten)]
+ outcome: TestOutcome,
+}
+
+#[derive(Serialize, Deserialize)]
#[serde(tag = "outcome", rename_all = "snake_case")]
pub(crate) enum TestOutcome {
Passed,
@@ -251,3 +331,9 @@ struct JsonInvocationSystemStats {
struct JsonStepSystemStats {
cpu_utilization_percent: f64,
}
+
+#[derive(Deserialize)]
+struct OnlyFormatVersion {
+ #[serde(default)] // For version 0 the field was not present.
+ format_version: usize,
+}
diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs
index 19019ad2c..fa0a48066 100644
--- a/src/bootstrap/render_tests.rs
+++ b/src/bootstrap/render_tests.rs
@@ -1,7 +1,7 @@
//! This module renders the JSON output of libtest into a human-readable form, trying to be as
//! similar to libtest's native output as possible.
//!
-//! This is needed because we need to use libtest in JSON mode to extract granluar information
+//! This is needed because we need to use libtest in JSON mode to extract granular information
//! about the executed tests. Doing so suppresses the human-readable output, and (compared to Cargo
//! and rustc) libtest doesn't include the rendered human-readable output as a JSON field. We had
//! to reimplement all the rendering logic in this module because of that.
@@ -124,6 +124,7 @@ impl<'a> Renderer<'a> {
ignore_reason: reason.map(|s| s.to_string()),
},
},
+ self.builder,
);
if self.builder.config.verbose_tests {
@@ -167,9 +168,14 @@ impl<'a> Renderer<'a> {
if !self.failures.is_empty() {
println!("\nfailures:\n");
for failure in &self.failures {
- if let Some(stdout) = &failure.stdout {
+ if failure.stdout.is_some() || failure.message.is_some() {
println!("---- {} stdout ----", failure.name);
- println!("{stdout}");
+ if let Some(stdout) = &failure.stdout {
+ println!("{stdout}");
+ }
+ if let Some(message) = &failure.message {
+ println!("note: {message}");
+ }
}
}
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index e14440f57..ec01f744b 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -1,9 +1,12 @@
use std::path::PathBuf;
use std::process::Command;
+use clap_complete::shells;
+
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::config::TargetSelection;
use crate::dist::distdir;
+use crate::flags::get_completion;
use crate::test;
use crate::tool::{self, SourceType, Tool};
use crate::util::output;
@@ -105,7 +108,7 @@ impl Step for BumpStage0 {
fn run(self, builder: &Builder<'_>) -> Self::Output {
let mut cmd = builder.tool_cmd(Tool::BumpStage0);
- cmd.args(builder.config.cmd.args());
+ cmd.args(builder.config.args());
builder.run(&mut cmd);
}
}
@@ -182,8 +185,7 @@ impl Step for Miri {
miri.add_rustc_lib_path(builder, compiler);
// Forward arguments.
miri.arg("--").arg("--target").arg(target.rustc_target_arg());
- miri.args(builder.config.cmd.args());
- miri.args(&builder.config.free_args);
+ miri.args(builder.config.args());
// miri tests need to know about the stage sysroot
miri.env("MIRI_SYSROOT", &miri_sysroot);
@@ -254,3 +256,56 @@ impl Step for GenerateCopyright {
dest
}
}
+
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct GenerateWindowsSys;
+
+impl Step for GenerateWindowsSys {
+ type Output = ();
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.path("src/tools/generate-windows-sys")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(GenerateWindowsSys);
+ }
+
+ fn run(self, builder: &Builder<'_>) {
+ let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys);
+ cmd.arg(&builder.src);
+ builder.run(&mut cmd);
+ }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct GenerateCompletions;
+
+impl Step for GenerateCompletions {
+ type Output = ();
+
+ /// Uses `clap_complete` to generate shell completions.
+ fn run(self, builder: &Builder<'_>) {
+ // FIXME(clubby789): enable zsh when clap#4898 is fixed
+ let [bash, fish, powershell] = ["x.py.sh", "x.py.fish", "x.py.ps1"]
+ .map(|filename| builder.src.join("src/etc/completions").join(filename));
+ if let Some(comp) = get_completion(shells::Bash, &bash) {
+ std::fs::write(&bash, comp).expect("writing bash completion");
+ }
+ if let Some(comp) = get_completion(shells::Fish, &fish) {
+ std::fs::write(&fish, comp).expect("writing fish completion");
+ }
+ if let Some(comp) = get_completion(shells::PowerShell, &powershell) {
+ std::fs::write(&powershell, comp).expect("writing powershell completion");
+ }
+ }
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.alias("generate-completions")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(GenerateCompletions);
+ }
+}
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 8a40b0f64..140259b02 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -100,7 +100,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 section of `config.toml` to download LLVM rather
+`[llvm]` section of `config.toml` to download LLVM rather
than building it.
"
);
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index aedf1ecab..44cd84be7 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -5,15 +5,17 @@
use std::env;
use std::ffi::OsString;
-use std::fmt;
use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
+use clap_complete::shells;
+
use crate::builder::crate_description;
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
+use crate::cache::INTERNER;
use crate::compile;
use crate::config::TargetSelection;
use crate::dist;
@@ -28,44 +30,6 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode};
const ADB_TEST_DIR: &str = "/data/local/tmp/work";
-/// The two modes of the test runner; tests or benchmarks.
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
-pub enum TestKind {
- /// Run `cargo test`.
- Test,
- /// Run `cargo bench`.
- Bench,
-}
-
-impl From<Kind> for TestKind {
- fn from(kind: Kind) -> Self {
- match kind {
- Kind::Test => TestKind::Test,
- Kind::Bench => TestKind::Bench,
- _ => panic!("unexpected kind in crate: {:?}", kind),
- }
- }
-}
-
-impl TestKind {
- // Return the cargo subcommand for this test kind
- fn subcommand(self) -> &'static str {
- match self {
- TestKind::Test => "test",
- TestKind::Bench => "bench",
- }
- }
-}
-
-impl fmt::Display for TestKind {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(match *self {
- TestKind::Test => "Testing",
- TestKind::Bench => "Benchmarking",
- })
- }
-}
-
fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
if !builder.fail_fast {
if !builder.try_run(cmd) {
@@ -93,26 +57,37 @@ fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct CrateJsonDocLint {
+pub struct CrateBootstrap {
+ path: Interned<PathBuf>,
host: TargetSelection,
}
-impl Step for CrateJsonDocLint {
+impl Step for CrateBootstrap {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/jsondoclint")
+ .path("src/tools/suggest-tests")
+ .path("src/tools/replace-version-placeholder")
+ .alias("tidyselftest")
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(CrateJsonDocLint { host: run.target });
+ for path in run.paths {
+ let path = INTERNER.intern_path(path.assert_single_path().path.clone());
+ run.builder.ensure(CrateBootstrap { host: run.target, path });
+ }
}
fn run(self, builder: &Builder<'_>) {
let bootstrap_host = builder.config.build;
let compiler = builder.compiler(0, bootstrap_host);
+ let mut path = self.path.to_str().unwrap();
+ if path == "tidyselftest" {
+ path = "src/tools/tidy";
+ }
let cargo = tool::prepare_tool_cargo(
builder,
@@ -120,47 +95,18 @@ impl Step for CrateJsonDocLint {
Mode::ToolBootstrap,
bootstrap_host,
"test",
- "src/tools/jsondoclint",
+ path,
SourceType::InTree,
&[],
);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct SuggestTestsCrate {
- host: TargetSelection,
-}
-
-impl Step for SuggestTestsCrate {
- type Output = ();
- const ONLY_HOSTS: bool = true;
- const DEFAULT: bool = true;
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/tools/suggest-tests")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(SuggestTestsCrate { host: run.target });
- }
-
- fn run(self, builder: &Builder<'_>) {
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
-
- let suggest_tests = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
+ builder.info(&format!(
+ "{} {} stage0 ({})",
+ builder.kind.test_description(),
+ path,
bootstrap_host,
- "test",
- "src/tools/suggest-tests",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut suggest_tests.into());
+ ));
+ let crate_name = path.rsplit_once('/').unwrap().1;
+ run_cargo_test(cargo, &[], &[], crate_name, compiler, bootstrap_host, builder);
}
}
@@ -209,7 +155,11 @@ You can skip linkcheck with --exclude src/tools/linkchecker"
SourceType::InTree,
&[],
);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "linkchecker", compiler, bootstrap_host, builder);
+
+ if builder.doc_tests == DocTests::No {
+ return;
+ }
// Build all the default documentation.
builder.default_doc(&[]);
@@ -315,7 +265,7 @@ impl Step for Cargotest {
builder,
cmd.arg(&cargo)
.arg(&out_dir)
- .args(builder.config.cmd.test_args())
+ .args(builder.config.test_args())
.env("RUSTC", builder.rustc(compiler))
.env("RUSTDOC", builder.rustdoc(compiler)),
);
@@ -345,7 +295,7 @@ impl Step for Cargo {
let compiler = builder.compiler(self.stage, self.host);
builder.ensure(tool::Cargo { compiler, target: self.host });
- let mut cargo = tool::prepare_tool_cargo(
+ let cargo = tool::prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
@@ -356,10 +306,8 @@ impl Step for Cargo {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- cargo.arg("--").args(builder.config.cmd.test_args());
+ // NOTE: can't use `run_cargo_test` because we need to overwrite `PATH`
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "cargo", compiler, self.host, builder);
// Don't run cross-compile tests, we may not have cross-compiled libstd libs
// available.
@@ -367,10 +315,21 @@ impl Step for Cargo {
// Forcibly disable tests using nightly features since any changes to
// those features won't be able to land.
cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
-
cargo.env("PATH", &path_for_cargo(builder, compiler));
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::CargoPackage {
+ crates: vec!["cargo".into()],
+ target: self.host.triple.to_string(),
+ host: self.host.triple.to_string(),
+ stage: self.stage,
+ },
+ builder,
+ );
+
+ let _time = util::timeit(&builder);
+ add_flags_and_try_run_tests(builder, &mut cargo);
}
}
@@ -427,9 +386,7 @@ impl Step for RustAnalyzer {
cargo.env("SKIP_SLOW_TESTS", "1");
cargo.add_rustc_lib_path(builder, compiler);
- cargo.arg("--").args(builder.config.cmd.test_args());
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rust-analyzer", compiler, host, builder);
}
}
@@ -472,17 +429,13 @@ impl Step for Rustfmt {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
let dir = testdir(builder, compiler.host);
t!(fs::create_dir_all(&dir));
cargo.env("RUSTFMT_TEST_DIR", dir);
cargo.add_rustc_lib_path(builder, compiler);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rustfmt", compiler, host, builder);
}
}
@@ -528,12 +481,9 @@ impl Step for RustDemangler {
t!(fs::create_dir_all(&dir));
cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler);
-
- cargo.arg("--").args(builder.config.cmd.test_args());
-
cargo.add_rustc_lib_path(builder, compiler);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rust-demangler", compiler, host, builder);
}
}
@@ -656,10 +606,6 @@ impl Step for Miri {
);
cargo.add_rustc_lib_path(builder, compiler);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
// miri tests need to know about the stage sysroot
cargo.env("MIRI_SYSROOT", &miri_sysroot);
cargo.env("MIRI_HOST_SYSROOT", sysroot);
@@ -671,13 +617,31 @@ impl Step for Miri {
// Set the target.
cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
- // Forward test filters.
- cargo.arg("--").args(builder.config.cmd.test_args());
- // This can NOT be `add_flags_and_try_run_tests` since the Miri test runner
- // does not understand those flags!
- let mut cargo = Command::from(cargo);
- builder.run(&mut cargo);
+ // This can NOT be `run_cargo_test` since the Miri test runner
+ // does not understand the flags added by `add_flags_and_try_run_test`.
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
+ {
+ let _time = util::timeit(&builder);
+ builder.run(&mut cargo);
+ }
+
+ // Run it again for mir-opt-level 4 to catch some miscompilations.
+ if builder.config.test_args().is_empty() {
+ cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
+ // Optimizations can change backtraces
+ cargo.env("MIRI_SKIP_UI_CHECKS", "1");
+ // `MIRI_SKIP_UI_CHECKS` and `MIRI_BLESS` are incompatible
+ cargo.env_remove("MIRI_BLESS");
+ // Optimizations can change error locations and remove UB so don't run `fail` tests.
+ cargo.args(&["tests/pass", "tests/panic"]);
+
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
+ {
+ let _time = util::timeit(&builder);
+ builder.run(&mut cargo);
+ }
+ }
// # Run `cargo miri test`.
// This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
@@ -700,7 +664,7 @@ impl Step for Miri {
.arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml"));
cargo.arg("--target").arg(target.rustc_target_arg());
cargo.arg("--tests"); // don't run doctests, they are too confused by the staging
- cargo.arg("--").args(builder.config.cmd.test_args());
+ cargo.arg("--").args(builder.config.test_args());
// Tell `cargo miri` where to find things.
cargo.env("MIRI_SYSROOT", &miri_sysroot);
@@ -710,7 +674,10 @@ impl Step for Miri {
cargo.env("RUST_BACKTRACE", "1");
let mut cargo = Command::from(cargo);
- builder.run(&mut cargo);
+ {
+ let _time = util::timeit(&builder);
+ builder.run(&mut cargo);
+ }
}
}
@@ -749,8 +716,7 @@ impl Step for CompiletestTest {
&[],
);
cargo.allow_features("test");
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "compiletest", compiler, host, builder);
}
}
@@ -793,20 +759,15 @@ impl Step for Clippy {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir());
cargo.env("HOST_LIBS", host_libs);
- cargo.arg("--").args(builder.config.cmd.test_args());
-
cargo.add_rustc_lib_path(builder, compiler);
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder);
- if builder.try_run(&mut cargo.into()) {
+ if builder.try_run(&mut cargo) {
// The tests succeeded; nothing to do.
return;
}
@@ -994,28 +955,6 @@ fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
.or_else(|| get_browser_ui_test_version_inner(npm, true))
}
-fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
- match fs::read_to_string(
- src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
- ) {
- Ok(v) => {
- if v.trim() != installed_version {
- eprintln!(
- "⚠️ Installed version of browser-ui-test (`{}`) is different than the \
- one used in the CI (`{}`)",
- installed_version, v
- );
- eprintln!(
- "You can install this version using `npm update browser-ui-test` or by using \
- `npm install browser-ui-test@{}`",
- v,
- );
- }
- }
- Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
- }
-}
-
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustdocGUI {
pub target: TargetSelection,
@@ -1047,79 +986,30 @@ impl Step for RustdocGUI {
}
fn run(self, builder: &Builder<'_>) {
- let nodejs = builder.config.nodejs.as_ref().expect("nodejs isn't available");
- let npm = builder.config.npm.as_ref().expect("npm isn't available");
-
builder.ensure(compile::Std::new(self.compiler, self.target));
- // The goal here is to check if the necessary packages are installed, and if not, we
- // panic.
- match get_browser_ui_test_version(&npm) {
- Some(version) => {
- // We also check the version currently used in CI and emit a warning if it's not the
- // same one.
- compare_browser_ui_test_version(&version, &builder.build.src);
- }
- None => {
- eprintln!(
- "error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` \
- dependency is missing",
- );
- eprintln!(
- "If you want to install the `{0}` dependency, run `npm install {0}`",
- "browser-ui-test",
- );
- panic!("Cannot run rustdoc-gui tests");
- }
- }
+ let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
let out_dir = builder.test_out(self.target).join("rustdoc-gui");
-
- // We remove existing folder to be sure there won't be artifacts remaining.
builder.clear_if_dirty(&out_dir, &builder.rustdoc(self.compiler));
- let src_path = builder.build.src.join("tests/rustdoc-gui/src");
- // We generate docs for the libraries present in the rustdoc-gui's src folder.
- for entry in src_path.read_dir().expect("read_dir call failed") {
- if let Ok(entry) = entry {
- let path = entry.path();
+ if let Some(src) = builder.config.src.to_str() {
+ cmd.arg("--rust-src").arg(src);
+ }
- if !path.is_dir() {
- continue;
- }
+ if let Some(out_dir) = out_dir.to_str() {
+ cmd.arg("--out-dir").arg(out_dir);
+ }
- let mut cargo = Command::new(&builder.initial_cargo);
- cargo
- .arg("doc")
- .arg("--target-dir")
- .arg(&out_dir)
- .env("RUSTC_BOOTSTRAP", "1")
- .env("RUSTDOC", builder.rustdoc(self.compiler))
- .env("RUSTC", builder.rustc(self.compiler))
- .current_dir(path);
- // FIXME: implement a `// compile-flags` command or similar
- // instead of hard-coding this test
- if entry.file_name() == "link_to_definition" {
- cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
- } else if entry.file_name() == "scrape_examples" {
- cargo.arg("-Zrustdoc-scrape-examples");
- } else if entry.file_name() == "extend_css" {
- cargo.env("RUSTDOCFLAGS", &format!("--extend-css extra.css"));
- }
- builder.run(&mut cargo);
- }
+ if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
+ cmd.arg("--initial-cargo").arg(initial_cargo);
}
- // We now run GUI tests.
- let mut command = Command::new(&nodejs);
- command
- .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js"))
- .arg("--jobs")
- .arg(&builder.jobs().to_string())
- .arg("--doc-folder")
- .arg(out_dir.join("doc"))
- .arg("--tests-folder")
- .arg(builder.build.src.join("tests/rustdoc-gui"));
+ cmd.arg("--jobs").arg(builder.jobs().to_string());
+
+ cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
+ .env("RUSTC", builder.rustc(self.compiler));
+
for path in &builder.paths {
if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
if !p.ends_with(".goml") {
@@ -1127,14 +1017,25 @@ impl Step for RustdocGUI {
panic!("Cannot run rustdoc-gui tests");
}
if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
- command.arg("--file").arg(name);
+ cmd.arg("--goml-file").arg(name);
}
}
}
- for test_arg in builder.config.cmd.test_args() {
- command.arg(test_arg);
+
+ for test_arg in builder.config.test_args() {
+ cmd.arg("--test-arg").arg(test_arg);
}
- builder.run(&mut command);
+
+ if let Some(ref nodejs) = builder.config.nodejs {
+ cmd.arg("--nodejs").arg(nodejs);
+ }
+
+ if let Some(ref npm) = builder.config.npm {
+ cmd.arg("--npm").arg(npm);
+ }
+
+ let _time = util::timeit(&builder);
+ crate::render_tests::try_run_tests(builder, &mut cmd);
}
}
@@ -1192,7 +1093,24 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
builder.info("tidy check");
try_run(builder, &mut cmd);
- builder.ensure(ExpandYamlAnchors {});
+ builder.ensure(ExpandYamlAnchors);
+
+ builder.info("x.py completions check");
+ let [bash, fish, powershell] = ["x.py.sh", "x.py.fish", "x.py.ps1"]
+ .map(|filename| builder.src.join("src/etc/completions").join(filename));
+ if builder.config.cmd.bless() {
+ builder.ensure(crate::run::GenerateCompletions);
+ } else {
+ if crate::flags::get_completion(shells::Bash, &bash).is_some()
+ || crate::flags::get_completion(shells::Fish, &fish).is_some()
+ || crate::flags::get_completion(shells::PowerShell, &powershell).is_some()
+ {
+ eprintln!(
+ "x.py completions were changed; run `x.py run generate-completions` to update them"
+ );
+ crate::detail_exit(1);
+ }
+ }
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1204,40 +1122,6 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
}
}
-/// Runs tidy's own tests.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct TidySelfTest;
-
-impl Step for TidySelfTest {
- type Output = ();
- const DEFAULT: bool = true;
- const ONLY_HOSTS: bool = true;
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.alias("tidyselftest")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(TidySelfTest);
- }
-
- fn run(self, builder: &Builder<'_>) {
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
- let cargo = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
- bootstrap_host,
- "test",
- "src/tools/tidy",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-}
-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ExpandYamlAnchors;
@@ -1448,7 +1332,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
crate::detail_exit(1);
}
- let compiler = self.compiler;
+ let mut compiler = self.compiler;
let target = self.target;
let mode = self.mode;
let suite = self.suite;
@@ -1461,15 +1345,28 @@ note: if you're sure you want to do this, please open an issue as to why. In the
return;
}
- if suite == "debuginfo" {
- builder
- .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
- }
+ // Support stage 1 ui-fulldeps. This is somewhat complicated: ui-fulldeps tests for the most
+ // part test the *API* of the compiler, not how it compiles a given file. As a result, we
+ // can run them against the stage 1 sources as long as we build them with the stage 0
+ // bootstrap compiler.
+ // NOTE: Only stage 1 is special cased because we need the rustc_private artifacts to match the
+ // running compiler in stage 2 when plugins run.
+ let stage_id = if suite == "ui-fulldeps" && compiler.stage == 1 {
+ compiler = builder.compiler(compiler.stage - 1, target);
+ format!("stage{}-{}", compiler.stage + 1, target)
+ } else {
+ format!("stage{}-{}", compiler.stage, target)
+ };
if suite.ends_with("fulldeps") {
builder.ensure(compile::Rustc::new(compiler, target));
}
+ if suite == "debuginfo" {
+ builder
+ .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
+ }
+
builder.ensure(compile::Std::new(compiler, target));
// ensure that `libproc_macro` is available on the host.
builder.ensure(compile::Std::new(compiler, compiler.host));
@@ -1528,7 +1425,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
cmd.arg("--src-base").arg(builder.src.join("tests").join(suite));
cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
cmd.arg("--sysroot-base").arg(builder.sysroot(compiler));
- cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
+ cmd.arg("--stage-id").arg(stage_id);
cmd.arg("--suite").arg(suite);
cmd.arg("--mode").arg(mode);
cmd.arg("--target").arg(target.rustc_target_arg());
@@ -1637,7 +1534,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
// Get paths from cmd args
let paths = match &builder.config.cmd {
- Subcommand::Test { ref paths, .. } => &paths[..],
+ Subcommand::Test { .. } => &builder.config.paths[..],
_ => &[],
};
@@ -1647,8 +1544,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
.filter_map(|p| util::is_valid_test_suite_arg(p, suite_path, builder))
.collect();
- test_args.append(&mut builder.config.cmd.test_args());
- test_args.extend(builder.config.free_args.iter().map(|s| s.as_str()));
+ test_args.append(&mut builder.config.test_args());
// On Windows, replace forward slashes in test-args by backslashes
// so the correct filters are passed to libtest
@@ -1804,12 +1700,29 @@ note: if you're sure you want to do this, please open an issue as to why. In the
cmd.arg("--channel").arg(&builder.config.channel);
+ if !builder.config.omit_git_hash {
+ cmd.arg("--git-hash");
+ }
+
if let Some(commit) = builder.config.download_rustc_commit() {
cmd.env("FAKE_DOWNLOAD_RUSTC_PREFIX", format!("/rustc/{commit}"));
}
builder.ci_env.force_coloring_in_ci(&mut cmd);
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::Compiletest {
+ suite: suite.into(),
+ mode: mode.into(),
+ compare_mode: None,
+ target: self.target.triple.to_string(),
+ host: self.compiler.host.triple.to_string(),
+ stage: self.compiler.stage,
+ },
+ builder,
+ );
+
builder.info(&format!(
"Check compiletest suite={} mode={} ({} -> {})",
suite, mode, &compiler.host, target
@@ -1819,6 +1732,20 @@ note: if you're sure you want to do this, please open an issue as to why. In the
if let Some(compare_mode) = compare_mode {
cmd.arg("--compare-mode").arg(compare_mode);
+
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::Compiletest {
+ suite: suite.into(),
+ mode: mode.into(),
+ compare_mode: Some(compare_mode.into()),
+ target: self.target.triple.to_string(),
+ host: self.compiler.host.triple.to_string(),
+ stage: self.compiler.stage,
+ },
+ builder,
+ );
+
builder.info(&format!(
"Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
suite, mode, compare_mode, &compiler.host, target
@@ -1888,7 +1815,13 @@ impl BookTest {
rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
builder.add_rust_test_threads(&mut rustbook_cmd);
- builder.info(&format!("Testing rustbook {}", self.path.display()));
+ let _guard = builder.msg(
+ Kind::Test,
+ compiler.stage,
+ format_args!("rustbook {}", self.path.display()),
+ compiler.host,
+ compiler.host,
+ );
let _time = util::timeit(&builder);
let toolstate = if try_run(builder, &mut rustbook_cmd) {
ToolState::TestPass
@@ -2016,7 +1949,8 @@ impl Step for ErrorIndex {
let mut tool = tool::ErrorIndex::command(builder);
tool.arg("markdown").arg(&output);
- builder.info(&format!("Testing error-index stage{}", compiler.stage));
+ let _guard =
+ builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
let _time = util::timeit(&builder);
builder.run_quiet(&mut tool);
// The tests themselves need to link to std, so make sure it is
@@ -2043,7 +1977,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
cmd.arg(markdown);
cmd.env("RUSTC_BOOTSTRAP", "1");
- let test_args = builder.config.cmd.test_args().join(" ");
+ let test_args = builder.config.test_args().join(" ");
cmd.arg("--test-args").arg(test_args);
if builder.config.verbose_tests {
@@ -2088,7 +2022,6 @@ impl Step for RustcGuide {
pub struct CrateLibrustc {
compiler: Compiler,
target: TargetSelection,
- test_kind: TestKind,
crates: Vec<Interned<String>>,
}
@@ -2110,9 +2043,8 @@ impl Step for CrateLibrustc {
.iter()
.map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
.collect();
- let test_kind = builder.kind.into();
- builder.ensure(CrateLibrustc { compiler, target: run.target, test_kind, crates });
+ builder.ensure(CrateLibrustc { compiler, target: run.target, crates });
}
fn run(self, builder: &Builder<'_>) {
@@ -2120,18 +2052,117 @@ impl Step for CrateLibrustc {
compiler: self.compiler,
target: self.target,
mode: Mode::Rustc,
- test_kind: self.test_kind,
crates: self.crates,
});
}
}
+/// Given a `cargo test` subcommand, add the appropriate flags and run it.
+///
+/// Returns whether the test succeeded.
+fn run_cargo_test(
+ cargo: impl Into<Command>,
+ libtest_args: &[&str],
+ crates: &[Interned<String>],
+ primary_crate: &str,
+ compiler: Compiler,
+ target: TargetSelection,
+ builder: &Builder<'_>,
+) -> bool {
+ let mut cargo =
+ prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder);
+ let _time = util::timeit(&builder);
+
+ #[cfg(feature = "build-metrics")]
+ builder.metrics.begin_test_suite(
+ crate::metrics::TestSuiteMetadata::CargoPackage {
+ crates: crates.iter().map(|c| c.to_string()).collect(),
+ target: target.triple.to_string(),
+ host: compiler.host.triple.to_string(),
+ stage: compiler.stage,
+ },
+ builder,
+ );
+ add_flags_and_try_run_tests(builder, &mut cargo)
+}
+
+/// Given a `cargo test` subcommand, pass it the appropriate test flags given a `builder`.
+fn prepare_cargo_test(
+ cargo: impl Into<Command>,
+ libtest_args: &[&str],
+ crates: &[Interned<String>],
+ primary_crate: &str,
+ compiler: Compiler,
+ target: TargetSelection,
+ builder: &Builder<'_>,
+) -> Command {
+ let mut cargo = cargo.into();
+
+ // Pass in some standard flags then iterate over the graph we've discovered
+ // in `cargo metadata` with the maps above and figure out what `-p`
+ // arguments need to get passed.
+ if builder.kind == Kind::Test && !builder.fail_fast {
+ cargo.arg("--no-fail-fast");
+ }
+ match builder.doc_tests {
+ DocTests::Only => {
+ cargo.arg("--doc");
+ }
+ DocTests::No => {
+ let krate = &builder
+ .crates
+ .get(&INTERNER.intern_str(primary_crate))
+ .unwrap_or_else(|| panic!("missing crate {primary_crate}"));
+ if krate.has_lib {
+ cargo.arg("--lib");
+ }
+ cargo.args(&["--bins", "--examples", "--tests", "--benches"]);
+ }
+ DocTests::Yes => {}
+ }
+
+ for &krate in crates {
+ cargo.arg("-p").arg(krate);
+ }
+
+ cargo.arg("--").args(&builder.config.test_args()).args(libtest_args);
+ if !builder.config.verbose_tests {
+ cargo.arg("--quiet");
+ }
+
+ // The tests are going to run with the *target* libraries, so we need to
+ // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
+ //
+ // Note that to run the compiler we need to run with the *host* libraries,
+ // but our wrapper scripts arrange for that to be the case anyway.
+ let mut dylib_path = dylib_path();
+ dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
+ cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
+
+ if target.contains("emscripten") {
+ cargo.env(
+ format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
+ builder.config.nodejs.as_ref().expect("nodejs not configured"),
+ );
+ } else if target.starts_with("wasm32") {
+ let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
+ let runner = format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
+ cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner);
+ } else if builder.remote_tested(target) {
+ cargo.env(
+ format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
+ format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
+ );
+ }
+
+ cargo
+}
+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Crate {
pub compiler: Compiler,
pub target: TargetSelection,
pub mode: Mode,
- pub test_kind: TestKind,
pub crates: Vec<Interned<String>>,
}
@@ -2140,21 +2171,20 @@ impl Step for Crate {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.crate_or_deps("test")
+ run.crate_or_deps("sysroot")
}
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
let host = run.build_triple();
let compiler = builder.compiler_for(builder.top_stage, host, host);
- let test_kind = builder.kind.into();
let crates = run
.paths
.iter()
.map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
.collect();
- builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, test_kind, crates });
+ builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
}
/// Runs all unit tests plus documentation tests for a given crate defined
@@ -2169,7 +2199,6 @@ impl Step for Crate {
let compiler = self.compiler;
let target = self.target;
let mode = self.mode;
- let test_kind = self.test_kind;
builder.ensure(compile::Std::new(compiler, target));
builder.ensure(RemoteCopyLibs { compiler, target });
@@ -2181,7 +2210,7 @@ impl Step for Crate {
let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
let mut cargo =
- builder.cargo(compiler, mode, SourceType::InTree, target, test_kind.subcommand());
+ builder.cargo(compiler, mode, SourceType::InTree, target, builder.kind.as_str());
match mode {
Mode::Std => {
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
@@ -2192,70 +2221,14 @@ impl Step for Crate {
_ => panic!("can only test libraries"),
};
- // Build up the base `cargo test` command.
- //
- // Pass in some standard flags then iterate over the graph we've discovered
- // in `cargo metadata` with the maps above and figure out what `-p`
- // arguments need to get passed.
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cargo.arg("--doc");
- }
- DocTests::No => {
- cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- for krate in &self.crates {
- cargo.arg("-p").arg(krate);
- }
-
- // The tests are going to run with the *target* libraries, so we need to
- // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
- //
- // Note that to run the compiler we need to run with the *host* libraries,
- // but our wrapper scripts arrange for that to be the case anyway.
- let mut dylib_path = dylib_path();
- dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
- cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
-
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
-
- cargo.arg("-Z").arg("unstable-options");
- cargo.arg("--format").arg("json");
-
- if target.contains("emscripten") {
- cargo.env(
- format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
- builder.config.nodejs.as_ref().expect("nodejs not configured"),
- );
- } else if target.starts_with("wasm32") {
- let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
- let runner =
- format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
- cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner);
- } else if builder.remote_tested(target) {
- cargo.env(
- format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
- format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
- );
- }
-
- builder.info(&format!(
- "{}{} stage{} ({} -> {})",
- test_kind,
- crate_description(&self.crates),
+ let _guard = builder.msg(
+ builder.kind,
compiler.stage,
- &compiler.host,
- target
- ));
- let _time = util::timeit(&builder);
- crate::render_tests::try_run_tests(builder, &mut cargo.into());
+ crate_description(&self.crates),
+ compiler.host,
+ target,
+ );
+ run_cargo_test(cargo, &[], &self.crates, &self.crates[0], compiler, target, builder);
}
}
@@ -2263,7 +2236,6 @@ impl Step for Crate {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CrateRustdoc {
host: TargetSelection,
- test_kind: TestKind,
}
impl Step for CrateRustdoc {
@@ -2278,13 +2250,10 @@ impl Step for CrateRustdoc {
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
- let test_kind = builder.kind.into();
-
- builder.ensure(CrateRustdoc { host: run.target, test_kind });
+ builder.ensure(CrateRustdoc { host: run.target });
}
fn run(self, builder: &Builder<'_>) {
- let test_kind = self.test_kind;
let target = self.host;
let compiler = if builder.download_rustc() {
@@ -2303,29 +2272,11 @@ impl Step for CrateRustdoc {
compiler,
Mode::ToolRustc,
target,
- test_kind.subcommand(),
+ builder.kind.as_str(),
"src/tools/rustdoc",
SourceType::InTree,
&[],
);
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cargo.arg("--doc");
- }
- DocTests::No => {
- cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- cargo.arg("-p").arg("rustdoc:0.0.0");
-
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
-
if self.host.contains("musl") {
cargo.arg("'-Ctarget-feature=-crt-static'");
}
@@ -2365,24 +2316,22 @@ impl Step for CrateRustdoc {
dylib_path.insert(0, PathBuf::from(&*libdir));
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
- if !builder.config.verbose_tests {
- cargo.arg("--quiet");
- }
-
- builder.info(&format!(
- "{} rustdoc stage{} ({} -> {})",
- test_kind, compiler.stage, &compiler.host, target
- ));
- let _time = util::timeit(&builder);
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ let _guard = builder.msg(builder.kind, compiler.stage, "rustdoc", compiler.host, target);
+ run_cargo_test(
+ cargo,
+ &[],
+ &[INTERNER.intern_str("rustdoc:0.0.0")],
+ "rustdoc",
+ compiler,
+ target,
+ builder,
+ );
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CrateRustdocJsonTypes {
host: TargetSelection,
- test_kind: TestKind,
}
impl Step for CrateRustdocJsonTypes {
@@ -2397,13 +2346,10 @@ impl Step for CrateRustdocJsonTypes {
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
- let test_kind = builder.kind.into();
-
- builder.ensure(CrateRustdocJsonTypes { host: run.target, test_kind });
+ builder.ensure(CrateRustdocJsonTypes { host: run.target });
}
fn run(self, builder: &Builder<'_>) {
- let test_kind = self.test_kind;
let target = self.host;
// Use the previous stage compiler to reuse the artifacts that are
@@ -2413,36 +2359,35 @@ impl Step for CrateRustdocJsonTypes {
let compiler = builder.compiler_for(builder.top_stage, target, target);
builder.ensure(compile::Rustc::new(compiler, target));
- let mut cargo = tool::prepare_tool_cargo(
+ let cargo = tool::prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
target,
- test_kind.subcommand(),
+ builder.kind.as_str(),
"src/rustdoc-json-types",
SourceType::InTree,
&[],
);
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
- cargo.arg("-p").arg("rustdoc-json-types");
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
-
- if self.host.contains("musl") {
- cargo.arg("'-Ctarget-feature=-crt-static'");
- }
-
- builder.info(&format!(
- "{} rustdoc-json-types stage{} ({} -> {})",
- test_kind, compiler.stage, &compiler.host, target
- ));
- let _time = util::timeit(&builder);
+ // FIXME: this looks very wrong, libtest doesn't accept `-C` arguments and the quotes are fishy.
+ let libtest_args = if self.host.contains("musl") {
+ ["'-Ctarget-feature=-crt-static'"].as_slice()
+ } else {
+ &[]
+ };
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ let _guard =
+ builder.msg(builder.kind, compiler.stage, "rustdoc-json-types", compiler.host, target);
+ run_cargo_test(
+ cargo,
+ libtest_args,
+ &[INTERNER.intern_str("rustdoc-json-types")],
+ "rustdoc-json-types",
+ compiler,
+ target,
+ builder,
+ );
}
}
@@ -2580,13 +2525,15 @@ impl Step for Bootstrap {
check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/"));
try_run(builder, &mut check_bootstrap);
+ let host = builder.config.build;
+ let compiler = builder.compiler(0, host);
let mut cmd = Command::new(&builder.initial_cargo);
cmd.arg("test")
.current_dir(builder.src.join("src/bootstrap"))
.env("RUSTFLAGS", "-Cdebuginfo=2")
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
.env("RUSTC_BOOTSTRAP", "1")
- .env("RUSTDOC", builder.rustdoc(builder.compiler(0, builder.build.build)))
+ .env("RUSTDOC", builder.rustdoc(compiler))
.env("RUSTC", &builder.initial_rustc);
if let Some(flags) = option_env!("RUSTFLAGS") {
// Use the same rustc flags for testing as for "normal" compilation,
@@ -2594,24 +2541,9 @@ impl Step for Bootstrap {
// https://github.com/rust-lang/rust/issues/49215
cmd.env("RUSTFLAGS", flags);
}
- if !builder.fail_fast {
- cmd.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cmd.arg("--doc");
- }
- DocTests::No => {
- cmd.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- cmd.arg("--").args(&builder.config.cmd.test_args());
// rustbuild tests are racy on directory creation so just run them one at a time.
// Since there's not many this shouldn't be a problem.
- cmd.arg("--test-threads=1");
- add_flags_and_try_run_tests(builder, &mut cmd);
+ run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", compiler, host, builder);
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -2668,43 +2600,6 @@ impl Step for TierCheck {
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct ReplacePlaceholderTest;
-
-impl Step for ReplacePlaceholderTest {
- type Output = ();
- const ONLY_HOSTS: bool = true;
- const DEFAULT: bool = true;
-
- /// Ensure the version placeholder replacement tool builds
- fn run(self, builder: &Builder<'_>) {
- builder.info("build check for version replacement placeholder");
-
- // Test the version placeholder replacement tool itself.
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
- let cargo = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
- bootstrap_host,
- "test",
- "src/tools/replace-version-placeholder",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/tools/replace-version-placeholder")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(Self);
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct LintDocs {
pub compiler: Compiler,
pub target: TargetSelection,
@@ -2761,7 +2656,7 @@ impl Step for RustInstaller {
SourceType::InTree,
&[],
);
- try_run(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "installer", compiler, bootstrap_host, builder);
// We currently don't support running the test.sh script outside linux(?) environments.
// Eventually this should likely migrate to #[test]s in rust-installer proper rather than a
@@ -2828,7 +2723,7 @@ impl Step for TestHelpers {
return;
}
- builder.info("Building test helpers");
+ let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
t!(fs::create_dir_all(&dst));
let mut cfg = cc::Build::new();
// FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index d1fd2e8c4..b3791efaf 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -1,4 +1,3 @@
-use std::collections::HashSet;
use std::env;
use std::fs;
use std::path::PathBuf;
@@ -12,6 +11,7 @@ use crate::toolstate::ToolState;
use crate::util::{add_dylib_path, exe, t};
use crate::Compiler;
use crate::Mode;
+use crate::{gha, Kind};
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum SourceType {
@@ -33,41 +33,27 @@ struct ToolBuild {
allow_features: &'static str,
}
-fn tooling_output(
- mode: Mode,
- tool: &str,
- build_stage: u32,
- host: &TargetSelection,
- target: &TargetSelection,
-) -> String {
- match mode {
- // depends on compiler stage, different to host compiler
- Mode::ToolRustc => {
- if host == target {
- format!("Building tool {} (stage{} -> stage{})", tool, build_stage, build_stage + 1)
- } else {
- format!(
- "Building tool {} (stage{}:{} -> stage{}:{})",
- tool,
- build_stage,
- host,
- build_stage + 1,
- target
- )
- }
+impl Builder<'_> {
+ fn msg_tool(
+ &self,
+ mode: Mode,
+ tool: &str,
+ build_stage: u32,
+ host: &TargetSelection,
+ target: &TargetSelection,
+ ) -> Option<gha::Group> {
+ match mode {
+ // depends on compiler stage, different to host compiler
+ Mode::ToolRustc => self.msg_sysroot_tool(
+ Kind::Build,
+ build_stage,
+ format_args!("tool {tool}"),
+ *host,
+ *target,
+ ),
+ // doesn't depend on compiler, same as host compiler
+ _ => self.msg(Kind::Build, build_stage, format_args!("tool {tool}"), *host, *target),
}
- // doesn't depend on compiler, same as host compiler
- Mode::ToolStd => {
- if host == target {
- format!("Building tool {} (stage{})", tool, build_stage)
- } else {
- format!(
- "Building tool {} (stage{}:{} -> stage{}:{})",
- tool, build_stage, host, build_stage, target
- )
- }
- }
- _ => format!("Building tool {} (stage{})", tool, build_stage),
}
}
@@ -112,143 +98,16 @@ impl Step for ToolBuild {
if !self.allow_features.is_empty() {
cargo.allow_features(self.allow_features);
}
- let msg = tooling_output(
+ let _guard = builder.msg_tool(
self.mode,
self.tool,
self.compiler.stage,
&self.compiler.host,
&self.target,
);
- builder.info(&msg);
- let mut duplicates = Vec::new();
- let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| {
- // Only care about big things like the RLS/Cargo for now
- match tool {
- "rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {}
-
- _ => return,
- }
- let (id, features, filenames) = match msg {
- compile::CargoMessage::CompilerArtifact {
- package_id,
- features,
- filenames,
- target: _,
- } => (package_id, features, filenames),
- _ => return,
- };
- let features = features.iter().map(|s| s.to_string()).collect::<Vec<_>>();
-
- for path in filenames {
- let val = (tool, PathBuf::from(&*path), features.clone());
- // we're only interested in deduplicating rlibs for now
- if val.1.extension().and_then(|s| s.to_str()) != Some("rlib") {
- continue;
- }
-
- // Don't worry about compiles that turn out to be host
- // dependencies or build scripts. To skip these we look for
- // anything that goes in `.../release/deps` but *doesn't* go in
- // `$target/release/deps`. This ensure that outputs in
- // `$target/release` are still considered candidates for
- // deduplication.
- if let Some(parent) = val.1.parent() {
- if parent.ends_with("release/deps") {
- let maybe_target = parent
- .parent()
- .and_then(|p| p.parent())
- .and_then(|p| p.file_name())
- .and_then(|p| p.to_str())
- .unwrap();
- if maybe_target != &*target.triple {
- continue;
- }
- }
- }
-
- // Record that we've built an artifact for `id`, and if one was
- // already listed then we need to see if we reused the same
- // artifact or produced a duplicate.
- let mut artifacts = builder.tool_artifacts.borrow_mut();
- let prev_artifacts = artifacts.entry(target).or_default();
- let prev = match prev_artifacts.get(&*id) {
- Some(prev) => prev,
- None => {
- prev_artifacts.insert(id.to_string(), val);
- continue;
- }
- };
- if prev.1 == val.1 {
- return; // same path, same artifact
- }
- // If the paths are different and one of them *isn't* inside of
- // `release/deps`, then it means it's probably in
- // `$target/release`, or it's some final artifact like
- // `libcargo.rlib`. In these situations Cargo probably just
- // copied it up from `$target/release/deps/libcargo-xxxx.rlib`,
- // so if the features are equal we can just skip it.
- let prev_no_hash = prev.1.parent().unwrap().ends_with("release/deps");
- let val_no_hash = val.1.parent().unwrap().ends_with("release/deps");
- if prev.2 == val.2 || !prev_no_hash || !val_no_hash {
- return;
- }
-
- // ... and otherwise this looks like we duplicated some sort of
- // compilation, so record it to generate an error later.
- duplicates.push((id.to_string(), val, prev.clone()));
- }
- });
-
- if is_expected && !duplicates.is_empty() {
- eprintln!(
- "duplicate artifacts found when compiling a tool, this \
- typically means that something was recompiled because \
- a transitive dependency has different features activated \
- than in a previous build:\n"
- );
- let (same, different): (Vec<_>, Vec<_>) =
- duplicates.into_iter().partition(|(_, cur, prev)| cur.2 == prev.2);
- if !same.is_empty() {
- eprintln!(
- "the following dependencies are duplicated although they \
- have the same features enabled:"
- );
- for (id, cur, prev) in same {
- eprintln!(" {}", id);
- // same features
- eprintln!(" `{}` ({:?})\n `{}` ({:?})", cur.0, cur.1, prev.0, prev.1);
- }
- }
- if !different.is_empty() {
- eprintln!("the following dependencies have different features:");
- for (id, cur, prev) in different {
- eprintln!(" {}", id);
- let cur_features: HashSet<_> = cur.2.into_iter().collect();
- let prev_features: HashSet<_> = prev.2.into_iter().collect();
- eprintln!(
- " `{}` additionally enabled features {:?} at {:?}",
- cur.0,
- &cur_features - &prev_features,
- cur.1
- );
- eprintln!(
- " `{}` additionally enabled features {:?} at {:?}",
- prev.0,
- &prev_features - &cur_features,
- prev.1
- );
- }
- }
- eprintln!();
- eprintln!(
- "to fix this you will probably want to edit the local \
- src/tools/rustc-workspace-hack/Cargo.toml crate, as \
- that will update the dependency graph to ensure that \
- these crates all share the same feature set"
- );
- panic!("tools should not compile multiple copies of the same crate");
- }
+ let mut cargo = Command::from(cargo);
+ let is_expected = builder.try_run(&mut cargo);
builder.save_toolstate(
tool,
@@ -282,7 +141,7 @@ pub fn prepare_tool_cargo(
mode: Mode,
target: TargetSelection,
command: &'static str,
- path: &'static str,
+ path: &str,
source_type: SourceType,
extra_features: &[String],
) -> CargoCommand {
@@ -299,7 +158,9 @@ pub fn prepare_tool_cargo(
|| path.ends_with("rustfmt")
{
cargo.env("LIBZ_SYS_STATIC", "1");
- features.push("rustc-workspace-hack/all-static".to_string());
+ }
+ if path.ends_with("cargo") {
+ features.push("all-static".to_string());
}
}
@@ -319,6 +180,12 @@ pub fn prepare_tool_cargo(
cargo.env("CFG_VERSION", builder.rust_version());
cargo.env("CFG_RELEASE_NUM", &builder.version);
cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
+ if let Some(ref ver_date) = builder.rust_info().commit_date() {
+ cargo.env("CFG_VER_DATE", ver_date);
+ }
+ if let Some(ref ver_hash) = builder.rust_info().sha() {
+ cargo.env("CFG_VER_HASH", ver_hash);
+ }
let info = GitInfo::new(builder.config.omit_git_hash, &dir);
if let Some(sha) = info.sha() {
@@ -434,6 +301,8 @@ bootstrap_tool!(
CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
SuggestTests, "src/tools/suggest-tests", "suggest-tests";
+ GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
+ RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
@@ -611,14 +480,13 @@ impl Step for Rustdoc {
cargo.rustflag("--cfg=parallel_compiler");
}
- let msg = tooling_output(
+ let _guard = builder.msg_tool(
Mode::ToolRustc,
"rustdoc",
build_compiler.stage,
&self.compiler.host,
&target,
);
- builder.info(&msg);
builder.run(&mut cargo.into());
// Cargo adds a number of paths to the dylib search path on windows, which results in
@@ -707,18 +575,18 @@ impl Step for Cargo {
if self.target.contains("windows") {
build_cred(
"cargo-credential-wincred",
- "src/tools/cargo/crates/credential/cargo-credential-wincred",
+ "src/tools/cargo/credential/cargo-credential-wincred",
);
}
if self.target.contains("apple-darwin") {
build_cred(
"cargo-credential-macos-keychain",
- "src/tools/cargo/crates/credential/cargo-credential-macos-keychain",
+ "src/tools/cargo/credential/cargo-credential-macos-keychain",
);
}
build_cred(
"cargo-credential-1password",
- "src/tools/cargo/crates/credential/cargo-credential-1password",
+ "src/tools/cargo/credential/cargo-credential-1password",
);
cargo_bin_path
}
@@ -867,6 +735,7 @@ macro_rules! tool_extended {
stable = $stable:expr
$(,tool_std = $tool_std:literal)?
$(,allow_features = $allow_features:expr)?
+ $(,add_bins_to_sysroot = $add_bins_to_sysroot:expr)?
;)+) => {
$(
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -909,7 +778,7 @@ macro_rules! tool_extended {
#[allow(unused_mut)]
fn run(mut $sel, $builder: &Builder<'_>) -> Option<PathBuf> {
- $builder.ensure(ToolBuild {
+ let tool = $builder.ensure(ToolBuild {
compiler: $sel.compiler,
target: $sel.target,
tool: $tool_name,
@@ -919,7 +788,27 @@ macro_rules! tool_extended {
is_optional_tool: true,
source_type: SourceType::InTree,
allow_features: concat!($($allow_features)*),
- })
+ })?;
+
+ if (false $(|| !$add_bins_to_sysroot.is_empty())?) && $sel.compiler.stage > 0 {
+ let bindir = $builder.sysroot($sel.compiler).join("bin");
+ t!(fs::create_dir_all(&bindir));
+
+ #[allow(unused_variables)]
+ let tools_out = $builder
+ .cargo_out($sel.compiler, Mode::ToolRustc, $sel.target);
+
+ $(for add_bin in $add_bins_to_sysroot {
+ let bin_source = tools_out.join(exe(add_bin, $sel.target));
+ let bin_destination = bindir.join(exe(add_bin, $sel.compiler.host));
+ $builder.copy(&bin_source, &bin_destination);
+ })?
+
+ let tool = bindir.join(exe($tool_name, $sel.compiler.host));
+ Some(tool)
+ } else {
+ Some(tool)
+ }
}
}
)+
@@ -933,15 +822,15 @@ macro_rules! tool_extended {
tool_extended!((self, builder),
Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true;
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true;
- Clippy, "src/tools/clippy", "clippy-driver", stable=true;
- Miri, "src/tools/miri", "miri", stable=false;
- CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true;
+ Clippy, "src/tools/clippy", "clippy-driver", stable=true, add_bins_to_sysroot = ["clippy-driver", "cargo-clippy"];
+ Miri, "src/tools/miri", "miri", stable=false, add_bins_to_sysroot = ["miri"];
+ CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true, add_bins_to_sysroot = ["cargo-miri"];
// FIXME: tool_std is not quite right, we shouldn't allow nightly features.
// But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0,
// and this is close enough for now.
Rls, "src/tools/rls", "rls", stable=true, tool_std=true;
RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, tool_std=true;
- Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true;
+ Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"];
);
impl<'a> Builder<'a> {
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 2e1adbf63..9bfdc77e6 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -488,7 +488,7 @@ fn absolute_windows(path: &std::path::Path) -> std::io::Result<std::path::PathBu
}
}
-/// Adapted from https://github.com/llvm/llvm-project/blob/782e91224601e461c019e0a4573bbccc6094fbcd/llvm/cmake/modules/HandleLLVMOptions.cmake#L1058-L1079
+/// Adapted from <https://github.com/llvm/llvm-project/blob/782e91224601e461c019e0a4573bbccc6094fbcd/llvm/cmake/modules/HandleLLVMOptions.cmake#L1058-L1079>
///
/// When `clang-cl` is used with instrumentation, we need to add clang's runtime library resource
/// directory to the linker flags, otherwise there will be linker errors about the profiler runtime
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index ea236bee5..e799d7c96 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -83,12 +83,12 @@ To run the image,
A number of these images take quite a long time to compile as they're building
whole gcc toolchains to do cross builds with. Much of this is relatively
self-explanatory but some images use [crosstool-ng] which isn't quite as self
-explanatory. Below is a description of where these `*.config` files come form,
+explanatory. Below is a description of where these `*.defconfig` files come form,
how to generate them, and how the existing ones were generated.
[crosstool-ng]: https://github.com/crosstool-ng/crosstool-ng
-### Generating a `.config` file
+### Generating a `.defconfig` file
**NOTE:** Existing Dockerfiles can also be a good guide for the process and order
of script execution.
@@ -100,14 +100,14 @@ next two steps.
these steps are outside the container:
```
-# Note: We use ubuntu:16.04 because that's the "base" of linux-cross Docker
+# Note: We use ubuntu:22.04 because that's the "base" of linux-cross Docker
# image, or simply run ./src/ci/docker/run.sh once, which will download the correct
# one and you can check it out with `docker images`
-$ docker run -it ubuntu:16.04 bash
+$ docker run -it ubuntu:22.04 bash
# in another terminal:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-cfbec05ed730 ubuntu:16.04 "bash" 16 seconds ago Up 15 seconds drunk_murdock
+cfbec05ed730 ubuntu:22.04 "bash" 16 seconds ago Up 15 seconds drunk_murdock
$ docker cp src/ci/docker/scripts drunk_murdock:/tmp/
```
@@ -127,7 +127,7 @@ $ bash ./crosstool-ng.sh
present. Otherwise one can use the TUI to load any config-file.
```
-$ docker cp arm-linux-gnueabi.config drunk_murdock:/tmp/.config
+$ docker cp arm-linux-gnueabi.defconfig drunk_murdock:/tmp/.config
```
- Now, inside the container run the following command to configure the
@@ -136,49 +136,54 @@ $ docker cp arm-linux-gnueabi.config drunk_murdock:/tmp/.config
```
$ cd /tmp/
+$ ct-ng olddefconfig
$ ct-ng menuconfig
+$ ct-ng savedefconfig
```
-- Finally, we retrieve the `.config` file from the container and give it a
+- Finally, we retrieve the `defconfig` file from the container and give it a
meaningful name. This is done outside the container.
```
-$ docker cp drunk_murdock:/tmp/.config arm-linux-gnueabi.config
+$ docker cp drunk_murdock:/tmp/defconfig arm-linux-gnueabi.defconfig
```
- Now you can shutdown the container or repeat the two last steps to generate a
- new `.config` file.
+ new `.defconfig` file.
### Toolchain configuration
Changes on top of the default toolchain configuration used to generate the
-`.config` files in this directory. The changes are formatted as follows:
+`.defconfig` files in this directory. The changes are formatted as follows:
```
$category > $option = $value -- $comment
```
-### `arm-linux-gnueabi.config`
+### `arm-linux-gnueabi.defconfig`
For targets: `arm-unknown-linux-gnueabi`
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
-- Path and misc options > Patches origin = Bundled only
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
- Target options > Target Architecture = arm
- Target options > Architecture level = armv6 -- (+)
- Target options > Floating point = software (no FPU) -- (\*)
- Operating System > Target OS = linux
- Operating System > Linux kernel version = 3.2.101
+- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.17.0
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
-### `arm-linux-gnueabihf.config`
+### `arm-linux-gnueabihf.defconfig`
For targets: `arm-unknown-linux-gnueabihf`
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
-- Path and misc options > Patches origin = Bundled only
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
- Target options > Target Architecture = arm
- Target options > Architecture level = armv6 -- (+)
- Target options > Use specific FPU = vfp -- (+)
@@ -186,16 +191,18 @@ For targets: `arm-unknown-linux-gnueabihf`
- Target options > Default instruction set mode = arm -- (+)
- Operating System > Target OS = linux
- Operating System > Linux kernel version = 3.2.101
+- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.17.0
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
-### `armv7-linux-gnueabihf.config`
+### `armv7-linux-gnueabihf.defconfig`
For targets: `armv7-unknown-linux-gnueabihf`
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
-- Path and misc options > Patches origin = Bundled only
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
- Target options > Target Architecture = arm
- Target options > Suffix to the arch-part = v7
- Target options > Architecture level = armv7-a -- (+)
@@ -204,17 +211,18 @@ For targets: `armv7-unknown-linux-gnueabihf`
- Target options > Default instruction set mode = thumb -- (\*)
- Operating System > Target OS = linux
- Operating System > Linux kernel version = 3.2.101
+- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.17.0
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
(\*) These options have been selected to match the configuration of the arm
toolchains shipped with Ubuntu 15.10
(+) These options have been selected to match the gcc flags we use to compile C
- libraries like jemalloc. See the mk/cfg/arm(v7)-uknown-linux-gnueabi{,hf}.mk
+ libraries like jemalloc. See the mk/cfg/arm(v7)-unknown-linux-gnueabi{,hf}.mk
file in Rust's source code.
-### `aarch64-linux-gnu.config`
+### `aarch64-linux-gnu.defconfig`
For targets: `aarch64-unknown-linux-gnu`
@@ -225,17 +233,16 @@ For targets: `aarch64-unknown-linux-gnu`
- Target options > Bitness = 64-bit
- Operating System > Target OS = linux
- Operating System > Linux kernel version = 4.1.49
-- Binary utilities > Version of binutils = 2.32
+- Binary utilities > Version of binutils = 2.29.1
- C-library > glibc version = 2.17 -- aarch64 support was introduced in this version
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
-### `i586-linux-gnu.config`
+### `i586-linux-gnu.defconfig`
For targets: `i586-unknown-linux-gnu`
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
-- Path and misc options > Patches origin = Bundled only
- Target options > Target Architecture = x86
- Target options > Architecture level = i586
- Target options > Target CFLAGS = -Wa,-mrelax-relocations=no
@@ -244,13 +251,29 @@ For targets: `i586-unknown-linux-gnu`
- Binary utilities > Version of binutils = 2.32
- Binary utilities > binutils extra config = --enable-compressed-debug-sections=none -- (\*)
- C-library > glibc version = 2.17.0
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE
(\*) Compressed debug is enabled by default for gas (assembly) on Linux/x86 targets,
but that makes our `compiler_builtins` incompatible with binutils < 2.32.
-### `mips-linux-gnu.config`
+### `loongarch64-linux-gnu.defconfig`
+
+For targets: `loongarch64-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Target options > Target Architecture = loongarch
+- Target options > Bitness = 64-bit
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 5.19.16
+- Binary utilities > Version of binutils = 2.40
+- C-library > glibc version = 2.36
+- C compiler > gcc version = 12.2.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
+### `mips-linux-gnu.defconfig`
For targets: `mips-unknown-linux-gnu`
@@ -265,14 +288,14 @@ For targets: `mips-unknown-linux-gnu`
- Target options > Bitness = 32-bit
- Target options > Architecture level = mips32r2
- Operating System > Target OS = linux
-- Operating System > Linux kernel version = 4.4.174
+- Operating System > Linux kernel version = 4.4.302
- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.23
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > gcc extra config = --with-fp-32=xx --with-odd-spreg-32=no
- C compiler > C++ = ENABLE -- to cross compile LLVM
-### `mipsel-linux-gnu.config`
+### `mipsel-linux-gnu.defconfig`
For targets: `mipsel-unknown-linux-gnu`
@@ -287,14 +310,14 @@ For targets: `mipsel-unknown-linux-gnu`
- Target options > Bitness = 32-bit
- Target options > Architecture level = mips32r2
- Operating System > Target OS = linux
-- Operating System > Linux kernel version = 4.4.174
+- Operating System > Linux kernel version = 4.4.302
- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.23
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > gcc extra config = --with-fp-32=xx --with-odd-spreg-32=no
- C compiler > C++ = ENABLE -- to cross compile LLVM
-### `mips64-linux-gnu.config`
+### `mips64-linux-gnu.defconfig`
For targets: `mips64-unknown-linux-gnuabi64`
@@ -309,13 +332,13 @@ For targets: `mips64-unknown-linux-gnuabi64`
- Target options > Bitness = 64-bit
- Target options > Architecture level = mips64r2
- Operating System > Target OS = linux
-- Operating System > Linux kernel version = 4.4.174
+- Operating System > Linux kernel version = 4.4.302
- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.23
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
-### `mips64el-linux-gnu.config`
+### `mips64el-linux-gnu.defconfig`
For targets: `mips64el-unknown-linux-gnuabi64`
@@ -330,13 +353,13 @@ For targets: `mips64el-unknown-linux-gnuabi64`
- Target options > Bitness = 64-bit
- Target options > Architecture level = mips64r2
- Operating System > Target OS = linux
-- Operating System > Linux kernel version = 4.4.174
+- Operating System > Linux kernel version = 4.4.302
- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.23
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
-### `powerpc-linux-gnu.config`
+### `powerpc-linux-gnu.defconfig`
For targets: `powerpc-unknown-linux-gnu`
@@ -349,10 +372,10 @@ For targets: `powerpc-unknown-linux-gnu`
- Operating System > Linux kernel version = 3.2.101
- Binary utilities > Version of binutils = 2.30
- C-library > glibc version = 2.17 -- ~RHEL7 glibc
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
-### `powerpc64-linux-gnu.config`
+### `powerpc64-linux-gnu.defconfig`
For targets: `powerpc64-unknown-linux-gnu`
@@ -367,12 +390,28 @@ For targets: `powerpc64-unknown-linux-gnu`
- Operating System > Linux kernel version = 3.2.101
- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.17 -- ~RHEL7 glibc
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
(+) These CPU options match the configuration of the toolchains in RHEL6.
-### `s390x-linux-gnu.config`
+### `riscv64-unknown-linux-gnu.defconfig`
+
+For targets: `riscv64-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Target options > Target Architecture = riscv
+- Target options > Bitness = 64-bit
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.20.17
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.29
+- C compiler > gcc version = 8.5.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
+### `s390x-linux-gnu.defconfig`
For targets: `s390x-unknown-linux-gnu`
@@ -385,6 +424,6 @@ For targets: `s390x-unknown-linux-gnu`
- Operating System > Linux kernel version = 3.2.101
- Binary utilities > Version of binutils = 2.32
- C-library > glibc version = 2.17 -- ~RHEL7 glibc
-- C compiler > gcc version = 8.3.0
+- C compiler > gcc version = 8.5.0
- C compiler > gcc extra config = --with-arch=z10 -- LLVM's minimum support
- C compiler > C++ = ENABLE -- to cross compile LLVM
diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch
index 08d0c5b2c..4437a870b 100644
--- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch
+++ b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Remove stime() function calls
stime() has been deprecated in glibc 2.31 and replaced with
clock_settime(). Let's replace the stime() function calls with
-clock_settime() in preperation.
+clock_settime() in preparation.
function old new delta
rdate_main 197 224 +27
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile
index 23fa23f0f..18972387e 100644
--- a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile
@@ -1,20 +1,18 @@
-FROM ubuntu:20.04
+FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
WORKDIR /tmp
-COPY host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config host-x86_64/dist-aarch64-linux/build-toolchains.sh /tmp/
-RUN ./build-toolchains.sh
-
-USER root
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config b/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config
deleted file mode 100644
index 4561e2a1e..000000000
--- a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.config
+++ /dev/null
@@ -1,754 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_BUNDLED_LOCAL is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-CT_ARCH_ARM=y
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="arm"
-CT_ARCH_CHOICE_KSYM="ARM"
-# CT_ARCH_ALPHA_EV4 is not set
-# CT_ARCH_ALPHA_EV45 is not set
-# CT_ARCH_ALPHA_EV5 is not set
-# CT_ARCH_ALPHA_EV56 is not set
-# CT_ARCH_ALPHA_EV6 is not set
-# CT_ARCH_ALPHA_EV67 is not set
-CT_ARCH_CPU=""
-CT_ARCH_TUNE=""
-CT_ARCH_ARM_SHOW=y
-
-#
-# Options for arm
-#
-CT_ARCH_ARM_PKG_KSYM=""
-# CT_ARCH_ARM_MODE_ARM is not set
-# CT_ARCH_ARM_MODE_THUMB is not set
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_SUPPORTS_BOTH_MMU=y
-CT_ARCH_DEFAULT_HAS_MMU=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_FLAT_FORMAT=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_LE=y
-# CT_ARCH_BE is not set
-CT_ARCH_LE=y
-CT_ARCH_ENDIAN="little"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=64
-# CT_ARCH_32 is not set
-CT_ARCH_64=y
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_CPU=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_EXCLUSIVE_WITH_CPU=y
-CT_ARCH_ARCH=""
-# CT_ARCH_FLOAT_AUTO is not set
-# CT_ARCH_FLOAT_HW is not set
-# CT_ARCH_FLOAT_SOFTFP is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-CT_LINUX_V_4_1=y
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="4.1.49"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_later_than_3_7=y
-CT_LINUX_3_7_or_later=y
-CT_LINUX_REQUIRE_3_7_or_later=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-# CT_BINUTILS_V_2_32 is not set
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-CT_BINUTILS_V_2_29=y
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.29.1"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_2_30_or_older=y
-CT_BINUTILS_older_than_2_30=y
-CT_BINUTILS_REQUIRE_older_than_2_30=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
-CT_BINUTILS_GOLD_SUPPORT=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-# CT_BINUTILS_LINKER_LD_GOLD is not set
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_NEWLIB is not set
-# CT_LIBC_NONE is not set
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-# CT_GLIBC_V_2_23 is not set
-# CT_GLIBC_V_2_19 is not set
-CT_GLIBC_V_2_17=y
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.17"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_older_than_2_23=y
-CT_GLIBC_2_20_or_older=y
-CT_GLIBC_older_than_2_20=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_2_17_or_older=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_NPTL_ADDON=y
-CT_GLIBC_HAS_PORTS_ADDON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-CT_GLIBC_USE_PORTS_ADDON=y
-CT_GLIBC_USE_NPTL_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="4.1.49"
-# CT_GLIBC_SSP_DEFAULT is not set
-# CT_GLIBC_SSP_NO is not set
-# CT_GLIBC_SSP_YES is not set
-# CT_GLIBC_SSP_ALL is not set
-# CT_GLIBC_SSP_STRONG is not set
-# CT_NEWLIB_USE_REDHAT is not set
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig
new file mode 100644
index 000000000..47e984ef8
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig
@@ -0,0 +1,12 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_ARM=y
+CT_ARCH_64=y
+CT_KERNEL_LINUX=y
+CT_LINUX_V_4_1=y
+CT_BINUTILS_V_2_29=y
+CT_GLIBC_V_2_17=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh
deleted file mode 100755
index f15a70816..000000000
--- a/src/ci/docker/host-x86_64/dist-aarch64-linux/build-toolchains.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../aarch64-linux-gnu.config .config
-ct-ng oldconfig
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
index 0c3b9ebdc..420c42bc9 100644
--- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
@@ -1,14 +1,13 @@
-FROM ubuntu:20.04
+FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
WORKDIR /build
-COPY scripts/musl-patch-configure.diff /build/
COPY scripts/musl-toolchain.sh /build/
# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
RUN CFLAGS="-Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \
@@ -17,13 +16,11 @@ RUN CFLAGS="-Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=non
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
WORKDIR /tmp
-COPY host-x86_64/dist-arm-linux/arm-linux-gnueabi.config host-x86_64/dist-arm-linux/build-toolchains.sh /tmp/
-RUN ./build-toolchains.sh
-
-USER root
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
@@ -36,6 +33,11 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \
ENV HOSTS=arm-unknown-linux-gnueabi,aarch64-unknown-linux-musl
-ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs --musl-root-aarch64=/usr/local/aarch64-linux-musl \
- --set target.aarch64-unknown-linux-musl.crt-static=false
+ENV RUST_CONFIGURE_ARGS \
+ --enable-full-tools \
+ --disable-docs \
+ --musl-root-aarch64=/usr/local/aarch64-linux-musl \
+ --enable-sanitizers \
+ --enable-profiler \
+ --set target.aarch64-unknown-linux-musl.crt-static=false
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config
deleted file mode 100644
index e047db926..000000000
--- a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config
+++ /dev/null
@@ -1,748 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-# CT_USE_MIRROR is not set
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_BUNDLED_LOCAL is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-CT_ARCH_ARM=y
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="arm"
-CT_ARCH_CHOICE_KSYM="ARM"
-CT_ARCH_CPU=""
-CT_ARCH_TUNE=""
-CT_ARCH_ARM_SHOW=y
-
-#
-# Options for arm
-#
-CT_ARCH_ARM_PKG_KSYM=""
-CT_ARCH_ARM_MODE="arm"
-CT_ARCH_ARM_MODE_ARM=y
-# CT_ARCH_ARM_MODE_THUMB is not set
-# CT_ARCH_ARM_INTERWORKING is not set
-CT_ARCH_ARM_EABI_FORCE=y
-CT_ARCH_ARM_EABI=y
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_SUPPORTS_BOTH_MMU=y
-CT_ARCH_DEFAULT_HAS_MMU=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_FLAT_FORMAT=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_LE=y
-# CT_ARCH_BE is not set
-CT_ARCH_LE=y
-CT_ARCH_ENDIAN="little"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=32
-CT_ARCH_32=y
-# CT_ARCH_64 is not set
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_CPU=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_SUPPORTS_WITH_FPU=y
-CT_ARCH_SUPPORTS_SOFTFP=y
-CT_ARCH_EXCLUSIVE_WITH_CPU=y
-CT_ARCH_ARCH="armv6"
-CT_ARCH_FPU=""
-# CT_ARCH_FLOAT_AUTO is not set
-# CT_ARCH_FLOAT_HW is not set
-# CT_ARCH_FLOAT_SOFTFP is not set
-CT_ARCH_FLOAT_SW=y
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="soft"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-CT_LINUX_V_3_2=y
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="3.2.101"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_3_7_or_older=y
-CT_LINUX_older_than_3_7=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
-CT_BINUTILS_GOLD_SUPPORT=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-# CT_BINUTILS_LINKER_LD_GOLD is not set
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-# CT_GLIBC_V_2_23 is not set
-# CT_GLIBC_V_2_19 is not set
-CT_GLIBC_V_2_17=y
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.17"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_older_than_2_23=y
-CT_GLIBC_2_20_or_older=y
-CT_GLIBC_older_than_2_20=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_2_17_or_older=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_NPTL_ADDON=y
-CT_GLIBC_HAS_PORTS_ADDON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-CT_GLIBC_USE_PORTS_ADDON=y
-CT_GLIBC_USE_NPTL_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="3.2.101"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="https://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig
new file mode 100644
index 000000000..e7afdbe9d
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig
@@ -0,0 +1,13 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_ARM=y
+CT_ARCH_ARCH="armv6"
+CT_ARCH_FLOAT_SW=y
+CT_KERNEL_LINUX=y
+CT_LINUX_V_3_2=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_17=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh
deleted file mode 100755
index ad53ba4dd..000000000
--- a/src/ci/docker/host-x86_64/dist-arm-linux/build-toolchains.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../arm-linux-gnueabi.config .config
-# FIXME ct-ng oldconfig is not working as intended.
-# ct-ng oldconfig
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
index 753d64505..855465aa3 100644
--- a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
@@ -1,20 +1,18 @@
-FROM ubuntu:20.04
+FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
WORKDIR /tmp
-COPY host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config host-x86_64/dist-armhf-linux/build-toolchains.sh /tmp/
-RUN ./build-toolchains.sh
-
-USER root
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config b/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config
deleted file mode 100644
index e0f641779..000000000
--- a/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config
+++ /dev/null
@@ -1,749 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-# CT_USE_MIRROR is not set
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_BUNDLED_LOCAL is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-CT_ARCH_ARM=y
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="arm"
-CT_ARCH_CHOICE_KSYM="ARM"
-CT_ARCH_CPU=""
-CT_ARCH_TUNE=""
-CT_ARCH_ARM_SHOW=y
-
-#
-# Options for arm
-#
-CT_ARCH_ARM_PKG_KSYM=""
-CT_ARCH_ARM_MODE="arm"
-CT_ARCH_ARM_MODE_ARM=y
-# CT_ARCH_ARM_MODE_THUMB is not set
-# CT_ARCH_ARM_INTERWORKING is not set
-CT_ARCH_ARM_EABI_FORCE=y
-CT_ARCH_ARM_EABI=y
-CT_ARCH_ARM_TUPLE_USE_EABIHF=y
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_SUPPORTS_BOTH_MMU=y
-CT_ARCH_DEFAULT_HAS_MMU=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_FLAT_FORMAT=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_LE=y
-# CT_ARCH_BE is not set
-CT_ARCH_LE=y
-CT_ARCH_ENDIAN="little"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=32
-CT_ARCH_32=y
-# CT_ARCH_64 is not set
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_CPU=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_SUPPORTS_WITH_FPU=y
-CT_ARCH_SUPPORTS_SOFTFP=y
-CT_ARCH_EXCLUSIVE_WITH_CPU=y
-CT_ARCH_ARCH="armv6"
-CT_ARCH_FPU="vfp"
-# CT_ARCH_FLOAT_AUTO is not set
-CT_ARCH_FLOAT_HW=y
-# CT_ARCH_FLOAT_SOFTFP is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="hard"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-CT_LINUX_V_3_2=y
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="3.2.101"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_3_7_or_older=y
-CT_LINUX_older_than_3_7=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
-CT_BINUTILS_GOLD_SUPPORT=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-# CT_BINUTILS_LINKER_LD_GOLD is not set
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-# CT_GLIBC_V_2_23 is not set
-# CT_GLIBC_V_2_19 is not set
-CT_GLIBC_V_2_17=y
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.17"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_older_than_2_23=y
-CT_GLIBC_2_20_or_older=y
-CT_GLIBC_older_than_2_20=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_2_17_or_older=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_NPTL_ADDON=y
-CT_GLIBC_HAS_PORTS_ADDON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-CT_GLIBC_USE_PORTS_ADDON=y
-CT_GLIBC_USE_NPTL_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="3.2.101"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="https://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.defconfig b/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.defconfig
new file mode 100644
index 000000000..c7c5b4d5a
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.defconfig
@@ -0,0 +1,14 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_ARM=y
+CT_ARCH_ARCH="armv6"
+CT_ARCH_FPU="vfp"
+CT_ARCH_FLOAT_HW=y
+CT_KERNEL_LINUX=y
+CT_LINUX_V_3_2=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_17=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile
index 7eb5097aa..dab0667ed 100644
--- a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile
@@ -1,20 +1,18 @@
-FROM ubuntu:20.04
+FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
WORKDIR /tmp
-COPY host-x86_64/dist-armv7-linux/build-toolchains.sh host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config /tmp/
-RUN ./build-toolchains.sh
-
-USER root
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config b/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config
deleted file mode 100644
index 2d8167f1f..000000000
--- a/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config
+++ /dev/null
@@ -1,746 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR=""
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-# CT_USE_MIRROR is not set
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_BUNDLED_LOCAL is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-CT_LOG_INFO=y
-# CT_LOG_EXTRA is not set
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="INFO"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-CT_ARCH_ARM=y
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="arm"
-CT_ARCH_CHOICE_KSYM="ARM"
-CT_ARCH_CPU=""
-CT_ARCH_TUNE=""
-CT_ARCH_ARM_SHOW=y
-
-#
-# Options for arm
-#
-CT_ARCH_ARM_PKG_KSYM=""
-CT_ARCH_ARM_MODE="thumb"
-# CT_ARCH_ARM_MODE_ARM is not set
-CT_ARCH_ARM_MODE_THUMB=y
-# CT_ARCH_ARM_INTERWORKING is not set
-CT_ARCH_ARM_EABI_FORCE=y
-CT_ARCH_ARM_EABI=y
-CT_ARCH_ARM_TUPLE_USE_EABIHF=y
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX="v7"
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_SUPPORTS_BOTH_MMU=y
-CT_ARCH_DEFAULT_HAS_MMU=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_FLAT_FORMAT=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_LE=y
-# CT_ARCH_BE is not set
-CT_ARCH_LE=y
-CT_ARCH_ENDIAN="little"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=32
-CT_ARCH_32=y
-# CT_ARCH_64 is not set
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_CPU=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_SUPPORTS_WITH_FPU=y
-CT_ARCH_SUPPORTS_SOFTFP=y
-CT_ARCH_EXCLUSIVE_WITH_CPU=y
-CT_ARCH_ARCH="armv7-a"
-CT_ARCH_FPU="vfpv3-d16"
-# CT_ARCH_FLOAT_AUTO is not set
-CT_ARCH_FLOAT_HW=y
-# CT_ARCH_FLOAT_SOFTFP is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="hard"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-CT_LINUX_V_3_2=y
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="3.2.101"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_3_7_or_older=y
-CT_LINUX_older_than_3_7=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
-CT_BINUTILS_GOLD_SUPPORT=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-# CT_BINUTILS_LINKER_LD_GOLD is not set
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-# CT_GLIBC_V_2_23 is not set
-# CT_GLIBC_V_2_19 is not set
-CT_GLIBC_V_2_17=y
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.17"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_older_than_2_23=y
-CT_GLIBC_2_20_or_older=y
-CT_GLIBC_older_than_2_20=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_2_17_or_older=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_NPTL_ADDON=y
-CT_GLIBC_HAS_PORTS_ADDON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-CT_GLIBC_USE_PORTS_ADDON=y
-CT_GLIBC_USE_NPTL_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="3.2.101"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-# CT_MPC_V_1_1 is not set
-CT_MPC_V_1_0=y
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.0.3"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_older=y
-CT_MPC_older_than_1_1_0=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_3_1=y
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="3.1.6"
-CT_MPFR_MIRRORS="https://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_4_0_0_or_older=y
-CT_MPFR_older_than_4_0_0=y
-CT_MPFR_REQUIRE_older_than_4_0_0=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="https://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.defconfig b/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.defconfig
new file mode 100644
index 000000000..3f37e546b
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.defconfig
@@ -0,0 +1,16 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_ARM=y
+CT_ARCH_ARM_MODE_THUMB=y
+CT_ARCH_SUFFIX="v7"
+CT_ARCH_ARCH="armv7-a"
+CT_ARCH_FPU="vfpv3-d16"
+CT_ARCH_FLOAT_HW=y
+CT_KERNEL_LINUX=y
+CT_LINUX_V_3_2=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_17=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh
deleted file mode 100755
index 602ad8ac8..000000000
--- a/src/ci/docker/host-x86_64/dist-armv7-linux/build-toolchains.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../armv7-linux-gnueabihf.config .config
-# FIXME ct-ng oldconfig is not working as intended.
-# ct-ng oldconfig
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
index 34829adf7..a62f98b21 100644
--- a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
@@ -21,17 +21,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
WORKDIR /tmp
-COPY host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config \
- host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh \
- /tmp/
-RUN su rustbuild -c ./build-i586-gnu-toolchain.sh
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
+
ENV PATH=$PATH:/x-tools/i586-unknown-linux-gnu/bin
ENV \
CC_i586_unknown_linux_gnu=i586-unknown-linux-gnu-gcc \
diff --git a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh
deleted file mode 100755
index ceab60cfb..000000000
--- a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../i586-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config
deleted file mode 100644
index cdbd52d23..000000000
--- a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config
+++ /dev/null
@@ -1,726 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_BUNDLED_LOCAL is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-CT_ARCH_X86=y
-# CT_ARCH_XTENSA is not set
-CT_ARCH="x86"
-CT_ARCH_CHOICE_KSYM="X86"
-CT_ARCH_CPU=""
-CT_ARCH_TUNE=""
-CT_ARCH_X86_SHOW=y
-
-#
-# Options for x86
-#
-CT_ARCH_X86_PKG_KSYM=""
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=32
-CT_ARCH_32=y
-# CT_ARCH_64 is not set
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_CPU=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_ARCH="i586"
-CT_TARGET_CFLAGS="-Wa,-mrelax-relocations=no"
-CT_TARGET_LDFLAGS=""
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-CT_LINUX_V_3_2=y
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="3.2.101"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_3_7_or_older=y
-CT_LINUX_older_than_3_7=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
-CT_BINUTILS_GOLD_SUPPORT=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-# CT_BINUTILS_LINKER_LD_GOLD is not set
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY="--enable-compressed-debug-sections=none"
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-# CT_GLIBC_V_2_23 is not set
-# CT_GLIBC_V_2_19 is not set
-CT_GLIBC_V_2_17=y
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.17"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_older_than_2_23=y
-CT_GLIBC_2_20_or_older=y
-CT_GLIBC_older_than_2_20=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_2_17_or_older=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_NPTL_ADDON=y
-CT_GLIBC_HAS_PORTS_ADDON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-CT_GLIBC_USE_NPTL_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="3.2.101"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-CT_CC_GCC_LIBMPX=y
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.defconfig
new file mode 100644
index 000000000..01fe493a9
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.defconfig
@@ -0,0 +1,14 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_X86=y
+CT_ARCH_ARCH="i586"
+CT_TARGET_CFLAGS="-Wa,-mrelax-relocations=no"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_3_2=y
+CT_BINUTILS_V_2_32=y
+CT_BINUTILS_EXTRA_CONFIG_ARRAY="--enable-compressed-debug-sections=none"
+CT_GLIBC_V_2_17=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
new file mode 100644
index 000000000..78689c429
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
@@ -0,0 +1,30 @@
+FROM ubuntu:22.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+# The latest released version does not support LoongArch.
+COPY scripts/crosstool-ng-git.sh /scripts/
+RUN sh /scripts/crosstool-ng-git.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV PATH=$PATH:/x-tools/loongarch64-unknown-linux-gnu/bin
+
+ENV CC_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-gcc \
+ AR_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-ar \
+ CXX_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-g++
+
+ENV HOSTS=loongarch64-unknown-linux-gnu
+
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
new file mode 100644
index 000000000..576f3631c
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
@@ -0,0 +1,14 @@
+CT_CONFIG_VERSION="4"
+CT_EXPERIMENTAL=y
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_LOONGARCH=y
+# CT_DEMULTILIB is not set
+CT_ARCH_USE_MMU=y
+CT_ARCH_ARCH="loongarch64"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_5_19=y
+CT_GLIBC_V_2_36=y
+CT_CC_GCC_ENABLE_DEFAULT_PIE=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
index eb511b321..c08febf42 100644
--- a/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
@@ -3,16 +3,17 @@ FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
WORKDIR /tmp
+COPY scripts/crosstool-ng-build.sh /scripts/
COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
-COPY host-x86_64/dist-mips-linux/mips-linux-gnu.config host-x86_64/dist-mips-linux/build-mips-toolchain.sh /tmp/
-RUN su rustbuild -c ./build-mips-toolchain.sh
+COPY host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh
deleted file mode 100755
index 32612cf68..000000000
--- a/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../mips-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config
deleted file mode 100644
index 575584ef0..000000000
--- a/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config
+++ /dev/null
@@ -1,740 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-# CT_PATCH_BUNDLED is not set
-CT_PATCH_BUNDLED_LOCAL=y
-CT_PATCH_ORDER="bundled,local"
-CT_PATCH_USE_LOCAL=y
-CT_LOCAL_PATCH_DIR="/tmp/patches"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-CT_ARCH_MIPS=y
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="mips"
-CT_ARCH_CHOICE_KSYM="MIPS"
-CT_ARCH_TUNE=""
-CT_ARCH_MIPS_SHOW=y
-
-#
-# Options for mips
-#
-CT_ARCH_MIPS_PKG_KSYM=""
-CT_ARCH_mips_o32=y
-CT_ARCH_mips_ABI="32"
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_BE=y
-CT_ARCH_BE=y
-# CT_ARCH_LE is not set
-CT_ARCH_ENDIAN="big"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=32
-CT_ARCH_32=y
-# CT_ARCH_64 is not set
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_ARCH="mips32r2"
-CT_ARCH_FLOAT_AUTO=y
-# CT_ARCH_FLOAT_HW is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="auto"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-CT_LINUX_V_4_4=y
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-# CT_LINUX_V_3_2 is not set
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="4.4.174"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_later_than_3_7=y
-CT_LINUX_3_7_or_later=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-CT_GLIBC_V_2_23=y
-# CT_GLIBC_V_2_19 is not set
-# CT_GLIBC_V_2_17 is not set
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.23"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_later=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_later_than_2_20=y
-CT_GLIBC_2_20_or_later=y
-CT_GLIBC_later_than_2_17=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_NO_SPARC_V8=y
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="4.4.174"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-fp-32=xx --with-odd-spreg-32=no"
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_CC_GCC_HAS_ARCH_OPTIONS=y
-
-#
-# archictecture-specific options
-#
-CT_CC_GCC_mips_llsc=m
-CT_CC_GCC_mips_synci=m
-# CT_CC_GCC_mips_plt is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig
new file mode 100644
index 000000000..75743fe81
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.defconfig
@@ -0,0 +1,16 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_PATCH_BUNDLED_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+CT_ARCH_MIPS=y
+CT_ARCH_mips_o32=y
+CT_ARCH_ARCH="mips32r2"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_4_4=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_23=y
+CT_GCC_V_8=y
+CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-fp-32=xx --with-odd-spreg-32=no"
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
index de862e1df..10f31075e 100644
--- a/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
@@ -3,16 +3,17 @@ FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
WORKDIR /tmp
+COPY scripts/crosstool-ng-build.sh /scripts/
COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
-COPY host-x86_64/dist-mips64-linux/mips64-linux-gnu.config host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh /tmp/
-RUN su rustbuild -c ./build-mips64-toolchain.sh
+COPY host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh
deleted file mode 100755
index f554a5f47..000000000
--- a/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../mips64-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config
deleted file mode 100644
index 4b1efe24a..000000000
--- a/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config
+++ /dev/null
@@ -1,741 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-# CT_PATCH_BUNDLED is not set
-CT_PATCH_BUNDLED_LOCAL=y
-CT_PATCH_ORDER="bundled,local"
-CT_PATCH_USE_LOCAL=y
-CT_LOCAL_PATCH_DIR="/tmp/patches"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-CT_ARCH_MIPS=y
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="mips"
-CT_ARCH_CHOICE_KSYM="MIPS"
-CT_ARCH_TUNE=""
-CT_ARCH_MIPS_SHOW=y
-
-#
-# Options for mips
-#
-CT_ARCH_MIPS_PKG_KSYM=""
-# CT_ARCH_mips_n32 is not set
-CT_ARCH_mips_n64=y
-CT_ARCH_mips_ABI="64"
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_BE=y
-CT_ARCH_BE=y
-# CT_ARCH_LE is not set
-CT_ARCH_ENDIAN="big"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=64
-# CT_ARCH_32 is not set
-CT_ARCH_64=y
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_ARCH="mips64r2"
-CT_ARCH_FLOAT_AUTO=y
-# CT_ARCH_FLOAT_HW is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="auto"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-CT_LINUX_V_4_4=y
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-# CT_LINUX_V_3_2 is not set
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="4.4.174"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_later_than_3_7=y
-CT_LINUX_3_7_or_later=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-CT_GLIBC_V_2_23=y
-# CT_GLIBC_V_2_19 is not set
-# CT_GLIBC_V_2_17 is not set
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.23"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_later=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_later_than_2_20=y
-CT_GLIBC_2_20_or_later=y
-CT_GLIBC_later_than_2_17=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_NO_SPARC_V8=y
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="4.4.174"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_CC_GCC_HAS_ARCH_OPTIONS=y
-
-#
-# archictecture-specific options
-#
-CT_CC_GCC_mips_llsc=m
-CT_CC_GCC_mips_synci=m
-# CT_CC_GCC_mips_plt is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig
new file mode 100644
index 000000000..4b8f7a549
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.defconfig
@@ -0,0 +1,16 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_PATCH_BUNDLED_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+CT_ARCH_MIPS=y
+CT_ARCH_mips_n64=y
+CT_ARCH_64=y
+CT_ARCH_ARCH="mips64r2"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_4_4=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_23=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
index b90950f73..5ab4a53de 100644
--- a/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
@@ -3,16 +3,17 @@ FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
WORKDIR /tmp
+COPY scripts/crosstool-ng-build.sh /scripts/
COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
-COPY host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh /tmp/
-RUN su rustbuild -c ./build-mips64el-toolchain.sh
+COPY host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh
deleted file mode 100755
index 1ad406800..000000000
--- a/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../mips64el-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config
deleted file mode 100644
index baff944cf..000000000
--- a/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config
+++ /dev/null
@@ -1,741 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-# CT_PATCH_BUNDLED is not set
-CT_PATCH_BUNDLED_LOCAL=y
-CT_PATCH_ORDER="bundled,local"
-CT_PATCH_USE_LOCAL=y
-CT_LOCAL_PATCH_DIR="/tmp/patches"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-CT_ARCH_MIPS=y
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="mips"
-CT_ARCH_CHOICE_KSYM="MIPS"
-CT_ARCH_TUNE=""
-CT_ARCH_MIPS_SHOW=y
-
-#
-# Options for mips
-#
-CT_ARCH_MIPS_PKG_KSYM=""
-# CT_ARCH_mips_n32 is not set
-CT_ARCH_mips_n64=y
-CT_ARCH_mips_ABI="64"
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_BE=y
-# CT_ARCH_BE is not set
-CT_ARCH_LE=y
-CT_ARCH_ENDIAN="little"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=64
-# CT_ARCH_32 is not set
-CT_ARCH_64=y
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_ARCH="mips64r2"
-CT_ARCH_FLOAT_AUTO=y
-# CT_ARCH_FLOAT_HW is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="auto"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-CT_LINUX_V_4_4=y
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-# CT_LINUX_V_3_2 is not set
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="4.4.174"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_later_than_3_7=y
-CT_LINUX_3_7_or_later=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-CT_GLIBC_V_2_23=y
-# CT_GLIBC_V_2_19 is not set
-# CT_GLIBC_V_2_17 is not set
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.23"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_later=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_later_than_2_20=y
-CT_GLIBC_2_20_or_later=y
-CT_GLIBC_later_than_2_17=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_NO_SPARC_V8=y
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="4.4.174"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_CC_GCC_HAS_ARCH_OPTIONS=y
-
-#
-# archictecture-specific options
-#
-CT_CC_GCC_mips_llsc=m
-CT_CC_GCC_mips_synci=m
-# CT_CC_GCC_mips_plt is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig
new file mode 100644
index 000000000..9c8eb5007
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.defconfig
@@ -0,0 +1,17 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_PATCH_BUNDLED_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+CT_ARCH_MIPS=y
+CT_ARCH_mips_n64=y
+CT_ARCH_LE=y
+CT_ARCH_64=y
+CT_ARCH_ARCH="mips64r2"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_4_4=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_23=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
index 6cc2de5e4..0bbaf0033 100644
--- a/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
@@ -3,16 +3,17 @@ FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
WORKDIR /tmp
+COPY scripts/crosstool-ng-build.sh /scripts/
COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
-COPY host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh /tmp/
-RUN su rustbuild -c ./build-mipsel-toolchain.sh
+COPY host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh b/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh
deleted file mode 100755
index 598e48933..000000000
--- a/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../mipsel-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config
deleted file mode 100644
index adb2da7dd..000000000
--- a/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config
+++ /dev/null
@@ -1,740 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-# CT_PATCH_BUNDLED is not set
-CT_PATCH_BUNDLED_LOCAL=y
-CT_PATCH_ORDER="bundled,local"
-CT_PATCH_USE_LOCAL=y
-CT_LOCAL_PATCH_DIR="/tmp/patches"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-CT_ARCH_MIPS=y
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="mips"
-CT_ARCH_CHOICE_KSYM="MIPS"
-CT_ARCH_TUNE=""
-CT_ARCH_MIPS_SHOW=y
-
-#
-# Options for mips
-#
-CT_ARCH_MIPS_PKG_KSYM=""
-CT_ARCH_mips_o32=y
-CT_ARCH_mips_ABI="32"
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_BE=y
-# CT_ARCH_BE is not set
-CT_ARCH_LE=y
-CT_ARCH_ENDIAN="little"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=32
-CT_ARCH_32=y
-# CT_ARCH_64 is not set
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_ARCH="mips32r2"
-CT_ARCH_FLOAT_AUTO=y
-# CT_ARCH_FLOAT_HW is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="auto"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-CT_LINUX_V_4_4=y
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-# CT_LINUX_V_3_2 is not set
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="4.4.174"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_later_than_3_7=y
-CT_LINUX_3_7_or_later=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-CT_GLIBC_V_2_23=y
-# CT_GLIBC_V_2_19 is not set
-# CT_GLIBC_V_2_17 is not set
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.23"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_later=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_later_than_2_20=y
-CT_GLIBC_2_20_or_later=y
-CT_GLIBC_later_than_2_17=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_NO_SPARC_V8=y
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="4.4.174"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-fp-32=xx --with-odd-spreg-32=no"
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_CC_GCC_HAS_ARCH_OPTIONS=y
-
-#
-# archictecture-specific options
-#
-CT_CC_GCC_mips_llsc=m
-CT_CC_GCC_mips_synci=m
-# CT_CC_GCC_mips_plt is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig
new file mode 100644
index 000000000..a9dae121e
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.defconfig
@@ -0,0 +1,17 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_PATCH_BUNDLED_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+CT_ARCH_MIPS=y
+CT_ARCH_mips_o32=y
+CT_ARCH_LE=y
+CT_ARCH_ARCH="mips32r2"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_4_4=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_23=y
+CT_GCC_V_8=y
+CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-fp-32=xx --with-odd-spreg-32=no"
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile
index 94a837151..b546f571f 100644
--- a/src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-powerpc-linux/Dockerfile
@@ -1,20 +1,18 @@
-FROM ubuntu:20.04
+FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
WORKDIR /tmp
-COPY host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh /tmp/
-RUN ./build-powerpc-toolchain.sh
-
-USER root
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh b/src/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh
deleted file mode 100755
index 264d0764f..000000000
--- a/src/ci/docker/host-x86_64/dist-powerpc-linux/build-powerpc-toolchain.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../powerpc-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config b/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config
deleted file mode 100644
index 0df859ad9..000000000
--- a/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config
+++ /dev/null
@@ -1,736 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_BUNDLED_LOCAL is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_NIOS2 is not set
-CT_ARCH_POWERPC=y
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="powerpc"
-CT_ARCH_CHOICE_KSYM="POWERPC"
-CT_ARCH_CPU="powerpc"
-CT_ARCH_TUNE=""
-CT_ARCH_POWERPC_SHOW=y
-
-#
-# Options for powerpc
-#
-CT_ARCH_POWERPC_PKG_KSYM=""
-CT_ARCH_powerpc_ABI=""
-CT_ARCH_powerpc_ABI_DEFAULT=y
-# CT_ARCH_powerpc_ABI_SPE is not set
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_BE=y
-CT_ARCH_BE=y
-# CT_ARCH_LE is not set
-CT_ARCH_ENDIAN="big"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=32
-CT_ARCH_32=y
-# CT_ARCH_64 is not set
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ABI=y
-CT_ARCH_SUPPORTS_WITH_CPU=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_ABI=""
-CT_ARCH_FLOAT_AUTO=y
-# CT_ARCH_FLOAT_HW is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="auto"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-CT_LINUX_V_3_2=y
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="3.2.101"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_3_7_or_older=y
-CT_LINUX_older_than_3_7=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-# CT_BINUTILS_V_2_32 is not set
-# CT_BINUTILS_V_2_31 is not set
-CT_BINUTILS_V_2_30=y
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.30"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_2_30_or_older=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-# CT_GLIBC_V_2_23 is not set
-# CT_GLIBC_V_2_19 is not set
-CT_GLIBC_V_2_17=y
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.17"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_older_than_2_23=y
-CT_GLIBC_2_20_or_older=y
-CT_GLIBC_older_than_2_20=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_2_17_or_older=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_NPTL_ADDON=y
-CT_GLIBC_HAS_PORTS_ADDON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-CT_GLIBC_USE_PORTS_ADDON=y
-CT_GLIBC_USE_NPTL_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="3.2.101"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.defconfig
new file mode 100644
index 000000000..6a0e96a3b
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.defconfig
@@ -0,0 +1,12 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_POWERPC=y
+CT_ARCH_CPU="powerpc"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_3_2=y
+CT_BINUTILS_V_2_30=y
+CT_GLIBC_V_2_17=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile
index c976536cb..c88185a20 100644
--- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile
@@ -1,20 +1,18 @@
-FROM ubuntu:20.04
+FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
WORKDIR /tmp
-COPY host-x86_64/dist-powerpc64-linux/shared.sh host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config host-x86_64/dist-powerpc64-linux/build-powerpc64-toolchain.sh /tmp/
-RUN ./build-powerpc64-toolchain.sh
-
-USER root
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/build-powerpc64-toolchain.sh b/src/ci/docker/host-x86_64/dist-powerpc64-linux/build-powerpc64-toolchain.sh
deleted file mode 100755
index f7aa2cd32..000000000
--- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/build-powerpc64-toolchain.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-source shared.sh
-
-mkdir build
-cd build
-cp ../powerpc64-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config b/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config
deleted file mode 100644
index d3293eab2..000000000
--- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config
+++ /dev/null
@@ -1,736 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_BUNDLED_LOCAL is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_NIOS2 is not set
-CT_ARCH_POWERPC=y
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="powerpc"
-CT_ARCH_CHOICE_KSYM="POWERPC"
-CT_ARCH_CPU="power4"
-CT_ARCH_TUNE="power6"
-CT_ARCH_POWERPC_SHOW=y
-
-#
-# Options for powerpc
-#
-CT_ARCH_POWERPC_PKG_KSYM=""
-CT_ARCH_powerpc_ABI=""
-CT_ARCH_powerpc_ABI_DEFAULT=y
-# CT_ARCH_powerpc_ABI_SPE is not set
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
-CT_ARCH_DEFAULT_BE=y
-CT_ARCH_BE=y
-# CT_ARCH_LE is not set
-CT_ARCH_ENDIAN="big"
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=64
-# CT_ARCH_32 is not set
-CT_ARCH_64=y
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ABI=y
-CT_ARCH_SUPPORTS_WITH_CPU=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_SUPPORTS_WITH_FLOAT=y
-CT_ARCH_ABI=""
-CT_ARCH_FLOAT_AUTO=y
-# CT_ARCH_FLOAT_HW is not set
-# CT_ARCH_FLOAT_SW is not set
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-CT_ARCH_FLOAT="auto"
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-CT_LINUX_V_3_2=y
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="3.2.101"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_3_7_or_older=y
-CT_LINUX_older_than_3_7=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-# CT_GLIBC_V_2_23 is not set
-# CT_GLIBC_V_2_19 is not set
-CT_GLIBC_V_2_17=y
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.17"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_older_than_2_23=y
-CT_GLIBC_2_20_or_older=y
-CT_GLIBC_older_than_2_20=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_2_17_or_older=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_NPTL_ADDON=y
-CT_GLIBC_HAS_PORTS_ADDON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-CT_GLIBC_USE_PORTS_ADDON=y
-CT_GLIBC_USE_NPTL_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="3.2.101"
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig
new file mode 100644
index 000000000..2b442cbe7
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig
@@ -0,0 +1,14 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_POWERPC=y
+CT_ARCH_CPU="power4"
+CT_ARCH_TUNE="power6"
+CT_ARCH_64=y
+CT_KERNEL_LINUX=y
+CT_LINUX_V_3_2=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_17=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh b/src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh
deleted file mode 100644
index dc86dddd4..000000000
--- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/shared.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
diff --git a/src/ci/docker/host-x86_64/dist-riscv64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-riscv64-linux/Dockerfile
index 397f9538b..426e601f5 100644
--- a/src/ci/docker/host-x86_64/dist-riscv64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-riscv64-linux/Dockerfile
@@ -1,20 +1,18 @@
-FROM ubuntu:20.04
+FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
WORKDIR /tmp
-COPY host-x86_64/dist-riscv64-linux/build-toolchains.sh host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config /tmp/
-RUN ./build-toolchains.sh
-
-USER root
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh b/src/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh
deleted file mode 100755
index a7025b2b7..000000000
--- a/src/ci/docker/host-x86_64/dist-riscv64-linux/build-toolchains.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../riscv64-unknown-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config b/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config
deleted file mode 100644
index 7400a8a03..000000000
--- a/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config
+++ /dev/null
@@ -1,907 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-CT_EXPERIMENTAL=y
-# CT_ALLOW_BUILD_AS_ROOT is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-# CT_USE_MIRROR is not set
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_LOCAL is not set
-# CT_PATCH_BUNDLED_LOCAL is not set
-# CT_PATCH_LOCAL_BUNDLED is not set
-# CT_PATCH_NONE is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-# CT_LOG_EXTRA is not set
-CT_LOG_ALL=y
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="ALL"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MICROBLAZE is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_MOXIE is not set
-# CT_ARCH_MSP430 is not set
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-CT_ARCH_RISCV=y
-# CT_ARCH_S390 is not set
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="riscv"
-CT_ARCH_CHOICE_KSYM="RISCV"
-CT_ARCH_TUNE=""
-CT_ARCH_RISCV_SHOW=y
-
-#
-# Options for riscv
-#
-CT_ARCH_RISCV_PKG_KSYM=""
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-# CT_DEMULTILIB is not set
-CT_ARCH_SUPPORTS_BOTH_MMU=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=64
-# CT_ARCH_32 is not set
-CT_ARCH_64=y
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_ARCH=y
-CT_ARCH_SUPPORTS_WITH_ABI=y
-CT_ARCH_SUPPORTS_WITH_TUNE=y
-CT_ARCH_ARCH="rv64gc"
-CT_ARCH_ABI=""
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-# CT_NATIVE is not set
-CT_CROSS=y
-# CT_CROSS_NATIVE is not set
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-# CT_LINUX_SRC_DEVEL is not set
-# CT_LINUX_SRC_CUSTOM is not set
-CT_LINUX_PATCH_GLOBAL=y
-# CT_LINUX_PATCH_BUNDLED is not set
-# CT_LINUX_PATCH_LOCAL is not set
-# CT_LINUX_PATCH_BUNDLED_LOCAL is not set
-# CT_LINUX_PATCH_LOCAL_BUNDLED is not set
-# CT_LINUX_PATCH_NONE is not set
-CT_LINUX_PATCH_ORDER="global"
-CT_LINUX_V_4_20=y
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-# CT_LINUX_V_3_2 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="4.20.8"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_later_than_4_8=y
-CT_LINUX_4_8_or_later=y
-CT_LINUX_later_than_3_7=y
-CT_LINUX_3_7_or_later=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_LINUX_REQUIRE_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-# CT_BINUTILS_SRC_DEVEL is not set
-# CT_BINUTILS_SRC_CUSTOM is not set
-CT_BINUTILS_PATCH_GLOBAL=y
-# CT_BINUTILS_PATCH_BUNDLED is not set
-# CT_BINUTILS_PATCH_LOCAL is not set
-# CT_BINUTILS_PATCH_BUNDLED_LOCAL is not set
-# CT_BINUTILS_PATCH_LOCAL_BUNDLED is not set
-# CT_BINUTILS_PATCH_NONE is not set
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_REQUIRE_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_MUSL is not set
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-# CT_GLIBC_SRC_DEVEL is not set
-# CT_GLIBC_SRC_CUSTOM is not set
-CT_GLIBC_PATCH_GLOBAL=y
-# CT_GLIBC_PATCH_BUNDLED is not set
-# CT_GLIBC_PATCH_LOCAL is not set
-# CT_GLIBC_PATCH_BUNDLED_LOCAL is not set
-# CT_GLIBC_PATCH_LOCAL_BUNDLED is not set
-# CT_GLIBC_PATCH_NONE is not set
-CT_GLIBC_PATCH_ORDER="global"
-CT_GLIBC_V_2_29=y
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.29"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_later=y
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_REQUIRE_2_29_or_later=y
-CT_GLIBC_later_than_2_27=y
-CT_GLIBC_2_27_or_later=y
-CT_GLIBC_later_than_2_26=y
-CT_GLIBC_2_26_or_later=y
-CT_GLIBC_later_than_2_25=y
-CT_GLIBC_2_25_or_later=y
-CT_GLIBC_later_than_2_24=y
-CT_GLIBC_2_24_or_later=y
-CT_GLIBC_later_than_2_23=y
-CT_GLIBC_2_23_or_later=y
-CT_GLIBC_later_than_2_20=y
-CT_GLIBC_2_20_or_later=y
-CT_GLIBC_later_than_2_17=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_BUILD_SSP=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_NO_SPARC_V8=y
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_ENABLE_FORTIFIED_BUILD is not set
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-CT_GLIBC_KERNEL_VERSION_NONE=y
-# CT_GLIBC_KERNEL_VERSION_AS_HEADERS is not set
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL=""
-CT_GLIBC_SSP_DEFAULT=y
-# CT_GLIBC_SSP_NO is not set
-# CT_GLIBC_SSP_YES is not set
-# CT_GLIBC_SSP_ALL is not set
-# CT_GLIBC_SSP_STRONG is not set
-# CT_GLIBC_ENABLE_WERROR is not set
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-# CT_GCC_USE_LINARO is not set
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-# CT_GCC_SRC_DEVEL is not set
-# CT_GCC_SRC_CUSTOM is not set
-CT_GCC_PATCH_GLOBAL=y
-# CT_GCC_PATCH_BUNDLED is not set
-# CT_GCC_PATCH_LOCAL is not set
-# CT_GCC_PATCH_BUNDLED_LOCAL is not set
-# CT_GCC_PATCH_LOCAL_BUNDLED is not set
-# CT_GCC_PATCH_NONE is not set
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_REQUIRE_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_REQUIRE_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_REQUIRE_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-# CT_CC_LANG_ADA is not set
-# CT_CC_LANG_OBJC is not set
-# CT_CC_LANG_OBJCXX is not set
-# CT_CC_LANG_GOLANG is not set
-CT_CC_LANG_OTHERS=""
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-CT_DEBUG_GDB=y
-CT_DEBUG_GDB_PKG_KSYM="GDB"
-CT_GDB_DIR_NAME="gdb"
-CT_GDB_USE_GNU=y
-CT_GDB_USE="GDB"
-CT_GDB_PKG_NAME="gdb"
-CT_GDB_SRC_RELEASE=y
-# CT_GDB_SRC_DEVEL is not set
-# CT_GDB_SRC_CUSTOM is not set
-CT_GDB_PATCH_GLOBAL=y
-# CT_GDB_PATCH_BUNDLED is not set
-# CT_GDB_PATCH_LOCAL is not set
-# CT_GDB_PATCH_BUNDLED_LOCAL is not set
-# CT_GDB_PATCH_LOCAL_BUNDLED is not set
-# CT_GDB_PATCH_NONE is not set
-CT_GDB_PATCH_ORDER="global"
-CT_GDB_V_8_2=y
-# CT_GDB_V_8_1 is not set
-# CT_GDB_V_8_0 is not set
-# CT_GDB_NO_VERSIONS is not set
-CT_GDB_VERSION="8.2.1"
-CT_GDB_MIRRORS="$(CT_Mirrors GNU gdb) $(CT_Mirrors sourceware gdb/releases)"
-CT_GDB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GDB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GDB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GDB_SIGNATURE_FORMAT=""
-CT_GDB_later_than_8_0=y
-CT_GDB_8_0_or_later=y
-CT_GDB_REQUIRE_8_0_or_later=y
-CT_GDB_later_than_7_12=y
-CT_GDB_7_12_or_later=y
-CT_GDB_later_than_7_2=y
-CT_GDB_7_2_or_later=y
-CT_GDB_later_than_7_0=y
-CT_GDB_7_0_or_later=y
-CT_GDB_CROSS=y
-# CT_GDB_CROSS_STATIC is not set
-# CT_GDB_CROSS_SIM is not set
-# CT_GDB_CROSS_PYTHON is not set
-CT_GDB_CROSS_EXTRA_CONFIG_ARRAY=""
-# CT_GDB_NATIVE is not set
-# CT_GDB_GDBSERVER is not set
-CT_GDB_HAS_PKGVERSION_BUGURL=y
-CT_GDB_HAS_PYTHON=y
-CT_GDB_INSTALL_GDBINIT=y
-CT_GDB_HAS_IPA_LIB=y
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-CT_COMP_LIBS_EXPAT=y
-CT_COMP_LIBS_EXPAT_PKG_KSYM="EXPAT"
-CT_EXPAT_DIR_NAME="expat"
-CT_EXPAT_PKG_NAME="expat"
-CT_EXPAT_SRC_RELEASE=y
-# CT_EXPAT_SRC_DEVEL is not set
-# CT_EXPAT_SRC_CUSTOM is not set
-CT_EXPAT_PATCH_GLOBAL=y
-# CT_EXPAT_PATCH_BUNDLED is not set
-# CT_EXPAT_PATCH_LOCAL is not set
-# CT_EXPAT_PATCH_BUNDLED_LOCAL is not set
-# CT_EXPAT_PATCH_LOCAL_BUNDLED is not set
-# CT_EXPAT_PATCH_NONE is not set
-CT_EXPAT_PATCH_ORDER="global"
-CT_EXPAT_V_2_2=y
-# CT_EXPAT_NO_VERSIONS is not set
-CT_EXPAT_VERSION="2.4.1"
-CT_EXPAT_VERSION_TAG="2_4_1"
-CT_EXPAT_MIRRORS="https://github.com/libexpat/libexpat/releases/download/R_${CT_EXPAT_VERSION_TAG}"
-CT_EXPAT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_EXPAT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_EXPAT_ARCHIVE_FORMATS=".tar.bz2"
-CT_EXPAT_SIGNATURE_FORMAT=""
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-# CT_GETTEXT_SRC_DEVEL is not set
-# CT_GETTEXT_SRC_CUSTOM is not set
-CT_GETTEXT_PATCH_GLOBAL=y
-# CT_GETTEXT_PATCH_BUNDLED is not set
-# CT_GETTEXT_PATCH_LOCAL is not set
-# CT_GETTEXT_PATCH_BUNDLED_LOCAL is not set
-# CT_GETTEXT_PATCH_LOCAL_BUNDLED is not set
-# CT_GETTEXT_PATCH_NONE is not set
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-# CT_GMP_SRC_DEVEL is not set
-# CT_GMP_SRC_CUSTOM is not set
-CT_GMP_PATCH_GLOBAL=y
-# CT_GMP_PATCH_BUNDLED is not set
-# CT_GMP_PATCH_LOCAL is not set
-# CT_GMP_PATCH_BUNDLED_LOCAL is not set
-# CT_GMP_PATCH_LOCAL_BUNDLED is not set
-# CT_GMP_PATCH_NONE is not set
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-# CT_ISL_SRC_DEVEL is not set
-# CT_ISL_SRC_CUSTOM is not set
-CT_ISL_PATCH_GLOBAL=y
-# CT_ISL_PATCH_BUNDLED is not set
-# CT_ISL_PATCH_LOCAL is not set
-# CT_ISL_PATCH_BUNDLED_LOCAL is not set
-# CT_ISL_PATCH_LOCAL_BUNDLED is not set
-# CT_ISL_PATCH_NONE is not set
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-# CT_LIBICONV_SRC_DEVEL is not set
-# CT_LIBICONV_SRC_CUSTOM is not set
-CT_LIBICONV_PATCH_GLOBAL=y
-# CT_LIBICONV_PATCH_BUNDLED is not set
-# CT_LIBICONV_PATCH_LOCAL is not set
-# CT_LIBICONV_PATCH_BUNDLED_LOCAL is not set
-# CT_LIBICONV_PATCH_LOCAL_BUNDLED is not set
-# CT_LIBICONV_PATCH_NONE is not set
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-# CT_MPC_SRC_DEVEL is not set
-# CT_MPC_SRC_CUSTOM is not set
-CT_MPC_PATCH_GLOBAL=y
-# CT_MPC_PATCH_BUNDLED is not set
-# CT_MPC_PATCH_LOCAL is not set
-# CT_MPC_PATCH_BUNDLED_LOCAL is not set
-# CT_MPC_PATCH_LOCAL_BUNDLED is not set
-# CT_MPC_PATCH_NONE is not set
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-# CT_MPFR_SRC_DEVEL is not set
-# CT_MPFR_SRC_CUSTOM is not set
-CT_MPFR_PATCH_GLOBAL=y
-# CT_MPFR_PATCH_BUNDLED is not set
-# CT_MPFR_PATCH_LOCAL is not set
-# CT_MPFR_PATCH_BUNDLED_LOCAL is not set
-# CT_MPFR_PATCH_LOCAL_BUNDLED is not set
-# CT_MPFR_PATCH_NONE is not set
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-# CT_NCURSES_SRC_DEVEL is not set
-# CT_NCURSES_SRC_CUSTOM is not set
-CT_NCURSES_PATCH_GLOBAL=y
-# CT_NCURSES_PATCH_BUNDLED is not set
-# CT_NCURSES_PATCH_LOCAL is not set
-# CT_NCURSES_PATCH_BUNDLED_LOCAL is not set
-# CT_NCURSES_PATCH_LOCAL_BUNDLED is not set
-# CT_NCURSES_PATCH_NONE is not set
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-# CT_NCURSES_NEW_ABI is not set
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-# CT_ZLIB_SRC_DEVEL is not set
-# CT_ZLIB_SRC_CUSTOM is not set
-CT_ZLIB_PATCH_GLOBAL=y
-# CT_ZLIB_PATCH_BUNDLED is not set
-# CT_ZLIB_PATCH_LOCAL is not set
-# CT_ZLIB_PATCH_BUNDLED_LOCAL is not set
-# CT_ZLIB_PATCH_LOCAL_BUNDLED is not set
-# CT_ZLIB_PATCH_NONE is not set
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="https://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_EXPAT_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_EXPAT=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
-
-#
-# Test suite
-#
-# CT_TEST_SUITE_GCC is not set
diff --git a/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.defconfig
new file mode 100644
index 000000000..10075907b
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.defconfig
@@ -0,0 +1,16 @@
+CT_CONFIG_VERSION="4"
+CT_EXPERIMENTAL=y
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_RISCV=y
+# CT_DEMULTILIB is not set
+CT_ARCH_USE_MMU=y
+CT_ARCH_64=y
+CT_ARCH_ARCH="rv64gc"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_4_20=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_29=y
+CT_GCC_V_8=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile
index adb98d7eb..de776911d 100644
--- a/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile
@@ -1,20 +1,18 @@
-FROM ubuntu:20.04
+FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-COPY scripts/crosstool-ng-1.24.sh /scripts/
-RUN sh /scripts/crosstool-ng-1.24.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
WORKDIR /tmp
-COPY host-x86_64/dist-s390x-linux/s390x-linux-gnu.config host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh /tmp/
-RUN ./build-s390x-toolchain.sh
-
-USER root
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-s390x-linux/s390x-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh b/src/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh
deleted file mode 100755
index 6f8d6be84..000000000
--- a/src/ci/docker/host-x86_64/dist-s390x-linux/build-s390x-toolchain.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-hide_output() {
- set +x
- on_err="
-echo ERROR: An error was encountered with the build.
-cat /tmp/build.log
-exit 1
-"
- trap "$on_err" ERR
- bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
- PING_LOOP_PID=$!
- "$@" &> /tmp/build.log
- rm /tmp/build.log
- trap - ERR
- kill $PING_LOOP_PID
- set -x
-}
-
-mkdir build
-cd build
-cp ../s390x-linux-gnu.config .config
-hide_output ct-ng build
-cd ..
-rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config b/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config
deleted file mode 100644
index 51ef36b03..000000000
--- a/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config
+++ /dev/null
@@ -1,732 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# crosstool-NG Configuration
-#
-CT_CONFIGURE_has_static_link=y
-CT_CONFIGURE_has_cxx11=y
-CT_CONFIGURE_has_wget=y
-CT_CONFIGURE_has_curl=y
-CT_CONFIGURE_has_make_3_81_or_newer=y
-CT_CONFIGURE_has_make_4_0_or_newer=y
-CT_CONFIGURE_has_libtool_2_4_or_newer=y
-CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
-CT_CONFIGURE_has_autoconf_2_65_or_newer=y
-CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
-CT_CONFIGURE_has_automake_1_15_or_newer=y
-CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
-CT_CONFIGURE_has_python_3_4_or_newer=y
-CT_CONFIGURE_has_bison_2_7_or_newer=y
-CT_CONFIGURE_has_python=y
-CT_CONFIGURE_has_git=y
-CT_CONFIGURE_has_md5sum=y
-CT_CONFIGURE_has_sha1sum=y
-CT_CONFIGURE_has_sha256sum=y
-CT_CONFIGURE_has_sha512sum=y
-CT_CONFIGURE_has_install_with_strip_program=y
-CT_CONFIG_VERSION_CURRENT="3"
-CT_CONFIG_VERSION="3"
-CT_MODULES=y
-
-#
-# Paths and misc options
-#
-
-#
-# crosstool-NG behavior
-#
-# CT_OBSOLETE is not set
-# CT_EXPERIMENTAL is not set
-# CT_DEBUG_CT is not set
-
-#
-# Paths
-#
-CT_LOCAL_TARBALLS_DIR="${HOME}/src"
-CT_SAVE_TARBALLS=y
-# CT_TARBALLS_BUILDROOT_LAYOUT is not set
-CT_WORK_DIR="${CT_TOP_DIR}/.build"
-CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
-CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
-CT_RM_RF_PREFIX_DIR=y
-CT_REMOVE_DOCS=y
-CT_INSTALL_LICENSES=y
-CT_PREFIX_DIR_RO=y
-CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
-# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
-
-#
-# Downloading
-#
-CT_DOWNLOAD_AGENT_WGET=y
-# CT_DOWNLOAD_AGENT_CURL is not set
-# CT_DOWNLOAD_AGENT_NONE is not set
-# CT_FORBID_DOWNLOAD is not set
-# CT_FORCE_DOWNLOAD is not set
-CT_CONNECT_TIMEOUT=10
-CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
-# CT_ONLY_DOWNLOAD is not set
-CT_USE_MIRROR=y
-# CT_FORCE_MIRROR is not set
-CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
-CT_VERIFY_DOWNLOAD_DIGEST=y
-CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
-# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
-CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
-# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
-
-#
-# Extracting
-#
-# CT_FORCE_EXTRACT is not set
-CT_OVERRIDE_CONFIG_GUESS_SUB=y
-# CT_ONLY_EXTRACT is not set
-CT_PATCH_BUNDLED=y
-# CT_PATCH_BUNDLED_LOCAL is not set
-CT_PATCH_ORDER="bundled"
-
-#
-# Build behavior
-#
-CT_PARALLEL_JOBS=0
-CT_LOAD=""
-CT_USE_PIPES=y
-CT_EXTRA_CFLAGS_FOR_BUILD=""
-CT_EXTRA_LDFLAGS_FOR_BUILD=""
-CT_EXTRA_CFLAGS_FOR_HOST=""
-CT_EXTRA_LDFLAGS_FOR_HOST=""
-# CT_CONFIG_SHELL_SH is not set
-# CT_CONFIG_SHELL_ASH is not set
-CT_CONFIG_SHELL_BASH=y
-# CT_CONFIG_SHELL_CUSTOM is not set
-CT_CONFIG_SHELL="${bash}"
-
-#
-# Logging
-#
-# CT_LOG_ERROR is not set
-# CT_LOG_WARN is not set
-# CT_LOG_INFO is not set
-CT_LOG_EXTRA=y
-# CT_LOG_ALL is not set
-# CT_LOG_DEBUG is not set
-CT_LOG_LEVEL_MAX="EXTRA"
-# CT_LOG_SEE_TOOLS_WARN is not set
-CT_LOG_PROGRESS_BAR=y
-CT_LOG_TO_FILE=y
-CT_LOG_FILE_COMPRESS=y
-
-#
-# Target options
-#
-# CT_ARCH_ALPHA is not set
-# CT_ARCH_ARC is not set
-# CT_ARCH_ARM is not set
-# CT_ARCH_AVR is not set
-# CT_ARCH_M68K is not set
-# CT_ARCH_MIPS is not set
-# CT_ARCH_NIOS2 is not set
-# CT_ARCH_POWERPC is not set
-CT_ARCH_S390=y
-# CT_ARCH_SH is not set
-# CT_ARCH_SPARC is not set
-# CT_ARCH_X86 is not set
-# CT_ARCH_XTENSA is not set
-CT_ARCH="s390"
-CT_ARCH_CHOICE_KSYM="S390"
-# CT_ARCH_ALPHA_EV4 is not set
-# CT_ARCH_ALPHA_EV45 is not set
-# CT_ARCH_ALPHA_EV5 is not set
-# CT_ARCH_ALPHA_EV56 is not set
-# CT_ARCH_ALPHA_EV6 is not set
-# CT_ARCH_ALPHA_EV67 is not set
-CT_ARCH_S390_SHOW=y
-
-#
-# Options for s390
-#
-CT_ARCH_S390_PKG_KSYM=""
-CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
-CT_ARCH_SUFFIX=""
-# CT_OMIT_TARGET_VENDOR is not set
-
-#
-# Generic target options
-#
-# CT_MULTILIB is not set
-CT_DEMULTILIB=y
-CT_ARCH_USE_MMU=y
-CT_ARCH_SUPPORTS_32=y
-CT_ARCH_SUPPORTS_64=y
-CT_ARCH_DEFAULT_32=y
-CT_ARCH_BITNESS=64
-# CT_ARCH_32 is not set
-CT_ARCH_64=y
-
-#
-# Target optimisations
-#
-CT_ARCH_SUPPORTS_WITH_FPU=y
-CT_ARCH_FPU=""
-CT_TARGET_CFLAGS=""
-CT_TARGET_LDFLAGS=""
-
-#
-# Toolchain options
-#
-
-#
-# General toolchain options
-#
-CT_FORCE_SYSROOT=y
-CT_USE_SYSROOT=y
-CT_SYSROOT_NAME="sysroot"
-CT_SYSROOT_DIR_PREFIX=""
-CT_WANTS_STATIC_LINK=y
-CT_WANTS_STATIC_LINK_CXX=y
-# CT_STATIC_TOOLCHAIN is not set
-CT_SHOW_CT_VERSION=y
-CT_TOOLCHAIN_PKGVERSION=""
-CT_TOOLCHAIN_BUGURL=""
-
-#
-# Tuple completion and aliasing
-#
-CT_TARGET_VENDOR="unknown"
-CT_TARGET_ALIAS_SED_EXPR=""
-CT_TARGET_ALIAS=""
-
-#
-# Toolchain type
-#
-CT_CROSS=y
-# CT_CANADIAN is not set
-CT_TOOLCHAIN_TYPE="cross"
-
-#
-# Build system
-#
-CT_BUILD=""
-CT_BUILD_PREFIX=""
-CT_BUILD_SUFFIX=""
-
-#
-# Misc options
-#
-# CT_TOOLCHAIN_ENABLE_NLS is not set
-
-#
-# Operating System
-#
-CT_KERNEL_SUPPORTS_SHARED_LIBS=y
-# CT_KERNEL_BARE_METAL is not set
-CT_KERNEL_LINUX=y
-CT_KERNEL="linux"
-CT_KERNEL_CHOICE_KSYM="LINUX"
-CT_KERNEL_LINUX_SHOW=y
-
-#
-# Options for linux
-#
-CT_KERNEL_LINUX_PKG_KSYM="LINUX"
-CT_LINUX_DIR_NAME="linux"
-CT_LINUX_PKG_NAME="linux"
-CT_LINUX_SRC_RELEASE=y
-CT_LINUX_PATCH_ORDER="global"
-# CT_LINUX_V_4_20 is not set
-# CT_LINUX_V_4_19 is not set
-# CT_LINUX_V_4_18 is not set
-# CT_LINUX_V_4_17 is not set
-# CT_LINUX_V_4_16 is not set
-# CT_LINUX_V_4_15 is not set
-# CT_LINUX_V_4_14 is not set
-# CT_LINUX_V_4_13 is not set
-# CT_LINUX_V_4_12 is not set
-# CT_LINUX_V_4_11 is not set
-# CT_LINUX_V_4_10 is not set
-# CT_LINUX_V_4_9 is not set
-# CT_LINUX_V_4_4 is not set
-# CT_LINUX_V_4_1 is not set
-# CT_LINUX_V_3_16 is not set
-# CT_LINUX_V_3_13 is not set
-# CT_LINUX_V_3_12 is not set
-# CT_LINUX_V_3_10 is not set
-# CT_LINUX_V_3_4 is not set
-CT_LINUX_V_3_2=y
-# CT_LINUX_V_2_6_32 is not set
-# CT_LINUX_NO_VERSIONS is not set
-CT_LINUX_VERSION="3.2.101"
-CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
-CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
-CT_LINUX_4_8_or_older=y
-CT_LINUX_older_than_4_8=y
-CT_LINUX_3_7_or_older=y
-CT_LINUX_older_than_3_7=y
-CT_LINUX_later_than_3_2=y
-CT_LINUX_3_2_or_later=y
-CT_KERNEL_LINUX_VERBOSITY_0=y
-# CT_KERNEL_LINUX_VERBOSITY_1 is not set
-# CT_KERNEL_LINUX_VERBOSITY_2 is not set
-CT_KERNEL_LINUX_VERBOSE_LEVEL=0
-CT_KERNEL_LINUX_INSTALL_CHECK=y
-CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
-
-#
-# Common kernel options
-#
-CT_SHARED_LIBS=y
-
-#
-# Binary utilities
-#
-CT_ARCH_BINFMT_ELF=y
-CT_BINUTILS_BINUTILS=y
-CT_BINUTILS="binutils"
-CT_BINUTILS_CHOICE_KSYM="BINUTILS"
-CT_BINUTILS_BINUTILS_SHOW=y
-
-#
-# Options for binutils
-#
-CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
-CT_BINUTILS_DIR_NAME="binutils"
-CT_BINUTILS_USE_GNU=y
-CT_BINUTILS_USE="BINUTILS"
-CT_BINUTILS_PKG_NAME="binutils"
-CT_BINUTILS_SRC_RELEASE=y
-CT_BINUTILS_PATCH_ORDER="global"
-CT_BINUTILS_V_2_32=y
-# CT_BINUTILS_V_2_31 is not set
-# CT_BINUTILS_V_2_30 is not set
-# CT_BINUTILS_V_2_29 is not set
-# CT_BINUTILS_V_2_28 is not set
-# CT_BINUTILS_V_2_27 is not set
-# CT_BINUTILS_V_2_26 is not set
-# CT_BINUTILS_NO_VERSIONS is not set
-CT_BINUTILS_VERSION="2.32"
-CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
-CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
-CT_BINUTILS_later_than_2_30=y
-CT_BINUTILS_2_30_or_later=y
-CT_BINUTILS_later_than_2_27=y
-CT_BINUTILS_2_27_or_later=y
-CT_BINUTILS_later_than_2_25=y
-CT_BINUTILS_2_25_or_later=y
-CT_BINUTILS_later_than_2_23=y
-CT_BINUTILS_2_23_or_later=y
-
-#
-# GNU binutils
-#
-CT_BINUTILS_HAS_HASH_STYLE=y
-CT_BINUTILS_HAS_GOLD=y
-CT_BINUTILS_HAS_PLUGINS=y
-CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
-CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
-CT_BINUTILS_LINKER_LD=y
-CT_BINUTILS_LINKERS_LIST="ld"
-CT_BINUTILS_LINKER_DEFAULT="bfd"
-# CT_BINUTILS_PLUGINS is not set
-CT_BINUTILS_RELRO=m
-CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
-# CT_BINUTILS_FOR_TARGET is not set
-CT_ALL_BINUTILS_CHOICES="BINUTILS"
-
-#
-# C-library
-#
-CT_LIBC_GLIBC=y
-# CT_LIBC_NEWLIB is not set
-# CT_LIBC_NONE is not set
-# CT_LIBC_UCLIBC is not set
-CT_LIBC="glibc"
-CT_LIBC_CHOICE_KSYM="GLIBC"
-CT_THREADS="nptl"
-CT_LIBC_GLIBC_SHOW=y
-
-#
-# Options for glibc
-#
-CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
-CT_GLIBC_DIR_NAME="glibc"
-CT_GLIBC_USE_GNU=y
-CT_GLIBC_USE="GLIBC"
-CT_GLIBC_PKG_NAME="glibc"
-CT_GLIBC_SRC_RELEASE=y
-CT_GLIBC_PATCH_ORDER="global"
-# CT_GLIBC_V_2_29 is not set
-# CT_GLIBC_V_2_28 is not set
-# CT_GLIBC_V_2_27 is not set
-# CT_GLIBC_V_2_26 is not set
-# CT_GLIBC_V_2_25 is not set
-# CT_GLIBC_V_2_24 is not set
-# CT_GLIBC_V_2_23 is not set
-# CT_GLIBC_V_2_19 is not set
-CT_GLIBC_V_2_17=y
-# CT_GLIBC_V_2_12_1 is not set
-# CT_GLIBC_NO_VERSIONS is not set
-CT_GLIBC_VERSION="2.17"
-CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
-CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
-CT_GLIBC_2_29_or_older=y
-CT_GLIBC_older_than_2_29=y
-CT_GLIBC_2_27_or_older=y
-CT_GLIBC_older_than_2_27=y
-CT_GLIBC_2_26_or_older=y
-CT_GLIBC_older_than_2_26=y
-CT_GLIBC_2_25_or_older=y
-CT_GLIBC_older_than_2_25=y
-CT_GLIBC_2_24_or_older=y
-CT_GLIBC_older_than_2_24=y
-CT_GLIBC_2_23_or_older=y
-CT_GLIBC_older_than_2_23=y
-CT_GLIBC_2_20_or_older=y
-CT_GLIBC_older_than_2_20=y
-CT_GLIBC_2_17_or_later=y
-CT_GLIBC_2_17_or_older=y
-CT_GLIBC_later_than_2_14=y
-CT_GLIBC_2_14_or_later=y
-CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
-CT_GLIBC_DEP_BINUTILS=y
-CT_GLIBC_DEP_GCC=y
-CT_GLIBC_DEP_PYTHON=y
-CT_GLIBC_HAS_NPTL_ADDON=y
-CT_GLIBC_HAS_PORTS_ADDON=y
-CT_GLIBC_HAS_LIBIDN_ADDON=y
-CT_GLIBC_USE_NPTL_ADDON=y
-# CT_GLIBC_USE_LIBIDN_ADDON is not set
-CT_GLIBC_HAS_OBSOLETE_RPC=y
-CT_GLIBC_EXTRA_CONFIG_ARRAY=""
-CT_GLIBC_CONFIGPARMS=""
-CT_GLIBC_EXTRA_CFLAGS=""
-CT_GLIBC_ENABLE_OBSOLETE_RPC=y
-# CT_GLIBC_DISABLE_VERSIONING is not set
-CT_GLIBC_OLDEST_ABI=""
-CT_GLIBC_FORCE_UNWIND=y
-# CT_GLIBC_LOCALES is not set
-# CT_GLIBC_KERNEL_VERSION_NONE is not set
-CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
-# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
-CT_GLIBC_MIN_KERNEL="3.2.101"
-# CT_GLIBC_SSP_DEFAULT is not set
-# CT_GLIBC_SSP_NO is not set
-# CT_GLIBC_SSP_YES is not set
-# CT_GLIBC_SSP_ALL is not set
-# CT_GLIBC_SSP_STRONG is not set
-# CT_NEWLIB_USE_REDHAT is not set
-CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
-CT_LIBC_SUPPORT_THREADS_ANY=y
-CT_LIBC_SUPPORT_THREADS_NATIVE=y
-
-#
-# Common C library options
-#
-CT_THREADS_NATIVE=y
-# CT_CREATE_LDSO_CONF is not set
-CT_LIBC_XLDD=y
-
-#
-# C compiler
-#
-CT_CC_CORE_PASSES_NEEDED=y
-CT_CC_CORE_PASS_1_NEEDED=y
-CT_CC_CORE_PASS_2_NEEDED=y
-CT_CC_SUPPORT_CXX=y
-CT_CC_SUPPORT_FORTRAN=y
-CT_CC_SUPPORT_ADA=y
-CT_CC_SUPPORT_OBJC=y
-CT_CC_SUPPORT_OBJCXX=y
-CT_CC_SUPPORT_GOLANG=y
-CT_CC_GCC=y
-CT_CC="gcc"
-CT_CC_CHOICE_KSYM="GCC"
-CT_CC_GCC_SHOW=y
-
-#
-# Options for gcc
-#
-CT_CC_GCC_PKG_KSYM="GCC"
-CT_GCC_DIR_NAME="gcc"
-CT_GCC_USE_GNU=y
-CT_GCC_USE="GCC"
-CT_GCC_PKG_NAME="gcc"
-CT_GCC_SRC_RELEASE=y
-CT_GCC_PATCH_ORDER="global"
-CT_GCC_V_8=y
-# CT_GCC_V_7 is not set
-# CT_GCC_V_6 is not set
-# CT_GCC_V_5 is not set
-# CT_GCC_V_4_9 is not set
-# CT_GCC_NO_VERSIONS is not set
-CT_GCC_VERSION="8.3.0"
-CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
-CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_GCC_SIGNATURE_FORMAT=""
-CT_GCC_later_than_7=y
-CT_GCC_7_or_later=y
-CT_GCC_later_than_6=y
-CT_GCC_6_or_later=y
-CT_GCC_later_than_5=y
-CT_GCC_5_or_later=y
-CT_GCC_later_than_4_9=y
-CT_GCC_4_9_or_later=y
-CT_GCC_later_than_4_8=y
-CT_GCC_4_8_or_later=y
-CT_CC_GCC_HAS_LIBMPX=y
-CT_CC_GCC_ENABLE_CXX_FLAGS=""
-CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
-CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-arch=z10"
-CT_CC_GCC_STATIC_LIBSTDCXX=y
-# CT_CC_GCC_SYSTEM_ZLIB is not set
-CT_CC_GCC_CONFIG_TLS=m
-
-#
-# Optimisation features
-#
-CT_CC_GCC_USE_GRAPHITE=y
-CT_CC_GCC_USE_LTO=y
-
-#
-# Settings for libraries running on target
-#
-CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
-# CT_CC_GCC_LIBMUDFLAP is not set
-# CT_CC_GCC_LIBGOMP is not set
-# CT_CC_GCC_LIBSSP is not set
-# CT_CC_GCC_LIBQUADMATH is not set
-# CT_CC_GCC_LIBSANITIZER is not set
-
-#
-# Misc. obscure options.
-#
-CT_CC_CXA_ATEXIT=y
-# CT_CC_GCC_DISABLE_PCH is not set
-CT_CC_GCC_SJLJ_EXCEPTIONS=m
-CT_CC_GCC_LDBL_128=m
-# CT_CC_GCC_BUILD_ID is not set
-CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
-# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
-# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
-# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
-CT_CC_GCC_LNK_HASH_STYLE=""
-CT_CC_GCC_DEC_FLOAT_AUTO=y
-# CT_CC_GCC_DEC_FLOAT_BID is not set
-# CT_CC_GCC_DEC_FLOAT_DPD is not set
-# CT_CC_GCC_DEC_FLOATS_NO is not set
-CT_ALL_CC_CHOICES="GCC"
-
-#
-# Additional supported languages:
-#
-CT_CC_LANG_CXX=y
-# CT_CC_LANG_FORTRAN is not set
-
-#
-# Debug facilities
-#
-# CT_DEBUG_DUMA is not set
-# CT_DEBUG_GDB is not set
-# CT_DEBUG_LTRACE is not set
-# CT_DEBUG_STRACE is not set
-CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
-
-#
-# Companion libraries
-#
-# CT_COMPLIBS_CHECK is not set
-# CT_COMP_LIBS_CLOOG is not set
-# CT_COMP_LIBS_EXPAT is not set
-CT_COMP_LIBS_GETTEXT=y
-CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
-CT_GETTEXT_DIR_NAME="gettext"
-CT_GETTEXT_PKG_NAME="gettext"
-CT_GETTEXT_SRC_RELEASE=y
-CT_GETTEXT_PATCH_ORDER="global"
-CT_GETTEXT_V_0_19_8_1=y
-# CT_GETTEXT_NO_VERSIONS is not set
-CT_GETTEXT_VERSION="0.19.8.1"
-CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
-CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
-CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_GMP=y
-CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
-CT_GMP_DIR_NAME="gmp"
-CT_GMP_PKG_NAME="gmp"
-CT_GMP_SRC_RELEASE=y
-CT_GMP_PATCH_ORDER="global"
-CT_GMP_V_6_1=y
-# CT_GMP_NO_VERSIONS is not set
-CT_GMP_VERSION="6.1.2"
-CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
-CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
-CT_GMP_SIGNATURE_FORMAT="packed/.sig"
-CT_GMP_later_than_5_1_0=y
-CT_GMP_5_1_0_or_later=y
-CT_GMP_later_than_5_0_0=y
-CT_GMP_5_0_0_or_later=y
-CT_GMP_REQUIRE_5_0_0_or_later=y
-CT_COMP_LIBS_ISL=y
-CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
-CT_ISL_DIR_NAME="isl"
-CT_ISL_PKG_NAME="isl"
-CT_ISL_SRC_RELEASE=y
-CT_ISL_PATCH_ORDER="global"
-CT_ISL_V_0_20=y
-# CT_ISL_V_0_19 is not set
-# CT_ISL_V_0_18 is not set
-# CT_ISL_V_0_17 is not set
-# CT_ISL_V_0_16 is not set
-# CT_ISL_V_0_15 is not set
-# CT_ISL_NO_VERSIONS is not set
-CT_ISL_VERSION="0.20"
-CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
-CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
-CT_ISL_SIGNATURE_FORMAT=""
-CT_ISL_later_than_0_18=y
-CT_ISL_0_18_or_later=y
-CT_ISL_later_than_0_15=y
-CT_ISL_0_15_or_later=y
-CT_ISL_REQUIRE_0_15_or_later=y
-CT_ISL_later_than_0_14=y
-CT_ISL_0_14_or_later=y
-CT_ISL_REQUIRE_0_14_or_later=y
-CT_ISL_later_than_0_13=y
-CT_ISL_0_13_or_later=y
-CT_ISL_later_than_0_12=y
-CT_ISL_0_12_or_later=y
-CT_ISL_REQUIRE_0_12_or_later=y
-# CT_COMP_LIBS_LIBELF is not set
-CT_COMP_LIBS_LIBICONV=y
-CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
-CT_LIBICONV_DIR_NAME="libiconv"
-CT_LIBICONV_PKG_NAME="libiconv"
-CT_LIBICONV_SRC_RELEASE=y
-CT_LIBICONV_PATCH_ORDER="global"
-CT_LIBICONV_V_1_15=y
-# CT_LIBICONV_NO_VERSIONS is not set
-CT_LIBICONV_VERSION="1.15"
-CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
-CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
-CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
-CT_COMP_LIBS_MPC=y
-CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
-CT_MPC_DIR_NAME="mpc"
-CT_MPC_PKG_NAME="mpc"
-CT_MPC_SRC_RELEASE=y
-CT_MPC_PATCH_ORDER="global"
-CT_MPC_V_1_1=y
-# CT_MPC_V_1_0 is not set
-# CT_MPC_NO_VERSIONS is not set
-CT_MPC_VERSION="1.1.0"
-CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
-CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPC_ARCHIVE_FORMATS=".tar.gz"
-CT_MPC_SIGNATURE_FORMAT="packed/.sig"
-CT_MPC_1_1_0_or_later=y
-CT_MPC_1_1_0_or_older=y
-CT_COMP_LIBS_MPFR=y
-CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
-CT_MPFR_DIR_NAME="mpfr"
-CT_MPFR_PKG_NAME="mpfr"
-CT_MPFR_SRC_RELEASE=y
-CT_MPFR_PATCH_ORDER="global"
-CT_MPFR_V_4_0=y
-# CT_MPFR_V_3_1 is not set
-# CT_MPFR_NO_VERSIONS is not set
-CT_MPFR_VERSION="4.0.2"
-CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
-CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
-CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
-CT_MPFR_later_than_4_0_0=y
-CT_MPFR_4_0_0_or_later=y
-CT_MPFR_later_than_3_0_0=y
-CT_MPFR_3_0_0_or_later=y
-CT_MPFR_REQUIRE_3_0_0_or_later=y
-CT_COMP_LIBS_NCURSES=y
-CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
-CT_NCURSES_DIR_NAME="ncurses"
-CT_NCURSES_PKG_NAME="ncurses"
-CT_NCURSES_SRC_RELEASE=y
-CT_NCURSES_PATCH_ORDER="global"
-CT_NCURSES_V_6_1=y
-# CT_NCURSES_V_6_0 is not set
-# CT_NCURSES_NO_VERSIONS is not set
-CT_NCURSES_VERSION="6.1"
-CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
-CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
-CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
-CT_NCURSES_HOST_CONFIG_ARGS=""
-CT_NCURSES_HOST_DISABLE_DB=y
-CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
-CT_NCURSES_TARGET_CONFIG_ARGS=""
-# CT_NCURSES_TARGET_DISABLE_DB is not set
-CT_NCURSES_TARGET_FALLBACKS=""
-CT_COMP_LIBS_ZLIB=y
-CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
-CT_ZLIB_DIR_NAME="zlib"
-CT_ZLIB_PKG_NAME="zlib"
-CT_ZLIB_SRC_RELEASE=y
-CT_ZLIB_PATCH_ORDER="global"
-CT_ZLIB_V_1_2_11=y
-# CT_ZLIB_NO_VERSIONS is not set
-CT_ZLIB_VERSION="1.2.11"
-CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
-CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
-CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
-CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
-CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
-CT_LIBICONV_NEEDED=y
-CT_GETTEXT_NEEDED=y
-CT_GMP_NEEDED=y
-CT_MPFR_NEEDED=y
-CT_ISL_NEEDED=y
-CT_MPC_NEEDED=y
-CT_NCURSES_NEEDED=y
-CT_ZLIB_NEEDED=y
-CT_LIBICONV=y
-CT_GETTEXT=y
-CT_GMP=y
-CT_MPFR=y
-CT_ISL=y
-CT_MPC=y
-CT_NCURSES=y
-CT_ZLIB=y
-
-#
-# Companion tools
-#
-# CT_COMP_TOOLS_FOR_HOST is not set
-# CT_COMP_TOOLS_AUTOCONF is not set
-# CT_COMP_TOOLS_AUTOMAKE is not set
-# CT_COMP_TOOLS_BISON is not set
-# CT_COMP_TOOLS_DTC is not set
-# CT_COMP_TOOLS_LIBTOOL is not set
-# CT_COMP_TOOLS_M4 is not set
-# CT_COMP_TOOLS_MAKE is not set
-CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.defconfig
new file mode 100644
index 000000000..1fe219666
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.defconfig
@@ -0,0 +1,13 @@
+CT_CONFIG_VERSION="4"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_S390=y
+CT_ARCH_64=y
+CT_KERNEL_LINUX=y
+CT_LINUX_V_3_2=y
+CT_BINUTILS_V_2_32=y
+CT_GLIBC_V_2_17=y
+CT_GCC_V_8=y
+CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-arch=z10"
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
index 2089bf387..55fefd2b7 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
@@ -6,12 +6,13 @@ RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list
COPY scripts/cross-apt-packages.sh /tmp/
RUN bash /tmp/cross-apt-packages.sh
-# Required for cross-build gcc
+# Required for cross-build gcc, and we install python2 to test general compatibility.
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libgmp-dev \
libmpfr-dev \
libmpc-dev \
+ python2.7 \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/illumos-toolchain.sh /tmp/
@@ -35,4 +36,4 @@ ENV \
ENV HOSTS=x86_64-unknown-illumos
ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
-ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
+ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh
index 41ca1385c..6da3f8922 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh
@@ -22,8 +22,7 @@ cd gcc-$GCC
# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
# instead here.
#
-# FIXME: use HTTPS (see https://github.com/rust-lang/rust/pull/86586#issuecomment-868355356)
-sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
+sed -i'' 's|ftp://gcc\.gnu\.org/|https://gcc.gnu.org/|g' ./contrib/download_prerequisites
./contrib/download_prerequisites
mkdir ../gcc-build
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
index 13eaf7fce..6f04dcad9 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
@@ -25,7 +25,6 @@ WORKDIR /build/
COPY scripts/cmake.sh /scripts/
RUN /scripts/cmake.sh
-COPY scripts/musl-patch-configure.diff /build/
COPY scripts/musl-toolchain.sh /build/
# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
RUN CFLAGS="-Wa,-mrelax-relocations=no -Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \
diff --git a/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh b/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh
index 0b06f5e36..a5691da8c 100755
--- a/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh
+++ b/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# A quick smoke test to make sure publish_tooolstate.py works.
+# A quick smoke test to make sure publish_toolstate.py works.
set -euo pipefail
IFS=$'\n\t'
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index 62e3f627e..1dc7b7987 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -33,7 +33,6 @@ RUN curl -sL --output ovmf-ia32.deb http://mirrors.kernel.org/ubuntu/pool/univer
RUN dpkg -i ovmf-ia32.deb && rm ovmf-ia32.deb
WORKDIR /build/
-COPY scripts/musl-patch-configure.diff /build/
COPY scripts/musl-toolchain.sh /build/
RUN bash musl-toolchain.sh x86_64 && rm -rf build
WORKDIR /
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile
index 21dcf29b4..d45ef0a7d 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile
@@ -32,6 +32,10 @@ RUN sh /scripts/sccache.sh
# LLVM, rather than the typical src/llvm-project LLVM.
ENV NO_DOWNLOAD_CI_LLVM 1
+# This is not the latest LLVM version, so some components required by tests may
+# be missing.
+ENV IS_NOT_LATEST_LLVM 1
+
# Using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile
index cfb638e8b..1f28b9397 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile
@@ -38,6 +38,10 @@ RUN sh /scripts/sccache.sh
# LLVM, rather than the typical src/llvm-project LLVM.
ENV NO_DOWNLOAD_CI_LLVM 1
+# This is not the latest LLVM version, so some components required by tests may
+# be missing.
+ENV IS_NOT_LATEST_LLVM 1
+
# Using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
index fb5037e3b..960683b92 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
@@ -2,7 +2,6 @@ FROM ubuntu:22.10
ARG DEBIAN_FRONTEND=noninteractive
-# NOTE: intentionally installs both python2 and python3 so we can test support for both.
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
gcc-multilib \
@@ -11,7 +10,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
file \
curl \
ca-certificates \
- python2.7 \
python3 \
git \
cmake \
@@ -40,6 +38,10 @@ RUN sh /scripts/sccache.sh
# LLVM, rather than the typical src/llvm-project LLVM.
ENV NO_DOWNLOAD_CI_LLVM 1
+# This is not the latest LLVM version, so some components required by tests may
+# be missing.
+ENV IS_NOT_LATEST_LLVM 1
+
# Using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
@@ -63,6 +65,4 @@ ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
# work.
#
../x.ps1 --stage 2 test tests/ui --pass=check \
- --host='' --target=i686-unknown-linux-gnu && \
- # Run tidy at the very end, after all the other tests.
- python2.7 ../x.py --stage 2 test src/tools/tidy
+ --host='' --target=i686-unknown-linux-gnu
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
new file mode 100644
index 000000000..7c75d0df5
--- /dev/null
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
@@ -0,0 +1,64 @@
+FROM ubuntu:23.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ g++ \
+ gcc-multilib \
+ make \
+ ninja-build \
+ file \
+ curl \
+ ca-certificates \
+ python3 \
+ git \
+ cmake \
+ sudo \
+ gdb \
+ llvm-16-tools \
+ llvm-16-dev \
+ libedit-dev \
+ libssl-dev \
+ pkg-config \
+ zlib1g-dev \
+ xz-utils \
+ nodejs \
+ mingw-w64 \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install powershell (universal package) so we can test x.ps1 on Linux
+RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
+ dpkg -i powershell.deb && \
+ rm -f powershell.deb
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+ --build=x86_64-unknown-linux-gnu \
+ --llvm-root=/usr/lib/llvm-16 \
+ --enable-llvm-link-shared \
+ --set rust.thin-lto-import-instr-limit=10
+
+# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
+ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
+ # Run the `mir-opt` tests again but this time for a 32-bit target.
+ # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
+ # both 32-bit and 64-bit outputs updated by the PR author, before
+ # the PR is approved and tested for merging.
+ # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
+ # despite having different output on 32-bit vs 64-bit targets.
+ ../x --stage 2 test tests/mir-opt \
+ --host='' --target=i686-unknown-linux-gnu && \
+ # Run the UI test suite again, but in `--pass=check` mode
+ #
+ # This is intended to make sure that both `--pass=check` continues to
+ # work.
+ #
+ ../x.ps1 --stage 2 test tests/ui --pass=check \
+ --host='' --target=i686-unknown-linux-gnu
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 7092c7c46..806935b82 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.15.0 \ No newline at end of file
+0.16.4 \ No newline at end of file
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 69d4916e5..8bea8cd4c 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -169,6 +169,7 @@ if [ "$SCCACHE_BUCKET" != "" ]; then
args="$args --env SCCACHE_REGION"
args="$args --env AWS_ACCESS_KEY_ID"
args="$args --env AWS_SECRET_ACCESS_KEY"
+ args="$args --env AWS_REGION"
else
mkdir -p $HOME/.cache/sccache
args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache"
diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh
index 2f8bf1194..398362ca5 100644
--- a/src/ci/docker/scripts/cross-apt-packages.sh
+++ b/src/ci/docker/scripts/cross-apt-packages.sh
@@ -22,6 +22,7 @@ apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install
patch \
pkg-config \
python3 \
+ rsync \
sudo \
texinfo \
unzip \
diff --git a/src/ci/docker/scripts/crosstool-ng-1.24.sh b/src/ci/docker/scripts/crosstool-ng-1.24.sh
deleted file mode 100644
index 3a40f6cdd..000000000
--- a/src/ci/docker/scripts/crosstool-ng-1.24.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-set -ex
-
-# Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz
-url="https://ci-mirrors.rust-lang.org/rustc/crosstool-ng-1.24.0.tar.gz"
-curl -Lf $url | tar xzf -
-cd crosstool-ng-crosstool-ng-1.24.0
-./bootstrap
-./configure --prefix=/usr/local
-make -j$(nproc)
-make install
-cd ..
-rm -rf crosstool-ng-crosstool-ng-1.24.0
diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh b/src/ci/docker/scripts/crosstool-ng-build.sh
index 6b5374422..c813d10eb 100755
--- a/src/ci/docker/host-x86_64/dist-armhf-linux/build-toolchains.sh
+++ b/src/ci/docker/scripts/crosstool-ng-build.sh
@@ -2,6 +2,10 @@
set -ex
+if [ $UID -eq 0 ]; then
+ exec su rustbuild -c "$0"
+fi
+
hide_output() {
set +x
on_err="
@@ -21,9 +25,8 @@ exit 1
mkdir build
cd build
-cp ../arm-linux-gnueabihf.config .config
-# FIXME ct-ng oldconfig is not working as intended.
-# ct-ng oldconfig
+cp ../crosstool.defconfig .config
+ct-ng olddefconfig
hide_output ct-ng build
cd ..
rm -rf build
diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh
new file mode 100644
index 000000000..449cc476f
--- /dev/null
+++ b/src/ci/docker/scripts/crosstool-ng-git.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -ex
+
+URL=https://github.com/crosstool-ng/crosstool-ng
+REV=943364711a650d9b9e84c1b42c91cc0265b6ab5c
+
+mkdir crosstool-ng
+cd crosstool-ng
+git init
+git fetch --depth=1 ${URL} ${REV}
+git reset --hard FETCH_HEAD
+./bootstrap
+./configure --prefix=/usr/local
+make -j$(nproc)
+make install
+cd ..
+rm -rf crosstool-ng
diff --git a/src/ci/docker/scripts/crosstool-ng.sh b/src/ci/docker/scripts/crosstool-ng.sh
index 1d0c28c8e..a28d7bde2 100644
--- a/src/ci/docker/scripts/crosstool-ng.sh
+++ b/src/ci/docker/scripts/crosstool-ng.sh
@@ -1,12 +1,19 @@
#!/bin/sh
set -ex
-url="https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.22.0.tar.gz"
+CT_NG=1.25.0
+
+url="https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-$CT_NG.tar.gz"
curl -Lf $url | tar xzf -
-cd crosstool-ng-crosstool-ng-1.22.0
+cd crosstool-ng-crosstool-ng-$CT_NG
+
+# https://github.com/crosstool-ng/crosstool-ng/issues/1832
+# "download source of zlib is invalid now"
+sed -e "s|zlib.net/'|zlib.net/fossils'|" -i packages/zlib/package.desc
+
./bootstrap
./configure --prefix=/usr/local
make -j$(nproc)
make install
cd ..
-rm -rf crosstool-ng-crosstool-ng-1.22.0
+rm -rf crosstool-ng-crosstool-ng-$CT_NG
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index e7d1d9781..ecef56f56 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -168,85 +168,17 @@ class TestEnvironment:
def ffx_isolate_dir(self):
return os.path.join(self.tmp_dir(), "ffx_isolate")
- def ffx_home_dir(self):
- return os.path.join(self.ffx_isolate_dir(), "user-home")
+ def home_dir(self):
+ return os.path.join(self.tmp_dir(), "user-home")
- def ffx_tmp_dir(self):
- return os.path.join(self.ffx_isolate_dir(), "tmp")
-
- def ffx_log_dir(self):
- return os.path.join(self.ffx_isolate_dir(), "log")
-
- def ffx_user_config_dir(self):
- return os.path.join(self.ffx_xdg_config_home(), "Fuchsia", "ffx", "config")
-
- def ffx_user_config_path(self):
- return os.path.join(self.ffx_user_config_dir(), "config.json")
-
- def ffx_xdg_config_home(self):
- if platform.system() == "Darwin":
- return os.path.join(self.ffx_home_dir(), "Library", "Preferences")
- return os.path.join(self.ffx_home_dir(), ".local", "share")
-
- def ffx_ascendd_path(self):
- return os.path.join(self.ffx_tmp_dir(), "ascendd")
def start_ffx_isolation(self):
# Most of this is translated directly from ffx's isolate library
os.mkdir(self.ffx_isolate_dir())
- os.mkdir(self.ffx_home_dir())
- os.mkdir(self.ffx_tmp_dir())
- os.mkdir(self.ffx_log_dir())
-
- fuchsia_dir = os.path.join(self.ffx_home_dir(), ".fuchsia")
- os.mkdir(fuchsia_dir)
-
- fuchsia_debug_dir = os.path.join(fuchsia_dir, "debug")
- os.mkdir(fuchsia_debug_dir)
-
- metrics_dir = os.path.join(fuchsia_dir, "metrics")
- os.mkdir(metrics_dir)
+ os.mkdir(self.home_dir())
- analytics_path = os.path.join(metrics_dir, "analytics-status")
- with open(analytics_path, "w", encoding="utf-8") as analytics_file:
- print("0", file=analytics_file)
-
- ffx_path = os.path.join(metrics_dir, "ffx")
- with open(ffx_path, "w", encoding="utf-8") as ffx_file:
- print("1", file=ffx_file)
-
- os.makedirs(self.ffx_user_config_dir())
-
- with open(
- self.ffx_user_config_path(), "w", encoding="utf-8"
- ) as config_json_file:
- user_config_for_test = {
- "log": {
- "enabled": True,
- "dir": self.ffx_log_dir(),
- },
- "overnet": {
- "socket": self.ffx_ascendd_path(),
- },
- "ssh": {
- "pub": self.ssh_authfile_path(),
- "priv": self.ssh_keyfile_path(),
- },
- "test": {
- "is_isolated": True,
- "experimental_structured_output": True,
- },
- }
- print(json.dumps(user_config_for_test), file=config_json_file)
-
- ffx_env_path = os.path.join(self.ffx_user_config_dir(), ".ffx_env")
- with open(ffx_env_path, "w", encoding="utf-8") as ffx_env_file:
- ffx_env_config_for_test = {
- "user": self.ffx_user_config_path(),
- "build": None,
- "global": None,
- }
- print(json.dumps(ffx_env_config_for_test), file=ffx_env_file)
+ ffx_path = self.tool_path("ffx")
+ ffx_env = self.ffx_cmd_env()
# Start ffx daemon
# We want this to be a long-running process that persists after the script finishes
@@ -256,23 +188,54 @@ class TestEnvironment:
) as ffx_daemon_log_file:
subprocess.Popen(
[
- self.tool_path("ffx"),
- "--config",
- self.ffx_user_config_path(),
+ ffx_path,
"daemon",
"start",
],
- env=self.ffx_cmd_env(),
+ env=ffx_env,
stdout=ffx_daemon_log_file,
stderr=ffx_daemon_log_file,
)
+ # Disable analytics
+ subprocess.check_call(
+ [
+ ffx_path,
+ "config",
+ "analytics",
+ "disable",
+ ],
+ env=ffx_env,
+ stdout=self.subprocess_output(),
+ stderr=self.subprocess_output(),
+ )
+
+ # Set configs
+ configs = {
+ "log.enabled": "true",
+ "ssh.pub": self.ssh_authfile_path(),
+ "ssh.priv": self.ssh_keyfile_path(),
+ "test.is_isolated": "true",
+ "test.experimental_structured_output": "true",
+ }
+ for key, value in configs.items():
+ subprocess.check_call(
+ [
+ self.tool_path("ffx"),
+ "config",
+ "set",
+ key,
+ value,
+ ],
+ env=self.ffx_cmd_env(),
+ stdout=self.subprocess_output(),
+ stderr=self.subprocess_output(),
+ )
+
def ffx_cmd_env(self):
- result = {
- "HOME": self.ffx_home_dir(),
- "XDG_CONFIG_HOME": self.ffx_xdg_config_home(),
- "ASCENDD": self.ffx_ascendd_path(),
- "FUCHSIA_SSH_KEY": self.ssh_keyfile_path(),
+ return {
+ "HOME": self.home_dir(),
+ "FFX_ISOLATE_DIR": self.ffx_isolate_dir(),
# We want to use our own specified temp directory
"TMP": self.tmp_dir(),
"TEMP": self.tmp_dir(),
@@ -280,14 +243,10 @@ class TestEnvironment:
"TEMPDIR": self.tmp_dir(),
}
- return result
-
def stop_ffx_isolation(self):
subprocess.check_call(
[
self.tool_path("ffx"),
- "--config",
- self.ffx_user_config_path(),
"daemon",
"stop",
],
@@ -709,8 +668,6 @@ class TestEnvironment:
subprocess.run(
[
self.tool_path("ffx"),
- "--config",
- self.ffx_user_config_path(),
"test",
"run",
f"fuchsia-pkg://{self.TEST_REPO_NAME}/{package_name}#meta/{package_name}.cm",
@@ -849,8 +806,6 @@ class TestEnvironment:
def debug(self, args):
command = [
self.tool_path("ffx"),
- "--config",
- self.ffx_user_config_path(),
"debug",
"connect",
"--",
@@ -948,8 +903,6 @@ class TestEnvironment:
subprocess.run(
[
self.tool_path("ffx"),
- "--config",
- self.ffx_user_config_path(),
"log",
"--since",
"now",
diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh
index e358b8139..bc1b30e2d 100644
--- a/src/ci/docker/scripts/musl-toolchain.sh
+++ b/src/ci/docker/scripts/musl-toolchain.sh
@@ -4,7 +4,7 @@
#
# Versions of the toolchain components are configurable in `musl-cross-make/Makefile` and
# musl unlike GLIBC is forward compatible so upgrading it shouldn't break old distributions.
-# Right now we have: Binutils 2.31.1, GCC 9.2.0, musl 1.1.24.
+# Right now we have: Binutils 2.31.1, GCC 9.2.0, musl 1.2.3.
# ignore-tidy-linelength
@@ -32,6 +32,7 @@ TARGET=$ARCH-linux-musl
# Don't depend on the mirrors of sabotage linux that musl-cross-make uses.
LINUX_HEADERS_SITE=https://ci-mirrors.rust-lang.org/rustc/sabotage-linux-tarballs
+LINUX_VER=headers-4.19.88
OUTPUT=/usr/local
shift
@@ -44,18 +45,11 @@ export CFLAGS="-fPIC -g1 $CFLAGS"
git clone https://github.com/richfelker/musl-cross-make # -b v0.9.9
cd musl-cross-make
-# A few commits ahead of v0.9.9 to include the cowpatch fix:
-git checkout a54eb56f33f255dfca60be045f12a5cfaf5a72a9
+# A version that includes support for building musl 1.2.3
+git checkout fe915821b652a7fa37b34a596f47d8e20bc72338
-# Fix the cfi detection script in musl's configure so cfi is generated
-# when debug info is asked for. This patch is derived from
-# https://git.musl-libc.org/cgit/musl/commit/?id=c4d4028dde90562f631edf559fbc42d8ec1b29de.
-# When we upgrade to a version that includes this commit, we can remove the patch.
-mkdir patches/musl-1.1.24
-cp ../musl-patch-configure.diff patches/musl-1.1.24/0001-fix-cfi-detection.diff
-
-hide_output make -j$(nproc) TARGET=$TARGET MUSL_VER=1.1.24 LINUX_HEADERS_SITE=$LINUX_HEADERS_SITE
-hide_output make install TARGET=$TARGET MUSL_VER=1.1.24 LINUX_HEADERS_SITE=$LINUX_HEADERS_SITE OUTPUT=$OUTPUT
+hide_output make -j$(nproc) TARGET=$TARGET MUSL_VER=1.2.3 LINUX_HEADERS_SITE=$LINUX_HEADERS_SITE LINUX_VER=$LINUX_VER
+hide_output make install TARGET=$TARGET MUSL_VER=1.2.3 LINUX_HEADERS_SITE=$LINUX_HEADERS_SITE LINUX_VER=$LINUX_VER OUTPUT=$OUTPUT
cd -
diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh
index 3e5dc4af0..ece8e6c15 100644
--- a/src/ci/docker/scripts/musl.sh
+++ b/src/ci/docker/scripts/musl.sh
@@ -25,7 +25,7 @@ shift
# Apparently applying `-fPIC` everywhere allows them to link successfully.
export CFLAGS="-fPIC $CFLAGS"
-MUSL=musl-1.1.24
+MUSL=musl-1.2.3
# may have been downloaded in a previous run
if [ ! -d $MUSL ]; then
diff --git a/src/ci/docker/scripts/qemu-bare-bones-rcS b/src/ci/docker/scripts/qemu-bare-bones-rcS
index 3c29bedc1..c5d807b2d 100644
--- a/src/ci/docker/scripts/qemu-bare-bones-rcS
+++ b/src/ci/docker/scripts/qemu-bare-bones-rcS
@@ -9,7 +9,7 @@ mount -t sysfs none /sys
/addentropy < /addentropy
cat /dev/urandom | head -n 2048 | /addentropy
-# Set up IP that qemu expects. This confgures eth0 with the public IP that QEMU
+# Set up IP that qemu expects. This configures eth0 with the public IP that QEMU
# will communicate to as well as the loopback 127.0.0.1 address.
ifconfig eth0 10.0.2.15
ifconfig lo up
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index bfca7b3ab..fd619467f 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -53,6 +53,7 @@ x--expand-yaml-anchors--remove:
# (caches, artifacts...).
CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
+ AWS_REGION: us-west-1
CACHE_DOMAIN: ci-caches.rust-lang.org
- &dummy-variables
@@ -68,11 +69,16 @@ x--expand-yaml-anchors--remove:
# (caches, artifacts...).
CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5
ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF
+ AWS_REGION: us-west-1
CACHE_DOMAIN: ci-caches-gha.rust-lang.org
- &base-job
env: {}
+ - &job-linux-4c
+ os: ubuntu-20.04-4core-16gb
+ <<: *base-job
+
- &job-linux-8c
os: ubuntu-20.04-8core-32gb
<<: *base-job
@@ -154,10 +160,6 @@ x--expand-yaml-anchors--remove:
run: src/ci/scripts/dump-environment.sh
<<: *step
- - name: install awscli
- run: src/ci/scripts/install-awscli.sh
- <<: *step
-
- name: install sccache
run: src/ci/scripts/install-sccache.sh
<<: *step
@@ -296,25 +298,21 @@ jobs:
env:
<<: [*shared-ci-variables, *public-variables]
if: github.event_name == 'pull_request'
- continue-on-error: ${{ matrix.tidy }}
+ continue-on-error: ${{ matrix.name == 'mingw-check-tidy' }}
strategy:
matrix:
include:
- name: mingw-check
<<: *job-linux-16c
- tidy: false
- name: mingw-check-tidy
<<: *job-linux-16c
- tidy: true
- name: x86_64-gnu-llvm-14
<<: *job-linux-16c
- tidy: false
- name: x86_64-gnu-tools
<<: *job-linux-16c
- tidy: false
auto:
permissions:
@@ -361,6 +359,9 @@ jobs:
- name: dist-i686-linux
<<: *job-linux-8c
+ - name: dist-loongarch64-linux
+ <<: *job-linux-8c
+
- name: dist-mips-linux
<<: *job-linux-8c
@@ -416,13 +417,13 @@ jobs:
<<: *job-linux-8c
- name: i686-gnu
- <<: *job-linux-16c
+ <<: *job-linux-8c
- name: i686-gnu-nopt
- <<: *job-linux-16c
+ <<: *job-linux-8c
- name: mingw-check
- <<: *job-linux-8c
+ <<: *job-linux-4c
- name: test-various
<<: *job-linux-8c
@@ -431,7 +432,7 @@ jobs:
<<: *job-linux-8c
- name: x86_64-gnu
- <<: *job-linux-8c
+ <<: *job-linux-4c
# This job ensures commits landing on nightly still pass the full
# test suite on the stable channel. There are some UI tests that
@@ -446,10 +447,10 @@ jobs:
# could cause failures when `dev: 1` in `stage0.txt`, and running
# this on stable is useless.
CI_ONLY_WHEN_CHANNEL: nightly
- <<: *job-linux-8c
+ <<: *job-linux-4c
- name: x86_64-gnu-aux
- <<: *job-linux-8c
+ <<: *job-linux-4c
- name: x86_64-gnu-debug
<<: *job-linux-8c
@@ -457,6 +458,11 @@ jobs:
- name: x86_64-gnu-distcheck
<<: *job-linux-8c
+ - name: x86_64-gnu-llvm-16
+ env:
+ RUST_BACKTRACE: 1
+ <<: *job-linux-8c
+
- name: x86_64-gnu-llvm-15
env:
RUST_BACKTRACE: 1
@@ -473,7 +479,7 @@ jobs:
<<: *job-linux-8c
- name: x86_64-gnu-nopt
- <<: *job-linux-8c
+ <<: *job-linux-4c
- name: x86_64-gnu-tools
env:
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 3056d9fc0..966af3abc 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -143,7 +143,11 @@ if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ]
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-missing-tools"
fi
-export COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS=1
+# Unless we're using an older version of LLVM, check that all LLVM components
+# used by tests are available.
+if [ "$IS_NOT_LATEST_LLVM" = "" ]; then
+ export COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS=1
+fi
# Print the date from the local machine and the date from an external source to
# check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure
diff --git a/src/ci/scripts/install-awscli.sh b/src/ci/scripts/install-awscli.sh
deleted file mode 100755
index aa62407ea..000000000
--- a/src/ci/scripts/install-awscli.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-# This script downloads and installs awscli from the packages mirrored in our
-# own S3 bucket. This follows the recommendations at:
-#
-# https://packaging.python.org/guides/index-mirrors-and-caches/#caching-with-pip
-#
-# To create a new mirrored copy you can run the command:
-#
-# pip wheel awscli
-#
-# Before compressing please make sure all the wheels end with `-none-any.whl`.
-# If that's not the case you'll need to remove the non-cross-platform ones and
-# replace them with the .tar.gz downloaded from https://pypi.org.
-
-set -euo pipefail
-IFS=$'\n\t'
-
-source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
-
-MIRROR="${MIRRORS_BASE}/2023-04-28-awscli.tar"
-DEPS_DIR="/tmp/awscli-deps"
-
-pip="pip"
-pipflags=""
-if isLinux; then
- pip="pip3"
- pipflags="--user"
-
- sudo apt-get install -y python3-setuptools python3-wheel
- ciCommandAddPath "${HOME}/.local/bin"
-elif isMacOS; then
- pip="pip3"
-fi
-
-mkdir -p "${DEPS_DIR}"
-curl "${MIRROR}" | tar xf - -C "${DEPS_DIR}"
-"${pip}" install ${pipflags} --no-index "--find-links=${DEPS_DIR}" awscli
-rm -rf "${DEPS_DIR}"
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index 7cd5e88f6..8d03d3759 100644
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -48,7 +48,6 @@ RUSTC_PGO_CRATES = [
LLVM_BOLT_CRATES = LLVM_PGO_CRATES
-
class Pipeline:
# Paths
def checkout_path(self) -> Path:
@@ -451,6 +450,44 @@ def cmd(
)
return subprocess.run(args, env=environment, check=True)
+class BenchmarkRunner:
+ def run_rustc(self, pipeline: Pipeline):
+ raise NotImplementedError
+
+ def run_llvm(self, pipeline: Pipeline):
+ raise NotImplementedError
+
+ def run_bolt(self, pipeline: Pipeline):
+ raise NotImplementedError
+
+class DefaultBenchmarkRunner(BenchmarkRunner):
+ def run_rustc(self, pipeline: Pipeline):
+ # Here we're profiling the `rustc` frontend, so we also include `Check`.
+ # The benchmark set includes various stress tests that put the frontend under pressure.
+ run_compiler_benchmarks(
+ pipeline,
+ profiles=["Check", "Debug", "Opt"],
+ scenarios=["All"],
+ crates=RUSTC_PGO_CRATES,
+ env=dict(
+ LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
+ )
+ )
+ def run_llvm(self, pipeline: Pipeline):
+ run_compiler_benchmarks(
+ pipeline,
+ profiles=["Debug", "Opt"],
+ scenarios=["Full"],
+ crates=LLVM_PGO_CRATES
+ )
+
+ def run_bolt(self, pipeline: Pipeline):
+ run_compiler_benchmarks(
+ pipeline,
+ profiles=["Check", "Debug", "Opt"],
+ scenarios=["Full"],
+ crates=LLVM_BOLT_CRATES
+ )
def run_compiler_benchmarks(
pipeline: Pipeline,
@@ -580,14 +617,10 @@ def create_pipeline() -> Pipeline:
raise Exception(f"Optimized build is not supported for platform {sys.platform}")
-def gather_llvm_profiles(pipeline: Pipeline):
+def gather_llvm_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
LOGGER.info("Running benchmarks with PGO instrumented LLVM")
- run_compiler_benchmarks(
- pipeline,
- profiles=["Debug", "Opt"],
- scenarios=["Full"],
- crates=LLVM_PGO_CRATES
- )
+
+ runner.run_llvm(pipeline)
profile_path = pipeline.llvm_profile_merged_file()
LOGGER.info(f"Merging LLVM PGO profiles to {profile_path}")
@@ -609,20 +642,12 @@ def gather_llvm_profiles(pipeline: Pipeline):
delete_directory(pipeline.llvm_profile_dir_root())
-def gather_rustc_profiles(pipeline: Pipeline):
+def gather_rustc_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
LOGGER.info("Running benchmarks with PGO instrumented rustc")
- # Here we're profiling the `rustc` frontend, so we also include `Check`.
- # The benchmark set includes various stress tests that put the frontend under pressure.
- run_compiler_benchmarks(
- pipeline,
- profiles=["Check", "Debug", "Opt"],
- scenarios=["All"],
- crates=RUSTC_PGO_CRATES,
- env=dict(
- LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
- )
- )
+
+ runner.run_rustc(pipeline)
+
profile_path = pipeline.rustc_profile_merged_file()
LOGGER.info(f"Merging Rustc PGO profiles to {profile_path}")
@@ -644,14 +669,10 @@ def gather_rustc_profiles(pipeline: Pipeline):
delete_directory(pipeline.rustc_profile_dir_root())
-def gather_llvm_bolt_profiles(pipeline: Pipeline):
+def gather_llvm_bolt_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
LOGGER.info("Running benchmarks with BOLT instrumented LLVM")
- run_compiler_benchmarks(
- pipeline,
- profiles=["Check", "Debug", "Opt"],
- scenarios=["Full"],
- crates=LLVM_BOLT_CRATES
- )
+
+ runner.run_bolt(pipeline)
merged_profile_path = pipeline.llvm_bolt_profile_merged_file()
profile_files_path = Path("/tmp/prof.fdata")
@@ -744,7 +765,7 @@ def record_metrics(pipeline: Pipeline, timer: Timer):
log_metrics(metrics)
-def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: List[str]):
+def execute_build_pipeline(timer: Timer, pipeline: Pipeline, runner: BenchmarkRunner, final_build_args: List[str]):
# Clear and prepare tmp directory
shutil.rmtree(pipeline.opt_artifacts(), ignore_errors=True)
os.makedirs(pipeline.opt_artifacts(), exist_ok=True)
@@ -762,7 +783,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
record_metrics(pipeline, rustc_build)
with stage1.section("Gather profiles"):
- gather_llvm_profiles(pipeline)
+ gather_llvm_profiles(pipeline, runner)
print_free_disk_space(pipeline)
clear_llvm_files(pipeline)
@@ -781,7 +802,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
record_metrics(pipeline, rustc_build)
with stage2.section("Gather profiles"):
- gather_rustc_profiles(pipeline)
+ gather_rustc_profiles(pipeline, runner)
print_free_disk_space(pipeline)
clear_llvm_files(pipeline)
@@ -804,7 +825,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
record_metrics(pipeline, rustc_build)
with stage3.section("Gather profiles"):
- gather_llvm_bolt_profiles(pipeline)
+ gather_llvm_bolt_profiles(pipeline, runner)
# LLVM is not being cleared here, we want to reuse the previous build
print_free_disk_space(pipeline)
@@ -819,7 +840,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
record_metrics(pipeline, stage4)
-if __name__ == "__main__":
+def run(runner: BenchmarkRunner):
logging.basicConfig(
level=logging.DEBUG,
format="%(name)s %(levelname)-4s: %(message)s",
@@ -832,8 +853,9 @@ if __name__ == "__main__":
timer = Timer()
pipeline = create_pipeline()
+
try:
- execute_build_pipeline(timer, pipeline, build_args)
+ execute_build_pipeline(timer, pipeline, runner, build_args)
except BaseException as e:
LOGGER.error("The multi-stage build has failed")
raise e
@@ -842,3 +864,7 @@ if __name__ == "__main__":
print_free_disk_space(pipeline)
print_binary_sizes(pipeline)
+
+if __name__ == "__main__":
+ runner = DefaultBenchmarkRunner()
+ run(runner)
diff --git a/src/doc/book/LICENSE-APACHE b/src/doc/book/LICENSE-APACHE
index 16fe87b06..38634daab 100644
--- a/src/doc/book/LICENSE-APACHE
+++ b/src/doc/book/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 [yyyy] [name of copyright owner]
+Copyright 2010 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/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md
index 434352943..d4ebd23bf 100644
--- a/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md
+++ b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md
@@ -13,7 +13,7 @@ The following sections dig into the details of these steps, and some of the issu
> It's our intention that the migration to new editions is as smooth an
> experience as possible. If it's difficult for you to upgrade to the latest edition,
> we consider that a bug. If you run into problems with this process, please
-> [file a bug](https://github.com/rust-lang/rust/issues/new/choose). Thank you!
+> [file a bug report](https://github.com/rust-lang/rust/issues/new/choose). Thank you!
## Starting the migration
diff --git a/src/doc/embedded-book/src/interoperability/c-with-rust.md b/src/doc/embedded-book/src/interoperability/c-with-rust.md
index 6bec3bd87..9c56c6aaa 100644
--- a/src/doc/embedded-book/src/interoperability/c-with-rust.md
+++ b/src/doc/embedded-book/src/interoperability/c-with-rust.md
@@ -127,7 +127,9 @@ In the simplest case of compiling a single C file as a dependency to a static li
```rust,ignore
fn main() {
cc::Build::new()
- .file("foo.c")
- .compile("libfoo.a");
+ .file("src/foo.c")
+ .compile("foo");
}
```
+
+The `build.rs` is placed at the root of the package. Then `cargo build` will compile and execute it before the build of the package. A static archive named `libfoo.a` is generated and placed in the `target` directory.
diff --git a/src/doc/embedded-book/src/interoperability/index.md b/src/doc/embedded-book/src/interoperability/index.md
index 4ff5fd9df..267bd6788 100644
--- a/src/doc/embedded-book/src/interoperability/index.md
+++ b/src/doc/embedded-book/src/interoperability/index.md
@@ -2,40 +2,42 @@
Interoperability between Rust and C code is always dependent
on transforming data between the two languages.
-For this purposes there are two dedicated modules
+For this purpose, there is a dedicated module
in the `stdlib` called
-[`std::ffi`](https://doc.rust-lang.org/std/ffi/index.html) and
-[`std::os::raw`](https://doc.rust-lang.org/std/os/raw/index.html).
+[`std::ffi`](https://doc.rust-lang.org/std/ffi/index.html).
-`std::os::raw` deals with low-level primitive types that can
-be converted implicitly by the compiler
-because the memory layout between Rust and C
-is similar enough or the same.
+`std::ffi` provides type definitions for C primitive types,
+such as `char`, `int`, and `long`.
+It also provides some utility for converting more complex
+types such as strings, mapping both `&str` and `String`
+to C types that are easier and safer to handle.
-`std::ffi` provides some utility for converting more complex
-types such as Strings, mapping both `&str` and `String`
-to C-types that are easier and safer to handle.
-
-Neither of these modules are available in `core`, but you can find a `#![no_std]`
-compatible version of `std::ffi::{CStr,CString}` in the [`cstr_core`] crate, and
-most of the `std::os::raw` types in the [`cty`] crate.
+As of Rust 1.30,
+functionalities of `std::ffi` are available
+in either `core::ffi` or `alloc::ffi`
+depending on whether or not memory allocation is involved.
+The [`cty`] crate and the [`cstr_core`] crate
+also offer similar functionalities.
[`cstr_core`]: https://crates.io/crates/cstr_core
[`cty`]: https://crates.io/crates/cty
-| Rust type | Intermediate | C type |
-|------------|--------------|--------------|
-| String | CString | *char |
-| &str | CStr | *const char |
-| () | c_void | void |
-| u32 or u64 | c_uint | unsigned int |
-| etc | ... | ... |
+| Rust type | Intermediate | C type |
+|----------------|--------------|----------------|
+| `String` | `CString` | `char *` |
+| `&str` | `CStr` | `const char *` |
+| `()` | `c_void` | `void` |
+| `u32` or `u64` | `c_uint` | `unsigned int` |
+| etc | ... | ... |
-As mentioned above, primitive types can be converted
-by the compiler implicitly.
+A value of a C primitive type can be used
+as one of the corresponding Rust type and vice versa,
+since the former is simply a type alias of the latter.
+For example, the following code compiles on platforms
+where `unsigned int` is 32-bit long.
```rust,ignore
-unsafe fn foo(num: u32) {
+fn foo(num: u32) {
let c_num: c_uint = num;
let r_num: u32 = c_num;
}
@@ -51,7 +53,6 @@ We are collecting examples and use cases for this on our issue tracker in
[issue #61]: https://github.com/rust-embedded/book/issues/61
-
## Interoperability with RTOSs
Integrating Rust with an RTOS such as FreeRTOS or ChibiOS is still a work in
diff --git a/src/doc/embedded-book/src/intro/index.md b/src/doc/embedded-book/src/intro/index.md
index 7a600fee0..272c2428f 100644
--- a/src/doc/embedded-book/src/intro/index.md
+++ b/src/doc/embedded-book/src/intro/index.md
@@ -60,6 +60,7 @@ If you are unfamiliar with anything mentioned above or if you want more informat
| Rust, Embedded | [Embedded Rust Bookshelf](https://docs.rust-embedded.org) | Here you can find several other resources provided by Rust's Embedded Working Group. |
| Rust, Embedded | [Embedonomicon](https://docs.rust-embedded.org/embedonomicon/) | The nitty gritty details when doing embedded programming in Rust. |
| Rust, Embedded | [embedded FAQ](https://docs.rust-embedded.org/faq.html) | Frequently asked questions about Rust in an embedded context. |
+| Rust, Embedded | [Comprehensive Rust 🦀: Bare Metal](https://google.github.io/comprehensive-rust/bare-metal.html) | Teaching material for a 1-day class on bare-metal Rust development |
| Interrupts | [Interrupt](https://en.wikipedia.org/wiki/Interrupt) | - |
| Memory-mapped IO/Peripherals | [Memory-mapped I/O](https://en.wikipedia.org/wiki/Memory-mapped_I/O) | - |
| SPI, UART, RS232, USB, I2C, TTL | [Stack Exchange about SPI, UART, and other interfaces](https://electronics.stackexchange.com/questions/37814/usart-uart-rs232-usb-spi-i2c-ttl-etc-what-are-all-of-these-and-how-do-th) | - |
diff --git a/src/doc/embedded-book/src/start/exceptions.md b/src/doc/embedded-book/src/start/exceptions.md
index b15717da9..bd9b85b76 100644
--- a/src/doc/embedded-book/src/start/exceptions.md
+++ b/src/doc/embedded-book/src/start/exceptions.md
@@ -50,7 +50,7 @@ possible.
> Note that the `exception` attribute transforms definitions of static variables
> inside the function by wrapping them into `unsafe` blocks and providing us
> with new appropriate variables of type `&mut` of the same name.
-> Thus we can derefence the reference via `*` to access the values of the variables without
+> Thus we can dereference the reference via `*` to access the values of the variables without
> needing to wrap them in an `unsafe` block.
## A complete example
@@ -258,7 +258,7 @@ ResetTrampoline:
800094c: b #-0x4 <ResetTrampoline+0xa>
```
-You can lookup the value of the program counter `0x0800094a` in the dissassembly.
+You can lookup the value of the program counter `0x0800094a` in the disassembly.
You'll see that a load operation (`ldr r0, [r0]` ) caused the exception.
The `r0` field of `ExceptionFrame` will tell you the value of register `r0`
was `0x3fff_fffe` at that time.
diff --git a/src/doc/embedded-book/src/start/registers.md b/src/doc/embedded-book/src/start/registers.md
index fe184792c..2d4a8e85b 100644
--- a/src/doc/embedded-book/src/start/registers.md
+++ b/src/doc/embedded-book/src/start/registers.md
@@ -134,7 +134,7 @@ pwm0.enable.write(temp); // Uh oh! Wrong variable!
## Using a HAL crate
-The HAL crate for a chip typically works by implementing a custom Trait for the raw structures exposed by the PAC. Often this trait will define a function called `constrain()` for single peripherals or `split()` for things like GPIO ports with multiple pins. This function will consume the underlying raw peripheral structure and return a new object with a higher-level API. This API may also do things like have the Serial port `new` function require a borrow on some `Clock` structure, which can only be generated by calling the function which configures the PLLs and sets up all the clock frequencies. In this way, it is statically impossible to create a Serial port object without first having configured the clock rates, or for the Serial port object to mis-convert the baud rate into clock ticks. Some crates even define special traits for the states each GPIO pin can be in, requiring the user to put a pin into the correct state (say, by selecting the appropriate Alternate Function Mode) before passing the pin into Peripheral. All with no run-time cost!
+The HAL crate for a chip typically works by implementing a custom Trait for the raw structures exposed by the PAC. Often this trait will define a function called `constrain()` for single peripherals or `split()` for things like GPIO ports with multiple pins. This function will consume the underlying raw peripheral structure and return a new object with a higher-level API. This API may also do things like have the Serial port `new` function require a borrow on some `Clock` structure, which can only be generated by calling the function which configures the PLLs and sets up all the clock frequencies. In this way, it is statically impossible to create a Serial port object without first having configured the clock rates, or for the Serial port object to misconvert the baud rate into clock ticks. Some crates even define special traits for the states each GPIO pin can be in, requiring the user to put a pin into the correct state (say, by selecting the appropriate Alternate Function Mode) before passing the pin into Peripheral. All with no run-time cost!
Let's see an example:
diff --git a/src/doc/nomicon/book.toml b/src/doc/nomicon/book.toml
index a2011c61f..693aca4a4 100644
--- a/src/doc/nomicon/book.toml
+++ b/src/doc/nomicon/book.toml
@@ -32,4 +32,4 @@ git-repository-url = "https://github.com/rust-lang/nomicon"
"./arc.html" = "./arc-mutex/arc.html"
[rust]
-edition = "2018"
+edition = "2021"
diff --git a/src/doc/nomicon/src/intro.md b/src/doc/nomicon/src/intro.md
index 4e77ffafe..323c0ceb3 100644
--- a/src/doc/nomicon/src/intro.md
+++ b/src/doc/nomicon/src/intro.md
@@ -39,7 +39,7 @@ Topics that are within the scope of this book include: the meaning of (un)safety
The Rustonomicon is not a place to exhaustively describe the semantics and guarantees of every single API in the standard library, nor is it a place to exhaustively describe every feature of Rust.
-Unless otherwise noted, Rust code in this book uses the Rust 2018 edition.
+Unless otherwise noted, Rust code in this book uses the Rust 2021 edition.
[trpl]: ../book/index.html
[ref]: ../reference/index.html
diff --git a/src/doc/nomicon/src/unbounded-lifetimes.md b/src/doc/nomicon/src/unbounded-lifetimes.md
index 03febd6ad..9ca2a2f2e 100644
--- a/src/doc/nomicon/src/unbounded-lifetimes.md
+++ b/src/doc/nomicon/src/unbounded-lifetimes.md
@@ -1,13 +1,13 @@
# Unbounded Lifetimes
Unsafe code can often end up producing references or lifetimes out of thin air.
-Such lifetimes come into the world as *unbounded*. The most common source of this
-is dereferencing a raw pointer, which produces a reference with an unbounded lifetime.
-Such a lifetime becomes as big as context demands. This is in fact more powerful
-than simply becoming `'static`, because for instance `&'static &'a T`
-will fail to typecheck, but the unbound lifetime will perfectly mold into
-`&'a &'a T` as needed. However for most intents and purposes, such an unbounded
-lifetime can be regarded as `'static`.
+Such lifetimes come into the world as *unbounded*. The most common source of
+this is taking a reference to a dereferenced raw pointer, which produces a
+reference with an unbounded lifetime. Such a lifetime becomes as big as context
+demands. This is in fact more powerful than simply becoming `'static`, because
+for instance `&'static &'a T` will fail to typecheck, but the unbound lifetime
+will perfectly mold into `&'a &'a T` as needed. However for most intents and
+purposes, such an unbounded lifetime can be regarded as `'static`.
Almost no reference is `'static`, so this is probably wrong. `transmute` and
`transmute_copy` are the two other primary offenders. One should endeavor to
@@ -17,17 +17,25 @@ boundaries.
Given a function, any output lifetimes that don't derive from inputs are
unbounded. For instance:
-<!-- ignore: simplified code -->
-```rust,ignore
-fn get_str<'a>() -> &'a str;
+<!-- no_run: This example exhibits undefined behavior. -->
+```rust,no_run
+fn get_str<'a>(s: *const String) -> &'a str {
+ unsafe { &*s }
+}
+
+fn main() {
+ let soon_dropped = String::from("hello");
+ let dangling = get_str(&soon_dropped);
+ drop(soon_dropped);
+ println!("Invalid str: {}", dangling); // Invalid str: gӚ_`
+}
```
-will produce an `&str` with an unbounded lifetime. The easiest way to avoid
-unbounded lifetimes is to use lifetime elision at the function boundary.
-If an output lifetime is elided, then it *must* be bounded by an input lifetime.
-Of course it might be bounded by the *wrong* lifetime, but this will usually
-just cause a compiler error, rather than allow memory safety to be trivially
-violated.
+The easiest way to avoid unbounded lifetimes is to use lifetime elision at the
+function boundary. If an output lifetime is elided, then it *must* be bounded by
+an input lifetime. Of course it might be bounded by the *wrong* lifetime, but
+this will usually just cause a compiler error, rather than allow memory safety
+to be trivially violated.
Within a function, bounding lifetimes is more error-prone. The safest and easiest
way to bound a lifetime is to return it from a function with a bound lifetime.
diff --git a/src/doc/reference/src/SUMMARY.md b/src/doc/reference/src/SUMMARY.md
index 4d9cc1d76..2b17bf45d 100644
--- a/src/doc/reference/src/SUMMARY.md
+++ b/src/doc/reference/src/SUMMARY.md
@@ -44,6 +44,7 @@
- [Code generation](attributes/codegen.md)
- [Limits](attributes/limits.md)
- [Type System](attributes/type_system.md)
+ - [Debugger](attributes/debugger.md)
- [Statements and expressions](statements-and-expressions.md)
- [Statements](statements.md)
diff --git a/src/doc/reference/src/attributes.md b/src/doc/reference/src/attributes.md
index 5d619c990..92ce1cd09 100644
--- a/src/doc/reference/src/attributes.md
+++ b/src/doc/reference/src/attributes.md
@@ -271,6 +271,8 @@ The following is an index of all built-in attributes.
- Type System
- [`non_exhaustive`] — Indicate that a type will have more fields/variants
added in future.
+- Debugger
+ - [`debugger_visualizer`] — Embeds a file that specifies debugger output for a type.
[Doc comments]: comments.md#doc-comments
[ECMA-334]: https://www.ecma-international.org/publications/standards/Ecma-334.htm
@@ -291,6 +293,7 @@ The following is an index of all built-in attributes.
[`cold`]: attributes/codegen.md#the-cold-attribute
[`crate_name`]: crates-and-source-files.md#the-crate_name-attribute
[`crate_type`]: linkage.md
+[`debugger_visualizer`]: attributes/debugger.md#the-debugger_visualizer-attribute
[`deny`]: attributes/diagnostics.md#lint-check-attributes
[`deprecated`]: attributes/diagnostics.md#the-deprecated-attribute
[`derive`]: attributes/derive.md
diff --git a/src/doc/reference/src/attributes/codegen.md b/src/doc/reference/src/attributes/codegen.md
index ab59cd8e7..8629e835d 100644
--- a/src/doc/reference/src/attributes/codegen.md
+++ b/src/doc/reference/src/attributes/codegen.md
@@ -89,6 +89,7 @@ Feature | Implicitly Enables | Description
`bmi1` | | [BMI1] — Bit Manipulation Instruction Sets
`bmi2` | | [BMI2] — Bit Manipulation Instruction Sets 2
`cmpxchg16b`| | [`cmpxchg16b`] - Compares and exchange 16 bytes (128 bits) of data atomically
+`f16c` | `avx` | [F16C] — 16-bit floating point conversion instructions
`fma` | `avx` | [FMA3] — Three-operand fused multiply-add
`fxsr` | | [`fxsave`] and [`fxrstor`] — Save and restore x87 FPU, MMX Technology, and SSE State
`lzcnt` | | [`lzcnt`] — Leading zeros count
@@ -118,6 +119,7 @@ Feature | Implicitly Enables | Description
[BMI1]: https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets
[BMI2]: https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets#BMI2
[`cmpxchg16b`]: https://www.felixcloutier.com/x86/cmpxchg8b:cmpxchg16b
+[F16C]: https://en.wikipedia.org/wiki/F16C
[FMA3]: https://en.wikipedia.org/wiki/FMA_instruction_set
[`fxsave`]: https://www.felixcloutier.com/x86/fxsave
[`fxrstor`]: https://www.felixcloutier.com/x86/fxrstor
diff --git a/src/doc/reference/src/attributes/debugger.md b/src/doc/reference/src/attributes/debugger.md
new file mode 100644
index 000000000..6ea80221e
--- /dev/null
+++ b/src/doc/reference/src/attributes/debugger.md
@@ -0,0 +1,141 @@
+# Debugger attributes
+
+The following [attributes] are used for enhancing the debugging experience when using third-party debuggers like GDB or WinDbg.
+
+## The `debugger_visualizer` attribute
+
+The *`debugger_visualizer` attribute* can be used to embed a debugger visualizer file into the debug information.
+This enables an improved debugger experience for displaying values in the debugger.
+It uses the [_MetaListNameValueStr_] syntax to specify its inputs, and must be specified as a crate attribute.
+
+### Using `debugger_visualizer` with Natvis
+
+Natvis is an XML-based framework for Microsoft debuggers (such as Visual Studio and WinDbg) that uses declarative rules to customize the display of types.
+For detailed information on the Natvis format, refer to Microsoft's [Natvis documentation].
+
+This attribute only supports embedding Natvis files on `-windows-msvc` targets.
+
+The path to the Natvis file is specified with the `natvis_file` key, which is a path relative to the crate source file:
+
+<!-- ignore: requires external files, and msvc -->
+```rust ignore
+#![debugger_visualizer(natvis_file = "Rectangle.natvis")]
+
+struct FancyRect {
+ x: f32,
+ y: f32,
+ dx: f32,
+ dy: f32,
+}
+
+fn main() {
+ let fancy_rect = FancyRect { x: 10.0, y: 10.0, dx: 5.0, dy: 5.0 };
+ println!("set breakpoint here");
+}
+```
+
+and `Rectangle.natvis` contains:
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+ <Type Name="foo::FancyRect">
+ <DisplayString>({x},{y}) + ({dx}, {dy})</DisplayString>
+ <Expand>
+ <Synthetic Name="LowerLeft">
+ <DisplayString>({x}, {y})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="UpperLeft">
+ <DisplayString>({x}, {y + dy})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="UpperRight">
+ <DisplayString>({x + dx}, {y + dy})</DisplayString>
+ </Synthetic>
+ <Synthetic Name="LowerRight">
+ <DisplayString>({x + dx}, {y})</DisplayString>
+ </Synthetic>
+ </Expand>
+ </Type>
+</AutoVisualizer>
+```
+
+When viewed under WinDbg, the `fancy_rect` variable would be shown as follows:
+
+```text
+> Variables:
+ > fancy_rect: (10.0, 10.0) + (5.0, 5.0)
+ > LowerLeft: (10.0, 10.0)
+ > UpperLeft: (10.0, 15.0)
+ > UpperRight: (15.0, 15.0)
+ > LowerRight: (15.0, 10.0)
+```
+
+### Using `debugger_visualizer` with GDB
+
+GDB supports the use of a structured Python script, called a *pretty printer*, that describes how a type should be visualized in the debugger view.
+For detailed information on pretty printers, refer to GDB's [pretty printing documentation].
+
+Embedded pretty printers are not automatically loaded when debugging a binary under GDB.
+There are two ways to enable auto-loading embedded pretty printers:
+1. Launch GDB with extra arguments to explicitly add a directory or binary to the auto-load safe path: `gdb -iex "add-auto-load-safe-path safe-path path/to/binary" path/to/binary`
+ For more information, see GDB's [auto-loading documentation].
+1. Create a file named `gdbinit` under `$HOME/.config/gdb` (you may need to create the directory if it doesn't already exist). Add the following line to that file: `add-auto-load-safe-path path/to/binary`.
+
+These scripts are embedded using the `gdb_script_file` key, which is a path relative to the crate source file.
+
+<!-- ignore: requires external files -->
+```rust ignore
+#![debugger_visualizer(gdb_script_file = "printer.py")]
+
+struct Person {
+ name: String,
+ age: i32,
+}
+
+fn main() {
+ let bob = Person { name: String::from("Bob"), age: 10 };
+ println!("set breakpoint here");
+}
+```
+
+and `printer.py` contains:
+
+```python
+import gdb
+
+class PersonPrinter:
+ "Print a Person"
+
+ def __init__(self, val):
+ self.val = val
+ self.name = val["name"]
+ self.age = int(val["age"])
+
+ def to_string(self):
+ return "{} is {} years old.".format(self.name, self.age)
+
+def lookup(val):
+ lookup_tag = val.type.tag
+ if lookup_tag is None:
+ return None
+ if "foo::Person" == lookup_tag:
+ return PersonPrinter(val)
+
+ return None
+
+gdb.current_objfile().pretty_printers.append(lookup)
+```
+
+When the crate's debug executable is passed into GDB[^rust-gdb], `print bob` will display:
+
+```text
+"Bob" is 10 years old.
+```
+
+[^rust-gdb]: Note: This assumes you are using the `rust-gdb` script which configures pretty-printers for standard library types like `String`.
+
+[auto-loading documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Auto_002dloading-safe-path.html
+[attributes]: ../attributes.md
+[Natvis documentation]: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects
+[pretty printing documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html
+[_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax
diff --git a/src/doc/reference/src/inline-assembly.md b/src/doc/reference/src/inline-assembly.md
index a12f495ff..6c23d592c 100644
--- a/src/doc/reference/src/inline-assembly.md
+++ b/src/doc/reference/src/inline-assembly.md
@@ -17,6 +17,7 @@ The compiler will emit an error if `asm!` is used on an unsupported target.
## Example
```rust
+# #[cfg(target_arch = "x86_64")] {
use std::arch::asm;
// Multiply x by 6 using shifts and adds
@@ -32,6 +33,7 @@ unsafe {
);
}
assert_eq!(x, 4 * 6);
+# }
```
## Syntax
diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md
index ce2190829..25ae37bc3 100644
--- a/src/doc/reference/src/items/external-blocks.md
+++ b/src/doc/reference/src/items/external-blocks.md
@@ -231,9 +231,38 @@ resolution logic to find that import library. Alternatively, specifying
`kind = "raw-dylib"` instructs the compiler to generate an import library
during compilation and provide that to the linker instead.
-`raw-dylib` is only supported on Windows and not supported on 32-bit x86
-(`target_arch="x86"`). Using it when targeting other platforms or
-x86 on Windows will result in a compiler error.
+`raw-dylib` is only supported on Windows. Using it when targeting other
+platforms will result in a compiler error.
+
+#### The `import_name_type` key
+
+On x86 Windows, names of functions are "decorated" (i.e., have a specific prefix
+and/or suffix added) to indicate their calling convention. For example, a
+`stdcall` calling convention function with the name `fn1` that has no arguments
+would be decorated as `_fn1@0`. However, the [PE Format] does also permit names
+to have no prefix or be undecorated. Additionally, the MSVC and GNU toolchains
+use different decorations for the same calling conventions which means, by
+default, some Win32 functions cannot be called using the `raw-dylib` link kind
+via the GNU toolchain.
+
+To allow for these differences, when using the `raw-dylib` link kind you may
+also specify the `import_name_type` key with one of the following values to
+change how functions are named in the generated import library:
+
+* `decorated`: The function name will be fully-decorated using the MSVC
+ toolchain format.
+* `noprefix`: The function name will be decorated using the MSVC toolchain
+ format, but skipping the leading `?`, `@`, or optionally `_`.
+* `undecorated`: The function name will not be decorated.
+
+If the `import_name_type` key is not specified, then the function name will be
+fully-decorated using the target toolchain's format.
+
+Variables are never decorated and so the `import_name_type` key has no effect on
+how they are named in the generated import library.
+
+The `import_name_type` key is only supported on x86 Windows. Using it when
+targeting other platforms will result in a compiler error.
### The `link_name` attribute
@@ -308,3 +337,4 @@ restrictions as [regular function parameters].
[`whole-archive` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive
[`verbatim` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-verbatim
[`dylib` versus `raw-dylib`]: #dylib-versus-raw-dylib
+[PE Format]: https://learn.microsoft.com/windows/win32/debug/pe-format#import-name-type
diff --git a/src/doc/reference/src/keywords.md b/src/doc/reference/src/keywords.md
index 67f1089d8..1855a35d0 100644
--- a/src/doc/reference/src/keywords.md
+++ b/src/doc/reference/src/keywords.md
@@ -111,6 +111,7 @@ is possible to declare a variable or method with the name `union`.
Beginning in the 2018 edition, `dyn` has been promoted to a strict keyword.
> **<sup>Lexer</sup>**\
+> KW_MACRO_RULES : `macro_rules`\
> KW_UNION : `union`\
> KW_STATICLIFETIME : `'static`
>
diff --git a/src/doc/reference/src/macros-by-example.md b/src/doc/reference/src/macros-by-example.md
index cd9dc3402..51aa919fc 100644
--- a/src/doc/reference/src/macros-by-example.md
+++ b/src/doc/reference/src/macros-by-example.md
@@ -166,7 +166,7 @@ The repetition operators are:
- `*` — indicates any number of repetitions.
- `+` — indicates any number but at least one.
-- `?` — indicates an optional fragment with zero or one occurrences.
+- `?` — indicates an optional fragment with zero or one occurrence.
Since `?` represents at most one occurrence, it cannot be used with a
separator.
diff --git a/src/doc/reference/src/procedural-macros.md b/src/doc/reference/src/procedural-macros.md
index 31f029a63..7d69ab72d 100644
--- a/src/doc/reference/src/procedural-macros.md
+++ b/src/doc/reference/src/procedural-macros.md
@@ -251,7 +251,7 @@ use my_macro::show_streams;
#[show_streams]
fn invoke1() {}
// out: attr: ""
-// out: item: "fn invoke1() { }"
+// out: item: "fn invoke1() {}"
// Example: Attribute with input
#[show_streams(bar)]
diff --git a/src/doc/reference/src/types/impl-trait.md b/src/doc/reference/src/types/impl-trait.md
index 413f999f8..af900408e 100644
--- a/src/doc/reference/src/types/impl-trait.md
+++ b/src/doc/reference/src/types/impl-trait.md
@@ -31,15 +31,15 @@ The caller must provide a type that satisfies the bounds declared by the anonymo
For example, these two forms are almost equivalent:
-```rust,ignore
+```rust
trait Trait {}
// generic type parameter
-fn foo<T: Trait>(arg: T) {
+fn with_generic_type<T: Trait>(arg: T) {
}
// impl Trait in argument position
-fn foo(arg: impl Trait) {
+fn with_impl_trait(arg: impl Trait) {
}
```
@@ -96,16 +96,24 @@ With `impl Trait`, unlike with a generic type parameter, the function chooses th
The function:
-```rust,ignore
+```rust
+# trait Trait {}
fn foo<T: Trait>() -> T {
+ // ...
+# panic!()
+}
```
allows the caller to determine the return type, `T`, and the function returns that type.
The function:
-```rust,ignore
+```rust
+# trait Trait {}
+# impl Trait for () {}
fn foo() -> impl Trait {
+ // ...
+}
```
doesn't allow the caller to determine the return type.
diff --git a/src/doc/rust-by-example/README.md b/src/doc/rust-by-example/README.md
index 462f733e5..e43b044c8 100644
--- a/src/doc/rust-by-example/README.md
+++ b/src/doc/rust-by-example/README.md
@@ -15,11 +15,11 @@ to read it online.
If you'd like to read it locally, [install Rust], and then:
```bash
-$ git clone https://github.com/rust-lang/rust-by-example
-$ cd rust-by-example
-$ cargo install mdbook
-$ mdbook build
-$ mdbook serve
+git clone https://github.com/rust-lang/rust-by-example
+cd rust-by-example
+cargo install mdbook
+mdbook build
+mdbook serve
```
[install Rust]: https://www.rust-lang.org/tools/install
diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md b/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md
index 61f80fc3e..998b741e7 100644
--- a/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md
+++ b/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md
@@ -5,7 +5,7 @@ Notice in the previous example that our immediate reaction to calling
error:
```rust,ignore
-.and_then(|s| s.parse::<i32>()
+.and_then(|s| s.parse::<i32>())
.map_err(|e| e.into())
```
diff --git a/src/doc/rust-by-example/src/hello/print.md b/src/doc/rust-by-example/src/hello/print.md
index d578337ad..bf23a9023 100644
--- a/src/doc/rust-by-example/src/hello/print.md
+++ b/src/doc/rust-by-example/src/hello/print.md
@@ -44,8 +44,9 @@ fn main() {
println!("{number:>5}", number=1);
// You can pad numbers with extra zeroes,
+ println!("{number:0>5}", number=1); // 00001
// and left-adjust by flipping the sign. This will output "10000".
- println!("{number:0<5}", number=1);
+ println!("{number:0<5}", number=1); // 10000
// You can use named arguments in the format specifier by appending a `$`.
println!("{number:0>width$}", number=1, width=5);
@@ -62,7 +63,7 @@ fn main() {
// This will not compile because `Structure` does not implement
// fmt::Display.
- //println!("This struct `{}` won't print...", Structure(3));
+ // println!("This struct `{}` won't print...", Structure(3));
// TODO ^ Try uncommenting this line
// For Rust 1.58 and above, you can directly capture the argument from a
diff --git a/src/doc/rust-by-example/src/primitives/array.md b/src/doc/rust-by-example/src/primitives/array.md
index 9cec24d69..5f5e69944 100644
--- a/src/doc/rust-by-example/src/primitives/array.md
+++ b/src/doc/rust-by-example/src/primitives/array.md
@@ -63,7 +63,9 @@ fn main() {
}
}
- // Out of bound indexing causes compile time error.
+ // Out of bound indexing on array causes compile time error.
//println!("{}", xs[5]);
+ // Out of bound indexing on slice causes runtime error.
+ //println!("{}", xs[..][5]);
}
```
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index b01cb6797..58a476bdc 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -24,6 +24,7 @@
- [Test headers](./tests/headers.md)
- [Performance testing](./tests/perf.md)
- [Crater](./tests/crater.md)
+ - [Suggest tests tool](./tests/suggest-tests.md)
- [Debugging the compiler](./compiler-debugging.md)
- [Using the tracing/logging instrumentation](./tracing.md)
- [Profiling the compiler](./profiling.md)
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 59893bdc1..eb674c8fe 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
@@ -99,10 +99,10 @@ Also, note that `x.py` supports all kinds of path suffixes for `compiler`, `libr
and `src/tools` directories. So, you can simply run `x.py test tidy` instead of
`x.py test src/tools/tidy`. Or, `x.py build std` instead of `x.py build library/std`.
-[rust-analyzer]: ./building/suggested.html#configuring-rust-analyzer-for-rustc
+[rust-analyzer]: suggested.html#configuring-rust-analyzer-for-rustc
-See the chapters on [building](./building/how-to-build-and-run.md),
-[testing](./tests/intro.md), and [rustdoc](./rustdoc.md) for more details.
+See the chapters on [building](how-to-build-and-run),
+[testing](../tests/intro), and [rustdoc](../rustdoc) for more details.
### Building the compiler
diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md
index 3049d87db..9dcc795f2 100644
--- a/src/doc/rustc-dev-guide/src/building/suggested.md
+++ b/src/doc/rustc-dev-guide/src/building/suggested.md
@@ -109,6 +109,23 @@ the problem. A nice side-effect of this style is that you are left
with a fairly fine-grained set of commits at the end, all of which
build and pass tests. This often helps reviewing.
+## `x suggest`
+
+The `x suggest` subcommand suggests (and runs) a subset of the extensive
+`rust-lang/rust` tests based on files you have changed. This is especially useful
+for new contributors who have not mastered the arcane `x` flags yet and more
+experienced contributors as a shorthand for reducing mental effort. In all cases
+it is useful not to run the full tests (which can take on the order of tens of
+minutes) and just run a subset which are relevant to your changes. For example,
+running `tidy` and `linkchecker` is useful when editing Markdown files, whereas UI
+tests are much less likely to be helpful. While `x suggest` is a useful tool, it
+does not guarantee perfect coverage (just as PR CI isn't a substitute for bors).
+See the [dedicated chapter](../tests/suggest-tests.md) for more information and
+contribution instructions.
+
+Please note that `x suggest` is in a beta state currently and the tests that it
+will suggest are limited.
+
## Configuring `rustup` to use nightly
Some parts of the bootstrap process uses pinned, nightly versions of tools like
@@ -322,3 +339,13 @@ pkgs.mkShell {
RUST_BOOTSTRAP_CONFIG = config;
}
```
+
+## Shell Completions
+
+If you use Bash, Fish or PowerShell, you can find automatically-generated shell completion scripts for `x.py` in [`src/etc/completions`](https://github.com/rust-lang/rust/tree/master/src/etc/completions).
+Zsh support will also be included once issues with [`clap_complete`](https://crates.io/crates/clap_complete) have been resolved.
+
+You can use `source ./src/etc/completions/x.py.<extension>`
+to load completions for your shell of choice,
+or `source .\src\etc\completions\x.py.ps1` for PowerShell.
+Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion. \ No newline at end of file
diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md
index d5c948994..297873d98 100644
--- a/src/doc/rustc-dev-guide/src/getting-started.md
+++ b/src/doc/rustc-dev-guide/src/getting-started.md
@@ -90,7 +90,7 @@ filtering the search to areas you're interested in. For example:
Not all important or beginner work has issue labels.
See below for how to find work that isn't labelled.
-[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CE-help-wanted%2CE-mentor
+[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+
[Triage]: ./contributing.md#issue-triage
### Recurring work
@@ -169,7 +169,7 @@ incredibly helpful:
## Cloning and Building
-See ["How to build and run the compiler"](./building//how-to-build-and-run.md).
+See ["How to build and run the compiler"](./building/how-to-build-and-run.md).
## Contributor Procedures
diff --git a/src/doc/rustc-dev-guide/src/hir-debugging.md b/src/doc/rustc-dev-guide/src/hir-debugging.md
index 8788ad4de..c25a558a0 100644
--- a/src/doc/rustc-dev-guide/src/hir-debugging.md
+++ b/src/doc/rustc-dev-guide/src/hir-debugging.md
@@ -3,6 +3,6 @@
The `-Z unpretty=hir-tree` flag will dump out the HIR.
If you are trying to correlate `NodeId`s or `DefId`s with source code, the
-`--pretty expanded,identified` flag may be useful.
+`-Z unpretty=expanded,identified` flag may be useful.
TODO: anything else? [#1159](https://github.com/rust-lang/rustc-dev-guide/issues/1159)
diff --git a/src/doc/rustc-dev-guide/src/mir/optimizations.md b/src/doc/rustc-dev-guide/src/mir/optimizations.md
index 037cf5874..293d2fe91 100644
--- a/src/doc/rustc-dev-guide/src/mir/optimizations.md
+++ b/src/doc/rustc-dev-guide/src/mir/optimizations.md
@@ -131,6 +131,6 @@ needed for correctness), then fuel should not be used. An example of this is `Pr
perform optimizations. In these situations, we should allow for the initial gathering pass
and then check fuel as close to the mutation as possible. This allows for the best
debugging experience, because we can determine where in the list of candidates an optimization
-may have been misapplied. Examples of this are `InstCombine` and `ConstantPropagation`.
+may have been misapplied. Examples of this are `InstSimplify` and `ConstantPropagation`.
[consideroptimizing]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.consider_optimizing
diff --git a/src/doc/rustc-dev-guide/src/solve/trait-solving.md b/src/doc/rustc-dev-guide/src/solve/trait-solving.md
index 71f6581c2..b0cd9af6c 100644
--- a/src/doc/rustc-dev-guide/src/solve/trait-solving.md
+++ b/src/doc/rustc-dev-guide/src/solve/trait-solving.md
@@ -96,6 +96,10 @@ Trait solving during codegen should have the same result as during typeck. As we
all free regions during codegen we must not rely on them during typeck. A noteworthy example
is special behavior for `'static`.
+We also have to be careful with relying on equality of regions in the trait solver.
+This is fine for codegen, as we treat all erased regions are equal. We can however
+lose equality information from HIR to MIR typeck.
+
### 7. Removing ambiguity makes strictly more things compile
We *should* not rely on ambiguity for things to compile.
diff --git a/src/doc/rustc-dev-guide/src/tests/headers.md b/src/doc/rustc-dev-guide/src/tests/headers.md
index 5b71f3ea1..682c96b44 100644
--- a/src/doc/rustc-dev-guide/src/tests/headers.md
+++ b/src/doc/rustc-dev-guide/src/tests/headers.md
@@ -52,6 +52,8 @@ found in [`header.rs`] from the compiletest source.
* [`stderr-per-bitwidth`](ui.md#output-comparison) — separate output per bit width
* [`dont-check-compiler-stderr`](ui.md#output-comparison) — don't validate stderr
* [`dont-check-compiler-stdout`](ui.md#output-comparison) — don't validate stdout
+ * [`compare-output-lines-by-subset`](ui.md#output-comparison) — checks output by
+ line subset
* [Building auxiliary crates](compiletest.md#building-auxiliary-crates)
* `aux-build`
* `aux-crate`
@@ -72,6 +74,7 @@ found in [`header.rs`] from the compiletest source.
* [Environment variable headers](#environment-variable-headers)
* `rustc-env`
* `exec-env`
+ * `unset-exec-env`
* `unset-rustc-env`
* [Miscellaneous headers](#miscellaneous-headers)
* `compile-flags` — adds compiler flags
@@ -177,6 +180,8 @@ The following headers affect environment variables.
form `KEY=VALUE`.
* `exec-env` is an environment variable to set when executing a test of the
form `KEY=VALUE`.
+* `unset-exec-env` specifies an environment variable to unset when executing a
+ test.
* `unset-rustc-env` specifies an environment variable to unset when running
`rustc`.
diff --git a/src/doc/rustc-dev-guide/src/tests/suggest-tests.md b/src/doc/rustc-dev-guide/src/tests/suggest-tests.md
new file mode 100644
index 000000000..f6b6d1537
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/tests/suggest-tests.md
@@ -0,0 +1,55 @@
+# Suggest tests tool
+
+This chapter is about the internals of and contribution instructions for the
+`suggest-tests` tool. For a high-level overview of the tool, see
+[this section](../building/suggested.md#x-suggest). This tool is currently in a
+beta state and is tracked by [this](https://github.com/rust-lang/rust/issues/109933)
+issue on Github. Currently the number of tests it will suggest are very limited
+in scope, we are looking to expand this (contributions welcome!).
+
+## Internals
+
+The tool is defined in a separate crate ([`src/tools/suggest-tests`](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests))
+which outputs suggestions which are parsed by a shim in bootstrap
+([`src/bootstrap/suggest.rs`](https://github.com/rust-lang/rust/blob/master/src/bootstrap/suggest.rs)).
+The only notable thing the bootstrap shim does is (when invoked with the
+`--run` flag) use bootstrap's internal mechanisms to create a new `Builder` and
+uses it to invoke the suggested commands. The `suggest-tests` crate is where the
+fun happens, two kinds of suggestions are defined: "static" and "dynamic"
+suggestions.
+
+### Static suggestions
+
+Defined [here](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/static_suggestions.rs).
+Static suggestions are simple: they are just [globs](https://crates.io/crates/glob)
+which map to a `x` command. In `suggest-tests`, this is implemented with a
+simple `macro_rules` macro.
+
+### Dynamic suggestions
+
+Defined [here](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/dynamic_suggestions.rs).
+These are more complicated than static suggestions and are implemented as
+functions with the following signature: `fn(&Path) -> Vec<Suggestion>`. In
+other words, each suggestion takes a path to a modified file and (after running
+arbitrary Rust code) can return any number of suggestions, or none. Dynamic
+suggestions are useful for situations where fine-grained control over
+suggestions is needed. For example, modifications to the `compiler/xyz/` path
+should trigger the `x test compiler/xyz` suggestion. In the future, dynamic
+suggestions might even read file contents to determine if (what) tests should
+run.
+
+## Adding a suggestion
+
+The following steps should serve as a rough guide to add suggestions to
+`suggest-tests` (very welcome!):
+
+1. Determine the rules for your suggestion. Is it simple and operates only on
+ a single path or does it match globs? Does it need fine-grained control over
+ the resulting command or does "one size fit all"?
+2. Based on the previous step, decide if your suggestion should be implemented
+ as either static or dynamic.
+3. Implement the suggestion. If it is dynamic then a test is highly recommended,
+ to verify that your logic is correct and to give an example of the suggestion.
+ See the [tests.rs](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/tests.rs)
+ file.
+4. Open a PR implementing your suggestion. **(TODO: add example PR)**
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index cc32ad1d3..d94d8cc4e 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -84,6 +84,9 @@ check for output files:
[Normalization](#normalization)).
* `dont-check-compiler-stderr` — Ignores stderr from the compiler.
* `dont-check-compiler-stdout` — Ignores stdout from the compiler.
+* `compare-output-lines-by-subset` — Checks that the output contains the
+ contents of the stored output files by lines opposed to checking for strict
+ equality.
UI tests run with with `-Zdeduplicate-diagnostics=no` flag which disables
rustc's built-in diagnostic deduplication mechanism.
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 8ded2ee59..73343ba9d 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -27,6 +27,7 @@
- [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
- [\*-android and \*-androideabi](platform-support/android.md)
- [\*-linux-ohos](platform-support/openharmony.md)
+ - [\*-esp-espidf](platform-support/esp-idf.md)
- [\*-unknown-fuchsia](platform-support/fuchsia.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
- [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md)
@@ -42,6 +43,7 @@
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
+ - [x86_64h-apple-darwin](platform-support/x86_64h-apple-darwin.md)
- [Targets](targets/index.md)
- [Built-in Targets](targets/built-in.md)
- [Custom Targets](targets/custom.md)
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 62347f169..1041d5026 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -84,12 +84,20 @@ Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`.
This flag controls whether or not the linker includes its default libraries.
It takes one of the following values:
-* `y`, `yes`, `on`, `true` or no value: include default libraries (the default).
-* `n`, `no`, `off` or `false`: exclude default libraries.
+* `y`, `yes`, `on`, `true`: include default libraries.
+* `n`, `no`, `off` or `false` or no value: exclude default libraries (the default).
For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to
the linker.
+## dlltool
+
+On `windows-gnu` targets, this flag controls which dlltool `rustc` invokes to
+generate import libraries when using the [`raw-dylib` link kind](../../reference/items/external-blocks.md#the-link-attribute).
+It takes a path to [the dlltool executable](https://sourceware.org/binutils/docs/binutils/dlltool.html).
+If this flag is not specified, a dlltool executable will be inferred based on
+the host environment and target.
+
## embed-bitcode
This flag controls whether or not the compiler embeds LLVM bitcode into object
@@ -574,7 +582,8 @@ change in the future.
This instructs `rustc` to generate code specifically for a particular processor.
You can run `rustc --print target-cpus` to see the valid options to pass
-here. Each target has a default base CPU. Special values include:
+and the default target CPU for the current buid target.
+Each target has a default base CPU. Special values include:
* `native` can be passed to use the processor of the host machine.
* `generic` refers to an LLVM target with minimal features but modern tuning.
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index d4d26654e..3be4382b0 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -248,8 +248,14 @@ The valid types of print values are:
exact format of this debugging output is not a stable guarantee, other than
that it will include the linker executable and the text of each command-line
argument passed to the linker.
+- `deployment-target` - The currently selected [deployment target] (or minimum OS version)
+ for the selected Apple platform target. This value can be used or passed along to other
+ components alongside a Rust build that need this information, such as C compilers.
+ This returns rustc's minimum supported deployment target if no `*_DEPLOYMENT_TARGET` variable
+ is present in the environment, or otherwise returns the variable's parsed value.
[conditional compilation]: ../reference/conditional-compilation.html
+[deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html
<a id="option-g-debug"></a>
## `-g`: include debug information
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
index 98b49e071..a82a53248 100644
--- a/src/doc/rustc/src/exploit-mitigations.md
+++ b/src/doc/rustc/src/exploit-mitigations.md
@@ -115,9 +115,9 @@ equivalent.
<tr>
<td>Stack smashing protection
</td>
- <td>No
+ <td>Yes
</td>
- <td>
+ <td>Nightly
</td>
</tr>
<tr>
@@ -432,18 +432,16 @@ saved return instruction pointer, and checking if this value has changed
when returning from a function. This is also known as “Stack Protector” or
“Stack Smashing Protector (SSP)”.
-The Rust compiler does not support stack smashing protection. However, more
-comprehensive alternatives to stack smashing protection exist, such as
-shadow and safe stack (see backward-edge control flow protection).
+The Rust compiler supports stack smashing protection on nightly builds[42].
![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.")
Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in
hello-rust.
To check if stack smashing protection is enabled for a given binary, search
-for cross references to `__stack_chk_fail`. The only cross references to
-`__stack_chk_fail` in hello-rust are from the statically-linked libbacktrace
-library (see Fig. 14).
+for cross references to `__stack_chk_fail`. The presence of these
+cross-references in Rust-compiled code (e.g., `hello_rust::main`) indicates
+that the stack smashing protection is enabled (see Fig. 14).
### Forward-edge control flow protection
@@ -697,3 +695,6 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
41. “ControlFlowIntegrity.” The Rust Unstable Book.
[https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
+
+42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.”
+ GitHub. <https://github.com/rust-lang/rust/pull/84197>
diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png
index a49e14b5e..ef02c605e 100644
--- a/src/doc/rustc/src/images/image3.png
+++ b/src/doc/rustc/src/images/image3.png
Binary files differ
diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md
index b0b2f4196..2535cd4f1 100644
--- a/src/doc/rustc/src/instrument-coverage.md
+++ b/src/doc/rustc/src/instrument-coverage.md
@@ -117,7 +117,7 @@ $ ls formatjson5.profraw
formatjson5.profraw
```
-If `LLVM_PROFILE_FILE` contains a path to a non-existent directory, the missing directory structure will be created. Additionally, the following special pattern strings are rewritten:
+If `LLVM_PROFILE_FILE` contains a path to a nonexistent directory, the missing directory structure will be created. Additionally, the following special pattern strings are rewritten:
- `%p` - The process ID.
- `%h` - The hostname of the machine running the program.
diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md
index d8843280b..11d7b5b59 100644
--- a/src/doc/rustc/src/json.md
+++ b/src/doc/rustc/src/json.md
@@ -61,7 +61,7 @@ Diagnostics have the following format:
/* The file where the span is located.
Note that this path may not exist. For example, if the path
points to the standard library, and the rust src is not
- available in the sysroot, then it may point to a non-existent
+ available in the sysroot, then it may point to a nonexistent
file. Beware that this may also point to the source of an
external crate.
*/
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index c378532db..3b2463aa5 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -88,6 +88,7 @@ target | notes
`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 Linux, hardfloat (kernel 3.2, glibc 2.17)
+[`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36)
`mips-unknown-linux-gnu` | MIPS Linux (kernel 4.4, glibc 2.23)
`mips64-unknown-linux-gnuabi64` | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23)
`mips64el-unknown-linux-gnuabi64` | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23)
@@ -266,7 +267,6 @@ target | std | host | notes
`i686-uwp-windows-gnu` | ? | |
`i686-uwp-windows-msvc` | ? | |
`i686-wrs-vxworks` | ? | |
-[`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | ? | | LoongArch64 Linux (LP64D ABI)
[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux
`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc
[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux MUSL
@@ -297,7 +297,7 @@ target | std | host | notes
`riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
`riscv32im-unknown-none-elf` | * | | Bare RISC-V (RV32IM ISA)
[`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA)
-`riscv32imc-esp-espidf` | ✓ | | RISC-V ESP-IDF
+[`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
`riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia
`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0)
@@ -327,5 +327,6 @@ target | std | host | notes
`x86_64-uwp-windows-gnu` | ✓ | |
`x86_64-uwp-windows-msvc` | ✓ | |
`x86_64-wrs-vxworks` | ? | |
+`x86_64h-apple-darwin` | ✓ | ✓ | macOS with late-gen Intel (at least Haswell)
[runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets
diff --git a/src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md b/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md
index 6619c90b8..d75bd92be 100644
--- a/src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md
+++ b/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md
@@ -1,26 +1,40 @@
-# armv7-sony-vita-eabihf
+# armv7-sony-vita-newlibeabihf
**Tier: 3**
This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. `armv7-vita-newlibeabihf` aims to have support for `std` crate using `newlib` as a bridge.
+Rust support for this target is not affiliated with Sony, and is not derived
+from nor used with any official Sony SDK.
+
## Designated Developers
* [@amg98](https://github.com/amg98)
+* [@nikarh](https://github.com/nikarh)
## Requirements
-This target is cross compiled, and requires installing [VITASDK](https://vitasdk.org/) toolchain on your system.
+This target is cross-compiled, and requires installing [VITASDK](https://vitasdk.org/) toolchain on your system. Dynamic linking is not supported.
+
+`#![no_std]` crates can be built using `build-std` to build `core`, and optionally
+`alloc`, and `panic_abort`.
+
+`std` is partially supported, but mostly works. Some APIs are unimplemented
+and will simply return an error, such as `std::process`. An allocator is provided
+by default.
+
+In order to support some APIs, binaries must be linked against `libc` written
+for the target, using a linker for the target. These are provided by the
+VITASDK toolchain.
+
+This target generates binaries in the ELF format.
## Building
-You can build Rust with support for the target by adding it to the `target`
-list in `config.toml`:
+Rust does not ship pre-compiled artifacts for this target. You can use `build-std` flag to build binaries with `std`:
-```toml
-[build]
-build-stage = 1
-target = ["armv7-sony-vita-newlibeabihf"]
+```sh
+cargo build -Z build-std=std,panic_abort --target=armv7-sony-vita-newlibeabihf --release
```
## Cross-compilation
@@ -33,26 +47,81 @@ Currently there is no support to run the rustc test suite for this target.
## Building and Running Rust Programs
-To test your developed rust programs for PlayStation Vita, first you have to prepare a proper executable for the device using the resulting ELF file you get from compilation step. The needed steps can be automated using tools like `cargo-make`. Use the example below as a template for your project:
+`std` support for this target relies on newlib. In order to work, newlib must be initialized correctly. The easiest way to achieve this with VITASDK newlib implementation is by compiling your program as a staticlib with and exposing your main function from rust to `_init` function in `crt0`.
+
+Add this to your `Cargo.toml`:
+
+```toml
+[lib]
+crate-type = ["staticlib"]
+
+[profile.release]
+panic = 'abort'
+lto = true
+opt-level = 3
+```
+
+Your entrypoint should look roughly like this, `src/lib.rs`:
+```rust,ignore,no_run
+#[used]
+#[export_name = "_newlib_heap_size_user"]
+pub static _NEWLIB_HEAP_SIZE_USER: u32 = 100 * 1024 * 1024; // Default heap size is only 32mb, increase it to something suitable for your application
+
+#[no_mangle]
+pub extern "C" fn main() {
+ println!("Hello, world!");
+}
+```
+
+To test your developed rust programs on PlayStation Vita, first you must correctly link and package your rust staticlib. These steps can be preformed using tools available in VITASDK, and can be automated using tools like `cargo-make`.
+
+First, set up environment variables for `VITASDK`, and it's binaries:
+
+```sh
+export VITASDK=/opt/vitasdk
+export PATH=$PATH:$VITASDK/bin
+```
+
+Use the example below as a template for your project:
```toml
[env]
TITLE = "Rust Hello World"
TITLEID = "RUST00001"
+# Add other libs required by your project here
+LINKER_LIBS = "-lpthread -lm -lmathneon"
+
# At least a "sce_sys" folder should be place there for app metadata (title, icons, description...)
# You can find sample assets for that on $VITASDK/share/gcc-arm-vita-eabi/samples/hello_world/sce_sys/
STATIC_DIR = "static" # Folder where static assets should be placed (sce_sys folder is at $STATIC_DIR/sce_sys)
CARGO_TARGET_DIR = { script = ["echo ${CARGO_TARGET_DIR:=target}"] }
-RUST_TARGET_PATH = { script = ["echo $(pwd)"]}
RUST_TARGET = "armv7-sony-vita-newlibeabihf"
CARGO_OUT_DIR = "${CARGO_TARGET_DIR}/${RUST_TARGET}/release"
-[tasks.xbuild]
-# This is the command where you get the ELF executable file (e.g. call to cargo build)
+TARGET_LINKER = "arm-vita-eabi-gcc"
+TARGET_LINKER_FLAGS = "-Wl,-q"
+
+[tasks.build]
+description = "Build the project using `cargo` as a static lib."
+command = "cargo"
+args = ["build", "-Z", "build-std=std,panic_abort", "--target=armv7-sony-vita-newlibeabihf", "--release"]
+
+[tasks.link]
+description = "Build an ELF executable using the `vitasdk` linker."
+dependencies = ["build"]
+script = [
+ """
+ ${TARGET_LINKER} ${TARGET_LINKER_FLAGS} \
+ -L"${CARGO_OUT_DIR}" \
+ -l"${CARGO_MAKE_CRATE_FS_NAME}" \
+ ${LINKER_LIBS} \
+ -o"${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.elf"
+ """
+]
[tasks.strip]
description = "Strip the produced ELF executable."
-dependencies = ["xbuild"]
+dependencies = ["link"]
command = "arm-vita-eabi-strip"
args = ["-g", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_FS_NAME}.elf']
@@ -124,4 +193,4 @@ script = [
]
```
-After running the above script, you should be able to get a *.vpk file in the same folder your *.elf executable resides. Now you can pick it and install it on your own PlayStation Vita using, for example, [VitaShell](https://github.com/TheOfficialFloW/VitaShell/releases) or you can use an emulator. For the time being, the most mature emulator for PlayStation Vita is [Vita3K](https://vita3k.org/), although I personally recommend testing your programs in real hardware, as the emulator is quite experimental.
+After running the above script, you should be able to get a *.vpk file in the same folder your *.elf executable resides. Now you can pick it and install it on your own PlayStation Vita using, or you can use an [Vita3K](https://vita3k.org/) emulator.
diff --git a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md
index 09e03e4dc..e351ea001 100644
--- a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md
+++ b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md
@@ -66,7 +66,7 @@ After completing these steps you can use rust normally in a native environment.
To cross compile, you'll need to:
-* Build the rust cross toochain using [rust-bootstrap-armv7-unknown-linux-uclibceabi](https://github.com/lancethepants/rust-bootstrap-armv7-unknown-linux-uclibceabi) or your own built toolchain.
+* Build the rust cross toolchain using [rust-bootstrap-armv7-unknown-linux-uclibceabi](https://github.com/lancethepants/rust-bootstrap-armv7-unknown-linux-uclibceabi) or your own built toolchain.
* Link your built toolchain with
```text
diff --git a/src/doc/rustc/src/platform-support/esp-idf.md b/src/doc/rustc/src/platform-support/esp-idf.md
new file mode 100644
index 000000000..8a4ca347e
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/esp-idf.md
@@ -0,0 +1,41 @@
+# `*-esp-espidf`
+
+**Tier: 3**
+
+Targets for the [ESP-IDF](https://github.com/espressif/esp-idf) development framework running on RISC-V and Xtensa CPUs.
+
+## Target maintainers
+
+- Ivan Markov [@ivmarkov](https://github.com/ivmarkov)
+- Scott Mabin [@MabezDev](https://github.com/MabezDev)
+
+## Requirements
+
+The target names follow this format: `$ARCH-esp-espidf`, where `$ARCH` specifies the target processor architecture. The following targets are currently defined:
+
+| Target name | Target CPU(s) |
+|--------------------------------|-----------------------|
+| `riscv32imc-esp-espidf` | [ESP32-C3](https://www.espressif.com/en/products/socs/esp32-c3) |
+
+The minimum supported ESP-IDF version is `v4.3`, though it is recommended to use the latest stable release if possible.
+
+## Building the target
+
+The target can be built by enabling it for a `rustc` build. The `build-std` feature is required to build the standard library for ESP-IDF. `ldproxy` is also required for linking, it can be installed from crates.io.
+
+```toml
+[build]
+target = ["$ARCH-esp-espidf"]
+
+[target.$ARCH-esp-espidf]
+linker = "ldproxy"
+
+[unstable]
+build-std = ["std", "panic_abort"]
+```
+
+The `esp-idf-sys` crate will handle the compilation of ESP-IDF, including downloading the relevant toolchains for the build.
+
+## Cross-compilation toolchains and C code
+
+`esp-idf-sys` exposes the toolchain used in the compilation of ESP-IDF, see the crate [documentation for build output propagation](https://github.com/esp-rs/esp-idf-sys#conditional-compilation) for more information.
diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md
index d7d31d872..999e71f80 100644
--- a/src/doc/rustc/src/platform-support/loongarch-linux.md
+++ b/src/doc/rustc/src/platform-support/loongarch-linux.md
@@ -1,6 +1,6 @@
# loongarch\*-unknown-linux-\*
-**Tier: 3**
+**Tier: 2**
[LoongArch] is a new RISC ISA developed by Loongson Technology Corporation Limited.
@@ -15,6 +15,8 @@ While the integer base ABI is implied by the machine field, the floating po
| f32 | The base ABI uses 32-bit FPRs for parameter passing. (lp64f)|
| sf | The base ABI uses no FPR for parameter passing. (lp64s) |
+<br>
+
|`ABI type(Base ABI/ABI extension)`| `C library` | `kernel` | `target tuple` |
|----------------------------------|-------------|----------|----------------------------------|
| lp64d/base | glibc | linux | loongarch64-unknown-linux-gnu |
diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md
index e2bdf73a9..03fa28462 100644
--- a/src/doc/rustc/src/platform-support/unknown-uefi.md
+++ b/src/doc/rustc/src/platform-support/unknown-uefi.md
@@ -123,7 +123,7 @@ There are 3 common ways to compile native C code for UEFI targets:
targets. Be wary of any includes that are not specifically suitable for UEFI
targets (especially the C standard library includes are not always
compatible). Freestanding compilations are recommended to avoid
- incompatibilites.
+ incompatibilities.
## Ecosystem
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
new file mode 100644
index 000000000..1a6f7bb83
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md
@@ -0,0 +1,57 @@
+# `x86_64h-apple-darwin`
+
+**Tier: 3**
+
+Target for macOS on late-generation `x86_64` Apple chips, usable as the
+`x86_64h` entry in universal binaries, and equivalent to LLVM's
+`x86_64h-apple-macosx*` targets.
+
+## Target maintainers
+
+- Thom Chiovoloni `thom@shift.click` <https://github.com/thomcc>
+
+## Requirements
+
+This target is an `x86_64` target that only supports Apple's late-gen
+(Haswell-compatible) Intel chips. It enables a set of target features available
+on these chips (AVX2 and similar), and MachO binaries built with this target may
+be used as the `x86_64h` entry in universal binaries ("fat" MachO binaries), and
+will fail to load on machines that do not support this.
+
+It should support the full standard library (`std` and `alloc` either with
+default or user-defined allocators). This target is probably most useful when
+targetted via cross-compilation (including from `x86_64-apple-darwin`), but if
+built manually, the host tools work.
+
+It is similar to `x86_64-apple-darwin` in nearly all respects, although the
+minimum supported OS version is slightly higher (it requires 10.8 rather than
+`x86_64-apple-darwin`'s 10.7).
+
+## Building the target
+
+Users on Apple targets can build this by adding it to the `target` list in
+`config.toml`, or with `-Zbuild-std`.
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `core` by using
+`build-std` or similar.
+
+## Testing
+
+Code built with this target can be run on the set of Intel macOS machines that
+support running `x86_64h` binaries (relatively recent Intel macs). The Rust test
+suite seems to work.
+
+## Cross-compilation toolchains and C code
+
+Cross-compilation to this target from Apple hosts should generally work without
+much configuration, so long as XCode and the CommandLineTools are installed.
+Targetting it from non-Apple hosts is difficult, but no moreso than targetting
+`x86_64-apple-darwin`.
+
+When compiling C code for this target, either the "`x86_64h-apple-macosx*`" LLVM
+targets should be used, or an argument like `-arch x86_64h` should be passed to
+the C compiler.
diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md
index 747cc629b..b512135d9 100644
--- a/src/doc/rustdoc/src/SUMMARY.md
+++ b/src/doc/rustdoc/src/SUMMARY.md
@@ -3,6 +3,7 @@
- [What is rustdoc?](what-is-rustdoc.md)
- [Command-line arguments](command-line-arguments.md)
- [How to read rustdoc output](how-to-read-rustdoc.md)
+ - [In-doc settings](read-documentation/in-doc-settings.md)
- [How to write documentation](how-to-write-documentation.md)
- [What to include (and exclude)](write-documentation/what-to-include.md)
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md
index 56342f65d..ccd77fb17 100644
--- a/src/doc/rustdoc/src/how-to-read-rustdoc.md
+++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md
@@ -43,7 +43,7 @@ including automatic and blanket implementations that `rustdoc` knows about.
Subheadings, variants, fields, and many other things in this documentation
are anchors and can be clicked on and deep-linked to,
which is a great way to communicate exactly what you're talking about.
-The typograpical character "§" appears next to lines with anchors on them
+The typographical character "§" appears next to lines with anchors on them
when hovered or given keyboard focus.
## The Navigation Bar
@@ -68,7 +68,7 @@ Typing in the search bar instantly searches the available documentation for
the string entered with a fuzzy matching algorithm that is tolerant of minor
typos.
-By default, the search results give are "In Names",
+By default, the search results given are "In Names",
meaning that the fuzzy match is made against the names of items.
Matching names are shown on the left, and the first few words of their
descriptions are given on the right.
@@ -105,11 +105,6 @@ will match these queries:
But it *does not* match `Result<Vec, u8>` or `Result<u8<Vec>>`.
-### Changing displayed theme
-
-You can change the displayed theme by opening the settings menu (the gear
-icon in the upper right) and then pick a new one from there.
-
### Shortcuts
Pressing `S` while focused elsewhere on the page will move focus to the
diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md
index 38fd1db5c..1fa9f8144 100644
--- a/src/doc/rustdoc/src/how-to-write-documentation.md
+++ b/src/doc/rustdoc/src/how-to-write-documentation.md
@@ -165,15 +165,15 @@ extensions:
### Strikethrough
Text may be rendered with a horizontal line through the center by wrapping the
-text with two tilde characters on each side:
+text with one or two tilde characters on each side:
```text
-An example of ~~strikethrough text~~.
+An example of ~~strikethrough text~~. You can also use ~single tildes~.
```
This example will render as:
-> An example of ~~strikethrough text~~.
+> An example of ~~strikethrough text~~. You can also use ~single tildes~.
This follows the [GitHub Strikethrough extension][strikethrough].
diff --git a/src/doc/rustdoc/src/images/collapsed-long-item.png b/src/doc/rustdoc/src/images/collapsed-long-item.png
new file mode 100644
index 000000000..c382870c6
--- /dev/null
+++ b/src/doc/rustdoc/src/images/collapsed-long-item.png
Binary files differ
diff --git a/src/doc/rustdoc/src/images/collapsed-trait-impls.png b/src/doc/rustdoc/src/images/collapsed-trait-impls.png
new file mode 100644
index 000000000..f685656e0
--- /dev/null
+++ b/src/doc/rustdoc/src/images/collapsed-trait-impls.png
Binary files differ
diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md
index 45db3bb9b..fd57b0796 100644
--- a/src/doc/rustdoc/src/lints.md
+++ b/src/doc/rustdoc/src/lints.md
@@ -374,3 +374,41 @@ warning: this URL is not a hyperlink
warning: 2 warnings emitted
```
+
+## `unescaped_backticks`
+
+This lint is **allowed by default**. It detects backticks (\`) that are not escaped.
+This usually means broken inline code. For example:
+
+```rust
+#![warn(rustdoc::unescaped_backticks)]
+
+/// `add(a, b) is the same as `add(b, a)`.
+pub fn add(a: i32, b: i32) -> i32 { a + b }
+```
+
+Which will give:
+
+```text
+warning: unescaped backtick
+ --> src/lib.rs:3:41
+ |
+3 | /// `add(a, b) is the same as `add(b, a)`.
+ | ^
+ |
+note: the lint level is defined here
+ --> src/lib.rs:1:9
+ |
+1 | #![warn(rustdoc::unescaped_backticks)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: a previous inline code might be longer than expected
+ |
+3 | /// `add(a, b)` is the same as `add(b, a)`.
+ | +
+help: if you meant to use a literal backtick, escape it
+ |
+3 | /// `add(a, b) is the same as `add(b, a)\`.
+ | +
+
+warning: 1 warning emitted
+```
diff --git a/src/doc/rustdoc/src/read-documentation/in-doc-settings.md b/src/doc/rustdoc/src/read-documentation/in-doc-settings.md
new file mode 100644
index 000000000..12928a4f3
--- /dev/null
+++ b/src/doc/rustdoc/src/read-documentation/in-doc-settings.md
@@ -0,0 +1,64 @@
+# Rustdoc in-doc settings
+
+Rustdoc's HTML output includes a settings menu, and this chapter describes what
+each setting in this menu does.
+
+It can be accessed by clicking on the gear button
+(<i class="fa fa-cog" aria-hidden="true"></i>) in the upper right.
+
+## Changing displayed theme
+
+It is possible to change the theme. If you pick the "system preference", you
+will be able to see two new sub-menus: "Preferred light theme" and "Preferred
+dark theme". It means that if your system preference is set to "light", then
+rustdoc will use the theme you selected in "Preferred light theme".
+
+## Auto-hide item contents for large items
+
+If the type definition contains more than 12 items, and this setting is enabled,
+it'll collapse them by default. You can see them by clicking on the `[+]` button
+to expand them.
+
+A good example of this setting in use can be seen in the
+[`Iterator`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) doc
+page:
+
+![Collapsed long item](../images/collapsed-long-item.png)
+
+## Auto-hide item methods' documentation
+
+If enabled, this setting will collapse all trait implementations blocks. It is
+convenient if you just want an overview of all the methods available. You can
+still see a method's documentation by expanding it.
+
+## Auto-hide trait implementation documentation
+
+If enabled, this setting will collapse all trait implementations blocks (you can
+see them in the "Trait Implementations" section). It is convenient if you just
+want an overview of all the trait implemented on a type. You can still see
+a trait implementation's associated items by expanding it.
+
+Example:
+
+![Collapsed trait implementations](../images/collapsed-trait-impls.png)
+
+## Directly go to item in search if there is only one result
+
+If this setting is enabled, you will directly be taken to the result page if
+your search only returned one element. Useful if you know exactly what you're
+looking for and want to be taken there directly and not waste time selecting the
+only search result.
+
+## Show line numbers on code examples
+
+If enabled, this setting will add line numbers to the code examples in the
+documentation. It provides a visual aide for the code reading.
+
+## Disable keyboard shortcuts
+
+If this setting is enabled, the keyboard shortcuts will be disabled. It's useful
+in case some of these shortcuts are already used by a web extension you're
+using.
+
+To see the full list of the rustdoc keyboard shortcuts, you can open the help
+menu (the button with the question mark on the left of the setting menu button).
diff --git a/src/doc/rustdoc/src/references.md b/src/doc/rustdoc/src/references.md
index 45cf4e88e..2e0cb1c0a 100644
--- a/src/doc/rustdoc/src/references.md
+++ b/src/doc/rustdoc/src/references.md
@@ -13,15 +13,15 @@ If you know of other great resources, please submit a pull request!
## Community
- [API Guidelines]
-- [Github tagged RFCs]
-- [Github tagged issues]
+- [GitHub tagged RFCs]
+- [GitHub tagged issues]
- [RFC (stalled) front page styleguide]
- [Guide on how to write documentation for a Rust crate]
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html
-[Github tagged RFCs]: https://github.com/rust-lang/rfcs/issues?q=label%3AT-rustdoc
-[Github tagged issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AT-rustdoc
+[GitHub tagged RFCs]: https://github.com/rust-lang/rfcs/issues?q=label%3AT-rustdoc
+[GitHub tagged issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AT-rustdoc
[Guide on how to write documentation for a Rust crate]: https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate
[Learn Rust]: https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments
[RFC 1574: More API Documentation Conventions]: https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html
diff --git a/src/doc/rustdoc/src/scraped-examples.md b/src/doc/rustdoc/src/scraped-examples.md
index d75f6d522..7197e01c8 100644
--- a/src/doc/rustdoc/src/scraped-examples.md
+++ b/src/doc/rustdoc/src/scraped-examples.md
@@ -24,14 +24,14 @@ Then this code snippet will be included in the documentation for `a_func`. This
This feature is unstable, so you can enable it by calling Rustdoc with the unstable `rustdoc-scrape-examples` flag:
```bash
-cargo doc -Zunstable-options -Zrustdoc-scrape-examples=examples
+cargo doc -Zunstable-options -Zrustdoc-scrape-examples
```
To enable this feature on [docs.rs](https://docs.rs), add this to your Cargo.toml:
```toml
[package.metadata.docs.rs]
-cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples=examples"]
+cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
```
diff --git a/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
index eb2285ef9..72157b5cd 100644
--- a/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
+++ b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
@@ -88,13 +88,16 @@ fn Foo() {}
```
These prefixes will be stripped when displayed in the documentation, so `[struct@Foo]` will be
-rendered as `Foo`.
+rendered as `Foo`. The following prefixes are available: `struct`, `enum`, `trait`, `union`,
+`mod`, `module`, `const`, `constant`, `fn`, `function`, `method`, `derive`, `type`, `value`,
+`macro`, `prim` or `primitive`.
You can also disambiguate for functions by adding `()` after the function name,
-or for macros by adding `!` after the macro name:
+or for macros by adding `!` after the macro name. The macro `!` can be followed by `()`, `{}`,
+or `[]`. Example:
```rust
-/// This is different from [`foo!`]
+/// This is different from [`foo!()`].
fn foo() {}
/// This is different from [`foo()`]
diff --git a/src/doc/style-guide/src/principles.md b/src/doc/style-guide/src/principles.md
index 216689731..2d203f264 100644
--- a/src/doc/style-guide/src/principles.md
+++ b/src/doc/style-guide/src/principles.md
@@ -6,7 +6,7 @@ following principles (in rough priority order):
* readability
- scan-ability
- avoiding misleading formatting
- - accessibility - readable and editable by users using the the widest
+ - accessibility - readable and editable by users using the widest
variety of hardware, including non-visual accessibility interfaces
- readability of code in contexts without syntax highlighting or IDE
assistance, such as rustc error messages, diffs, grep, and other
diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md
index 4ab1c36f9..671e6d31a 100644
--- a/src/doc/style-guide/src/statements.md
+++ b/src/doc/style-guide/src/statements.md
@@ -138,18 +138,31 @@ Otherwise, the `else` keyword and opening brace should be placed on the next lin
For example:
```rust
-let Some(x) = abcdef()
- .foo(
- "abc",
- some_really_really_really_long_ident,
- "ident",
- "123456",
- )
- .bar()
- .baz()
- .qux("fffffffffffffffff")
-else {
- foo_bar()
+fn main() {
+ let Some(x) = abcdef()
+ .foo(
+ "abc",
+ some_really_really_really_long_ident,
+ "ident",
+ "123456",
+ )
+ .bar()
+ .baz()
+ .qux("fffffffffffffffff")
+ else {
+ return
+ };
+
+ let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name
+ else {
+ return;
+ };
+
+ let Some(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ else {
+ return;
+ };
}
```
diff --git a/src/doc/style-guide/src/types.md b/src/doc/style-guide/src/types.md
index 25861ddab..ae456ef21 100644
--- a/src/doc/style-guide/src/types.md
+++ b/src/doc/style-guide/src/types.md
@@ -6,7 +6,7 @@
* `[T; expr]`, e.g., `[u32; 42]`, `[Vec<Foo>; 10 * 2 + foo()]` (space after colon, no spaces around square brackets)
* `*const T`, `*mut T` (no space after `*`, space before type)
* `&'a T`, `&T`, `&'a mut T`, `&mut T` (no space after `&`, single spaces separating other words)
-* `unsafe extern "C" fn<'a, 'b, 'c>(T, U, V) -> W` or `fn()` (single spaces around keyowrds and sigils, and after commas, no trailing commas, no spaces around brackets)
+* `unsafe extern "C" fn<'a, 'b, 'c>(T, U, V) -> W` or `fn()` (single spaces around keywords and sigils, and after commas, no trailing commas, no spaces around brackets)
* `!` should be treated like any other type name, `Name`
* `(A, B, C, D)` (spaces after commas, no spaces around parens, no trailing comma unless it is a one-tuple)
* `<Baz<T> as SomeTrait>::Foo::Bar` or `Foo::Bar` or `::Foo::Bar` (no spaces around `::` or angle brackets, single spaces around `as`)
diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
index 321992f7b..10f0fbc50 100644
--- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md
+++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
@@ -202,5 +202,5 @@ fn shoot_lasers() {}
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in
// the values(feature) list
-fn write_shakespear() {}
+fn write_shakespeare() {}
```
diff --git a/src/doc/unstable-book/src/compiler-flags/extern-options.md b/src/doc/unstable-book/src/compiler-flags/extern-options.md
index dfc1de77b..087b37dd8 100644
--- a/src/doc/unstable-book/src/compiler-flags/extern-options.md
+++ b/src/doc/unstable-book/src/compiler-flags/extern-options.md
@@ -4,6 +4,7 @@
* Tracking issue for `noprelude`: [#98398](https://github.com/rust-lang/rust/issues/98398)
* Tracking issue for `priv`: [#98399](https://github.com/rust-lang/rust/issues/98399)
* Tracking issue for `nounused`: [#98400](https://github.com/rust-lang/rust/issues/98400)
+* Tracking issue for `force`: [#111302](https://github.com/rust-lang/rust/issues/111302)
The behavior of the `--extern` flag can be modified with `noprelude`, `priv` or `nounused` options.
@@ -25,3 +26,4 @@ To use multiple options, separate them with a comma:
This is used by the [build-std project](https://github.com/rust-lang/wg-cargo-std-aware/) to simulate compatibility with sysroot-only crates.
* `priv`: Mark the crate as a private dependency for the [`exported_private_dependencies`](../../rustc/lints/listing/warn-by-default.html#exported-private-dependencies) lint.
* `nounused`: Suppress [`unused-crate-dependencies`](../../rustc/lints/listing/allowed-by-default.html#unused-crate-dependencies) warnings for the crate.
+* `force`: Resolve the crate as if it is used, even if it is not used. This can be used to satisfy compilation session requirements like the presence of an allocator or panic handler.
diff --git a/src/doc/unstable-book/src/compiler-flags/move-size-limit.md b/src/doc/unstable-book/src/compiler-flags/move-size-limit.md
index 88f022af2..aea054ba9 100644
--- a/src/doc/unstable-book/src/compiler-flags/move-size-limit.md
+++ b/src/doc/unstable-book/src/compiler-flags/move-size-limit.md
@@ -6,5 +6,5 @@ The `-Zmove-size-limit=N` compiler flag enables `large_assignments` lints which
will warn when moving objects whose size exceeds `N` bytes.
Lint warns only about moves in functions that participate in code generation.
-Consequently it will be ineffective for compiler invocatation that emit
+Consequently it will be ineffective for compiler invocation that emit
metadata only, i.e., `cargo check` like workflows.
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index b55348b78..aa776daf0 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -196,18 +196,18 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
# ControlFlowIntegrity
-The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially
-provides forward-edge control flow protection for Rust-compiled code only by
-aggregating function pointers in groups identified by their return and parameter
-types.
-
-Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
-binaries" (i.e., for when C or C++ and Rust -compiled code share the same
-virtual address space) will be provided in later work by defining and using
-compatible type identifiers (see Type metadata in the design document in the
-tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
-
-LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto).
+The LLVM Control Flow Integrity (CFI) support in the Rust compiler provides
+forward-edge control flow protection for both Rust-compiled code only and for C
+or C++ and Rust -compiled code mixed-language binaries, also known as “mixed
+binaries” (i.e., for when C or C++ and Rust -compiled code share the same
+virtual address space), by aggregating function pointers in groups identified by
+their return and parameter types.
+
+LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., `-Clto`).
+Cross-language LLVM CFI can be enabled with `-Zsanitizer=cfi`, and requires the
+`-Zsanitizer-cfi-normalize-integers` option to be used with Clang
+`-fsanitize-cfi-icall-normalize-integers` for normalizing integer types, and
+proper (i.e., non-rustc) LTO (i.e., `-Clinker-plugin-lto`).
See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details.
@@ -343,7 +343,7 @@ $
Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
```shell
-$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
Finished release [optimized] target(s) in 3.38s
Running `target/release/rust-cfi-2`
@@ -392,7 +392,7 @@ Closures][rust-book-ch19-05] chapter of the [The Rust Programming
Language][rust-book] book.
```shell
- cargo run --release
+$ cargo run --release
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
Finished release [optimized] target(s) in 0.74s
Running `target/release/rust-cfi-3`
@@ -404,7 +404,7 @@ $
Fig. 8. Build and execution of the modified example with LLVM CFI disabled.
```shell
-$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
Finished release [optimized] target(s) in 3.40s
Running `target/release/rust-cfi-3`
@@ -420,8 +420,92 @@ flow using an indirect branch/call to a function with different return and
parameter types than the return type expected and arguments intended/passed in
the call/branch site, the execution is also terminated (see Fig. 9).
-[rust-book-ch19-05]: ../../book/ch19-05-advanced-functions-and-closures.html
-[rust-book]: ../../book/title-page.html
+```ignore (cannot-test-this-because-uses-custom-build)
+int
+do_twice(int (*fn)(int), int arg) {
+ return fn(arg) + fn(arg);
+}
+```
+Fig. 10. Example C library.
+
+```ignore (cannot-test-this-because-uses-custom-build)
+use std::mem;
+
+#[link(name = "foo")]
+extern "C" {
+ fn do_twice(f: unsafe extern "C" fn(i32) -> i32, arg: i32) -> i32;
+}
+
+unsafe extern "C" fn add_one(x: i32) -> i32 {
+ x + 1
+}
+
+unsafe extern "C" fn add_two(x: i64) -> i64 {
+ x + 2
+}
+
+fn main() {
+ let answer = unsafe { do_twice(add_one, 5) };
+
+ println!("The answer is: {}", answer);
+
+ println!("With CFI enabled, you should not see the next answer");
+ let f: unsafe extern "C" fn(i32) -> i32 = unsafe {
+ mem::transmute::<*const u8, unsafe extern "C" fn(i32) -> i32>(add_two as *const u8)
+ };
+ let next_answer = unsafe { do_twice(f, 5) };
+
+ println!("The next answer is: {}", next_answer);
+}
+```
+Fig. 11. Another modified example from the [Advanced Functions and
+Closures][rust-book-ch19-05] chapter of the [The Rust Programming
+Language][rust-book] book.
+
+```shell
+$ make
+mkdir -p target/debug
+clang -I. -Isrc -Wall -flto -fvisibility=hidden -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
+llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
+RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build
+ Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.45s
+$ ./target/debug/main
+The answer is: 12
+With CFI enabled, you should not see the next answer
+The next answer is: 14
+$
+```
+Fig. 12. Build and execution of the modified example with LLVM CFI disabled.
+
+```shell
+$ make
+mkdir -p target/debug
+clang -I. -Isrc -Wall -flto -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-icall-normalize-integers -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
+llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
+RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build
+ Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.45s
+$ ./target/debug/main
+The answer is: 12
+With CFI enabled, you should not see the next answer
+Illegal instruction
+$
+```
+Fig. 13. Build and execution of the modified example with LLVM CFI enabled.
+
+When LLVM CFI is enabled, if there are any attempts to change/hijack control
+flow using an indirect branch/call to a function with different return and
+parameter types than the return type expected and arguments intended/passed in
+the call/branch site, even across the FFI boundary and for extern "C" function
+types indirectly called (i.e., callbacks/function pointers) across the FFI
+boundary, in C or C++ and Rust -compiled code mixed-language binaries, also
+known as “mixed binaries” (i.e., for when C or C++ and Rust -compiled code share
+the same virtual address space), the execution is also terminated (see Fig. 13).
+
+
+[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
+[rust-book]: https://doc.rust-lang.org/book/title-page.html
# HWAddressSanitizer
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index 1f52ab750..532cb9eea 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -17,6 +17,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
- AVR
- MSP430
- M68k
+- LoongArch
+- s390x
## Register classes
@@ -45,6 +47,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| M68k | `reg` | `d[0-7]`, `a[0-7]` | `r` |
| M68k | `reg_data` | `d[0-7]` | `d` |
| M68k | `reg_addr` | `a[0-3]` | `a` |
+| LoongArch | `reg` | `$r1`, `$r[4-20]`, `$r[23,30]` | `r` |
+| LoongArch | `freg` | `$f[0-31]` | `f` |
+| s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` |
+| s390x | `freg` | `f[0-15]` | `f` |
> **Notes**:
> - NVPTX doesn't have a fixed register set, so named registers are not supported.
@@ -76,6 +82,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| MSP430 | `reg` | None | `i8`, `i16` |
| M68k | `reg`, `reg_addr` | None | `i16`, `i32` |
| M68k | `reg_data` | None | `i8`, `i16`, `i32` |
+| LoongArch64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` |
+| LoongArch64 | `freg` | None | `f32`, `f64` |
+| s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` |
+| s390x | `freg` | None | `f32`, `f64` |
## Register aliases
@@ -97,6 +107,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| M68k | `a5` | `bp` |
| M68k | `a6` | `fp` |
| M68k | `a7` | `sp`, `usp`, `ssp`, `isp` |
+| LoongArch | `$r0` | `zero` |
+| LoongArch | `$r2` | `tp` |
+| LoongArch | `$r3` | `sp` |
+| LoongArch | `$r22` | `fp` |
> **Notes**:
> - TI does not mandate a frame pointer for MSP430, but toolchains are allowed
@@ -106,8 +120,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| Architecture | Unsupported register | Reason |
| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. |
-| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k) | The frame pointer cannot be used as an input or output. |
+| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. |
+| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `$fp` (LoongArch), `r11` (s390x) | The frame pointer cannot be used as an input or output. |
| All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
| MIPS | `$1` or `$at` | Reserved for assembler. |
@@ -118,6 +132,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. |
|MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. |
| M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. |
+| LoongArch | `$r0` or `$zero` | This is a constant zero register which can't be modified. |
+| LoongArch | `$r2` or `$tp` | This is reserved for TLS. |
+| LoongArch | `$r21` | This is reserved by the ABI. |
+| LoongArch | `$r31` or `$s8` | This is used internally by LLVM. |
## Template modifiers
@@ -132,6 +150,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| PowerPC | `reg` | None | `0` | None |
| PowerPC | `reg_nonzero` | None | `3` | `b` |
| PowerPC | `freg` | None | `0` | None |
+| LoongArch | `reg` | None | `$r2` | None |
+| LoongArch | `freg` | None | `$f0` | None |
+| s390x | `reg` | None | `%r0` | None |
+| s390x | `freg` | None | `%f0` | None |
# Flags covered by `preserves_flags`
@@ -142,3 +164,5 @@ These flags registers must be restored upon exiting the asm block if the `preser
- The status register `r2`.
- M68k
- The condition code register `ccr`.
+- s390x
+ - The condition code register `cc`.
diff --git a/src/doc/unstable-book/src/language-features/cfi-encoding.md b/src/doc/unstable-book/src/language-features/cfi-encoding.md
new file mode 100644
index 000000000..f2f74cc17
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/cfi-encoding.md
@@ -0,0 +1,25 @@
+# `cfi_encoding`
+
+The tracking issue for this feature is: [#89653]
+
+[#89653]: https://github.com/rust-lang/rust/issues/89653
+
+------------------------
+
+The `cfi_encoding` feature allows the user to define a CFI encoding for a type.
+It allows the user to use a different names for types that otherwise would be
+required to have the same name as used in externally defined C functions.
+
+## Examples
+
+```rust
+#![feature(cfi_encoding, extern_types)]
+
+#[cfi_encoding = "3Foo"]
+pub struct Type1(i32);
+
+extern {
+ #[cfi_encoding = "3Bar"]
+ type Type2;
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/debugger-visualizer.md b/src/doc/unstable-book/src/language-features/debugger-visualizer.md
deleted file mode 100644
index c7a0414b6..000000000
--- a/src/doc/unstable-book/src/language-features/debugger-visualizer.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# `debugger_visualizer`
-
-The tracking issue for this feature is: [#95939]
-
-[#95939]: https://github.com/rust-lang/rust/issues/95939
-
-------------------------
-
-The `debugger_visualizer` attribute can be used to instruct the compiler
-to embed a debugger visualizer file into the PDB/ELF generated by `rustc`.
-
-## Examples
-
-``` rust,ignore (partial-example)
-#![feature(debugger_visualizer)]
-#![debugger_visualizer(natvis_file = "foo.natvis")]
-#![debugger_visualizer(gdb_script_file = "foo.py")]
-struct Foo {
-
-}
-```
-
-## Limitations
-
-Currently, this feature only supports embedding Natvis files on `-windows-msvc`
-targets via the `natvis_file` meta item. `-windows-gnu` targets are not currently
-supported.
diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md
index a0fb4e743..ea9bace6d 100644
--- a/src/doc/unstable-book/src/language-features/intrinsics.md
+++ b/src/doc/unstable-book/src/language-features/intrinsics.md
@@ -22,7 +22,7 @@ via a declaration like
extern "rust-intrinsic" {
fn transmute<T, U>(x: T) -> U;
- fn offset<T>(dst: *const T, offset: isize) -> *const T;
+ fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
}
```
diff --git a/src/doc/unstable-book/src/language-features/raw-dylib.md b/src/doc/unstable-book/src/language-features/raw-dylib.md
deleted file mode 100644
index 5fd208ae7..000000000
--- a/src/doc/unstable-book/src/language-features/raw-dylib.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# `raw_dylib`
-
-The tracking issue for this feature is: [#58713]
-
-[#58713]: https://github.com/rust-lang/rust/issues/58713
-
-------------------------
-
-The `raw_dylib` feature allows you to link against the implementations of functions in an `extern`
-block without, on Windows, linking against an import library.
-
-```rust,ignore (partial-example)
-#![feature(raw_dylib)]
-
-#[link(name="library", kind="raw-dylib")]
-extern {
- fn extern_function(x: i32);
-}
-
-fn main() {
- unsafe {
- extern_function(14);
- }
-}
-```
-
-## Limitations
-
-This feature is unstable for the `x86` architecture, and stable for all other architectures.
-
-This feature is only supported on Windows.
-
-On the `x86` architecture, this feature supports only the `cdecl`, `stdcall`, `system`, `fastcall`, and
-`vectorcall` calling conventions.
diff --git a/src/doc/unstable-book/src/language-features/transparent-unions.md b/src/doc/unstable-book/src/language-features/transparent-unions.md
index 9b39b8971..bab88b148 100644
--- a/src/doc/unstable-book/src/language-features/transparent-unions.md
+++ b/src/doc/unstable-book/src/language-features/transparent-unions.md
@@ -65,7 +65,7 @@ pub union GenericUnion<T: Copy> { // Unions with non-`Copy` fields are unstable.
pub const THIS_IS_OKAY: GenericUnion<()> = GenericUnion { field: () };
```
-Like transarent `struct`s, a transparent `union` of type `U` has the same
+Like transparent `struct`s, a transparent `union` of type `U` has the same
layout, size, and ABI as its single non-ZST field. If it is generic over a type
`T`, and all its fields are ZSTs except for exactly one field of type `T`, then
it has the same layout and ABI as `T` (even if `T` is a ZST when monomorphized).
diff --git a/src/doc/unstable-book/src/library-features/libstd-thread-internals.md b/src/doc/unstable-book/src/library-features/libstd-thread-internals.md
deleted file mode 100644
index b682d12e7..000000000
--- a/src/doc/unstable-book/src/library-features/libstd-thread-internals.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# `libstd_thread_internals`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
new file mode 100644
index 000000000..9f65f1eee
--- /dev/null
+++ b/src/etc/completions/x.py.fish
@@ -0,0 +1,490 @@
+complete -c x.py -n "__fish_use_subcommand" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -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_use_subcommand" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_use_subcommand" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_use_subcommand" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_use_subcommand" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_use_subcommand" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_use_subcommand" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_use_subcommand" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_use_subcommand" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_use_subcommand" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_use_subcommand" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_use_subcommand" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_use_subcommand" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_use_subcommand" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_use_subcommand" -f -a "build" -d 'Compile either the compiler or libraries'
+complete -c x.py -n "__fish_use_subcommand" -f -a "check" -d 'Compile either the compiler or libraries, using cargo check'
+complete -c x.py -n "__fish_use_subcommand" -f -a "clippy" -d 'Run Clippy (uses rustup/cargo-installed clippy binary)'
+complete -c x.py -n "__fish_use_subcommand" -f -a "fix" -d 'Run cargo fix'
+complete -c x.py -n "__fish_use_subcommand" -f -a "fmt" -d 'Run rustfmt'
+complete -c x.py -n "__fish_use_subcommand" -f -a "doc" -d 'Build documentation'
+complete -c x.py -n "__fish_use_subcommand" -f -a "test" -d 'Build and run some test suites'
+complete -c x.py -n "__fish_use_subcommand" -f -a "bench" -d 'Build and run some benchmarks'
+complete -c x.py -n "__fish_use_subcommand" -f -a "clean" -d 'Clean out build directories'
+complete -c x.py -n "__fish_use_subcommand" -f -a "dist" -d 'Build distribution artifacts'
+complete -c x.py -n "__fish_use_subcommand" -f -a "install" -d 'Install distribution artifacts'
+complete -c x.py -n "__fish_use_subcommand" -f -a "run" -d 'Run tools contained in this repository'
+complete -c x.py -n "__fish_use_subcommand" -f -a "setup" -d 'Set up the environment for development'
+complete -c x.py -n "__fish_use_subcommand" -f -a "suggest" -d 'Suggest a subset of tests to run, based on modified files'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from build" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from build" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from build" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from build" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from check" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from check" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l all-targets -d 'Check all targets'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s A -d 'clippy lints to allow' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s D -d 'clippy lints to deny' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s W -d 'clippy lints to warn on' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s F -d 'clippy lints to forbid' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from clippy" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l fix
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from fix" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from fmt" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l check -d 'check formatting instead of applying'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from doc" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l open -d 'open the docs in a browser'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -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_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running tests' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l run -d 'whether to execute run-* tests' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from test" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from test" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l no-fail-fast -d 'run all tests regardless of failure'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l no-doc -d 'do not run doc tests'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l doc -d 'only run doc tests'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l bless -d 'whether to automatically update stderr/stdout files'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l force-rerun -d 'rerun tests even if the inputs are unchanged'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l only-modified -d 'only run tests that result has been changed'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rustfix-coverage -d 'enable this to generate a Rustfix coverage file, which is saved in `/<build_base>/rustfix_missing_coverage.txt`'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l test-args -r
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from bench" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from clean" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l all
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from dist" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from install" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from install" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from install" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from install" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l args -d 'arguments for the tool' -r
+complete -c x.py -n "__fish_seen_subcommand_from run" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from run" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from run" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from run" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from run" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from setup" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from 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_seen_subcommand_from suggest" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny ,warn ,default }"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always ,never ,auto }"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true ,false }"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l set -d 'override options in config.toml' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l run -d 'run suggested tests'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s h -l help -d 'Print help (see more with \'--help\')'
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
new file mode 100644
index 000000000..569c18655
--- /dev/null
+++ b/src/etc/completions/x.py.ps1
@@ -0,0 +1,622 @@
+
+using namespace System.Management.Automation
+using namespace System.Management.Automation.Language
+
+Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
+ param($wordToComplete, $commandAst, $cursorPosition)
+
+ $commandElements = $commandAst.CommandElements
+ $command = @(
+ 'x.py'
+ for ($i = 1; $i -lt $commandElements.Count; $i++) {
+ $element = $commandElements[$i]
+ if ($element -isnot [StringConstantExpressionAst] -or
+ $element.StringConstantType -ne [StringConstantType]::BareWord -or
+ $element.Value.StartsWith('-') -or
+ $element.Value -eq $wordToComplete) {
+ break
+ }
+ $element.Value
+ }) -join ';'
+
+ $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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+ [CompletionResult]::new('build', 'build', [CompletionResultType]::ParameterValue, 'Compile either the compiler or libraries')
+ [CompletionResult]::new('check', 'check', [CompletionResultType]::ParameterValue, 'Compile either the compiler or libraries, using cargo check')
+ [CompletionResult]::new('clippy', 'clippy', [CompletionResultType]::ParameterValue, 'Run Clippy (uses rustup/cargo-installed clippy binary)')
+ [CompletionResult]::new('fix', 'fix', [CompletionResultType]::ParameterValue, 'Run cargo fix')
+ [CompletionResult]::new('fmt', 'fmt', [CompletionResultType]::ParameterValue, 'Run rustfmt')
+ [CompletionResult]::new('doc', 'doc', [CompletionResultType]::ParameterValue, 'Build documentation')
+ [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'Build and run some test suites')
+ [CompletionResult]::new('bench', 'bench', [CompletionResultType]::ParameterValue, 'Build and run some benchmarks')
+ [CompletionResult]::new('clean', 'clean', [CompletionResultType]::ParameterValue, 'Clean out build directories')
+ [CompletionResult]::new('dist', 'dist', [CompletionResultType]::ParameterValue, 'Build distribution artifacts')
+ [CompletionResult]::new('install', 'install', [CompletionResultType]::ParameterValue, 'Install distribution artifacts')
+ [CompletionResult]::new('run', 'run', [CompletionResultType]::ParameterValue, 'Run tools contained in this repository')
+ [CompletionResult]::new('setup', 'setup', [CompletionResultType]::ParameterValue, 'Set up the environment for development')
+ [CompletionResult]::new('suggest', 'suggest', [CompletionResultType]::ParameterValue, 'Suggest a subset of tests to run, based on modified files')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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)')
+ [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ 'x.py;clippy' {
+ [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'clippy lints to allow')
+ [CompletionResult]::new('-D', 'D', [CompletionResultType]::ParameterName, 'clippy lints to deny')
+ [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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [CompletionResult]::new('--fix', 'fix', [CompletionResultType]::ParameterName, 'fix')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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)')
+ [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+ [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ 'x.py;test' {
+ [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times')
+ [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('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests')
+ [CompletionResult]::new('--compare-mode', 'compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to')
+ [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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--bless', 'bless', [CompletionResultType]::ParameterName, 'whether to automatically update stderr/stdout files')
+ [CompletionResult]::new('--force-rerun', 'force-rerun', [CompletionResultType]::ParameterName, 'rerun tests even if the inputs are unchanged')
+ [CompletionResult]::new('--only-modified', 'only-modified', [CompletionResultType]::ParameterName, 'only run tests that result has been changed')
+ [CompletionResult]::new('--rustfix-coverage', 'rustfix-coverage', [CompletionResultType]::ParameterName, 'enable this to generate a Rustfix coverage file, which is saved in `/<build_base>/rustfix_missing_coverage.txt`')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+ break
+ }
+ 'x.py;clean' {
+ [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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'all')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ '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', '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')
+ [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+ [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+ [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+ [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+ [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+ [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+ [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+ [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+ [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+ [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+ [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+ [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+ [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('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+ [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
+ [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)')
+ [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+ [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+ [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+ [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+ [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+ [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+ [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+ break
+ }
+ })
+
+ $completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
+ Sort-Object -Property ListItemText
+}
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
new file mode 100644
index 000000000..322afdb28
--- /dev/null
+++ b/src/etc/completions/x.py.sh
@@ -0,0 +1,1704 @@
+_x.py() {
+ local i cur prev opts cmd
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ cmd=""
+ opts=""
+
+ for i in ${COMP_WORDS[@]}
+ do
+ case "${cmd},${i}" in
+ ",$1")
+ cmd="x.py"
+ ;;
+ bootstrap,bench)
+ cmd="bootstrap__bench"
+ ;;
+ bootstrap,build)
+ cmd="bootstrap__build"
+ ;;
+ bootstrap,check)
+ cmd="bootstrap__check"
+ ;;
+ bootstrap,clean)
+ cmd="bootstrap__clean"
+ ;;
+ bootstrap,clippy)
+ cmd="bootstrap__clippy"
+ ;;
+ bootstrap,dist)
+ cmd="bootstrap__dist"
+ ;;
+ bootstrap,doc)
+ cmd="bootstrap__doc"
+ ;;
+ bootstrap,fix)
+ cmd="bootstrap__fix"
+ ;;
+ bootstrap,fmt)
+ cmd="bootstrap__fmt"
+ ;;
+ bootstrap,install)
+ cmd="bootstrap__install"
+ ;;
+ bootstrap,run)
+ cmd="bootstrap__run"
+ ;;
+ bootstrap,setup)
+ cmd="bootstrap__setup"
+ ;;
+ bootstrap,suggest)
+ cmd="bootstrap__suggest"
+ ;;
+ bootstrap,test)
+ cmd="bootstrap__test"
+ ;;
+ *)
+ ;;
+ esac
+ done
+
+ case "${cmd}" in
+ x.py)
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__bench)
+ opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --test-args)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__build)
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__check)
+ opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__clean)
+ opts="-v -i -j -h --all --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__clippy)
+ opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ -A)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ -D)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ -W)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ -F)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__dist)
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__doc)
+ opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__fix)
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__fmt)
+ opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__install)
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__run)
+ opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --args)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__setup)
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__suggest)
+ opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ x.py__test)
+ opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --skip)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --test-args)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-args)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --compare-mode)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --pass)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --run)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --config)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build-dir)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --build)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --host)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --target)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --exclude)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rustc-error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --on-fail)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --keep-stage-std)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --src)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --jobs)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ -j)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --warnings)
+ COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+ return 0
+ ;;
+ --error-format)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ --color)
+ COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+ return 0
+ ;;
+ --llvm-skip-rebuild)
+ COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+ return 0
+ ;;
+ --rust-profile-generate)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --rust-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --llvm-bolt-profile-use)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ --set)
+ COMPREPLY=("${cur}")
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
+ esac
+}
+
+complete -F _x.py -o bashdefault -o default x.py
diff --git a/src/etc/installer/pkg/Distribution.xml b/src/etc/installer/pkg/Distribution.xml
index 1643fc836..395814e74 100644
--- a/src/etc/installer/pkg/Distribution.xml
+++ b/src/etc/installer/pkg/Distribution.xml
@@ -23,7 +23,7 @@
</choices-outline>
<!--
These 'selected' scripts ensure that install and uninstall can never be selected at
- the same time. Exectly how they work is pretty mysterious, tied to the unspecified algorithm
+ the same time. Exactly how they work is pretty mysterious, tied to the unspecified algorithm
the installer uses to traverse the options after one is toggled.
-->
<choice id="install" visible="true"
diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py
index bca9c2ae1..36c7d82b3 100644
--- a/src/etc/lldb_lookup.py
+++ b/src/etc/lldb_lookup.py
@@ -115,4 +115,4 @@ def synthetic_lookup(valobj, dict):
if rust_type == RustType.STD_REF_CELL:
return StdRefSyntheticProvider(valobj, dict, is_cell=True)
- return DefaultSynthteticProvider(valobj, dict)
+ return DefaultSyntheticProvider(valobj, dict)
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index 697ad4293..c4381e202 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -31,7 +31,7 @@ from lldb import SBValue, SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLon
#
# You can find more information and examples here:
# 1. https://lldb.llvm.org/varformats.html
-# 2. https://lldb.llvm.org/python-reference.html
+# 2. https://lldb.llvm.org/use/python-reference.html
# 3. https://lldb.llvm.org/python_reference/lldb.formatters.cpp.libcxx-pysrc.html
# 4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa
####################################################################################################
@@ -69,9 +69,9 @@ def unwrap_unique_or_non_null(unique_or_nonnull):
return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0)
-class DefaultSynthteticProvider:
+class DefaultSyntheticProvider:
def __init__(self, valobj, dict):
- # type: (SBValue, dict) -> DefaultSynthteticProvider
+ # type: (SBValue, dict) -> DefaultSyntheticProvider
# logger = Logger.Logger()
# logger >> "Default synthetic provider for " + str(valobj.GetName())
self.valobj = valobj
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 9479b3ee0..baf2b0a85 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -1,7 +1,7 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::{self, Region, RegionVid, TypeFoldable, TypeSuperFoldable};
+use rustc_middle::ty::{self, Region, RegionVid, TypeFoldable};
use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult};
use thin_vec::ThinVec;
@@ -44,7 +44,7 @@ where
discard_positive_impl: bool,
) -> Option<Item> {
let tcx = self.cx.tcx;
- let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, [ty]));
+ let trait_ref = ty::Binder::dummy(ty::TraitRef::new(tcx, trait_def_id, [ty]));
if !self.cx.generated_synthetics.insert((ty, trait_def_id)) {
debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
return None;
@@ -141,7 +141,7 @@ where
let f = auto_trait::AutoTraitFinder::new(tcx);
debug!("get_auto_trait_impls({:?})", ty);
- let auto_traits: Vec<_> = self.cx.auto_traits.iter().copied().collect();
+ let auto_traits: Vec<_> = self.cx.auto_traits.to_vec();
let mut auto_traits: Vec<Item> = auto_traits
.into_iter()
.filter_map(|trait_def_id| {
@@ -556,7 +556,10 @@ where
WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
match *lhs {
Type::QPath(box QPathData {
- ref assoc, ref self_type, ref trait_, ..
+ ref assoc,
+ ref self_type,
+ trait_: Some(ref trait_),
+ ..
}) => {
let ty = &*self_type;
let mut new_trait = trait_.clone();
@@ -740,10 +743,11 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- (match *r {
- ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
- _ => None,
- })
- .unwrap_or_else(|| r.super_fold_with(self))
+ match *r {
+ // These are the regions that can be seen in the AST.
+ ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned().unwrap_or(r),
+ ty::ReEarlyBound(_) | ty::ReStatic | ty::ReLateBound(..) | ty::ReError(_) => r,
+ r => bug!("unexpected region: {r:?}"),
+ }
}
}
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 3a3bf6a7a..e4c05b573 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -20,7 +20,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
trace!("get_blanket_impls({:?})", ty);
let mut impls = Vec::new();
for trait_def_id in cx.tcx.all_traits() {
- if !cx.cache.effective_visibilities.is_directly_public(cx.tcx, trait_def_id)
+ if !cx.cache.effective_visibilities.is_reachable(cx.tcx, trait_def_id)
|| cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
{
continue;
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index cc5d13808..7dc08b3b1 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -152,8 +152,9 @@ pub(crate) fn try_inline_glob(
// reexported by the glob, e.g. because they are shadowed by something else.
let reexports = cx
.tcx
- .module_children_reexports(current_mod)
+ .module_children_local(current_mod)
.iter()
+ .filter(|child| !child.reexport_chain.is_empty())
.filter_map(|child| child.res.opt_def_id())
.collect();
let mut items = build_module_items(cx, did, visited, inlined_names, Some(&reexports));
@@ -354,9 +355,9 @@ pub(crate) fn build_impl(
return;
}
- let _prof_timer = cx.tcx.sess.prof.generic_activity("build_impl");
-
let tcx = cx.tcx;
+ let _prof_timer = tcx.sess.prof.generic_activity("build_impl");
+
let associated_trait = tcx.impl_trait_ref(did).map(ty::EarlyBinder::skip_binder);
// Only inline impl if the implemented trait is
@@ -528,7 +529,7 @@ pub(crate) fn build_impl(
items: trait_items,
polarity,
kind: if utils::has_doc_flag(tcx, did, sym::fake_variadic) {
- ImplKind::FakeVaradic
+ ImplKind::FakeVariadic
} else {
ImplKind::Normal
},
@@ -705,7 +706,12 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
g.where_predicates.retain(|pred| match pred {
clean::WherePredicate::BoundPredicate {
- ty: clean::QPath(box clean::QPathData { self_type: clean::Generic(ref s), trait_, .. }),
+ ty:
+ clean::QPath(box clean::QPathData {
+ self_type: clean::Generic(ref s),
+ trait_: Some(trait_),
+ ..
+ }),
bounds,
..
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 5fa0c120f..03adc19e3 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -119,7 +119,39 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
});
let kind = ModuleItem(Module { items, span });
- Item::from_def_id_and_parts(doc.def_id.to_def_id(), Some(doc.name), kind, cx)
+ generate_item_with_correct_attrs(cx, kind, doc.def_id, doc.name, doc.import_id, doc.renamed)
+}
+
+fn generate_item_with_correct_attrs(
+ cx: &mut DocContext<'_>,
+ kind: ItemKind,
+ local_def_id: LocalDefId,
+ name: Symbol,
+ import_id: Option<LocalDefId>,
+ renamed: Option<Symbol>,
+) -> Item {
+ let def_id = local_def_id.to_def_id();
+ let target_attrs = inline::load_attrs(cx, def_id);
+ let attrs = if let Some(import_id) = import_id {
+ let is_inline = inline::load_attrs(cx, import_id.to_def_id())
+ .lists(sym::doc)
+ .get_word_attr(sym::inline)
+ .is_some();
+ let mut attrs = get_all_import_attributes(cx, import_id, local_def_id, is_inline);
+ add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None);
+ attrs
+ } else {
+ // We only keep the item's attributes.
+ target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect()
+ };
+
+ let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
+ let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
+
+ let name = renamed.or(Some(name));
+ let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, Box::new(attrs), cfg);
+ item.inline_stmt_id = import_id.map(|local| local.to_def_id());
+ item
}
fn clean_generic_bound<'tcx>(
@@ -131,7 +163,7 @@ fn clean_generic_bound<'tcx>(
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
- let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
+ let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(cx.tcx, def_id));
let generic_args = clean_generic_args(generic_args, cx);
let GenericArgs::AngleBracketed { bindings, .. } = generic_args
@@ -304,7 +336,7 @@ pub(crate) fn clean_predicate<'tcx>(
clean_region_outlives_predicate(pred)
}
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(pred)) => {
- clean_type_outlives_predicate(pred, cx)
+ clean_type_outlives_predicate(bound_predicate.rebind(pred), cx)
}
ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
Some(clean_projection_predicate(bound_predicate.rebind(pred), cx))
@@ -345,7 +377,7 @@ fn clean_poly_trait_predicate<'tcx>(
}
fn clean_region_outlives_predicate<'tcx>(
- pred: ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>,
+ pred: ty::RegionOutlivesPredicate<'tcx>,
) -> Option<WherePredicate> {
let ty::OutlivesPredicate(a, b) = pred;
@@ -358,13 +390,13 @@ fn clean_region_outlives_predicate<'tcx>(
}
fn clean_type_outlives_predicate<'tcx>(
- pred: ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
+ pred: ty::Binder<'tcx, ty::TypeOutlivesPredicate<'tcx>>,
cx: &mut DocContext<'tcx>,
) -> Option<WherePredicate> {
- let ty::OutlivesPredicate(ty, lt) = pred;
+ let ty::OutlivesPredicate(ty, lt) = pred.skip_binder();
Some(WherePredicate::BoundPredicate {
- ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None),
+ ty: clean_middle_ty(pred.rebind(ty), cx, None),
bounds: vec![GenericBound::Outlives(
clean_middle_region(lt).expect("failed to clean lifetimes"),
)],
@@ -422,8 +454,8 @@ fn clean_projection<'tcx>(
let bounds = cx
.tcx
.explicit_item_bounds(ty.skip_binder().def_id)
- .iter()
- .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs))
+ .subst_iter_copied(cx.tcx, ty.skip_binder().substs)
+ .map(|(pred, _)| pred)
.collect::<Vec<_>>();
return clean_middle_opaque_bounds(cx, bounds);
}
@@ -441,7 +473,7 @@ fn clean_projection<'tcx>(
assoc: projection_to_path_segment(ty, cx),
should_show_cast,
self_type,
- trait_,
+ trait_: Some(trait_),
}))
}
@@ -1315,10 +1347,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
}
if let ty::TraitContainer = assoc_item.container {
- let bounds = tcx.explicit_item_bounds(assoc_item.def_id);
+ let bounds =
+ tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied();
let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
let predicates =
- tcx.arena.alloc_from_iter(bounds.into_iter().chain(predicates).copied());
+ tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
let mut generics = clean_ty_generics(
cx,
tcx.generics_of(assoc_item.def_id),
@@ -1329,7 +1362,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
let mut bounds: Vec<GenericBound> = Vec::new();
generics.where_predicates.retain_mut(|pred| match *pred {
WherePredicate::BoundPredicate {
- ty: QPath(box QPathData { ref assoc, ref self_type, ref trait_, .. }),
+ ty:
+ QPath(box QPathData {
+ ref assoc,
+ ref self_type,
+ trait_: Some(ref trait_),
+ ..
+ }),
bounds: ref mut pred_bounds,
..
} => {
@@ -1491,25 +1530,30 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
assoc: clean_path_segment(p.segments.last().expect("segments were empty"), cx),
should_show_cast,
self_type,
- trait_,
+ trait_: Some(trait_),
}))
}
hir::QPath::TypeRelative(qself, segment) => {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
- let res = match ty.kind() {
+ let self_type = clean_ty(qself, cx);
+
+ let (trait_, should_show_cast) = match ty.kind() {
ty::Alias(ty::Projection, proj) => {
- Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
+ let res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
+ let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
+ register_res(cx, trait_.res);
+ let self_def_id = res.opt_def_id();
+ let should_show_cast =
+ compute_should_show_cast(self_def_id, &trait_, &self_type);
+
+ (Some(trait_), should_show_cast)
}
+ ty::Alias(ty::Inherent, _) => (None, false),
// Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
ty::Error(_) => return Type::Infer,
- // Otherwise, this is an inherent associated type.
- _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None),
+ _ => bug!("clean: expected associated type, found `{ty:?}`"),
};
- let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
- register_res(cx, trait_.res);
- let self_def_id = res.opt_def_id();
- let self_type = clean_ty(qself, cx);
- let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
+
Type::QPath(Box::new(QPathData {
assoc: clean_path_segment(segment, cx),
should_show_cast,
@@ -1528,7 +1572,9 @@ fn maybe_expand_private_type_alias<'tcx>(
let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
// Substitute private type aliases
let def_id = def_id.as_local()?;
- let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id()) {
+ let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id())
+ && !cx.current_type_aliases.contains_key(&def_id.to_def_id())
+ {
&cx.tcx.hir().expect_item(def_id).kind
} else {
return None;
@@ -1608,7 +1654,7 @@ fn maybe_expand_private_type_alias<'tcx>(
}
}
- Some(cx.enter_alias(substs, |cx| clean_ty(ty, cx)))
+ Some(cx.enter_alias(substs, def_id.to_def_id(), |cx| clean_ty(ty, cx)))
}
pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
@@ -1699,7 +1745,7 @@ fn normalize<'tcx>(
pub(crate) fn clean_middle_ty<'tcx>(
bound_ty: ty::Binder<'tcx, Ty<'tcx>>,
cx: &mut DocContext<'tcx>,
- def_id: Option<DefId>,
+ parent_def_id: Option<DefId>,
) -> Type {
let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty);
match *bound_ty.skip_binder().kind() {
@@ -1829,7 +1875,32 @@ pub(crate) fn clean_middle_ty<'tcx>(
Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None)).collect())
}
- ty::Alias(ty::Projection, ref data) => clean_projection(bound_ty.rebind(*data), cx, def_id),
+ ty::Alias(ty::Projection, ref data) => {
+ clean_projection(bound_ty.rebind(*data), cx, parent_def_id)
+ }
+
+ ty::Alias(ty::Inherent, alias_ty) => {
+ let alias_ty = bound_ty.rebind(alias_ty);
+ let self_type = clean_middle_ty(alias_ty.map_bound(|ty| ty.self_ty()), cx, None);
+
+ Type::QPath(Box::new(QPathData {
+ assoc: PathSegment {
+ name: cx.tcx.associated_item(alias_ty.skip_binder().def_id).name,
+ args: GenericArgs::AngleBracketed {
+ args: substs_to_args(
+ cx,
+ alias_ty.map_bound(|ty| ty.substs.as_slice()),
+ true,
+ )
+ .into(),
+ bindings: Default::default(),
+ },
+ },
+ should_show_cast: false,
+ self_type,
+ trait_: None,
+ }))
+ }
ty::Param(ref p) => {
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
@@ -1840,15 +1911,30 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
- // by looking up the bounds associated with the def_id.
- let bounds = cx
- .tcx
- .explicit_item_bounds(def_id)
- .iter()
- .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs))
- .collect::<Vec<_>>();
- clean_middle_opaque_bounds(cx, bounds)
+ // If it's already in the same alias, don't get an infinite loop.
+ if cx.current_type_aliases.contains_key(&def_id) {
+ let path =
+ external_path(cx, def_id, false, ThinVec::new(), bound_ty.rebind(substs));
+ Type::Path { path }
+ } else {
+ *cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
+ // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
+ // by looking up the bounds associated with the def_id.
+ let bounds = cx
+ .tcx
+ .explicit_item_bounds(def_id)
+ .subst_iter_copied(cx.tcx, substs)
+ .map(|(bound, _)| bound)
+ .collect::<Vec<_>>();
+ let ty = clean_middle_opaque_bounds(cx, bounds);
+ if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
+ *count -= 1;
+ if *count == 0 {
+ cx.current_type_aliases.remove(&def_id);
+ }
+ }
+ ty
+ }
}
ty::Closure(..) => panic!("Closure"),
@@ -2069,9 +2155,9 @@ pub(crate) fn reexport_chain<'tcx>(
import_def_id: LocalDefId,
target_def_id: LocalDefId,
) -> &'tcx [Reexport] {
- for child in tcx.module_children_reexports(tcx.local_parent(import_def_id)) {
+ for child in tcx.module_children_local(tcx.local_parent(import_def_id)) {
if child.res.opt_def_id() == Some(target_def_id.to_def_id())
- && child.reexport_chain[0].id() == Some(import_def_id.to_def_id())
+ && child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id())
{
return &child.reexport_chain;
}
@@ -2228,13 +2314,17 @@ fn clean_maybe_renamed_item<'tcx>(
generics: clean_generics(ty.generics, cx),
}),
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 ty = clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
- TypedefItem(Box::new(Typedef {
- type_: rustdoc_ty,
- generics: clean_generics(generics, cx),
- item_type: Some(ty),
- }))
+ let generics = clean_generics(generics, cx);
+ if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
+ *count -= 1;
+ if *count == 0 {
+ cx.current_type_aliases.remove(&def_id);
+ }
+ }
+ TypedefItem(Box::new(Typedef { type_: rustdoc_ty, generics, item_type: Some(ty) }))
}
ItemKind::Enum(ref def, generics) => EnumItem(Enum {
variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
@@ -2287,29 +2377,14 @@ fn clean_maybe_renamed_item<'tcx>(
_ => unreachable!("not yet converted"),
};
- let target_attrs = inline::load_attrs(cx, def_id);
- let attrs = if let Some(import_id) = import_id {
- let is_inline = inline::load_attrs(cx, import_id.to_def_id())
- .lists(sym::doc)
- .get_word_attr(sym::inline)
- .is_some();
- let mut attrs =
- get_all_import_attributes(cx, import_id, item.owner_id.def_id, is_inline);
- add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None);
- attrs
- } else {
- // We only keep the item's attributes.
- target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect()
- };
-
- let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
- let attrs =
- Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
-
- let mut item =
- Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg);
- item.inline_stmt_id = import_id.map(|local| local.to_def_id());
- vec![item]
+ vec![generate_item_with_correct_attrs(
+ cx,
+ kind,
+ item.owner_id.def_id,
+ name,
+ import_id,
+ renamed,
+ )]
})
}
@@ -2339,14 +2414,15 @@ fn clean_impl<'tcx>(
}
let for_ = clean_ty(impl_.self_ty, cx);
- let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
- DefKind::TyAlias => Some(clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(did).subst_identity()),
- cx,
- Some(did),
- )),
- _ => None,
- });
+ let type_alias =
+ for_.def_id(&cx.cache).and_then(|alias_def_id: DefId| match tcx.def_kind(alias_def_id) {
+ DefKind::TyAlias => Some(clean_middle_ty(
+ ty::Binder::dummy(tcx.type_of(def_id).subst_identity()),
+ cx,
+ Some(def_id.to_def_id()),
+ )),
+ _ => None,
+ });
let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
let kind = ImplItem(Box::new(Impl {
unsafety: impl_.unsafety,
@@ -2356,7 +2432,7 @@ fn clean_impl<'tcx>(
items,
polarity: tcx.impl_polarity(def_id),
kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::fake_variadic) {
- ImplKind::FakeVaradic
+ ImplKind::FakeVariadic
} else {
ImplKind::Normal
},
@@ -2516,7 +2592,8 @@ fn clean_use_statement_inner<'tcx>(
} else {
if inline_attr.is_none()
&& let Res::Def(DefKind::Mod, did) = path.res
- && !did.is_local() && did.is_crate_root()
+ && !did.is_local()
+ && did.is_crate_root()
{
// if we're `pub use`ing an extern crate root, don't inline it unless we
// were specifically asked for it
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 6d2ce9e28..e9ccea2cf 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -11,6 +11,7 @@ use arrayvec::ArrayVec;
use thin_vec::ThinVec;
use rustc_ast as ast;
+use rustc_ast_pretty::pprust;
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -20,7 +21,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{BodyId, Mutability};
use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, TyCtxt, Visibility};
use rustc_resolve::rustdoc::{add_doc_fragment, attrs_to_doc_fragments, inner_docs, DocFragment};
@@ -156,7 +157,7 @@ impl ExternalCrate {
}
/// Attempts to find where an external crate is located, given that we're
- /// rendering in to the specified source destination.
+ /// rendering into the specified source destination.
pub(crate) fn location(
&self,
extern_url: Option<&str>,
@@ -400,12 +401,18 @@ impl Item {
.unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
}
- /// Finds the `doc` attribute as a NameValue and returns the corresponding
- /// value found.
- pub(crate) fn doc_value(&self) -> Option<String> {
+ /// Combine all doc strings into a single value handling indentation and newlines as needed.
+ pub(crate) fn doc_value(&self) -> String {
self.attrs.doc_value()
}
+ /// Combine all doc strings into a single value handling indentation and newlines as needed.
+ /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
+ /// documentation but it is empty (e.g. `#[doc = ""]`).
+ pub(crate) fn opt_doc_value(&self) -> Option<String> {
+ self.attrs.opt_doc_value()
+ }
+
pub(crate) fn from_def_id_and_parts(
def_id: DefId,
name: Option<Symbol>,
@@ -442,12 +449,6 @@ impl Item {
}
}
- /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
- /// with newlines.
- pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
- self.attrs.collapsed_doc_value()
- }
-
pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
use crate::html::format::{href, link_tooltip};
@@ -711,6 +712,78 @@ impl Item {
};
Some(tcx.visibility(def_id))
}
+
+ pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, keep_as_is: bool) -> Vec<String> {
+ const ALLOWED_ATTRIBUTES: &[Symbol] =
+ &[sym::export_name, sym::link_section, sym::no_mangle, sym::repr, sym::non_exhaustive];
+
+ use rustc_abi::IntegerType;
+ use rustc_middle::ty::ReprFlags;
+
+ let mut attrs: Vec<String> = self
+ .attrs
+ .other_attrs
+ .iter()
+ .filter_map(|attr| {
+ if keep_as_is {
+ Some(pprust::attribute_to_string(attr))
+ } else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
+ Some(
+ pprust::attribute_to_string(attr)
+ .replace("\\\n", "")
+ .replace('\n', "")
+ .replace(" ", " "),
+ )
+ } else {
+ None
+ }
+ })
+ .collect();
+ if let Some(def_id) = self.item_id.as_def_id() &&
+ !def_id.is_local() &&
+ // This check is needed because `adt_def` will panic if not a compatible type otherwise...
+ matches!(self.type_(), ItemType::Struct | ItemType::Enum | ItemType::Union)
+ {
+ let repr = tcx.adt_def(def_id).repr();
+ let mut out = Vec::new();
+ if repr.flags.contains(ReprFlags::IS_C) {
+ out.push("C");
+ }
+ if repr.flags.contains(ReprFlags::IS_TRANSPARENT) {
+ out.push("transparent");
+ }
+ if repr.flags.contains(ReprFlags::IS_SIMD) {
+ out.push("simd");
+ }
+ let pack_s;
+ if let Some(pack) = repr.pack {
+ pack_s = format!("packed({})", pack.bytes());
+ out.push(&pack_s);
+ }
+ let align_s;
+ if let Some(align) = repr.align {
+ align_s = format!("align({})", align.bytes());
+ out.push(&align_s);
+ }
+ let int_s;
+ if let Some(int) = repr.int {
+ int_s = match int {
+ IntegerType::Pointer(is_signed) => {
+ format!("{}size", if is_signed { 'i' } else { 'u' })
+ }
+ IntegerType::Fixed(size, is_signed) => {
+ format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8)
+ }
+ };
+ out.push(&int_s);
+ }
+ if out.is_empty() {
+ return Vec::new();
+ }
+ attrs.push(format!("#[repr({})]", out.join(", ")));
+ }
+ attrs
+ }
}
#[derive(Clone, Debug)]
@@ -751,7 +824,7 @@ pub(crate) enum ItemKind {
PrimitiveItem(PrimitiveType),
/// A required associated constant in a trait declaration.
TyAssocConstItem(Type),
- /// An associated associated constant in a trait impl or a provided one in a trait declaration.
+ /// An associated constant in a trait impl or a provided one in a trait declaration.
AssocConstItem(Type, ConstantKind),
/// A required associated type in a trait declaration.
///
@@ -995,17 +1068,6 @@ impl<I: Iterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
}
}
-/// Collapse a collection of [`DocFragment`]s into one string,
-/// handling indentation and newlines as needed.
-pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
- let mut acc = String::new();
- for frag in doc_strings {
- add_doc_fragment(&mut acc, frag);
- }
- acc.pop();
- acc
-}
-
/// A link that has not yet been rendered.
///
/// This link will be turned into a rendered link by [`Item::links`].
@@ -1090,29 +1152,23 @@ impl Attributes {
Attributes { doc_strings, other_attrs }
}
- /// Finds the `doc` attribute as a NameValue and returns the corresponding
- /// value found.
- pub(crate) fn doc_value(&self) -> Option<String> {
- let mut iter = self.doc_strings.iter();
-
- let ori = iter.next()?;
- let mut out = String::new();
- add_doc_fragment(&mut out, ori);
- for new_frag in iter {
- add_doc_fragment(&mut out, new_frag);
- }
- out.pop();
- if out.is_empty() { None } else { Some(out) }
+ /// Combine all doc strings into a single value handling indentation and newlines as needed.
+ pub(crate) fn doc_value(&self) -> String {
+ self.opt_doc_value().unwrap_or_default()
}
- /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
- /// with newlines.
- pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
- if self.doc_strings.is_empty() {
- None
- } else {
- Some(collapse_doc_fragments(&self.doc_strings))
- }
+ /// Combine all doc strings into a single value handling indentation and newlines as needed.
+ /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
+ /// documentation but it is empty (e.g. `#[doc = ""]`).
+ pub(crate) fn opt_doc_value(&self) -> Option<String> {
+ (!self.doc_strings.is_empty()).then(|| {
+ let mut res = String::new();
+ for frag in &self.doc_strings {
+ add_doc_fragment(&mut res, frag);
+ }
+ res.pop();
+ res
+ })
}
pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
@@ -1587,7 +1643,7 @@ impl Type {
pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
- Some((self_type, trait_.def_id(), assoc.clone()))
+ Some((self_type, trait_.as_ref()?.def_id(), assoc.clone()))
} else {
None
}
@@ -1631,7 +1687,7 @@ pub(crate) struct QPathData {
pub self_type: Type,
/// FIXME: compute this field on demand.
pub should_show_cast: bool,
- pub trait_: Path,
+ pub trait_: Option<Path>,
}
/// A primitive (aka, builtin) type.
@@ -2305,7 +2361,7 @@ impl Impl {
pub(crate) enum ImplKind {
Normal,
Auto,
- FakeVaradic,
+ FakeVariadic,
Blanket(Box<Type>),
}
@@ -2319,7 +2375,7 @@ impl ImplKind {
}
pub(crate) fn is_fake_variadic(&self) -> bool {
- matches!(self, ImplKind::FakeVaradic)
+ matches!(self, ImplKind::FakeVariadic)
}
pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
index d8c91a968..394954208 100644
--- a/src/librustdoc/clean/types/tests.rs
+++ b/src/librustdoc/clean/types/tests.rs
@@ -1,7 +1,5 @@
use super::*;
-use crate::clean::collapse_doc_fragments;
-
use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragment, DocFragmentKind};
use rustc_span::create_default_session_globals_then;
use rustc_span::source_map::DUMMY_SP;
@@ -22,7 +20,8 @@ fn run_test(input: &str, expected: &str) {
create_default_session_globals_then(|| {
let mut s = create_doc_fragment(input);
unindent_doc_fragments(&mut s);
- assert_eq!(collapse_doc_fragments(&s), expected);
+ let attrs = Attributes { doc_strings: s, other_attrs: Default::default() };
+ assert_eq!(attrs.doc_value(), expected);
});
}
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index cca50df0d..366f93952 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -193,7 +193,7 @@ pub(crate) fn build_deref_target_impls(
};
if let Some(prim) = target.primitive_type() {
- let _prof_timer = cx.tcx.sess.prof.generic_activity("build_primitive_inherent_impls");
+ let _prof_timer = tcx.sess.prof.generic_activity("build_primitive_inherent_impls");
for did in prim.impls(tcx).filter(|did| !did.is_local()) {
inline::build_impl(cx, did, None, ret);
}
@@ -243,9 +243,9 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs: _ }) => {
let s = if let Some(def) = def.as_local() {
- print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
+ print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def))
} else {
- inline::print_inlined_const(cx.tcx, def.did)
+ inline::print_inlined_const(cx.tcx, def)
};
s
@@ -594,9 +594,8 @@ pub(super) fn display_macro_source(
def_id: DefId,
vis: ty::Visibility<DefId>,
) -> String {
- let tts: Vec<_> = def.body.tokens.clone().into_trees().collect();
// Extract the spans of all matchers. They represent the "interface" of the macro.
- let matchers = tts.chunks(4).map(|arm| &arm[0]);
+ let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
if def.macro_rules {
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx.tcx, matchers, ";"))
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 1be4f364e..9f08609a6 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -314,7 +314,6 @@ impl Options {
matches: &getopts::Matches,
args: Vec<String>,
) -> Result<(Options, RenderOptions), i32> {
- let args = &args[1..];
// Check for unstable options.
nightly_options::check_nightly_options(matches, &opts());
@@ -382,7 +381,7 @@ impl Options {
match kind.parse() {
Ok(kind) => emit.push(kind),
Err(()) => {
- diag.err(&format!("unrecognized emission type: {}", kind));
+ diag.err(format!("unrecognized emission type: {}", kind));
return Err(1);
}
}
@@ -491,7 +490,7 @@ impl Options {
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset
//
// The original key values we have are the same as the DOM storage API keys and the
- // command line options, so contain `-`. Our Javascript needs to be able to look
+ // command line options, so contain `-`. Our JavaScript needs to be able to look
// these values up both in `dataset` and in the storage API, so it needs to be able
// to convert the names back and forth. Despite doing this kebab-case to
// StudlyCaps transformation automatically, the JS DOM API does not provide a
@@ -559,28 +558,28 @@ impl Options {
matches.opt_strs("theme").iter().map(|s| (PathBuf::from(&s), s.to_owned()))
{
if !theme_file.is_file() {
- diag.struct_err(&format!("invalid argument: \"{}\"", theme_s))
+ diag.struct_err(format!("invalid argument: \"{}\"", theme_s))
.help("arguments to --theme must be files")
.emit();
return Err(1);
}
if theme_file.extension() != Some(OsStr::new("css")) {
- diag.struct_err(&format!("invalid argument: \"{}\"", theme_s))
+ diag.struct_err(format!("invalid argument: \"{}\"", theme_s))
.help("arguments to --theme must have a .css extension")
.emit();
return Err(1);
}
let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag);
if !success {
- diag.struct_err(&format!("error loading theme file: \"{}\"", theme_s)).emit();
+ diag.struct_err(format!("error loading theme file: \"{}\"", theme_s)).emit();
return Err(1);
} else if !ret.is_empty() {
- diag.struct_warn(&format!(
+ diag.struct_warn(format!(
"theme file \"{}\" is missing CSS rules from the default theme",
theme_s
))
.warn("the theme may appear incorrect when loaded")
- .help(&format!(
+ .help(format!(
"to see what rules are missing, call `rustdoc --check-theme \"{}\"`",
theme_s
))
@@ -611,7 +610,7 @@ impl Options {
match matches.opt_str("r").as_deref() {
Some("rust") | None => {}
Some(s) => {
- diag.struct_err(&format!("unknown input format: {}", s)).emit();
+ diag.struct_err(format!("unknown input format: {}", s)).emit();
return Err(1);
}
}
@@ -631,7 +630,7 @@ impl Options {
let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) {
Ok(types) => types,
Err(e) => {
- diag.struct_err(&format!("unknown crate type: {}", e)).emit();
+ diag.struct_err(format!("unknown crate type: {}", e)).emit();
return Err(1);
}
};
@@ -649,7 +648,7 @@ impl Options {
out_fmt
}
Err(e) => {
- diag.struct_err(&e).emit();
+ diag.struct_err(e).emit();
return Err(1);
}
},
@@ -790,7 +789,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
for &flag in deprecated_flags.iter() {
if matches.opt_present(flag) {
- diag.struct_warn(&format!("the `{}` flag is deprecated", flag))
+ diag.struct_warn(format!("the `{}` flag is deprecated", flag))
.note(
"see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
for more information",
@@ -803,7 +802,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
for &flag in removed_flags.iter() {
if matches.opt_present(flag) {
- let mut err = diag.struct_warn(&format!("the `{}` flag no longer functions", flag));
+ let mut err = diag.struct_warn(format!("the `{}` flag no longer functions", flag));
err.note(
"see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
for more information",
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index b392ba058..e10a62977 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -46,6 +46,7 @@ pub(crate) struct DocContext<'tcx> {
// for expanding type aliases at the HIR level:
/// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const
pub(crate) substs: DefIdMap<clean::SubstParam>,
+ pub(crate) current_type_aliases: DefIdMap<usize>,
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
pub(crate) impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -82,13 +83,25 @@ impl<'tcx> DocContext<'tcx> {
/// Call the closure with the given parameters set as
/// the substitutions for a type alias' RHS.
- pub(crate) fn enter_alias<F, R>(&mut self, substs: DefIdMap<clean::SubstParam>, f: F) -> R
+ pub(crate) fn enter_alias<F, R>(
+ &mut self,
+ substs: DefIdMap<clean::SubstParam>,
+ def_id: DefId,
+ f: F,
+ ) -> R
where
F: FnOnce(&mut Self) -> R,
{
let old_substs = mem::replace(&mut self.substs, substs);
+ *self.current_type_aliases.entry(def_id).or_insert(0) += 1;
let r = f(self);
self.substs = old_substs;
+ if let Some(count) = self.current_type_aliases.get_mut(&def_id) {
+ *count -= 1;
+ if *count == 0 {
+ self.current_type_aliases.remove(&def_id);
+ }
+ }
r
}
@@ -258,8 +271,6 @@ pub(crate) fn create_config(
override_queries: Some(|_sess, providers, _external_providers| {
// Most lints will require typechecking, so just don't run them.
providers.lint_mod = |_, _| {};
- // Prevent `rustc_hir_analysis::check_crate` from calling `typeck` on all bodies.
- providers.typeck_item_bodies = |_, _| {};
// hack so that `used_trait_imports` won't try to call typeck
providers.used_trait_imports = |_, _| {
static EMPTY_SET: LazyLock<UnordSet<LocalDefId>> = LazyLock::new(UnordSet::default);
@@ -329,6 +340,7 @@ pub(crate) fn run_global_ctxt(
external_traits: Default::default(),
active_extern_traits: Default::default(),
substs: Default::default(),
+ current_type_aliases: Default::default(),
impl_trait_bounds: Default::default(),
generated_synthetics: Default::default(),
auto_traits,
@@ -355,7 +367,7 @@ pub(crate) fn run_global_ctxt(
let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
- if krate.module.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
+ if krate.module.doc_value().is_empty() {
let help = format!(
"The following guide may be of use:\n\
{}/rustdoc/how-to-write-documentation.html",
@@ -371,7 +383,7 @@ pub(crate) fn run_global_ctxt(
fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
let mut msg =
- diag.struct_span_warn(sp, &format!("the `#![doc({})]` attribute is deprecated", name));
+ diag.struct_span_warn(sp, format!("the `#![doc({})]` attribute is deprecated", name));
msg.note(
"see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
for more information",
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index daf10e5b8..f6631b66f 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -679,6 +679,10 @@ pub(crate) fn make_test(
// parse the source, but only has false positives, not false
// negatives.
if s.contains(crate_name) {
+ // rustdoc implicitly inserts an `extern crate` item for the own crate
+ // which may be unused, so we need to allow the lint.
+ prog.push_str(&format!("#[allow(unused_extern_crates)]\n"));
+
prog.push_str(&format!("extern crate r#{crate_name};\n"));
line_offset += 1;
}
@@ -1059,15 +1063,10 @@ impl Tester for Collector {
Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)),
},
ignore_message: None,
- #[cfg(not(bootstrap))]
source_file: "",
- #[cfg(not(bootstrap))]
start_line: 0,
- #[cfg(not(bootstrap))]
start_col: 0,
- #[cfg(not(bootstrap))]
end_line: 0,
- #[cfg(not(bootstrap))]
end_col: 0,
// compiler failures are test failures
should_panic: test::ShouldPanic::No,
@@ -1238,7 +1237,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
// The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
// anything else, this will combine them for us.
let attrs = Attributes::from_ast(ast_attrs);
- if let Some(doc) = attrs.collapsed_doc_value() {
+ if let Some(doc) = attrs.opt_doc_value() {
// Use the outermost invocation, so that doctest names come from where the docs were written.
let span = ast_attrs
.iter()
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index 360d2259e..a30fe28f9 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -38,6 +38,7 @@ fn make_test_crate_name() {
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
+#[allow(unused_extern_crates)]
extern crate r#asdf;
fn main() {
use asdf::qwop;
@@ -128,6 +129,7 @@ fn make_test_opts_attrs() {
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
let expected = "#![feature(sick_rad)]
+#[allow(unused_extern_crates)]
extern crate r#asdf;
fn main() {
use asdf::qwop;
@@ -141,6 +143,7 @@ assert_eq!(2+2, 4);
opts.attrs.push("feature(hella_dope)".to_string());
let expected = "#![feature(sick_rad)]
#![feature(hella_dope)]
+#[allow(unused_extern_crates)]
extern crate r#asdf;
fn main() {
use asdf::qwop;
@@ -236,6 +239,7 @@ assert_eq!(asdf::foo, 4);";
let expected = "#![allow(unused)]
extern crate hella_qwop;
+#[allow(unused_extern_crates)]
extern crate r#asdf;
fn main() {
assert_eq!(asdf::foo, 4);
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index 37fd909c9..88049c4ca 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -83,14 +83,14 @@ pub(crate) fn load_string<P: AsRef<Path>>(
let contents = match fs::read(file_path) {
Ok(bytes) => bytes,
Err(e) => {
- diag.struct_err(&format!("error reading `{}`: {}", file_path.display(), e)).emit();
+ diag.struct_err(format!("error reading `{}`: {}", file_path.display(), e)).emit();
return Err(LoadStringError::ReadFail);
}
};
match str::from_utf8(&contents) {
Ok(s) => Ok(s.to_string()),
Err(_) => {
- diag.struct_err(&format!("error reading `{}`: not UTF-8", file_path.display())).emit();
+ diag.struct_err(format!("error reading `{}`: not UTF-8", file_path.display())).emit();
Err(LoadStringError::BadUtf8)
}
}
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index c03291820..8aaad8bce 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -147,7 +147,7 @@ impl Cache {
// Cache where all our extern crates are located
// FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
- for &crate_num in cx.tcx.crates(()) {
+ for &crate_num in tcx.crates(()) {
let e = ExternalCrate { crate_num };
let name = e.name(tcx);
@@ -195,7 +195,13 @@ impl Cache {
impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
if item.item_id.is_local() {
- debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.item_id);
+ let is_stripped = matches!(*item.kind, clean::ItemKind::StrippedItem(..));
+ debug!(
+ "folding {} (stripped: {is_stripped:?}) \"{:?}\", id {:?}",
+ item.type_(),
+ item.name,
+ item.item_id
+ );
}
// If this is a stripped module,
@@ -300,14 +306,13 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
ParentStackItem::Impl { for_, .. } => for_.def_id(&self.cache),
ParentStackItem::Type(item_id) => item_id.as_def_id(),
};
- let path = match did.and_then(|did| self.cache.paths.get(&did)) {
+ let path = did
+ .and_then(|did| self.cache.paths.get(&did))
// The current stack not necessarily has correlation
// for where the type was defined. On the other
// hand, `paths` always has the right
// information if present.
- Some((fqp, _)) => Some(&fqp[..fqp.len() - 1]),
- None => None,
- };
+ .map(|(fqp, _)| &fqp[..fqp.len() - 1]);
((did, path), true)
}
}
@@ -322,9 +327,8 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
// which should not be indexed. The crate-item itself is
// inserted later on when serializing the search-index.
if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root()) {
- let desc = item.doc_value().map_or_else(String::new, |x| {
- short_markdown_summary(x.as_str(), &item.link_names(self.cache))
- });
+ let desc =
+ short_markdown_summary(&item.doc_value(), &item.link_names(self.cache));
let ty = item.type_();
if ty != ItemType::StructField
|| u16::from_str_radix(s.as_str(), 10).is_err()
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 1b445b898..d963d6092 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -167,7 +167,7 @@ pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
display_fn(move |f| {
let mut bounds_dup = FxHashSet::default();
- for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(b.clone())).enumerate() {
+ for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(*b)).enumerate() {
if i > 0 {
f.write_str(" + ")?;
}
@@ -439,6 +439,7 @@ impl clean::GenericBound {
let modifier_str = match modifier {
hir::TraitBoundModifier::None => "",
hir::TraitBoundModifier::Maybe => "?",
+ hir::TraitBoundModifier::Negative => "!",
// ~const is experimental; do not display those bounds in rustdoc
hir::TraitBoundModifier::MaybeConst => "",
};
@@ -1115,14 +1116,17 @@ fn fmt_type<'cx>(
ref trait_,
should_show_cast,
}) => {
+ // FIXME(inherent_associated_types): Once we support non-ADT self-types (#106719),
+ // we need to surround them with angle brackets in some cases (e.g. `<dyn …>::P`).
+
if f.alternate() {
- if should_show_cast {
+ if let Some(trait_) = trait_ && should_show_cast {
write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?
} else {
write!(f, "{:#}::", self_type.print(cx))?
}
} else {
- if should_show_cast {
+ if let Some(trait_) = trait_ && should_show_cast {
write!(f, "&lt;{} as {}&gt;::", self_type.print(cx), trait_.print(cx))?
} else {
write!(f, "{}::", self_type.print(cx))?
@@ -1138,15 +1142,36 @@ fn fmt_type<'cx>(
// the ugliness comes from inlining across crates where
// everything comes in as a fully resolved QPath (hard to
// look at).
- if !f.alternate() && let Ok((url, _, path)) = href(trait_.def_id(), cx) {
- write!(
- f,
- "<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
- title=\"type {path}::{name}\">{name}</a>",
- shortty = ItemType::AssocType,
- name = assoc.name,
- path = join_with_double_colon(&path),
- )
+ if !f.alternate() {
+ // FIXME(inherent_associated_types): We always link to the very first associated
+ // type (in respect to source order) that bears the given name (`assoc.name`) and that is
+ // affiliated with the computed `DefId`. This is obviously incorrect when we have
+ // multiple impl blocks. Ideally, we would thread the `DefId` of the assoc ty itself
+ // through here and map it to the corresponding HTML ID that was generated by
+ // `render::Context::derive_id` when the impl blocks were rendered.
+ // There is no such mapping unfortunately.
+ // As a hack, we could badly imitate `derive_id` here by keeping *count* when looking
+ // for the assoc ty `DefId` in `tcx.associated_items(self_ty_did).in_definition_order()`
+ // considering privacy, `doc(hidden)`, etc.
+ // I don't feel like that right now :cold_sweat:.
+
+ let parent_href = match trait_ {
+ Some(trait_) => href(trait_.def_id(), cx).ok(),
+ None => self_type.def_id(cx.cache()).and_then(|did| href(did, cx).ok()),
+ };
+
+ if let Some((url, _, path)) = parent_href {
+ write!(
+ f,
+ "<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
+ title=\"type {path}::{name}\">{name}</a>",
+ shortty = ItemType::AssocType,
+ name = assoc.name,
+ path = join_with_double_colon(&path),
+ )
+ } else {
+ write!(f, "{}", assoc.name)
+ }
} else {
write!(f, "{}", assoc.name)
}?;
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index b61dd5714..c94968b48 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -514,7 +514,7 @@ struct Classifier<'src> {
impl<'src> Classifier<'src> {
/// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
- /// file span which will be used later on by the `span_correspondance_map`.
+ /// file span which will be used later on by the `span_correspondence_map`.
fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> {
let tokens = PeekIter::new(TokenIter { src, cursor: Cursor::new(src) });
let decorations = decoration_info.map(Decorations::new);
@@ -649,7 +649,7 @@ impl<'src> Classifier<'src> {
///
/// `before` is the position of the given token in the `source` string and is used as "lo" byte
/// in case we want to try to generate a link for this token using the
- /// `span_correspondance_map`.
+ /// `span_correspondence_map`.
fn advance(
&mut self,
token: TokenKind,
@@ -811,7 +811,9 @@ impl<'src> Classifier<'src> {
| LiteralKind::Str { .. }
| LiteralKind::ByteStr { .. }
| LiteralKind::RawStr { .. }
- | LiteralKind::RawByteStr { .. } => Class::String,
+ | LiteralKind::RawByteStr { .. }
+ | LiteralKind::CStr { .. }
+ | LiteralKind::RawCStr { .. } => Class::String,
// Number literals.
LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number,
},
@@ -895,7 +897,7 @@ fn exit_span(out: &mut impl Write, closing_tag: &str) {
/// flexible.
///
/// Note that if `context` is not `None` and that the given `klass` contains a `Span`, the function
-/// will then try to find this `span` in the `span_correspondance_map`. If found, it'll then
+/// will then try to find this `span` in the `span_correspondence_map`. If found, it'll then
/// generate a link for this element (which corresponds to where its definition is located).
fn string<T: Display>(
out: &mut impl Write,
@@ -916,7 +918,7 @@ fn string<T: Display>(
/// * If `klass` is `Some` but `klass.get_span()` is `None`, it writes the text wrapped in a
/// `<span>` with the provided `klass`.
/// * If `klass` is `Some` and has a [`rustc_span::Span`], it then tries to generate a link (`<a>`
-/// element) by retrieving the link information from the `span_correspondance_map` that was filled
+/// element) by retrieving the link information from the `span_correspondence_map` that was filled
/// in `span_map.rs::collect_spans_and_sources`. If it cannot retrieve the information, then it's
/// the same as the second point (`klass` is `Some` but doesn't have a [`rustc_span::Span`]).
fn string_without_closing_tag<T: Display>(
@@ -963,7 +965,7 @@ fn string_without_closing_tag<T: Display>(
if let Some(href_context) = href_context {
if let Some(href) =
- href_context.context.shared.span_correspondance_map.get(&def_span).and_then(|href| {
+ href_context.context.shared.span_correspondence_map.get(&def_span).and_then(|href| {
let context = href_context.context;
// FIXME: later on, it'd be nice to provide two links (if possible) for all items:
// one to the documentation page and one to the source definition.
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 00aadb8e8..9bb20022c 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -551,7 +551,15 @@ impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
}
fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
- matches!(t, Tag::Paragraph | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote)
+ matches!(
+ t,
+ Tag::Paragraph
+ | Tag::Emphasis
+ | Tag::Strong
+ | Tag::Strikethrough
+ | Tag::Link(..)
+ | Tag::BlockQuote
+ )
}
fn is_forbidden_tag(t: &Tag<'_>) -> bool {
@@ -773,7 +781,7 @@ impl<'tcx> ExtraInfo<'tcx> {
ExtraInfo { def_id, sp, tcx }
}
- fn error_invalid_codeblock_attr(&self, msg: &str, help: &str) {
+ fn error_invalid_codeblock_attr(&self, msg: String, help: &str) {
if let Some(def_id) = self.def_id.as_local() {
self.tcx.struct_span_lint_hir(
crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
@@ -948,7 +956,7 @@ impl LangString {
} {
if let Some(extra) = extra {
extra.error_invalid_codeblock_attr(
- &format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
+ format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
help,
);
}
@@ -1229,7 +1237,27 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
pub(crate) struct MarkdownLink {
pub kind: LinkType,
pub link: String,
- pub range: Range<usize>,
+ pub range: MarkdownLinkRange,
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum MarkdownLinkRange {
+ /// Normally, markdown link warnings point only at the destination.
+ Destination(Range<usize>),
+ /// In some cases, it's not possible to point at the destination.
+ /// Usually, this happens because backslashes `\\` are used.
+ /// When that happens, point at the whole link, and don't provide structured suggestions.
+ WholeLink(Range<usize>),
+}
+
+impl MarkdownLinkRange {
+ /// Extracts the inner range.
+ pub fn inner_range(&self) -> &Range<usize> {
+ match self {
+ MarkdownLinkRange::Destination(range) => range,
+ MarkdownLinkRange::WholeLink(range) => range,
+ }
+ }
}
pub(crate) fn markdown_links<R>(
@@ -1249,9 +1277,9 @@ pub(crate) fn markdown_links<R>(
if md_start <= s_start && s_end <= md_end {
let start = s_start.offset_from(md_start) as usize;
let end = s_end.offset_from(md_start) as usize;
- start..end
+ MarkdownLinkRange::Destination(start..end)
} else {
- fallback
+ MarkdownLinkRange::WholeLink(fallback)
}
};
@@ -1259,6 +1287,7 @@ pub(crate) fn markdown_links<R>(
// For diagnostics, we want to underline the link's definition but `span` will point at
// where the link is used. This is a problem for reference-style links, where the definition
// is separate from the usage.
+
match link {
// `Borrowed` variant means the string (the link's destination) may come directly from
// the markdown text and we can locate the original link destination.
@@ -1267,10 +1296,82 @@ pub(crate) fn markdown_links<R>(
CowStr::Borrowed(s) => locate(s, span),
// For anything else, we can only use the provided range.
- CowStr::Boxed(_) | CowStr::Inlined(_) => span,
+ CowStr::Boxed(_) | CowStr::Inlined(_) => MarkdownLinkRange::WholeLink(span),
}
};
+ let span_for_offset_backward = |span: Range<usize>, open: u8, close: u8| {
+ let mut open_brace = !0;
+ let mut close_brace = !0;
+ for (i, b) in md.as_bytes()[span.clone()].iter().copied().enumerate().rev() {
+ let i = i + span.start;
+ if b == close {
+ close_brace = i;
+ break;
+ }
+ }
+ if close_brace < span.start || close_brace >= span.end {
+ return MarkdownLinkRange::WholeLink(span);
+ }
+ let mut nesting = 1;
+ for (i, b) in md.as_bytes()[span.start..close_brace].iter().copied().enumerate().rev() {
+ let i = i + span.start;
+ if b == close {
+ nesting += 1;
+ }
+ if b == open {
+ nesting -= 1;
+ }
+ if nesting == 0 {
+ open_brace = i;
+ break;
+ }
+ }
+ assert!(open_brace != close_brace);
+ if open_brace < span.start || open_brace >= span.end {
+ return MarkdownLinkRange::WholeLink(span);
+ }
+ // do not actually include braces in the span
+ let range = (open_brace + 1)..close_brace;
+ MarkdownLinkRange::Destination(range.clone())
+ };
+
+ let span_for_offset_forward = |span: Range<usize>, open: u8, close: u8| {
+ let mut open_brace = !0;
+ let mut close_brace = !0;
+ for (i, b) in md.as_bytes()[span.clone()].iter().copied().enumerate() {
+ let i = i + span.start;
+ if b == open {
+ open_brace = i;
+ break;
+ }
+ }
+ if open_brace < span.start || open_brace >= span.end {
+ return MarkdownLinkRange::WholeLink(span);
+ }
+ let mut nesting = 0;
+ for (i, b) in md.as_bytes()[open_brace..span.end].iter().copied().enumerate() {
+ let i = i + open_brace;
+ if b == close {
+ nesting -= 1;
+ }
+ if b == open {
+ nesting += 1;
+ }
+ if nesting == 0 {
+ close_brace = i;
+ break;
+ }
+ }
+ assert!(open_brace != close_brace);
+ if open_brace < span.start || open_brace >= span.end {
+ return MarkdownLinkRange::WholeLink(span);
+ }
+ // do not actually include braces in the span
+ let range = (open_brace + 1)..close_brace;
+ MarkdownLinkRange::Destination(range.clone())
+ };
+
Parser::new_with_broken_link_callback(
md,
main_body_opts(),
@@ -1279,11 +1380,20 @@ pub(crate) fn markdown_links<R>(
.into_offset_iter()
.filter_map(|(event, span)| match event {
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
- preprocess_link(MarkdownLink {
- kind: link_type,
- range: span_for_link(&dest, span),
- link: dest.into_string(),
- })
+ let range = match link_type {
+ // Link is pulled from the link itself.
+ LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
+ span_for_offset_backward(span, b'[', b']')
+ }
+ LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
+ LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
+ // Link is pulled from elsewhere in the document.
+ LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
+ span_for_link(&dest, span)
+ }
+ LinkType::Autolink | LinkType::Email => unreachable!(),
+ };
+ preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
}
_ => None,
})
@@ -1392,7 +1502,7 @@ static DEFAULT_ID_MAP: Lazy<FxHashMap<Cow<'static, str>, usize>> = Lazy::new(||
fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
let mut map = FxHashMap::default();
- // This is the list of IDs used in Javascript.
+ // This is the list of IDs used in JavaScript.
map.insert("help".into(), 1);
map.insert("settings".into(), 1);
map.insert("not-displayed".into(), 1);
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index ac5054ce1..56af257fd 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -122,9 +122,9 @@ pub(crate) struct SharedContext<'tcx> {
/// the crate.
redirections: Option<RefCell<FxHashMap<String, String>>>,
- /// Correspondance map used to link types used in the source code pages to allow to click on
+ /// Correspondence map used to link types used in the source code pages to allow to click on
/// links to jump to the type's definition.
- pub(crate) span_correspondance_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
+ pub(crate) span_correspondence_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
/// The [`Cache`] used during rendering.
pub(crate) cache: Cache,
@@ -184,11 +184,8 @@ impl<'tcx> Context<'tcx> {
};
title.push_str(" - Rust");
let tyname = it.type_();
- let desc = it
- .doc_value()
- .as_ref()
- .map(|doc| plain_text_summary(doc, &it.link_names(&self.cache())));
- let desc = if let Some(desc) = desc {
+ let desc = plain_text_summary(&it.doc_value(), &it.link_names(&self.cache()));
+ let desc = if !desc.is_empty() {
desc
} else if it.is_crate() {
format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate)
@@ -531,7 +528,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
errors: receiver,
redirections: if generate_redirect_map { Some(Default::default()) } else { None },
show_type_layout,
- span_correspondance_map: matches,
+ span_correspondence_map: matches,
cache,
call_locations,
};
@@ -647,7 +644,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
</div>\
<noscript>\
<section>\
- You need to enable Javascript be able to update your settings.\
+ You need to enable JavaScript be able to update your settings.\
</section>\
</noscript>\
<link rel=\"stylesheet\" \
@@ -709,7 +706,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
</div>\
<noscript>\
<section>\
- <p>You need to enable Javascript to use keyboard commands or search.</p>\
+ <p>You need to enable JavaScript to use keyboard commands or search.</p>\
<p>For more information, browse the <a href=\"https://doc.rust-lang.org/rustdoc/\">rustdoc handbook</a>.</p>\
</section>\
</noscript>",
@@ -746,7 +743,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
// Flush pending errors.
Rc::get_mut(&mut self.shared).unwrap().fs.close();
let nb_errors =
- self.shared.errors.iter().map(|err| self.tcx().sess.struct_err(&err).emit()).count();
+ self.shared.errors.iter().map(|err| self.tcx().sess.struct_err(err).emit()).count();
if nb_errors > 0 {
Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
} else {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 463184aca..9e3b5d10a 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -32,6 +32,7 @@ mod context;
mod print_item;
mod sidebar;
mod span_map;
+mod type_layout;
mod write_shared;
pub(crate) use self::context::*;
@@ -47,7 +48,6 @@ use std::str;
use std::string::ToString;
use askama::Template;
-use rustc_ast_pretty::pprust;
use rustc_attr::{ConstStability, Deprecation, StabilityLevel};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -468,7 +468,8 @@ fn document_short<'a, 'cx: 'a>(
if !show_def_docs {
return Ok(());
}
- if let Some(s) = item.doc_value() {
+ let s = item.doc_value();
+ if !s.is_empty() {
let (mut summary_html, has_more_content) =
MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
@@ -511,7 +512,7 @@ fn document_full_inner<'a, 'cx: 'a>(
heading_offset: HeadingOffset,
) -> impl fmt::Display + 'a + Captures<'cx> {
display_fn(move |f| {
- if let Some(s) = item.collapsed_doc_value() {
+ if let Some(s) = item.opt_doc_value() {
debug!("Doc block: =====\n{}\n=====", s);
if is_collapsible {
write!(
@@ -848,10 +849,10 @@ fn assoc_method(
let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
header_len += 4;
let indent_str = " ";
- write!(w, "{}", render_attributes_in_pre(meth, indent_str));
+ write!(w, "{}", render_attributes_in_pre(meth, indent_str, tcx));
(4, indent_str, Ending::NoNewline)
} else {
- render_attributes_in_code(w, meth);
+ render_attributes_in_code(w, meth, tcx);
(0, "", Ending::Newline)
};
w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len());
@@ -1020,36 +1021,15 @@ fn render_assoc_item(
}
}
-const ALLOWED_ATTRIBUTES: &[Symbol] =
- &[sym::export_name, sym::link_section, sym::no_mangle, sym::repr, sym::non_exhaustive];
-
-fn attributes(it: &clean::Item) -> Vec<String> {
- it.attrs
- .other_attrs
- .iter()
- .filter_map(|attr| {
- if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
- Some(
- pprust::attribute_to_string(attr)
- .replace("\\\n", "")
- .replace('\n', "")
- .replace(" ", " "),
- )
- } else {
- None
- }
- })
- .collect()
-}
-
// When an attribute is rendered inside a `<pre>` tag, it is formatted using
// a whitespace prefix and newline.
-fn render_attributes_in_pre<'a>(
+fn render_attributes_in_pre<'a, 'b: 'a>(
it: &'a clean::Item,
prefix: &'a str,
-) -> impl fmt::Display + Captures<'a> {
+ tcx: TyCtxt<'b>,
+) -> impl fmt::Display + Captures<'a> + Captures<'b> {
crate::html::format::display_fn(move |f| {
- for a in attributes(it) {
+ for a in it.attributes(tcx, false) {
writeln!(f, "{}{}", prefix, a)?;
}
Ok(())
@@ -1058,8 +1038,8 @@ fn render_attributes_in_pre<'a>(
// When an attribute is rendered inside a <code> tag, it is formatted using
// a div to produce a newline after it.
-fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item) {
- for a in attributes(it) {
+fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item, tcx: TyCtxt<'_>) {
+ for a in it.attributes(tcx, false) {
write!(w, "<div class=\"code-attribute\">{}</div>", a);
}
}
@@ -1154,10 +1134,10 @@ fn render_assoc_items_inner(
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() {
let mut tmp_buf = Buffer::html();
- let (render_mode, id) = match what {
+ let (render_mode, id, class_html) = match what {
AssocItemRender::All => {
write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations");
- (RenderMode::Normal, "implementations-list".to_owned())
+ (RenderMode::Normal, "implementations-list".to_owned(), "")
}
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
let id =
@@ -1174,7 +1154,11 @@ fn render_assoc_items_inner(
),
&id,
);
- (RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id))
+ (
+ RenderMode::ForDeref { mut_: deref_mut_ },
+ cx.derive_id(id),
+ r#" class="impl-items""#,
+ )
}
};
let mut impls_buf = Buffer::html();
@@ -1198,7 +1182,7 @@ fn render_assoc_items_inner(
}
if !impls_buf.is_empty() {
write!(w, "{}", tmp_buf.into_inner()).unwrap();
- write!(w, "<div id=\"{}\">", id).unwrap();
+ write!(w, "<div id=\"{id}\"{class_html}>").unwrap();
write!(w, "{}", impls_buf.into_inner()).unwrap();
w.write_str("</div>").unwrap();
}
@@ -1493,7 +1477,7 @@ fn render_impl(
if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
// We need the stability of the item from the trait
// because impls can't have a stability.
- if item.doc_value().is_some() {
+ if !item.doc_value().is_empty() {
document_item_info(cx, it, Some(parent))
.render_into(&mut info_buffer)
.unwrap();
@@ -1764,11 +1748,11 @@ fn render_impl(
write!(w, "</summary>")
}
- if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
+ if let Some(ref dox) = i.impl_item.opt_doc_value() {
if trait_.is_none() && i.inner_impl().items.is_empty() {
w.write_str(
"<div class=\"item-info\">\
- <div class=\"stab empty-impl\">This impl block contains no items.</div>
+ <div class=\"stab empty-impl\">This impl block contains no items.</div>\
</div>",
);
}
@@ -1787,12 +1771,14 @@ fn render_impl(
.into_string()
);
}
+ if !default_impl_items.is_empty() || !impl_items.is_empty() {
+ w.write_str("<div class=\"impl-items\">");
+ close_tags.insert_str(0, "</div>");
+ }
}
if !default_impl_items.is_empty() || !impl_items.is_empty() {
- w.write_str("<div class=\"impl-items\">");
w.push_buffer(default_impl_items);
w.push_buffer(impl_items);
- close_tags.insert_str(0, "</div>");
}
w.write_str(&close_tags);
}
@@ -1947,8 +1933,6 @@ pub(crate) fn small_url_encode(s: String) -> String {
// While the same is not true for hashes, rustdoc only needs to be
// consistent with itself when encoding them.
st += "+";
- } else if b == b'%' {
- st += "%%";
} else {
write!(st, "%{:02X}", b).unwrap();
}
@@ -2217,7 +2201,9 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
}
clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => {
work.push_back(self_type);
- process_path(trait_.def_id());
+ if let Some(trait_) = trait_ {
+ process_path(trait_.def_id());
+ }
}
_ => {}
}
@@ -2271,8 +2257,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
Ok(contents) => contents,
Err(err) => {
let span = item.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner());
- tcx.sess
- .span_err(span, &format!("failed to read file {}: {}", path.display(), err));
+ tcx.sess.span_err(span, format!("failed to read file {}: {}", path.display(), err));
return false;
}
};
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 9a968e48b..62027a3fa 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -6,16 +6,16 @@ use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::DefId;
use rustc_middle::middle::stability;
-use rustc_middle::span_bug;
-use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::{self, Adt, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_target::abi::{LayoutS, Primitive, TagEncoding, Variants};
+use std::borrow::Borrow;
+use std::cell::{RefCell, RefMut};
use std::cmp::Ordering;
use std::fmt;
use std::rc::Rc;
+use super::type_layout::document_type_layout;
use super::{
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
@@ -218,6 +218,53 @@ fn toggle_close(mut w: impl fmt::Write) {
w.write_str("</details>").unwrap();
}
+trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display {
+ fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>);
+}
+
+fn item_template_document<'a: 'b, 'b, 'cx: 'a>(
+ templ: &'b impl ItemTemplate<'a, 'cx>,
+) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+ display_fn(move |f| {
+ let (item, mut cx) = templ.item_and_mut_cx();
+ let v = document(*cx, item, None, HeadingOffset::H2);
+ write!(f, "{v}")
+ })
+}
+
+fn item_template_document_type_layout<'a: 'b, 'b, 'cx: 'a>(
+ templ: &'b impl ItemTemplate<'a, 'cx>,
+) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+ display_fn(move |f| {
+ let (item, cx) = templ.item_and_mut_cx();
+ let def_id = item.item_id.expect_def_id();
+ let v = document_type_layout(*cx, def_id);
+ write!(f, "{v}")
+ })
+}
+
+fn item_template_render_attributes_in_pre<'a: 'b, 'b, 'cx: 'a>(
+ templ: &'b impl ItemTemplate<'a, 'cx>,
+) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+ display_fn(move |f| {
+ let (item, cx) = templ.item_and_mut_cx();
+ let tcx = cx.tcx();
+ let v = render_attributes_in_pre(item, "", tcx);
+ write!(f, "{v}")
+ })
+}
+
+fn item_template_render_assoc_items<'a: 'b, 'b, 'cx: 'a>(
+ templ: &'b impl ItemTemplate<'a, 'cx>,
+) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+ display_fn(move |f| {
+ let (item, mut cx) = templ.item_and_mut_cx();
+ let def_id = item.item_id.expect_def_id();
+ let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All);
+ write!(f, "{v}")
+ })
+}
+
fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
write!(w, "{}", document(cx, item, None, HeadingOffset::H2));
@@ -358,18 +405,18 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
clean::ImportItem(ref import) => {
let stab_tags = if let Some(import_def_id) = import.source.did {
- let ast_attrs = cx.tcx().get_attrs_unchecked(import_def_id);
+ let ast_attrs = tcx.get_attrs_unchecked(import_def_id);
let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs));
// Just need an item with the correct def_id and attrs
let import_item = clean::Item {
item_id: import_def_id.into(),
attrs: import_attrs,
- cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg),
+ cfg: ast_attrs.cfg(tcx, &cx.cache().hidden_cfg),
..myitem.clone()
};
- let stab_tags = Some(extra_info_tags(&import_item, item, cx.tcx()).to_string());
+ let stab_tags = Some(extra_info_tags(&import_item, item, tcx).to_string());
stab_tags
} else {
None
@@ -407,8 +454,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
let unsafety_flag = match *myitem.kind {
clean::FunctionItem(_) | clean::ForeignFunctionItem(_)
- if myitem.fn_header(cx.tcx()).unwrap().unsafety
- == hir::Unsafety::Unsafe =>
+ if myitem.fn_header(tcx).unwrap().unsafety == hir::Unsafety::Unsafe =>
{
"<sup title=\"unsafe function\">⚠</sup>"
}
@@ -422,9 +468,9 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
_ => "",
};
- let doc_value = myitem.doc_value().unwrap_or_default();
w.write_str(ITEM_TABLE_ROW_OPEN);
- let docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string();
+ let docs =
+ MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string();
let (docs_before, docs_after) = if docs.is_empty() {
("", "")
} else {
@@ -441,7 +487,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
{docs_before}{docs}{docs_after}",
name = myitem.name.unwrap(),
visibility_emoji = visibility_emoji,
- stab_tags = extra_info_tags(myitem, item, cx.tcx()),
+ stab_tags = extra_info_tags(myitem, item, tcx),
class = myitem.type_(),
unsafety_flag = unsafety_flag,
href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
@@ -550,7 +596,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
w,
"{attrs}{vis}{constness}{asyncness}{unsafety}{abi}fn \
{name}{generics}{decl}{notable_traits}{where_clause}",
- attrs = render_attributes_in_pre(it, ""),
+ attrs = render_attributes_in_pre(it, "", tcx),
vis = visibility,
constness = constness,
asyncness = asyncness,
@@ -591,7 +637,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
it.name.unwrap(),
t.generics.print(cx),
bounds,
- attrs = render_attributes_in_pre(it, ""),
+ attrs = render_attributes_in_pre(it, "", tcx),
);
if !t.generics.where_predicates.is_empty() {
@@ -888,7 +934,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
for implementor in foreign {
- let provided_methods = implementor.inner_impl().provided_trait_methods(cx.tcx());
+ let provided_methods = implementor.inner_impl().provided_trait_methods(tcx);
let assoc_link =
AssocItemLink::GotoSource(implementor.impl_item.item_id, &provided_methods);
render_impl(
@@ -921,7 +967,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
}
w.write_str("</div>");
- if t.is_auto(cx.tcx()) {
+ if t.is_auto(tcx) {
write_small_section_header(
w,
"synthetic-implementors",
@@ -950,7 +996,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
"<div id=\"implementors-list\"></div>",
);
- if t.is_auto(cx.tcx()) {
+ if t.is_auto(tcx) {
write_small_section_header(
w,
"synthetic-implementors",
@@ -1065,7 +1111,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &
t.generics.print(cx),
print_where_clause(&t.generics, cx, 0, Ending::Newline),
bounds(&t.bounds, true, cx),
- attrs = render_attributes_in_pre(it, ""),
+ attrs = render_attributes_in_pre(it, "", cx.tcx()),
);
});
@@ -1087,7 +1133,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl
t.generics.print(cx),
where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
bounds = bounds(&t.bounds, false, cx),
- attrs = render_attributes_in_pre(it, ""),
+ attrs = render_attributes_in_pre(it, "", cx.tcx()),
);
});
@@ -1111,7 +1157,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
t.generics.print(cx),
where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
type_ = t.type_.print(cx),
- attrs = render_attributes_in_pre(it, ""),
+ attrs = render_attributes_in_pre(it, "", cx.tcx()),
);
});
}
@@ -1133,32 +1179,18 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
#[derive(Template)]
#[template(path = "item_union.html")]
struct ItemUnion<'a, 'cx> {
- cx: std::cell::RefCell<&'a mut Context<'cx>>,
+ cx: RefCell<&'a mut Context<'cx>>,
it: &'a clean::Item,
s: &'a clean::Union,
}
- impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
- fn render_assoc_items<'b>(
- &'b self,
- ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
- display_fn(move |f| {
- let def_id = self.it.item_id.expect_def_id();
- let mut cx = self.cx.borrow_mut();
- let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All);
- write!(f, "{v}")
- })
- }
- fn document_type_layout<'b>(
- &'b self,
- ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
- display_fn(move |f| {
- let def_id = self.it.item_id.expect_def_id();
- let cx = self.cx.borrow_mut();
- let v = document_type_layout(*cx, def_id);
- write!(f, "{v}")
- })
+ impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for ItemUnion<'a, 'cx> {
+ fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) {
+ (self.it, self.cx.borrow_mut())
}
+ }
+
+ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
display_fn(move |f| {
let cx = self.cx.borrow_mut();
@@ -1166,21 +1198,6 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
write!(f, "{v}")
})
}
- fn render_attributes_in_pre<'b>(
- &'b self,
- ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
- display_fn(move |f| {
- let v = render_attributes_in_pre(self.it, "");
- write!(f, "{v}")
- })
- }
- fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
- display_fn(move |f| {
- let mut cx = self.cx.borrow_mut();
- let v = document(*cx, self.it, None, HeadingOffset::H2);
- write!(f, "{v}")
- })
- }
fn document_field<'b>(
&'b self,
field: &'a clean::Item,
@@ -1220,7 +1237,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
}
}
- ItemUnion { cx: std::cell::RefCell::new(cx), it, s }.render_into(w).unwrap();
+ ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap();
}
fn print_tuple_struct_fields<'a, 'cx: 'a>(
@@ -1246,13 +1263,13 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
let tcx = cx.tcx();
let count_variants = e.variants().count();
wrap_item(w, |mut w| {
+ render_attributes_in_code(w, it, tcx);
write!(
w,
- "{attrs}{}enum {}{}",
+ "{}enum {}{}",
visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
it.name.unwrap(),
e.generics.print(cx),
- attrs = render_attributes_in_pre(it, ""),
);
if !print_where_clause_and_check(w, &e.generics, cx) {
// If there wasn't a `where` clause, we add a whitespace.
@@ -1339,7 +1356,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
clean::VariantKind::Tuple(fields) => {
// Documentation on tuple variant fields is rare, so to reduce noise we only emit
// the section if at least one field is documented.
- if fields.iter().any(|f| f.doc_value().is_some()) {
+ if fields.iter().any(|f| !f.doc_value().is_empty()) {
Some(("Tuple Fields", fields))
} else {
None
@@ -1447,7 +1464,7 @@ fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
wrap_item(w, |w| {
let tcx = cx.tcx();
- render_attributes_in_code(w, it);
+ render_attributes_in_code(w, it, tcx);
write!(
w,
@@ -1494,7 +1511,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
wrap_item(w, |w| {
- render_attributes_in_code(w, it);
+ render_attributes_in_code(w, it, cx.tcx());
render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
});
@@ -1542,11 +1559,12 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
write!(w, "{}", document_type_layout(cx, def_id));
}
-fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
- wrap_item(w, |w| {
- render_attributes_in_code(w, it);
+fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
+ let mut buffer = Buffer::new();
+ wrap_item(&mut buffer, |buffer| {
+ render_attributes_in_code(buffer, it, cx.tcx());
write!(
- w,
+ buffer,
"{vis}static {mutability}{name}: {typ}",
vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
mutability = s.mutability.print_with_space(),
@@ -1554,13 +1572,16 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
typ = s.type_.print(cx)
);
});
- write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+
+ write!(w, "{}", buffer.into_inner()).unwrap();
+
+ write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
}
fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
wrap_item(w, |w| {
w.write_str("extern {\n");
- render_attributes_in_code(w, it);
+ render_attributes_in_code(w, it, cx.tcx());
write!(
w,
" {}type {};\n}}",
@@ -1933,118 +1954,6 @@ fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a
})
}
-fn document_type_layout<'a, 'cx: 'a>(
- cx: &'a Context<'cx>,
- ty_def_id: DefId,
-) -> impl fmt::Display + 'a + Captures<'cx> {
- fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) {
- if layout.abi.is_unsized() {
- write!(w, "(unsized)").unwrap();
- } else {
- let size = layout.size.bytes() - tag_size;
- write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap();
- if layout.abi.is_uninhabited() {
- write!(
- w,
- " (<a href=\"https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\">uninhabited</a>)"
- ).unwrap();
- }
- }
- }
-
- display_fn(move |mut f| {
- if !cx.shared.show_type_layout {
- return Ok(());
- }
-
- writeln!(
- f,
- "<h2 id=\"layout\" class=\"small-section-header\"> \
- Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>"
- )?;
- writeln!(f, "<div class=\"docblock\">")?;
-
- let tcx = cx.tcx();
- let param_env = tcx.param_env(ty_def_id);
- let ty = tcx.type_of(ty_def_id).subst_identity();
- match tcx.layout_of(param_env.and(ty)) {
- Ok(ty_layout) => {
- writeln!(
- f,
- "<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \
- <strong>completely unstable</strong> and may even differ between compilations. \
- The only exception is types with certain <code>repr(...)</code> attributes. \
- Please see the Rust Reference’s \
- <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
- chapter for details on type layout guarantees.</p></div>"
- )?;
- f.write_str("<p><strong>Size:</strong> ")?;
- write_size_of_layout(&mut f, &ty_layout.layout.0, 0);
- writeln!(f, "</p>")?;
- if let Variants::Multiple { variants, tag, tag_encoding, .. } =
- &ty_layout.layout.variants()
- {
- if !variants.is_empty() {
- f.write_str(
- "<p><strong>Size for each variant:</strong></p>\
- <ul>",
- )?;
-
- let Adt(adt, _) = ty_layout.ty.kind() else {
- span_bug!(tcx.def_span(ty_def_id), "not an adt")
- };
-
- let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
- 0
- } else if let Primitive::Int(i, _) = tag.primitive() {
- i.size().bytes()
- } else {
- span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
- };
-
- for (index, layout) in variants.iter_enumerated() {
- let name = adt.variant(index).name;
- write!(&mut f, "<li><code>{name}</code>: ")?;
- write_size_of_layout(&mut f, layout, tag_size);
- writeln!(&mut f, "</li>")?;
- }
- f.write_str("</ul>")?;
- }
- }
- }
- // This kind of layout error can occur with valid code, e.g. if you try to
- // get the layout of a generic type such as `Vec<T>`.
- Err(LayoutError::Unknown(_)) => {
- writeln!(
- f,
- "<p><strong>Note:</strong> Unable to compute type layout, \
- possibly due to this type having generic parameters. \
- Layout can only be computed for concrete, fully-instantiated types.</p>"
- )?;
- }
- // This kind of error probably can't happen with valid code, but we don't
- // want to panic and prevent the docs from building, so we just let the
- // user know that we couldn't compute the layout.
- Err(LayoutError::SizeOverflow(_)) => {
- writeln!(
- f,
- "<p><strong>Note:</strong> Encountered an error during type layout; \
- the type was too big.</p>"
- )?;
- }
- Err(LayoutError::NormalizationFailure(_, _)) => {
- writeln!(
- f,
- "<p><strong>Note:</strong> Encountered an error during type layout; \
- the type failed to be normalized.</p>"
- )?;
- }
- }
-
- writeln!(f, "</div>")
- })
-}
-
fn pluralize(count: usize) -> &'static str {
if count > 1 { "s" } else { "" }
}
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index f5b4a3f5a..846299f02 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -28,9 +28,7 @@ pub(crate) fn build_index<'tcx>(
// has since been learned.
for &OrphanImplItem { parent, ref item, ref impl_generics } in &cache.orphan_impl_items {
if let Some((fqp, _)) = cache.paths.get(&parent) {
- let desc = item
- .doc_value()
- .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(cache)));
+ let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
cache.search_index.push(IndexItem {
ty: item.type_(),
name: item.name.unwrap(),
@@ -45,10 +43,8 @@ pub(crate) fn build_index<'tcx>(
}
}
- let crate_doc = krate
- .module
- .doc_value()
- .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(cache)));
+ let crate_doc =
+ short_markdown_summary(&krate.module.doc_value(), &krate.module.link_names(cache));
// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
// we need the alias element to have an array of items.
@@ -391,12 +387,14 @@ fn get_index_type_id(clean_type: &clean::Type) -> Option<RenderTypeId> {
clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => {
get_index_type_id(type_)
}
+ // The type parameters are converted to generics in `add_generics_and_bounds_as_types`
+ clean::Slice(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Slice)),
+ clean::Array(_, _) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Array)),
+ // Not supported yet
clean::BareFunction(_)
| clean::Generic(_)
| clean::ImplTrait(_)
| clean::Tuple(_)
- | clean::Slice(_)
- | clean::Array(_, _)
| clean::QPath { .. }
| clean::Infer => None,
}
@@ -563,6 +561,30 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>(
}
}
insert_ty(res, arg.clone(), ty_generics);
+ } else if let Type::Slice(ref ty) = *arg {
+ let mut ty_generics = Vec::new();
+ add_generics_and_bounds_as_types(
+ self_,
+ generics,
+ &ty,
+ tcx,
+ recurse + 1,
+ &mut ty_generics,
+ cache,
+ );
+ insert_ty(res, arg.clone(), ty_generics);
+ } else if let Type::Array(ref ty, _) = *arg {
+ let mut ty_generics = Vec::new();
+ add_generics_and_bounds_as_types(
+ self_,
+ generics,
+ &ty,
+ tcx,
+ recurse + 1,
+ &mut ty_generics,
+ cache,
+ );
+ insert_ty(res, arg.clone(), ty_generics);
} else {
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
// looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
new file mode 100644
index 000000000..c9b95b1e6
--- /dev/null
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -0,0 +1,86 @@
+use askama::Template;
+
+use rustc_data_structures::captures::Captures;
+use rustc_hir::def_id::DefId;
+use rustc_middle::span_bug;
+use rustc_middle::ty::layout::LayoutError;
+use rustc_middle::ty::Adt;
+use rustc_span::symbol::Symbol;
+use rustc_target::abi::{Primitive, TagEncoding, Variants};
+
+use std::fmt;
+
+use crate::html::format::display_fn;
+use crate::html::render::Context;
+
+#[derive(Template)]
+#[template(path = "type_layout.html")]
+struct TypeLayout<'cx> {
+ variants: Vec<(Symbol, TypeLayoutSize)>,
+ type_layout_size: Result<TypeLayoutSize, LayoutError<'cx>>,
+}
+
+#[derive(Template)]
+#[template(path = "type_layout_size.html")]
+struct TypeLayoutSize {
+ is_unsized: bool,
+ is_uninhabited: bool,
+ size: u64,
+}
+
+pub(crate) fn document_type_layout<'a, 'cx: 'a>(
+ cx: &'a Context<'cx>,
+ ty_def_id: DefId,
+) -> impl fmt::Display + 'a + Captures<'cx> {
+ display_fn(move |f| {
+ if !cx.shared.show_type_layout {
+ return Ok(());
+ }
+
+ let tcx = cx.tcx();
+ let param_env = tcx.param_env(ty_def_id);
+ let ty = tcx.type_of(ty_def_id).subst_identity();
+ let type_layout = tcx.layout_of(param_env.and(ty));
+
+ let variants =
+ if let Ok(type_layout) = type_layout &&
+ let Variants::Multiple { variants, tag, tag_encoding, .. } =
+ type_layout.layout.variants() &&
+ !variants.is_empty()
+ {
+ let tag_size =
+ if let TagEncoding::Niche { .. } = tag_encoding {
+ 0
+ } else if let Primitive::Int(i, _) = tag.primitive() {
+ i.size().bytes()
+ } else {
+ span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
+ };
+ variants
+ .iter_enumerated()
+ .map(|(variant_idx, variant_layout)| {
+ let Adt(adt, _) = type_layout.ty.kind() else {
+ span_bug!(tcx.def_span(ty_def_id), "not an adt")
+ };
+ let name = adt.variant(variant_idx).name;
+ let is_unsized = variant_layout.abi.is_unsized();
+ let is_uninhabited = variant_layout.abi.is_uninhabited();
+ let size = variant_layout.size.bytes() - tag_size;
+ let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size };
+ (name, type_layout_size)
+ })
+ .collect()
+ } else {
+ Vec::new()
+ };
+
+ let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| {
+ let is_unsized = layout.abi.is_unsized();
+ let is_uninhabited = layout.abi.is_uninhabited();
+ let size = layout.size.bytes();
+ TypeLayoutSize { is_unsized, is_uninhabited, size }
+ });
+
+ Ok(TypeLayout { variants, type_layout_size }.render_into(f).unwrap())
+ })
+}
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index c8397967c..a26fa3749 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -145,7 +145,7 @@ impl DocVisitor for SourceCollector<'_, '_> {
Err(e) => {
self.cx.shared.tcx.sess.span_err(
span,
- &format!(
+ format!(
"failed to render source code for `{}`: {}",
filename.prefer_local(),
e,
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 6fbb45086..a7d5f4977 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1259,6 +1259,10 @@ a.tooltip:hover::after {
background-color: var(--search-error-code-background-color);
}
+.search-corrections {
+ font-weight: normal;
+}
+
#src-sidebar-toggle {
position: sticky;
top: 0;
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index d13c783d2..c1324c076 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -1,13 +1,11 @@
.setting-line {
margin: 1.2em 0.6em;
- position: relative;
}
.setting-radio input, .setting-check input {
margin-right: 0.3em;
height: 1.2rem;
width: 1.2rem;
- color: inherit;
border: 2px solid var(--settings-input-border-color);
outline: none;
-webkit-appearance: none;
@@ -16,11 +14,6 @@
.setting-radio input {
border-radius: 50%;
}
-.setting-check input:checked {
- content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
- <path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
- <path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
-}
.setting-radio span, .setting-check span {
padding-bottom: 1px;
@@ -53,6 +46,9 @@
.setting-check input:checked {
background-color: var(--settings-input-color);
border-width: 1px;
+ content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
+ <path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
+ <path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
}
.setting-radio input:focus, .setting-check input:focus {
box-shadow: 0 0 1px 1px var(--settings-input-color);
diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js
index 4c81a0979..8b931f74e 100644
--- a/src/librustdoc/html/static/js/externs.js
+++ b/src/librustdoc/html/static/js/externs.js
@@ -9,6 +9,7 @@ function initSearch(searchIndex){}
/**
* @typedef {{
* name: string,
+ * id: integer,
* fullPath: Array<string>,
* pathWithoutLast: Array<string>,
* pathLast: string,
@@ -36,6 +37,8 @@ let ParserState;
* args: Array<QueryElement>,
* returned: Array<QueryElement>,
* foundElems: number,
+ * literalSearch: boolean,
+ * corrections: Array<{from: string, to: integer}>,
* }}
*/
let ParsedQuery;
@@ -139,7 +142,7 @@ let FunctionSearchType;
/**
* @typedef {{
- * name: (null|string),
+ * id: (null|number),
* ty: (null|number),
* generics: Array<FunctionType>,
* }}
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 6f5987e68..bccf675c1 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -275,8 +275,7 @@ function preLoadCss(cssUrl) {
document.title = searchState.titleBeforeSearch;
// We also remove the query parameter from the URL.
if (browserSupportsHistoryApi()) {
- history.replaceState(null, window.currentCrate + " - Rust",
- getNakedUrl() + window.location.hash);
+ history.replaceState(null, "", getNakedUrl() + window.location.hash);
}
},
getQueryStringParams: () => {
@@ -376,11 +375,7 @@ function preLoadCss(cssUrl) {
function handleEscape(ev) {
searchState.clearInputTimeout();
- switchDisplayedElement(null);
- if (browserSupportsHistoryApi()) {
- history.replaceState(null, window.currentCrate + " - Rust",
- getNakedUrl() + window.location.hash);
- }
+ searchState.hideResults();
ev.preventDefault();
searchState.defocus();
window.hideAllModals(true); // true = reset focus for tooltips
@@ -535,9 +530,11 @@ function preLoadCss(cssUrl) {
// ignored are included in the attribute `data-ignore-extern-crates`.
const script = document
.querySelector("script[data-ignore-extern-crates]");
- const ignoreExternCrates = script ? script.getAttribute("data-ignore-extern-crates") : "";
+ const ignoreExternCrates = new Set(
+ (script ? script.getAttribute("data-ignore-extern-crates") : "").split(",")
+ );
for (const lib of libs) {
- if (lib === window.currentCrate || ignoreExternCrates.indexOf(lib) !== -1) {
+ if (lib === window.currentCrate || ignoreExternCrates.has(lib)) {
continue;
}
const structs = imp[lib];
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 929dae81c..62afe40bb 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -58,6 +58,7 @@ function printTab(nb) {
}
iter += 1;
});
+ const isTypeSearch = (nb > 0 || iter === 1);
iter = 0;
onEachLazy(document.getElementById("results").childNodes, elem => {
if (nb === iter) {
@@ -70,6 +71,13 @@ function printTab(nb) {
});
if (foundCurrentTab && foundCurrentResultSet) {
searchState.currentTab = nb;
+ // Corrections only kick in on type-based searches.
+ const correctionsElem = document.getElementsByClassName("search-corrections");
+ if (isTypeSearch) {
+ removeClass(correctionsElem[0], "hidden");
+ } else {
+ addClass(correctionsElem[0], "hidden");
+ }
} else if (nb !== 0) {
printTab(0);
}
@@ -191,6 +199,13 @@ function initSearch(rawSearchIndex) {
*/
let searchIndex;
let currentResults;
+ /**
+ * Map from normalized type names to integers. Used to make type search
+ * more efficient.
+ *
+ * @type {Map<string, integer>}
+ */
+ let typeNameIdMap;
const ALIASES = new Map();
function isWhitespace(c) {
@@ -358,6 +373,7 @@ function initSearch(rawSearchIndex) {
parserState.typeFilter = null;
return {
name: name,
+ id: -1,
fullPath: pathSegments,
pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
pathLast: pathSegments[pathSegments.length - 1],
@@ -718,6 +734,7 @@ function initSearch(rawSearchIndex) {
foundElems: 0,
literalSearch: false,
error: null,
+ correction: null,
};
}
@@ -873,7 +890,7 @@ function initSearch(rawSearchIndex) {
*
* @param {Array<Result>} results_in_args
* @param {Array<Result>} results_returned
- * @param {Array<Result>} results_in_args
+ * @param {Array<Result>} results_others
* @param {ParsedQuery} parsedQuery
*
* @return {ResultsTable}
@@ -1091,48 +1108,50 @@ function initSearch(rawSearchIndex) {
*
* @param {Row} row - The object to check.
* @param {QueryElement} elem - The element from the parsed query.
- * @param {integer} defaultDistance - This is the value to return in case there are no
- * generics.
*
- * @return {integer} - Returns the best match (if any) or `maxEditDistance + 1`.
+ * @return {boolean} - Returns true if a match, false otherwise.
*/
- function checkGenerics(row, elem, defaultDistance, maxEditDistance) {
- if (row.generics.length === 0) {
- return elem.generics.length === 0 ? defaultDistance : maxEditDistance + 1;
- } else if (row.generics.length > 0 && row.generics[0].name === null) {
- return checkGenerics(row.generics[0], elem, defaultDistance, maxEditDistance);
- }
- // The names match, but we need to be sure that all generics kinda
- // match as well.
+ function checkGenerics(row, elem) {
+ if (row.generics.length === 0 || elem.generics.length === 0) {
+ return false;
+ }
+ // This function is called if the names match, but we need to make
+ // sure that all generics match as well.
+ //
+ // This search engine implements order-agnostic unification. There
+ // should be no missing duplicates (generics have "bag semantics"),
+ // and the row is allowed to have extras.
if (elem.generics.length > 0 && row.generics.length >= elem.generics.length) {
const elems = new Map();
- for (const entry of row.generics) {
- if (entry.name === "") {
+ const addEntryToElems = function addEntryToElems(entry) {
+ if (entry.id === -1) {
// Pure generic, needs to check into it.
- if (checkGenerics(entry, elem, maxEditDistance + 1, maxEditDistance)
- !== 0) {
- return maxEditDistance + 1;
+ for (const inner_entry of entry.generics) {
+ addEntryToElems(inner_entry);
}
- continue;
+ return;
}
let currentEntryElems;
- if (elems.has(entry.name)) {
- currentEntryElems = elems.get(entry.name);
+ if (elems.has(entry.id)) {
+ currentEntryElems = elems.get(entry.id);
} else {
currentEntryElems = [];
- elems.set(entry.name, currentEntryElems);
+ elems.set(entry.id, currentEntryElems);
}
currentEntryElems.push(entry);
+ };
+ for (const entry of row.generics) {
+ addEntryToElems(entry);
}
// We need to find the type that matches the most to remove it in order
// to move forward.
const handleGeneric = generic => {
- if (!elems.has(generic.name)) {
+ if (!elems.has(generic.id)) {
return false;
}
- const matchElems = elems.get(generic.name);
+ const matchElems = elems.get(generic.id);
const matchIdx = matchElems.findIndex(tmp_elem => {
- if (checkGenerics(tmp_elem, generic, 0, maxEditDistance) !== 0) {
+ if (generic.generics.length > 0 && !checkGenerics(tmp_elem, generic)) {
return false;
}
return typePassesFilter(generic.typeFilter, tmp_elem.ty);
@@ -1142,7 +1161,7 @@ function initSearch(rawSearchIndex) {
}
matchElems.splice(matchIdx, 1);
if (matchElems.length === 0) {
- elems.delete(generic.name);
+ elems.delete(generic.id);
}
return true;
};
@@ -1152,17 +1171,17 @@ function initSearch(rawSearchIndex) {
// own type.
for (const generic of elem.generics) {
if (generic.typeFilter !== -1 && !handleGeneric(generic)) {
- return maxEditDistance + 1;
+ return false;
}
}
for (const generic of elem.generics) {
if (generic.typeFilter === -1 && !handleGeneric(generic)) {
- return maxEditDistance + 1;
+ return false;
}
}
- return 0;
+ return true;
}
- return maxEditDistance + 1;
+ return false;
}
/**
@@ -1172,17 +1191,15 @@ function initSearch(rawSearchIndex) {
* @param {Row} row
* @param {QueryElement} elem - The element from the parsed query.
*
- * @return {integer} - Returns an edit distance to the best match.
+ * @return {boolean} - Returns true if found, false otherwise.
*/
- function checkIfInGenerics(row, elem, maxEditDistance) {
- let dist = maxEditDistance + 1;
+ function checkIfInGenerics(row, elem) {
for (const entry of row.generics) {
- dist = Math.min(checkType(entry, elem, true, maxEditDistance), dist);
- if (dist === 0) {
- break;
+ if (checkType(entry, elem)) {
+ return true;
}
}
- return dist;
+ return false;
}
/**
@@ -1191,75 +1208,26 @@ function initSearch(rawSearchIndex) {
*
* @param {Row} row
* @param {QueryElement} elem - The element from the parsed query.
- * @param {boolean} literalSearch
*
- * @return {integer} - Returns an edit distance to the best match. If there is
- * no match, returns `maxEditDistance + 1`.
+ * @return {boolean} - Returns true if the type matches, false otherwise.
*/
- function checkType(row, elem, literalSearch, maxEditDistance) {
- if (row.name === null) {
+ function checkType(row, elem) {
+ if (row.id === -1) {
// This is a pure "generic" search, no need to run other checks.
- if (row.generics.length > 0) {
- return checkIfInGenerics(row, elem, maxEditDistance);
- }
- return maxEditDistance + 1;
+ return row.generics.length > 0 ? checkIfInGenerics(row, elem) : false;
}
- let dist;
- if (typePassesFilter(elem.typeFilter, row.ty)) {
- dist = editDistance(row.name, elem.name, maxEditDistance);
- } else {
- dist = maxEditDistance + 1;
- }
- if (literalSearch) {
- if (dist !== 0) {
- // The name didn't match, let's try to check if the generics do.
- if (elem.generics.length === 0) {
- const checkGeneric = row.generics.length > 0;
- if (checkGeneric && row.generics
- .findIndex(tmp_elem => tmp_elem.name === elem.name &&
- typePassesFilter(elem.typeFilter, tmp_elem.ty)) !== -1) {
- return 0;
- }
- }
- return maxEditDistance + 1;
- } else if (elem.generics.length > 0) {
- return checkGenerics(row, elem, maxEditDistance + 1, maxEditDistance);
- }
- return 0;
- } else if (row.generics.length > 0) {
- if (elem.generics.length === 0) {
- if (dist === 0) {
- return 0;
- }
- // The name didn't match so we now check if the type we're looking for is inside
- // the generics!
- dist = Math.min(dist, checkIfInGenerics(row, elem, maxEditDistance));
- return dist;
- } else if (dist > maxEditDistance) {
- // So our item's name doesn't match at all and has generics.
- //
- // Maybe it's present in a sub generic? For example "f<A<B<C>>>()", if we're
- // looking for "B<C>", we'll need to go down.
- return checkIfInGenerics(row, elem, maxEditDistance);
- } else {
- // At this point, the name kinda match and we have generics to check, so
- // let's go!
- const tmp_dist = checkGenerics(row, elem, dist, maxEditDistance);
- if (tmp_dist > maxEditDistance) {
- return maxEditDistance + 1;
- }
- // We compute the median value of both checks and return it.
- return (tmp_dist + dist) / 2;
+ if (row.id === elem.id && typePassesFilter(elem.typeFilter, row.ty)) {
+ if (elem.generics.length > 0) {
+ return checkGenerics(row, elem);
}
- } else if (elem.generics.length > 0) {
- // In this case, we were expecting generics but there isn't so we simply reject this
- // one.
- return maxEditDistance + 1;
+ return true;
}
- // No generics on our query or on the target type so we can return without doing
- // anything else.
- return dist;
+
+ // If the current item does not match, try [unboxing] the generic.
+ // [unboxing]:
+ // https://ndmitchell.com/downloads/slides-hoogle_fast_type_searching-09_aug_2008.pdf
+ return checkIfInGenerics(row, elem);
}
/**
@@ -1267,17 +1235,11 @@ function initSearch(rawSearchIndex) {
*
* @param {Row} row
* @param {QueryElement} elem - The element from the parsed query.
- * @param {integer} maxEditDistance
* @param {Array<integer>} skipPositions - Do not return one of these positions.
*
- * @return {dist: integer, position: integer} - Returns an edit distance to the best match.
- * If there is no match, returns
- * `maxEditDistance + 1` and position: -1.
+ * @return {integer} - Returns the position of the match, or -1 if none.
*/
- function findArg(row, elem, maxEditDistance, skipPositions) {
- let dist = maxEditDistance + 1;
- let position = -1;
-
+ function findArg(row, elem, skipPositions) {
if (row && row.type && row.type.inputs && row.type.inputs.length > 0) {
let i = 0;
for (const input of row.type.inputs) {
@@ -1285,24 +1247,13 @@ function initSearch(rawSearchIndex) {
i += 1;
continue;
}
- const typeDist = checkType(
- input,
- elem,
- parsedQuery.literalSearch,
- maxEditDistance
- );
- if (typeDist === 0) {
- return {dist: 0, position: i};
- }
- if (typeDist < dist) {
- dist = typeDist;
- position = i;
+ if (checkType(input, elem)) {
+ return i;
}
i += 1;
}
}
- dist = parsedQuery.literalSearch ? maxEditDistance + 1 : dist;
- return {dist, position};
+ return -1;
}
/**
@@ -1310,43 +1261,25 @@ function initSearch(rawSearchIndex) {
*
* @param {Row} row
* @param {QueryElement} elem - The element from the parsed query.
- * @param {integer} maxEditDistance
* @param {Array<integer>} skipPositions - Do not return one of these positions.
*
- * @return {dist: integer, position: integer} - Returns an edit distance to the best match.
- * If there is no match, returns
- * `maxEditDistance + 1` and position: -1.
+ * @return {integer} - Returns the position of the matching item, or -1 if none.
*/
- function checkReturned(row, elem, maxEditDistance, skipPositions) {
- let dist = maxEditDistance + 1;
- let position = -1;
-
+ function checkReturned(row, elem, skipPositions) {
if (row && row.type && row.type.output.length > 0) {
- const ret = row.type.output;
let i = 0;
- for (const ret_ty of ret) {
+ for (const ret_ty of row.type.output) {
if (skipPositions.indexOf(i) !== -1) {
i += 1;
continue;
}
- const typeDist = checkType(
- ret_ty,
- elem,
- parsedQuery.literalSearch,
- maxEditDistance
- );
- if (typeDist === 0) {
- return {dist: 0, position: i};
- }
- if (typeDist < dist) {
- dist = typeDist;
- position = i;
+ if (checkType(ret_ty, elem)) {
+ return i;
}
i += 1;
}
}
- dist = parsedQuery.literalSearch ? maxEditDistance + 1 : dist;
- return {dist, position};
+ return -1;
}
function checkPath(contains, ty, maxEditDistance) {
@@ -1543,17 +1476,20 @@ function initSearch(rawSearchIndex) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
}
- let dist, index = -1, path_dist = 0;
+ let index = -1, path_dist = 0;
const fullId = row.id;
const searchWord = searchWords[pos];
- const in_args = findArg(row, elem, maxEditDistance, []);
- const returned = checkReturned(row, elem, maxEditDistance, []);
-
- // path_dist is 0 because no parent path information is currently stored
- // in the search index
- addIntoResults(results_in_args, fullId, pos, -1, in_args.dist, 0, maxEditDistance);
- addIntoResults(results_returned, fullId, pos, -1, returned.dist, 0, maxEditDistance);
+ const in_args = findArg(row, elem, []);
+ if (in_args !== -1) {
+ // path_dist is 0 because no parent path information is currently stored
+ // in the search index
+ addIntoResults(results_in_args, fullId, pos, -1, 0, 0, maxEditDistance);
+ }
+ const returned = checkReturned(row, elem, []);
+ if (returned !== -1) {
+ addIntoResults(results_returned, fullId, pos, -1, 0, 0, maxEditDistance);
+ }
if (!typePassesFilter(elem.typeFilter, row.ty)) {
return;
@@ -1574,16 +1510,6 @@ function initSearch(rawSearchIndex) {
index = row_index;
}
- // No need to check anything else if it's a "pure" generics search.
- if (elem.name.length === 0) {
- if (row.type !== null) {
- dist = checkGenerics(row.type, elem, maxEditDistance + 1, maxEditDistance);
- // path_dist is 0 because we know it's empty
- addIntoResults(results_others, fullId, pos, index, dist, 0, maxEditDistance);
- }
- return;
- }
-
if (elem.fullPath.length > 1) {
path_dist = checkPath(elem.pathWithoutLast, row, maxEditDistance);
if (path_dist > maxEditDistance) {
@@ -1598,7 +1524,7 @@ function initSearch(rawSearchIndex) {
return;
}
- dist = editDistance(searchWord, elem.pathLast, maxEditDistance);
+ const dist = editDistance(searchWord, elem.pathLast, maxEditDistance);
if (index === -1 && dist + path_dist > maxEditDistance) {
return;
@@ -1616,28 +1542,22 @@ function initSearch(rawSearchIndex) {
* @param {integer} pos - Position in the `searchIndex`.
* @param {Object} results
*/
- function handleArgs(row, pos, results, maxEditDistance) {
+ function handleArgs(row, pos, results) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
}
- let totalDist = 0;
- let nbDist = 0;
-
// If the result is too "bad", we return false and it ends this search.
function checkArgs(elems, callback) {
const skipPositions = [];
for (const elem of elems) {
// There is more than one parameter to the query so all checks should be "exact"
- const { dist, position } = callback(
+ const position = callback(
row,
elem,
- maxEditDistance,
skipPositions
);
- if (dist <= 1) {
- nbDist += 1;
- totalDist += dist;
+ if (position !== -1) {
skipPositions.push(position);
} else {
return false;
@@ -1652,11 +1572,7 @@ function initSearch(rawSearchIndex) {
return;
}
- if (nbDist === 0) {
- return;
- }
- const dist = Math.round(totalDist / nbDist);
- addIntoResults(results, row.id, pos, 0, dist, 0, maxEditDistance);
+ addIntoResults(results, row.id, pos, 0, 0, 0, Number.MAX_VALUE);
}
function innerRunQuery() {
@@ -1671,6 +1587,53 @@ function initSearch(rawSearchIndex) {
}
const maxEditDistance = Math.floor(queryLen / 3);
+ /**
+ * Convert names to ids in parsed query elements.
+ * This is not used for the "In Names" tab, but is used for the
+ * "In Params", "In Returns", and "In Function Signature" tabs.
+ *
+ * If there is no matching item, but a close-enough match, this
+ * function also that correction.
+ *
+ * See `buildTypeMapIndex` for more information.
+ *
+ * @param {QueryElement} elem
+ */
+ function convertNameToId(elem) {
+ if (typeNameIdMap.has(elem.name)) {
+ elem.id = typeNameIdMap.get(elem.name);
+ } else if (!parsedQuery.literalSearch) {
+ let match = -1;
+ let matchDist = maxEditDistance + 1;
+ let matchName = "";
+ for (const [name, id] of typeNameIdMap) {
+ const dist = editDistance(name, elem.name, maxEditDistance);
+ if (dist <= matchDist && dist <= maxEditDistance) {
+ if (dist === matchDist && matchName > name) {
+ continue;
+ }
+ match = id;
+ matchDist = dist;
+ matchName = name;
+ }
+ }
+ if (match !== -1) {
+ parsedQuery.correction = matchName;
+ }
+ elem.id = match;
+ }
+ for (const elem2 of elem.generics) {
+ convertNameToId(elem2);
+ }
+ }
+
+ for (const elem of parsedQuery.elems) {
+ convertNameToId(elem);
+ }
+ for (const elem of parsedQuery.returned) {
+ convertNameToId(elem);
+ }
+
if (parsedQuery.foundElems === 1) {
if (parsedQuery.elems.length === 1) {
elem = parsedQuery.elems[0];
@@ -1695,22 +1658,23 @@ function initSearch(rawSearchIndex) {
in_returned = checkReturned(
row,
elem,
- maxEditDistance,
[]
);
- addIntoResults(
- results_others,
- row.id,
- i,
- -1,
- in_returned.dist,
- maxEditDistance
- );
+ if (in_returned !== -1) {
+ addIntoResults(
+ results_others,
+ row.id,
+ i,
+ -1,
+ 0,
+ Number.MAX_VALUE
+ );
+ }
}
}
} else if (parsedQuery.foundElems > 0) {
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
- handleArgs(searchIndex[i], i, results_others, maxEditDistance);
+ handleArgs(searchIndex[i], i, results_others);
}
}
}
@@ -2030,6 +1994,16 @@ function initSearch(rawSearchIndex) {
currentTab = 0;
}
+ if (results.query.correction !== null) {
+ const orig = results.query.returned.length > 0
+ ? results.query.returned[0].name
+ : results.query.elems[0].name;
+ output += "<h3 class=\"search-corrections\">" +
+ `Type "${orig}" not found. ` +
+ "Showing results for closest type name " +
+ `"${results.query.correction}" instead.</h3>`;
+ }
+
const resultsElem = document.createElement("div");
resultsElem.id = "results";
resultsElem.appendChild(ret_others[0]);
@@ -2109,6 +2083,34 @@ function initSearch(rawSearchIndex) {
}
/**
+ * Add an item to the type Name->ID map, or, if one already exists, use it.
+ * Returns the number. If name is "" or null, return -1 (pure generic).
+ *
+ * This is effectively string interning, so that function matching can be
+ * done more quickly. Two types with the same name but different item kinds
+ * get the same ID.
+ *
+ * @param {Map<string, integer>} typeNameIdMap
+ * @param {string} name
+ *
+ * @returns {integer}
+ */
+ function buildTypeMapIndex(typeNameIdMap, name) {
+
+ if (name === "" || name === null) {
+ return -1;
+ }
+
+ if (typeNameIdMap.has(name)) {
+ return typeNameIdMap.get(name);
+ } else {
+ const id = typeNameIdMap.size;
+ typeNameIdMap.set(name, id);
+ return id;
+ }
+ }
+
+ /**
* Convert a list of RawFunctionType / ID to object-based FunctionType.
*
* Crates often have lots of functions in them, and it's common to have a large number of
@@ -2126,7 +2128,7 @@ function initSearch(rawSearchIndex) {
*
* @return {Array<FunctionSearchType>}
*/
- function buildItemSearchTypeAll(types, lowercasePaths) {
+ function buildItemSearchTypeAll(types, lowercasePaths, typeNameIdMap) {
const PATH_INDEX_DATA = 0;
const GENERICS_DATA = 1;
return types.map(type => {
@@ -2136,11 +2138,17 @@ function initSearch(rawSearchIndex) {
generics = [];
} else {
pathIndex = type[PATH_INDEX_DATA];
- generics = buildItemSearchTypeAll(type[GENERICS_DATA], lowercasePaths);
+ generics = buildItemSearchTypeAll(
+ type[GENERICS_DATA],
+ lowercasePaths,
+ typeNameIdMap
+ );
}
return {
// `0` is used as a sentinel because it's fewer bytes than `null`
- name: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].name,
+ id: pathIndex === 0
+ ? -1
+ : buildTypeMapIndex(typeNameIdMap, lowercasePaths[pathIndex - 1].name),
ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty,
generics: generics,
};
@@ -2159,10 +2167,11 @@ function initSearch(rawSearchIndex) {
*
* @param {RawFunctionSearchType} functionSearchType
* @param {Array<{name: string, ty: number}>} lowercasePaths
+ * @param {Map<string, integer>}
*
* @return {null|FunctionSearchType}
*/
- function buildFunctionSearchType(functionSearchType, lowercasePaths) {
+ function buildFunctionSearchType(functionSearchType, lowercasePaths, typeNameIdMap) {
const INPUTS_DATA = 0;
const OUTPUT_DATA = 1;
// `0` is used as a sentinel because it's fewer bytes than `null`
@@ -2173,23 +2182,35 @@ function initSearch(rawSearchIndex) {
if (typeof functionSearchType[INPUTS_DATA] === "number") {
const pathIndex = functionSearchType[INPUTS_DATA];
inputs = [{
- name: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].name,
+ id: pathIndex === 0
+ ? -1
+ : buildTypeMapIndex(typeNameIdMap, lowercasePaths[pathIndex - 1].name),
ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty,
generics: [],
}];
} else {
- inputs = buildItemSearchTypeAll(functionSearchType[INPUTS_DATA], lowercasePaths);
+ inputs = buildItemSearchTypeAll(
+ functionSearchType[INPUTS_DATA],
+ lowercasePaths,
+ typeNameIdMap
+ );
}
if (functionSearchType.length > 1) {
if (typeof functionSearchType[OUTPUT_DATA] === "number") {
const pathIndex = functionSearchType[OUTPUT_DATA];
output = [{
- name: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].name,
+ id: pathIndex === 0
+ ? -1
+ : buildTypeMapIndex(typeNameIdMap, lowercasePaths[pathIndex - 1].name),
ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty,
generics: [],
}];
} else {
- output = buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA], lowercasePaths);
+ output = buildItemSearchTypeAll(
+ functionSearchType[OUTPUT_DATA],
+ lowercasePaths,
+ typeNameIdMap
+ );
}
} else {
output = [];
@@ -2202,9 +2223,12 @@ function initSearch(rawSearchIndex) {
function buildIndex(rawSearchIndex) {
searchIndex = [];
/**
+ * List of normalized search words (ASCII lowercased, and undescores removed).
+ *
* @type {Array<string>}
*/
const searchWords = [];
+ typeNameIdMap = new Map();
const charA = "A".charCodeAt(0);
let currentIndex = 0;
let id = 0;
@@ -2337,7 +2361,11 @@ function initSearch(rawSearchIndex) {
path: itemPaths.has(i) ? itemPaths.get(i) : lastPath,
desc: itemDescs[i],
parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
- type: buildFunctionSearchType(itemFunctionSearchTypes[i], lowercasePaths),
+ type: buildFunctionSearchType(
+ itemFunctionSearchTypes[i],
+ lowercasePaths,
+ typeNameIdMap
+ ),
id: id,
normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
deprecated: deprecatedItems.has(i),
@@ -2412,10 +2440,6 @@ function initSearch(rawSearchIndex) {
const searchAfter500ms = () => {
searchState.clearInputTimeout();
if (searchState.input.value.length === 0) {
- if (browserSupportsHistoryApi()) {
- history.replaceState(null, window.currentCrate + " - Rust",
- getNakedUrl() + window.location.hash);
- }
searchState.hideResults();
} else {
searchState.timeout = setTimeout(search, 500);
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index ebbe6c1ca..2cba32c1b 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -1,5 +1,5 @@
// Local js definitions:
-/* global getSettingValue, getVirtualKey, updateLocalStorage, updateTheme */
+/* global getSettingValue, updateLocalStorage, updateTheme */
/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
/* global MAIN_ID, getVar, getSettingsButton */
@@ -32,21 +32,6 @@
}
}
- function handleKey(ev) {
- // Don't interfere with browser shortcuts
- if (ev.ctrlKey || ev.altKey || ev.metaKey) {
- return;
- }
- switch (getVirtualKey(ev)) {
- case "Enter":
- case "Return":
- case "Space":
- ev.target.checked = !ev.target.checked;
- ev.preventDefault();
- break;
- }
- }
-
function showLightAndDark() {
removeClass(document.getElementById("preferred-light-theme"), "hidden");
removeClass(document.getElementById("preferred-dark-theme"), "hidden");
@@ -77,8 +62,6 @@
toggle.onchange = function() {
changeSetting(this.id, this.checked);
};
- toggle.onkeyup = handleKey;
- toggle.onkeyrelease = handleKey;
});
onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => {
const settingId = elem.name;
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 9aa755173..d999f3b36 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -52,12 +52,12 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
const files = document.createElement("div");
files.className = "files";
if (elem[FILES_OFFSET]) {
+ const w = window.location.href.split("#")[0];
for (const file_text of elem[FILES_OFFSET]) {
const file = document.createElement("a");
file.innerText = file_text;
file.href = rootPath + "src/" + fullPath + file_text + ".html";
file.addEventListener("click", closeSidebarIfMobile);
- const w = window.location.href.split("#")[0];
if (!hasFoundFile && w === file.href) {
file.className = "selected";
dirEntry.open = true;
diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html
index a01457971..c21967005 100644
--- a/src/librustdoc/html/templates/item_union.html
+++ b/src/librustdoc/html/templates/item_union.html
@@ -1,8 +1,8 @@
<pre class="rust item-decl"><code>
- {{ self.render_attributes_in_pre() | safe }}
+ {{ self::item_template_render_attributes_in_pre(self.borrow()) | safe }}
{{ self.render_union() | safe }}
</code></pre>
-{{ self.document() | safe }}
+{{ self::item_template_document(self.borrow()) | safe }}
{% if self.fields_iter().peek().is_some() %}
<h2 id="fields" class="fields small-section-header">
Fields<a href="#fields" class="anchor">§</a>
@@ -19,5 +19,5 @@
{{ self.document_field(field) | safe }}
{% endfor %}
{% endif %}
-{{ self.render_assoc_items() | safe }}
-{{ self.document_type_layout() | safe }}
+{{ self::item_template_render_assoc_items(self.borrow()) | safe }}
+{{ self::item_template_document_type_layout(self.borrow()) | safe }}
diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html
new file mode 100644
index 000000000..20e09a548
--- /dev/null
+++ b/src/librustdoc/html/templates/type_layout.html
@@ -0,0 +1,58 @@
+<h2 id="layout" class="small-section-header"> {# #}
+ Layout<a href="#layout" class="anchor">§</a> {# #}
+</h2> {# #}
+<div class="docblock"> {# #}
+ {% match type_layout_size %}
+ {% when Ok(type_layout_size) %}
+ <div class="warning"> {# #}
+ <p> {# #}
+ <strong>Note:</strong> Most layout information is <strong>completely {#+ #}
+ unstable</strong> and may even differ between compilations. {#+ #}
+ The only exception is types with certain <code>repr(...)</code> {#+ #}
+ attributes. Please see the Rust Reference’s {#+ #}
+ <a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
+ chapter for details on type layout guarantees. {# #}
+ </p> {# #}
+ </div> {# #}
+ <p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
+ {% if !variants.is_empty() %}
+ <p> {# #}
+ <strong>Size for each variant:</strong> {# #}
+ </p> {# #}
+ <ul> {# #}
+ {% for (name, layout_size) in variants %}
+ <li> {# #}
+ <code>{{ name }}</code>: {#+ #}
+ {{ layout_size|safe }}
+ </li> {# #}
+ {% endfor %}
+ </ul> {# #}
+ {% endif %}
+ {# This kind of layout error can occur with valid code, e.g. if you try to
+ get the layout of a generic type such as `Vec<T>`. #}
+ {% when Err(LayoutError::Unknown(_)) %}
+ <p> {# #}
+ <strong>Note:</strong> Unable to compute type layout, {#+ #}
+ possibly due to this type having generic parameters. {#+ #}
+ Layout can only be computed for concrete, fully-instantiated types. {# #}
+ </p> {# #}
+ {# This kind of error probably can't happen with valid code, but we don't
+ want to panic and prevent the docs from building, so we just let the
+ user know that we couldn't compute the layout. #}
+ {% when Err(LayoutError::SizeOverflow(_)) %}
+ <p> {# #}
+ <strong>Note:</strong> Encountered an error during type layout; {#+ #}
+ the type was too big. {# #}
+ </p> {# #}
+ {% when Err(LayoutError::NormalizationFailure(_, _)) %}
+ <p> {# #}
+ <strong>Note:</strong> Encountered an error during type layout; {#+ #}
+ the type failed to be normalized. {# #}
+ </p> {# #}
+ {% when Err(LayoutError::Cycle) %}
+ <p> {# #}
+ <strong>Note:</strong> Encountered an error during type layout; {#+ #}
+ the type's layout depended on the type's layout itself. {# #}
+ </p> {# #}
+ {% endmatch %}
+</div> {# #}
diff --git a/src/librustdoc/html/templates/type_layout_size.html b/src/librustdoc/html/templates/type_layout_size.html
new file mode 100644
index 000000000..9c2b39edc
--- /dev/null
+++ b/src/librustdoc/html/templates/type_layout_size.html
@@ -0,0 +1,12 @@
+{% if is_unsized %}
+ (unsized)
+{% else %}
+ {% if size == 1 %}
+ 1 byte
+ {% else %}
+ {{ size +}} bytes
+ {% endif %}
+ {% if is_uninhabited %}
+ {# +#} (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)
+ {% endif %}
+{% endif %}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index cd6509607..935bb721f 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -40,13 +40,8 @@ impl JsonRenderer<'_> {
(String::from(&**link), id_from_item_default(id.into(), self.tcx))
})
.collect();
- let docs = item.attrs.collapsed_doc_value();
- let attrs = item
- .attrs
- .other_attrs
- .iter()
- .map(rustc_ast_pretty::pprust::attribute_to_string)
- .collect();
+ let docs = item.opt_doc_value();
+ let attrs = item.attributes(self.tcx, true);
let span = item.span(self.tcx);
let visibility = item.visibility(self.tcx);
let clean::Item { name, item_id, .. } = item;
@@ -538,6 +533,10 @@ pub(crate) fn from_trait_bound_modifier(
None => TraitBoundModifier::None,
Maybe => TraitBoundModifier::Maybe,
MaybeConst => TraitBoundModifier::MaybeConst,
+ // FIXME(negative-bounds): This bound should be rendered negative, but
+ // since that's experimental, maybe let's not add it to the rustdoc json
+ // API just now...
+ Negative => TraitBoundModifier::None,
}
}
@@ -575,7 +574,7 @@ impl FromWithTcx<clean::Type> for Type {
name: assoc.name.to_string(),
args: Box::new(assoc.args.into_tcx(tcx)),
self_type: Box::new(self_type.into_tcx(tcx)),
- trait_: trait_.into_tcx(tcx),
+ trait_: trait_.map(|trait_| trait_.into_tcx(tcx)),
},
}
}
@@ -665,7 +664,7 @@ impl FromWithTcx<clean::Impl> for Impl {
let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
// FIXME: use something like ImplKind in JSON?
let (synthetic, blanket_impl) = match kind {
- clean::ImplKind::Normal | clean::ImplKind::FakeVaradic => (false, None),
+ clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None),
clean::ImplKind::Auto => (true, None),
clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
};
@@ -740,7 +739,7 @@ impl FromWithTcx<clean::Variant> for Variant {
impl FromWithTcx<clean::Discriminant> for Discriminant {
fn from_tcx(disr: clean::Discriminant, tcx: TyCtxt<'_>) -> Self {
Discriminant {
- // expr is only none if going through the inlineing path, which gets
+ // expr is only none if going through the inlining path, which gets
// `rustc_middle` types, not `rustc_hir`, but because JSON never inlines
// the expr is always some.
expr: disr.expr(tcx).unwrap(),
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index d6da6e099..9392dd4d0 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -279,7 +279,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
p.set_extension("json");
let mut file = BufWriter::new(try_err!(File::create(&p), p));
- serde_json::ser::to_writer(&mut file, &output).unwrap();
+ self.tcx
+ .sess
+ .time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut file, &output))
+ .unwrap();
try_err!(file.flush(), p);
Ok(())
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 4a88dc525..12c622e02 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -7,14 +7,15 @@
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(drain_filter)]
+#![feature(impl_trait_in_assoc_type)]
+#![feature(iter_intersperse)]
+#![feature(lazy_cell)]
#![feature(let_chains)]
-#![feature(test)]
#![feature(never_type)]
-#![feature(lazy_cell)]
-#![feature(type_ascription)]
-#![feature(iter_intersperse)]
+#![feature(round_char_boundary)]
+#![feature(test)]
#![feature(type_alias_impl_trait)]
-#![cfg_attr(not(bootstrap), feature(impl_trait_in_assoc_type))]
+#![feature(type_ascription)]
#![recursion_limit = "256"]
#![warn(rustc::internal)]
#![allow(clippy::collapsible_if, clippy::collapsible_else_if)]
@@ -33,6 +34,7 @@ extern crate tracing;
// Dependencies listed in Cargo.toml do not need `extern crate`.
extern crate pulldown_cmark;
+extern crate rustc_abi;
extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_attr;
@@ -154,15 +156,19 @@ pub fn main() {
}
}
- rustc_driver::install_ice_hook();
+ rustc_driver::install_ice_hook(
+ "https://github.com/rust-lang/rust/issues/new\
+ ?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md",
+ |_| (),
+ );
- // When using CI artifacts (with `download_stage1 = true`), tracing is unconditionally built
+ // When using CI artifacts with `download-rustc`, tracing is unconditionally built
// with `--features=static_max_level_info`, which disables almost all rustdoc logging. To avoid
// this, compile our own version of `tracing` that logs all levels.
// NOTE: this compiles both versions of tracing unconditionally, because
// - The compile time hit is not that bad, especially compared to rustdoc's incremental times, and
- // - Otherwise, there's no warning that logging is being ignored when `download_stage1 = true`.
- // NOTE: The reason this doesn't show double logging when `download_stage1 = false` and
+ // - Otherwise, there's no warning that logging is being ignored when `download-rustc` is enabled
+ // NOTE: The reason this doesn't show double logging when `download-rustc = false` and
// `debug_logging = true` is because all rustc logging goes to its version of tracing (the one
// in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml).
init_logging();
@@ -170,7 +176,11 @@ pub fn main() {
let exit_code = rustc_driver::catch_with_exit_code(|| match get_args() {
Some(args) => main_args(&args),
- _ => Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()),
+ _ =>
+ {
+ #[allow(deprecated)]
+ Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+ }
});
process::exit(exit_code);
}
@@ -182,11 +192,11 @@ fn init_logging() {
Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(),
Ok(value) => early_error(
ErrorOutputType::default(),
- &format!("invalid log color value '{}': expected one of always, never, or auto", value),
+ format!("invalid log color value '{}': expected one of always, never, or auto", value),
),
Err(VarError::NotUnicode(value)) => early_error(
ErrorOutputType::default(),
- &format!(
+ format!(
"invalid log color value '{}': expected one of always, never, or auto",
value.to_string_lossy()
),
@@ -218,7 +228,7 @@ fn get_args() -> Option<Vec<String>> {
.map_err(|arg| {
early_warn(
ErrorOutputType::default(),
- &format!("Argument {} is not valid Unicode: {:?}", i, arg),
+ format!("Argument {} is not valid Unicode: {:?}", i, arg),
);
})
.ok()
@@ -675,7 +685,7 @@ fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainRes
match res {
Ok(()) => diag.has_errors().map_or(Ok(()), Err),
Err(err) => {
- let reported = diag.struct_err(&err).emit();
+ let reported = diag.struct_err(err).emit();
Err(reported)
}
}
@@ -691,10 +701,10 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
Ok(_) => tcx.sess.has_errors().map_or(Ok(()), Err),
Err(e) => {
let mut msg =
- tcx.sess.struct_err(&format!("couldn't generate documentation: {}", e.error));
+ tcx.sess.struct_err(format!("couldn't generate documentation: {}", e.error));
let file = e.file.display().to_string();
if !file.is_empty() {
- msg.note(&format!("failed to create or modify \"{}\"", file));
+ msg.note(format!("failed to create or modify \"{}\"", file));
}
Err(msg.emit())
}
@@ -702,16 +712,26 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
}
fn main_args(at_args: &[String]) -> MainResult {
+ // Throw away the first argument, the name of the binary.
+ // In case of at_args being empty, as might be the case by
+ // passing empty argument array to execve under some platforms,
+ // just use an empty slice.
+ //
+ // This situation was possible before due to arg_expand_all being
+ // called before removing the argument, enabling a crash by calling
+ // the compiler with @empty_file as argv[0] and no more arguments.
+ let at_args = at_args.get(1..).unwrap_or_default();
+
let args = rustc_driver::args::arg_expand_all(at_args);
let mut options = getopts::Options::new();
for option in opts() {
(option.apply)(&mut options);
}
- let matches = match options.parse(&args[1..]) {
+ let matches = match options.parse(&args) {
Ok(m) => m,
Err(err) => {
- early_error(ErrorOutputType::default(), &err.to_string());
+ early_error(ErrorOutputType::default(), err.to_string());
}
};
@@ -723,11 +743,15 @@ fn main_args(at_args: &[String]) -> MainResult {
return if code == 0 {
Ok(())
} else {
+ #[allow(deprecated)]
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
};
}
};
+ // Set parallel mode before error handler creation, which will create `Lock`s.
+ interface::set_thread_safe_mode(&options.unstable_opts);
+
let diag = core::new_handler(
options.error_format,
None,
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index 6d289eb99..749c1ff51 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -174,6 +174,17 @@ declare_rustdoc_lint! {
"codeblock could not be parsed as valid Rust or is empty"
}
+declare_rustdoc_lint! {
+ /// The `unescaped_backticks` lint detects unescaped backticks (\`), which usually
+ /// mean broken inline code. This is a `rustdoc` only lint, see the documentation
+ /// in the [rustdoc book].
+ ///
+ /// [rustdoc book]: ../../../rustdoc/lints.html#unescaped_backticks
+ UNESCAPED_BACKTICKS,
+ Allow,
+ "detects unescaped backticks in doc comments"
+}
+
pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
vec![
BROKEN_INTRA_DOC_LINKS,
@@ -185,6 +196,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
INVALID_HTML_TAGS,
BARE_URLS,
MISSING_CRATE_LEVEL_DOCS,
+ UNESCAPED_BACKTICKS,
]
});
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index be5286b24..6ead0cd96 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -206,13 +206,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
let has_docs = !i.attrs.doc_strings.is_empty();
let mut tests = Tests { found_tests: 0 };
- find_testable_code(
- &i.attrs.collapsed_doc_value().unwrap_or_default(),
- &mut tests,
- ErrorCodes::No,
- false,
- None,
- );
+ find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None);
let has_doc_example = tests.found_tests != 0;
let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 6b13e6c95..b6cd897d3 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -34,9 +34,7 @@ pub(crate) fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -
impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> {
fn visit_item(&mut self, item: &Item) {
- let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
-
- look_for_tests(self.cx, &dox, item);
+ look_for_tests(self.cx, &item.doc_value(), item);
self.visit_item_recur(item)
}
@@ -95,7 +93,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
}
if cx.tcx.is_doc_hidden(def_id.to_def_id())
- || inherits_doc_hidden(cx.tcx, def_id)
+ || inherits_doc_hidden(cx.tcx, def_id, None)
|| cx.tcx.def_span(def_id.to_def_id()).in_derive_expansion()
{
return false;
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 2cd9c8a87..061a572c4 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -8,12 +8,12 @@ use rustc_data_structures::{
fx::{FxHashMap, FxHashSet},
intern::Interned,
};
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticMessage};
use rustc_hir::def::Namespace::*;
use rustc_hir::def::{DefKind, Namespace, PerNS};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::Mutability;
-use rustc_middle::ty::{fast_reject::TreatProjections, Ty, TyCtxt};
+use rustc_middle::ty::{Ty, TyCtxt};
use rustc_middle::{bug, ty};
use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics};
@@ -24,13 +24,14 @@ use rustc_span::BytePos;
use smallvec::{smallvec, SmallVec};
use std::borrow::Cow;
+use std::fmt::Display;
use std::mem;
use std::ops::Range;
use crate::clean::{self, utils::find_nearest_parent_module};
use crate::clean::{Crate, Item, ItemLink, PrimitiveType};
use crate::core::DocContext;
-use crate::html::markdown::{markdown_links, MarkdownLink};
+use crate::html::markdown::{markdown_links, MarkdownLink, MarkdownLinkRange};
use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
use crate::passes::Pass;
use crate::visit::DocVisitor;
@@ -148,7 +149,7 @@ impl TryFrom<ResolveRes> for Res {
Def(kind, id) => Ok(Res::Def(kind, id)),
PrimTy(prim) => Ok(Res::Primitive(PrimitiveType::from_hir(prim))),
// e.g. `#[derive]`
- NonMacroAttr(..) | Err => Result::Err(()),
+ ToolMod | NonMacroAttr(..) | Err => Result::Err(()),
other => bug!("unrecognized res {:?}", other),
}
}
@@ -247,7 +248,7 @@ struct DiagnosticInfo<'a> {
item: &'a Item,
dox: &'a str,
ori_link: &'a str,
- link_range: Range<usize>,
+ link_range: MarkdownLinkRange,
}
struct LinkCollector<'a, 'tcx> {
@@ -722,7 +723,7 @@ fn resolve_associated_trait_item<'a>(
.iter()
.flat_map(|&(impl_, trait_)| {
filter_assoc_items_by_name_and_namespace(
- cx.tcx,
+ tcx,
trait_,
Ident::with_dummy_span(item_name),
ns,
@@ -772,11 +773,10 @@ fn trait_impls_for<'a>(
module: DefId,
) -> FxHashSet<(DefId, DefId)> {
let tcx = cx.tcx;
- let iter = tcx.doc_link_traits_in_scope(module).iter().flat_map(|&trait_| {
- trace!("considering explicit impl for trait {:?}", trait_);
+ let mut impls = FxHashSet::default();
- // Look at each trait implementation to see if it's an impl for `did`
- tcx.find_map_relevant_impl(trait_, ty, TreatProjections::ForLookup, |impl_| {
+ for &trait_ in tcx.doc_link_traits_in_scope(module) {
+ tcx.for_each_relevant_impl(trait_, ty, |impl_| {
let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
// Check if these are the same type.
let impl_type = trait_ref.skip_binder().self_ty();
@@ -800,10 +800,13 @@ fn trait_impls_for<'a>(
_ => false,
};
- if saw_impl { Some((impl_, trait_)) } else { None }
- })
- });
- iter.collect()
+ if saw_impl {
+ impls.insert((impl_, trait_));
+ }
+ });
+ }
+
+ impls
}
/// Check for resolve collisions between a trait and its derive.
@@ -830,7 +833,7 @@ impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
enum PreprocessingError {
/// User error: `[std#x#y]` is not valid
MultipleAnchors,
- Disambiguator(Range<usize>, String),
+ Disambiguator(MarkdownLinkRange, String),
MalformedGenerics(MalformedGenerics, String),
}
@@ -839,7 +842,7 @@ impl PreprocessingError {
match self {
PreprocessingError::MultipleAnchors => report_multiple_anchors(cx, diag_info),
PreprocessingError::Disambiguator(range, msg) => {
- disambiguator_error(cx, diag_info, range.clone(), msg)
+ disambiguator_error(cx, diag_info, range.clone(), msg.as_str())
}
PreprocessingError::MalformedGenerics(err, path_str) => {
report_malformed_generics(cx, diag_info, *err, path_str)
@@ -870,6 +873,7 @@ pub(crate) struct PreprocessedMarkdownLink(
/// `link_buffer` is needed for lifetime reasons; it will always be overwritten and the contents ignored.
fn preprocess_link(
ori_link: &MarkdownLink,
+ dox: &str,
) -> Option<Result<PreprocessingInfo, PreprocessingError>> {
// [] is mostly likely not supposed to be a link
if ori_link.link.is_empty() {
@@ -903,9 +907,15 @@ fn preprocess_link(
Err((err_msg, relative_range)) => {
// Only report error if we would not have ignored this link. See issue #83859.
if !should_ignore_link_with_disambiguators(link) {
- let no_backticks_range = range_between_backticks(ori_link);
- let disambiguator_range = (no_backticks_range.start + relative_range.start)
- ..(no_backticks_range.start + relative_range.end);
+ let disambiguator_range = match range_between_backticks(&ori_link.range, dox) {
+ MarkdownLinkRange::Destination(no_backticks_range) => {
+ MarkdownLinkRange::Destination(
+ (no_backticks_range.start + relative_range.start)
+ ..(no_backticks_range.start + relative_range.end),
+ )
+ }
+ mdlr @ MarkdownLinkRange::WholeLink(_) => mdlr,
+ };
return Some(Err(PreprocessingError::Disambiguator(disambiguator_range, err_msg)));
} else {
return None;
@@ -944,7 +954,7 @@ fn preprocess_link(
fn preprocessed_markdown_links(s: &str) -> Vec<PreprocessedMarkdownLink> {
markdown_links(s, |link| {
- preprocess_link(&link).map(|pp_link| PreprocessedMarkdownLink(pp_link, link))
+ preprocess_link(&link, s).map(|pp_link| PreprocessedMarkdownLink(pp_link, link))
})
}
@@ -1057,22 +1067,12 @@ impl LinkCollector<'_, '_> {
// valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
// for discussion on the matter.
let kind = self.cx.tcx.def_kind(id);
- self.verify_disambiguator(
- path_str,
- ori_link,
- kind,
- id,
- disambiguator,
- item,
- &diag_info,
- )?;
+ self.verify_disambiguator(path_str, kind, id, disambiguator, item, &diag_info)?;
} else {
match disambiguator {
Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
Some(other) => {
- self.report_disambiguator_mismatch(
- path_str, ori_link, other, res, &diag_info,
- );
+ self.report_disambiguator_mismatch(path_str, other, res, &diag_info);
return None;
}
}
@@ -1093,7 +1093,6 @@ impl LinkCollector<'_, '_> {
};
self.verify_disambiguator(
path_str,
- ori_link,
kind_for_dis,
id_for_dis,
disambiguator,
@@ -1115,7 +1114,6 @@ impl LinkCollector<'_, '_> {
fn verify_disambiguator(
&self,
path_str: &str,
- ori_link: &MarkdownLink,
kind: DefKind,
id: DefId,
disambiguator: Option<Disambiguator>,
@@ -1139,7 +1137,7 @@ impl LinkCollector<'_, '_> {
=> {}
(actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
(_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
- self.report_disambiguator_mismatch(path_str,ori_link,specified, Res::Def(kind, id),diag_info);
+ self.report_disambiguator_mismatch(path_str, specified, Res::Def(kind, id), diag_info);
return None;
}
}
@@ -1161,14 +1159,13 @@ impl LinkCollector<'_, '_> {
fn report_disambiguator_mismatch(
&self,
path_str: &str,
- ori_link: &MarkdownLink,
specified: Disambiguator,
resolved: Res,
diag_info: &DiagnosticInfo<'_>,
) {
// The resolved item did not match the disambiguator; give a better error than 'not found'
let msg = format!("incompatible link kind for `{}`", path_str);
- let callback = |diag: &mut Diagnostic, sp: Option<rustc_span::Span>| {
+ let callback = |diag: &mut Diagnostic, sp: Option<rustc_span::Span>, link_range| {
let note = format!(
"this link resolved to {} {}, which is not {} {}",
resolved.article(),
@@ -1177,18 +1174,28 @@ impl LinkCollector<'_, '_> {
specified.descr(),
);
if let Some(sp) = sp {
- diag.span_label(sp, &note);
+ diag.span_label(sp, note);
} else {
- diag.note(&note);
+ diag.note(note);
}
- suggest_disambiguator(resolved, diag, path_str, &ori_link.link, sp);
+ suggest_disambiguator(resolved, diag, path_str, link_range, sp, diag_info);
};
- report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, callback);
+ report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, callback);
}
- fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &Range<usize>, item: &Item) {
- let span = super::source_span_for_markdown_range(self.cx.tcx, dox, ori_link, &item.attrs)
- .unwrap_or_else(|| item.attr_span(self.cx.tcx));
+ fn report_rawptr_assoc_feature_gate(
+ &self,
+ dox: &str,
+ ori_link: &MarkdownLinkRange,
+ item: &Item,
+ ) {
+ let span = super::source_span_for_markdown_range(
+ self.cx.tcx,
+ dox,
+ ori_link.inner_range(),
+ &item.attrs,
+ )
+ .unwrap_or_else(|| item.attr_span(self.cx.tcx));
rustc_session::parse::feature_err(
&self.cx.tcx.sess.parse_sess,
sym::intra_doc_pointers,
@@ -1293,7 +1300,8 @@ impl LinkCollector<'_, '_> {
}
}
}
- resolution_failure(self, diag, path_str, disambiguator, smallvec![err])
+ resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+ return vec![];
}
}
}
@@ -1329,13 +1337,14 @@ impl LinkCollector<'_, '_> {
.fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
if len == 0 {
- return resolution_failure(
+ resolution_failure(
self,
diag,
path_str,
disambiguator,
candidates.into_iter().filter_map(|res| res.err()).collect(),
);
+ return vec![];
} else if len == 1 {
candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
} else {
@@ -1349,7 +1358,7 @@ impl LinkCollector<'_, '_> {
if has_derive_trait_collision {
candidates.macro_ns = None;
}
- candidates.into_iter().filter_map(|res| res).flatten().collect::<Vec<_>>()
+ candidates.into_iter().flatten().flatten().collect::<Vec<_>>()
}
}
}
@@ -1366,16 +1375,23 @@ impl LinkCollector<'_, '_> {
/// [`Foo`]
/// ^^^
/// ```
-fn range_between_backticks(ori_link: &MarkdownLink) -> Range<usize> {
- let after_first_backtick_group = ori_link.link.bytes().position(|b| b != b'`').unwrap_or(0);
- let before_second_backtick_group = ori_link
- .link
+///
+/// This function does nothing if `ori_link.range` is a `MarkdownLinkRange::WholeLink`.
+fn range_between_backticks(ori_link_range: &MarkdownLinkRange, dox: &str) -> MarkdownLinkRange {
+ let range = match ori_link_range {
+ mdlr @ MarkdownLinkRange::WholeLink(_) => return mdlr.clone(),
+ MarkdownLinkRange::Destination(inner) => inner.clone(),
+ };
+ let ori_link_text = &dox[range.clone()];
+ let after_first_backtick_group = ori_link_text.bytes().position(|b| b != b'`').unwrap_or(0);
+ let before_second_backtick_group = ori_link_text
.bytes()
.skip(after_first_backtick_group)
.position(|b| b == b'`')
- .unwrap_or(ori_link.link.len());
- (ori_link.range.start + after_first_backtick_group)
- ..(ori_link.range.start + before_second_backtick_group)
+ .unwrap_or(ori_link_text.len());
+ MarkdownLinkRange::Destination(
+ (range.start + after_first_backtick_group)..(range.start + before_second_backtick_group),
+ )
}
/// Returns true if we should ignore `link` due to it being unlikely
@@ -1419,6 +1435,7 @@ impl Disambiguator {
if let Some(idx) = link.find('@') {
let (prefix, rest) = link.split_at(idx);
let d = match prefix {
+ // If you update this list, please also update the relevant rustdoc book section!
"struct" => Kind(DefKind::Struct),
"enum" => Kind(DefKind::Enum),
"trait" => Kind(DefKind::Trait),
@@ -1437,6 +1454,7 @@ impl Disambiguator {
Ok(Some((d, &rest[1..], &rest[1..])))
} else {
let suffixes = [
+ // If you update this list, please also update the relevant rustdoc book section!
("!()", DefKind::Macro(MacroKind::Bang)),
("!{}", DefKind::Macro(MacroKind::Bang)),
("![]", DefKind::Macro(MacroKind::Bang)),
@@ -1523,14 +1541,23 @@ impl Suggestion {
sp: rustc_span::Span,
) -> Vec<(rustc_span::Span, String)> {
let inner_sp = match ori_link.find('(') {
+ Some(index) if index != 0 && ori_link.as_bytes()[index - 1] == b'\\' => {
+ sp.with_hi(sp.lo() + BytePos((index - 1) as _))
+ }
Some(index) => sp.with_hi(sp.lo() + BytePos(index as _)),
None => sp,
};
let inner_sp = match ori_link.find('!') {
+ Some(index) if index != 0 && ori_link.as_bytes()[index - 1] == b'\\' => {
+ sp.with_hi(sp.lo() + BytePos((index - 1) as _))
+ }
Some(index) => inner_sp.with_hi(inner_sp.lo() + BytePos(index as _)),
None => inner_sp,
};
let inner_sp = match ori_link.find('@') {
+ Some(index) if index != 0 && ori_link.as_bytes()[index - 1] == b'\\' => {
+ sp.with_hi(sp.lo() + BytePos((index - 1) as _))
+ }
Some(index) => inner_sp.with_lo(inner_sp.lo() + BytePos(index as u32 + 1)),
None => inner_sp,
};
@@ -1575,9 +1602,9 @@ impl Suggestion {
fn report_diagnostic(
tcx: TyCtxt<'_>,
lint: &'static Lint,
- msg: &str,
+ msg: impl Into<DiagnosticMessage> + Display,
DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
- decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>),
+ decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>, MarkdownLinkRange),
) {
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
else {
@@ -1589,16 +1616,32 @@ fn report_diagnostic(
let sp = item.attr_span(tcx);
tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |lint| {
- let span =
- super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| {
- if dox.as_bytes().get(link_range.start) == Some(&b'`')
- && dox.as_bytes().get(link_range.end - 1) == Some(&b'`')
- {
- sp.with_lo(sp.lo() + BytePos(1)).with_hi(sp.hi() - BytePos(1))
- } else {
- sp
- }
- });
+ let (span, link_range) = match link_range {
+ MarkdownLinkRange::Destination(md_range) => {
+ let mut md_range = md_range.clone();
+ let sp = super::source_span_for_markdown_range(tcx, dox, &md_range, &item.attrs)
+ .map(|mut sp| {
+ while dox.as_bytes().get(md_range.start) == Some(&b' ')
+ || dox.as_bytes().get(md_range.start) == Some(&b'`')
+ {
+ md_range.start += 1;
+ sp = sp.with_lo(sp.lo() + BytePos(1));
+ }
+ while dox.as_bytes().get(md_range.end - 1) == Some(&b' ')
+ || dox.as_bytes().get(md_range.end - 1) == Some(&b'`')
+ {
+ md_range.end -= 1;
+ sp = sp.with_hi(sp.hi() - BytePos(1));
+ }
+ sp
+ });
+ (sp, MarkdownLinkRange::Destination(md_range))
+ }
+ MarkdownLinkRange::WholeLink(md_range) => (
+ super::source_span_for_markdown_range(tcx, dox, &md_range, &item.attrs),
+ link_range.clone(),
+ ),
+ };
if let Some(sp) = span {
lint.set_span(sp);
@@ -1607,21 +1650,22 @@ fn report_diagnostic(
// ^ ~~~~
// | link_range
// last_new_line_offset
- let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+ let md_range = link_range.inner_range().clone();
+ let last_new_line_offset = dox[..md_range.start].rfind('\n').map_or(0, |n| n + 1);
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
- // Print the line containing the `link_range` and manually mark it with '^'s.
- lint.note(&format!(
+ // Print the line containing the `md_range` and manually mark it with '^'s.
+ lint.note(format!(
"the link appears in this line:\n\n{line}\n\
{indicator: <before$}{indicator:^<found$}",
line = line,
indicator = "",
- before = link_range.start - last_new_line_offset,
- found = link_range.len(),
+ before = md_range.start - last_new_line_offset,
+ found = md_range.len(),
));
}
- decorate(lint, span);
+ decorate(lint, span, link_range);
lint
});
@@ -1638,15 +1682,14 @@ fn resolution_failure(
path_str: &str,
disambiguator: Option<Disambiguator>,
kinds: SmallVec<[ResolutionFailure<'_>; 3]>,
-) -> Vec<(Res, Option<DefId>)> {
+) {
let tcx = collector.cx.tcx;
- let mut recovered_res = None;
report_diagnostic(
tcx,
BROKEN_INTRA_DOC_LINKS,
- &format!("unresolved link to `{}`", path_str),
+ format!("unresolved link to `{}`", path_str),
&diag_info,
- |diag, sp| {
+ |diag, sp, link_range| {
let item = |res: Res| format!("the {} `{}`", res.descr(), res.name(tcx),);
let assoc_item_not_allowed = |res: Res| {
let name = res.name(tcx);
@@ -1700,7 +1743,7 @@ fn resolution_failure(
if let Ok(v_res) = collector.resolve(start, ns, item_id, module_id) {
debug!("found partial_res={:?}", v_res);
if !v_res.is_empty() {
- *partial_res = Some(full_res(collector.cx.tcx, v_res[0]));
+ *partial_res = Some(full_res(tcx, v_res[0]));
*unresolved = end.into();
break 'outer;
}
@@ -1725,26 +1768,32 @@ fn resolution_failure(
format!("no item named `{}` in scope", unresolved)
};
if let Some(span) = sp {
- diag.span_label(span, &note);
+ diag.span_label(span, note);
} else {
- diag.note(&note);
+ diag.note(note);
}
if !path_str.contains("::") {
if disambiguator.map_or(true, |d| d.ns() == MacroNS)
- && let Some(&res) = collector.cx.tcx.resolutions(()).all_macro_rules
- .get(&Symbol::intern(path_str))
+ && collector
+ .cx
+ .tcx
+ .resolutions(())
+ .all_macro_rules
+ .get(&Symbol::intern(path_str))
+ .is_some()
{
diag.note(format!(
"`macro_rules` named `{path_str}` exists in this crate, \
but it is not in scope at this link's location"
));
- recovered_res = res.try_into().ok().map(|res| (res, None));
} else {
// If the link has `::` in it, assume it was meant to be an
// intra-doc link. Otherwise, the `[]` might be unrelated.
- diag.help("to escape `[` and `]` characters, \
- add '\\' before them like `\\[` or `\\]`");
+ diag.help(
+ "to escape `[` and `]` characters, \
+ add '\\' before them like `\\[` or `\\]`",
+ );
}
}
@@ -1776,9 +1825,9 @@ fn resolution_failure(
let variant = res.name(tcx);
let note = format!("variant `{variant}` has no such field");
if let Some(span) = sp {
- diag.span_label(span, &note);
+ diag.span_label(span, note);
} else {
- diag.note(&note);
+ diag.note(note);
}
return;
}
@@ -1801,9 +1850,9 @@ fn resolution_failure(
| InlineConst => {
let note = assoc_item_not_allowed(res);
if let Some(span) = sp {
- diag.span_label(span, &note);
+ diag.span_label(span, note);
} else {
- diag.note(&note);
+ diag.note(note);
}
return;
}
@@ -1823,9 +1872,9 @@ fn resolution_failure(
unresolved,
);
if let Some(span) = sp {
- diag.span_label(span, &note);
+ diag.span_label(span, note);
} else {
- diag.note(&note);
+ diag.note(note);
}
continue;
@@ -1833,7 +1882,14 @@ fn resolution_failure(
let note = match failure {
ResolutionFailure::NotResolved { .. } => unreachable!("handled above"),
ResolutionFailure::WrongNamespace { res, expected_ns } => {
- suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
+ suggest_disambiguator(
+ res,
+ diag,
+ path_str,
+ link_range.clone(),
+ sp,
+ &diag_info,
+ );
format!(
"this link resolves to {}, which is not in the {} namespace",
@@ -1843,39 +1899,34 @@ fn resolution_failure(
}
};
if let Some(span) = sp {
- diag.span_label(span, &note);
+ diag.span_label(span, note);
} else {
- diag.note(&note);
+ diag.note(note);
}
}
},
);
-
- match recovered_res {
- Some(r) => vec![r],
- None => Vec::new(),
- }
}
fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
let msg = format!("`{}` contains multiple anchors", diag_info.ori_link);
- anchor_failure(cx, diag_info, &msg, 1)
+ anchor_failure(cx, diag_info, msg, 1)
}
fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, def_id: DefId) {
let (link, kind) = (diag_info.ori_link, Res::from_def_id(cx.tcx, def_id).descr());
let msg = format!("`{link}` contains an anchor, but links to {kind}s are already anchored");
- anchor_failure(cx, diag_info, &msg, 0)
+ anchor_failure(cx, diag_info, msg, 0)
}
/// Report an anchor failure.
fn anchor_failure(
cx: &DocContext<'_>,
diag_info: DiagnosticInfo<'_>,
- msg: &str,
+ msg: String,
anchor_idx: usize,
) {
- report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, sp| {
+ report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, sp, _link_range| {
if let Some(mut sp) = sp {
if let Some((fragment_offset, _)) =
diag_info.ori_link.char_indices().filter(|(_, x)| *x == '#').nth(anchor_idx)
@@ -1891,16 +1942,16 @@ fn anchor_failure(
fn disambiguator_error(
cx: &DocContext<'_>,
mut diag_info: DiagnosticInfo<'_>,
- disambiguator_range: Range<usize>,
- msg: &str,
+ disambiguator_range: MarkdownLinkRange,
+ msg: impl Into<DiagnosticMessage> + Display,
) {
diag_info.link_range = disambiguator_range;
- report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
+ report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp, _link_range| {
let msg = format!(
"see {}/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators",
crate::DOC_RUST_LANG_ORG_CHANNEL
);
- diag.note(&msg);
+ diag.note(msg);
});
}
@@ -1913,9 +1964,9 @@ fn report_malformed_generics(
report_diagnostic(
cx.tcx,
BROKEN_INTRA_DOC_LINKS,
- &format!("unresolved link to `{}`", path_str),
+ format!("unresolved link to `{}`", path_str),
&diag_info,
- |diag, sp| {
+ |diag, sp, _link_range| {
let note = match err {
MalformedGenerics::UnbalancedAngleBrackets => "unbalanced angle brackets",
MalformedGenerics::MissingType => "missing type for generic parameters",
@@ -1988,7 +2039,7 @@ fn ambiguity_error(
}
}
- report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
+ report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, |diag, sp, link_range| {
if let Some(sp) = sp {
diag.span_label(sp, "ambiguous link");
} else {
@@ -1996,7 +2047,7 @@ fn ambiguity_error(
}
for res in kinds {
- suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
+ suggest_disambiguator(res, diag, path_str, link_range.clone(), sp, diag_info);
}
});
true
@@ -2008,22 +2059,28 @@ fn suggest_disambiguator(
res: Res,
diag: &mut Diagnostic,
path_str: &str,
- ori_link: &str,
+ link_range: MarkdownLinkRange,
sp: Option<rustc_span::Span>,
+ diag_info: &DiagnosticInfo<'_>,
) {
let suggestion = res.disambiguator_suggestion();
let help = format!("to link to the {}, {}", res.descr(), suggestion.descr());
- if let Some(sp) = sp {
+ let ori_link = match link_range {
+ MarkdownLinkRange::Destination(range) => Some(&diag_info.dox[range]),
+ MarkdownLinkRange::WholeLink(_) => None,
+ };
+
+ if let (Some(sp), Some(ori_link)) = (sp, ori_link) {
let mut spans = suggestion.as_help_span(path_str, ori_link, sp);
if spans.len() > 1 {
- diag.multipart_suggestion(&help, spans, Applicability::MaybeIncorrect);
+ diag.multipart_suggestion(help, spans, Applicability::MaybeIncorrect);
} else {
let (sp, suggestion_text) = spans.pop().unwrap();
- diag.span_suggestion_verbose(sp, &help, suggestion_text, Applicability::MaybeIncorrect);
+ diag.span_suggestion_verbose(sp, help, suggestion_text, Applicability::MaybeIncorrect);
}
} else {
- diag.help(&format!("{}: {}", help, suggestion.as_help(path_str)));
+ diag.help(format!("{}: {}", help, suggestion.as_help(path_str)));
}
}
@@ -2040,7 +2097,7 @@ fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str:
let msg =
format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
- report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
+ report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, msg, diag_info, |diag, sp, _link_range| {
if let Some(sp) = sp {
diag.span_label(sp, "this item is private");
}
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 8d204ddb7..fbf827cce 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -19,9 +19,10 @@ pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass {
};
pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+ let tcx = cx.tcx;
// We need to check if there are errors before running this pass because it would crash when
// we try to get auto and blanket implementations.
- if cx.tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
+ if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
return krate;
}
@@ -32,8 +33,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
});
let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
- let prims: FxHashSet<PrimitiveType> =
- local_crate.primitives(cx.tcx).iter().map(|p| p.1).collect();
+ let prims: FxHashSet<PrimitiveType> = local_crate.primitives(tcx).iter().map(|p| p.1).collect();
let crate_items = {
let mut coll = ItemCollector::new();
@@ -46,9 +46,9 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
// External trait impls.
{
- let _prof_timer = cx.tcx.sess.prof.generic_activity("build_extern_trait_impls");
- for &cnum in cx.tcx.crates(()) {
- for &impl_def_id in cx.tcx.trait_impls_in_crate(cnum) {
+ let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls");
+ for &cnum in tcx.crates(()) {
+ for &impl_def_id in tcx.trait_impls_in_crate(cnum) {
inline::build_impl(cx, impl_def_id, None, &mut new_items_external);
}
}
@@ -56,14 +56,13 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
// Local trait impls.
{
- let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls");
+ let _prof_timer = tcx.sess.prof.generic_activity("build_local_trait_impls");
let mut attr_buf = Vec::new();
- for &impl_def_id in cx.tcx.trait_impls_in_crate(LOCAL_CRATE) {
- let mut parent = Some(cx.tcx.parent(impl_def_id));
+ for &impl_def_id in tcx.trait_impls_in_crate(LOCAL_CRATE) {
+ let mut parent = Some(tcx.parent(impl_def_id));
while let Some(did) = parent {
attr_buf.extend(
- cx.tcx
- .get_attrs(did, sym::doc)
+ tcx.get_attrs(did, sym::doc)
.filter(|attr| {
if let Some([attr]) = attr.meta_item_list().as_deref() {
attr.has_name(sym::cfg)
@@ -73,25 +72,24 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
})
.cloned(),
);
- parent = cx.tcx.opt_parent(did);
+ parent = tcx.opt_parent(did);
}
inline::build_impl(cx, impl_def_id, Some((&attr_buf, None)), &mut new_items_local);
attr_buf.clear();
}
}
- cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
- for def_id in PrimitiveType::all_impls(cx.tcx) {
+ tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
+ for def_id in PrimitiveType::all_impls(tcx) {
// Try to inline primitive impls from other crates.
if !def_id.is_local() {
inline::build_impl(cx, def_id, None, &mut new_items_external);
}
}
- for (prim, did) in PrimitiveType::primitive_locations(cx.tcx) {
+ for (prim, did) in PrimitiveType::primitive_locations(tcx) {
// Do not calculate blanket impl list for docs that are not going to be rendered.
// While the `impl` blocks themselves are only in `libcore`, the module with `doc`
// attached is directly included in `libstd` as well.
- let tcx = cx.tcx;
if did.is_local() {
for def_id in prim.impls(tcx).filter(|def_id| {
// Avoid including impl blocks with filled-in generics.
@@ -157,7 +155,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
for it in new_items_external.iter().chain(new_items_local.iter()) {
if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind &&
- trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() &&
+ trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() &&
cleaner.keep_impl(for_, true)
{
let target = items
@@ -199,7 +197,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
cleaner.keep_impl(
for_,
- trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(),
+ trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(),
) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into()))
|| kind.is_blanket()
} else {
diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs
index 97031c4f0..e653207b9 100644
--- a/src/librustdoc/passes/lint.rs
+++ b/src/librustdoc/passes/lint.rs
@@ -4,6 +4,7 @@
mod bare_urls;
mod check_code_block_syntax;
mod html_tags;
+mod unescaped_backticks;
use super::Pass;
use crate::clean::*;
@@ -27,6 +28,7 @@ impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> {
bare_urls::visit_item(self.cx, item);
check_code_block_syntax::visit_item(self.cx, item);
html_tags::visit_item(self.cx, item);
+ unescaped_backticks::visit_item(self.cx, item);
self.visit_item_recur(item)
}
diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs
index 423230cfe..a10d5fdb4 100644
--- a/src/librustdoc/passes/lint/bare_urls.rs
+++ b/src/librustdoc/passes/lint/bare_urls.rs
@@ -18,7 +18,7 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) {
// If non-local, no need to check anything.
return;
};
- let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
+ let dox = item.doc_value();
if !dox.is_empty() {
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 26fbb03a4..f489f5081 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -17,7 +17,7 @@ use crate::html::markdown::{self, RustCodeBlock};
use crate::passes::source_span_for_markdown_range;
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) {
- if let Some(dox) = &item.attrs.collapsed_doc_value() {
+ if let Some(dox) = &item.opt_doc_value() {
let sp = item.attr_span(cx.tcx);
let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp);
for code_block in markdown::rust_code_blocks(dox, &extra) {
@@ -108,7 +108,7 @@ fn check_rust_syntax(
// just give a `help` instead.
lint.span_help(
sp.from_inner(InnerSpan::new(0, 3)),
- &format!("{}: ```text", explanation),
+ format!("{}: ```text", explanation),
);
} else if empty_block {
lint.span_suggestion(
@@ -119,12 +119,12 @@ fn check_rust_syntax(
);
}
} else if empty_block || is_ignore {
- lint.help(&format!("{}: ```text", explanation));
+ lint.help(format!("{}: ```text", explanation));
}
// FIXME(#67563): Provide more context for these errors by displaying the spans inline.
for message in buffer.messages.iter() {
- lint.note(message);
+ lint.note(message.clone());
}
lint
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 4f72df5a5..f0403647a 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -15,7 +15,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
// If non-local, no need to check anything.
else { return };
- let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
+ let dox = item.doc_value();
if !dox.is_empty() {
let report_diag = |msg: &str, range: &Range<usize>, is_open_tag: bool| {
let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs) {
diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs
new file mode 100644
index 000000000..865212205
--- /dev/null
+++ b/src/librustdoc/passes/lint/unescaped_backticks.rs
@@ -0,0 +1,416 @@
+//! Detects unescaped backticks (\`) in doc comments.
+
+use crate::clean::Item;
+use crate::core::DocContext;
+use crate::html::markdown::main_body_opts;
+use crate::passes::source_span_for_markdown_range;
+use pulldown_cmark::{BrokenLink, Event, Parser};
+use rustc_errors::DiagnosticBuilder;
+use rustc_lint_defs::Applicability;
+use std::ops::Range;
+
+pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
+ let tcx = cx.tcx;
+ let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) else {
+ // If non-local, no need to check anything.
+ return;
+ };
+
+ let dox = item.doc_value();
+ if dox.is_empty() {
+ return;
+ }
+
+ let link_names = item.link_names(&cx.cache);
+ let mut replacer = |broken_link: BrokenLink<'_>| {
+ link_names
+ .iter()
+ .find(|link| *link.original_text == *broken_link.reference)
+ .map(|link| ((*link.href).into(), (*link.new_text).into()))
+ };
+ let parser = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer))
+ .into_offset_iter();
+
+ let mut element_stack = Vec::new();
+
+ let mut prev_text_end = 0;
+ for (event, event_range) in parser {
+ match event {
+ Event::Start(_) => {
+ element_stack.push(Element::new(event_range));
+ }
+ Event::End(_) => {
+ let element = element_stack.pop().unwrap();
+
+ let Some(backtick_index) = element.backtick_index else {
+ continue;
+ };
+
+ // If we can't get a span of the backtick, because it is in a `#[doc = ""]` attribute,
+ // use the span of the entire attribute as a fallback.
+ let span = source_span_for_markdown_range(
+ tcx,
+ &dox,
+ &(backtick_index..backtick_index + 1),
+ &item.attrs,
+ )
+ .unwrap_or_else(|| item.attr_span(tcx));
+
+ tcx.struct_span_lint_hir(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| {
+ let mut help_emitted = false;
+
+ match element.prev_code_guess {
+ PrevCodeGuess::None => {}
+ PrevCodeGuess::Start { guess, .. } => {
+ // "foo` `bar`" -> "`foo` `bar`"
+ if let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges)
+ && can_suggest_backtick(&dox, suggest_index)
+ {
+ suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the opening backtick of a previous inline code may be missing");
+ help_emitted = true;
+ }
+ }
+ PrevCodeGuess::End { guess, .. } => {
+ // "`foo `bar`" -> "`foo` `bar`"
+ // Don't `clamp_end` here, because the suggestion is guaranteed to be inside
+ // an inline code node and we intentionally "break" the inline code here.
+ let suggest_index = guess;
+ if can_suggest_backtick(&dox, suggest_index) {
+ suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "a previous inline code might be longer than expected");
+ help_emitted = true;
+ }
+ }
+ }
+
+ if !element.prev_code_guess.is_confident() {
+ // "`foo` bar`" -> "`foo` `bar`"
+ if let Some(guess) = guess_start_of_code(&dox, element.element_range.start..backtick_index)
+ && let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges)
+ && can_suggest_backtick(&dox, suggest_index)
+ {
+ suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the opening backtick of an inline code may be missing");
+ help_emitted = true;
+ }
+
+ // "`foo` `bar" -> "`foo` `bar`"
+ // Don't suggest closing backtick after single trailing char,
+ // if we already suggested opening backtick. For example:
+ // "foo`." -> "`foo`." or "foo`s" -> "`foo`s".
+ if let Some(guess) = guess_end_of_code(&dox, backtick_index + 1..element.element_range.end)
+ && let Some(suggest_index) = clamp_end(guess, &element.suggestible_ranges)
+ && can_suggest_backtick(&dox, suggest_index)
+ && (!help_emitted || suggest_index - backtick_index > 2)
+ {
+ suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the closing backtick of an inline code may be missing");
+ help_emitted = true;
+ }
+ }
+
+ if !help_emitted {
+ lint.help("the opening or closing backtick of an inline code may be missing");
+ }
+
+ suggest_insertion(cx, item, &dox, lint, backtick_index, '\\', "if you meant to use a literal backtick, escape it");
+
+ lint
+ });
+ }
+ Event::Code(_) => {
+ let element = element_stack
+ .last_mut()
+ .expect("expected inline code node to be inside of an element");
+ assert!(
+ event_range.start >= element.element_range.start
+ && event_range.end <= element.element_range.end
+ );
+
+ // This inline code might be longer than it's supposed to be.
+ // Only check single backtick inline code for now.
+ if !element.prev_code_guess.is_confident()
+ && dox.as_bytes().get(event_range.start) == Some(&b'`')
+ && dox.as_bytes().get(event_range.start + 1) != Some(&b'`')
+ {
+ let range_inside = event_range.start + 1..event_range.end - 1;
+ let text_inside = &dox[range_inside.clone()];
+
+ let is_confident = text_inside.starts_with(char::is_whitespace)
+ || text_inside.ends_with(char::is_whitespace);
+
+ if let Some(guess) = guess_end_of_code(&dox, range_inside) {
+ // Find earlier end of code.
+ element.prev_code_guess = PrevCodeGuess::End { guess, is_confident };
+ } else {
+ // Find alternate start of code.
+ let range_before = element.element_range.start..event_range.start;
+ if let Some(guess) = guess_start_of_code(&dox, range_before) {
+ element.prev_code_guess = PrevCodeGuess::Start { guess, is_confident };
+ }
+ }
+ }
+ }
+ Event::Text(text) => {
+ let element = element_stack
+ .last_mut()
+ .expect("expected inline text node to be inside of an element");
+ assert!(
+ event_range.start >= element.element_range.start
+ && event_range.end <= element.element_range.end
+ );
+
+ // The first char is escaped if the prev char is \ and not part of a text node.
+ let is_escaped = prev_text_end < event_range.start
+ && dox.as_bytes()[event_range.start - 1] == b'\\';
+
+ // Don't lint backslash-escaped (\`) or html-escaped (&#96;) backticks.
+ if *text == *"`" && !is_escaped && *text == dox[event_range.clone()] {
+ // We found a stray backtick.
+ assert!(
+ element.backtick_index.is_none(),
+ "expected at most one unescaped backtick per element",
+ );
+ element.backtick_index = Some(event_range.start);
+ }
+
+ prev_text_end = event_range.end;
+
+ if is_escaped {
+ // Ensure that we suggest "`\x" and not "\`x".
+ element.suggestible_ranges.push(event_range.start - 1..event_range.end);
+ } else {
+ element.suggestible_ranges.push(event_range);
+ }
+ }
+ _ => {}
+ }
+ }
+}
+
+/// A previous inline code node, that looks wrong.
+///
+/// `guess` is the position, where we want to suggest a \` and the guess `is_confident` if an
+/// inline code starts or ends with a whitespace.
+#[derive(Debug)]
+enum PrevCodeGuess {
+ None,
+
+ /// Missing \` at start.
+ ///
+ /// ```markdown
+ /// foo` `bar`
+ /// ```
+ Start {
+ guess: usize,
+ is_confident: bool,
+ },
+
+ /// Missing \` at end.
+ ///
+ /// ```markdown
+ /// `foo `bar`
+ /// ```
+ End {
+ guess: usize,
+ is_confident: bool,
+ },
+}
+
+impl PrevCodeGuess {
+ fn is_confident(&self) -> bool {
+ match *self {
+ PrevCodeGuess::None => false,
+ PrevCodeGuess::Start { is_confident, .. } | PrevCodeGuess::End { is_confident, .. } => {
+ is_confident
+ }
+ }
+ }
+}
+
+/// A markdown [tagged element], which may or may not contain an unescaped backtick.
+///
+/// [tagged element]: https://docs.rs/pulldown-cmark/0.9/pulldown_cmark/enum.Tag.html
+#[derive(Debug)]
+struct Element {
+ /// The full range (span) of the element in the doc string.
+ element_range: Range<usize>,
+
+ /// The ranges where we're allowed to put backticks.
+ /// This is used to prevent breaking markdown elements like links or lists.
+ suggestible_ranges: Vec<Range<usize>>,
+
+ /// The unescaped backtick.
+ backtick_index: Option<usize>,
+
+ /// Suggest a different start or end of an inline code.
+ prev_code_guess: PrevCodeGuess,
+}
+
+impl Element {
+ const fn new(element_range: Range<usize>) -> Self {
+ Self {
+ element_range,
+ suggestible_ranges: Vec::new(),
+ backtick_index: None,
+ prev_code_guess: PrevCodeGuess::None,
+ }
+ }
+}
+
+/// Given a potentially unclosed inline code, attempt to find the start.
+fn guess_start_of_code(dox: &str, range: Range<usize>) -> Option<usize> {
+ assert!(dox.as_bytes()[range.end] == b'`');
+
+ let mut braces = 0;
+ let mut guess = 0;
+ for (idx, ch) in dox[range.clone()].char_indices().rev() {
+ match ch {
+ ')' | ']' | '}' => braces += 1,
+ '(' | '[' | '{' => {
+ if braces == 0 {
+ guess = idx + 1;
+ break;
+ }
+ braces -= 1;
+ }
+ ch if ch.is_whitespace() && braces == 0 => {
+ guess = idx + 1;
+ break;
+ }
+ _ => (),
+ }
+ }
+
+ guess += range.start;
+
+ // Don't suggest empty inline code or duplicate backticks.
+ can_suggest_backtick(dox, guess).then_some(guess)
+}
+
+/// Given a potentially unclosed inline code, attempt to find the end.
+fn guess_end_of_code(dox: &str, range: Range<usize>) -> Option<usize> {
+ // Punctuation that should be outside of the inline code.
+ const TRAILING_PUNCTUATION: &[u8] = b".,";
+
+ assert!(dox.as_bytes()[range.start - 1] == b'`');
+
+ let text = dox[range.clone()].trim_end();
+ let mut braces = 0;
+ let mut guess = text.len();
+ for (idx, ch) in text.char_indices() {
+ match ch {
+ '(' | '[' | '{' => braces += 1,
+ ')' | ']' | '}' => {
+ if braces == 0 {
+ guess = idx;
+ break;
+ }
+ braces -= 1;
+ }
+ ch if ch.is_whitespace() && braces == 0 => {
+ guess = idx;
+ break;
+ }
+ _ => (),
+ }
+ }
+
+ // Strip a single trailing punctuation.
+ if guess >= 1
+ && TRAILING_PUNCTUATION.contains(&text.as_bytes()[guess - 1])
+ && (guess < 2 || !TRAILING_PUNCTUATION.contains(&text.as_bytes()[guess - 2]))
+ {
+ guess -= 1;
+ }
+
+ guess += range.start;
+
+ // Don't suggest empty inline code or duplicate backticks.
+ can_suggest_backtick(dox, guess).then_some(guess)
+}
+
+/// Returns whether inserting a backtick at `dox[index]` will not produce double backticks.
+fn can_suggest_backtick(dox: &str, index: usize) -> bool {
+ (index == 0 || dox.as_bytes()[index - 1] != b'`')
+ && (index == dox.len() || dox.as_bytes()[index] != b'`')
+}
+
+/// Increase the index until it is inside or one past the end of one of the ranges.
+///
+/// The ranges must be sorted for this to work correctly.
+fn clamp_start(index: usize, ranges: &[Range<usize>]) -> Option<usize> {
+ for range in ranges {
+ if range.start >= index {
+ return Some(range.start);
+ }
+ if index <= range.end {
+ return Some(index);
+ }
+ }
+ None
+}
+
+/// Decrease the index until it is inside or one past the end of one of the ranges.
+///
+/// The ranges must be sorted for this to work correctly.
+fn clamp_end(index: usize, ranges: &[Range<usize>]) -> Option<usize> {
+ for range in ranges.iter().rev() {
+ if range.end <= index {
+ return Some(range.end);
+ }
+ if index >= range.start {
+ return Some(index);
+ }
+ }
+ None
+}
+
+/// Try to emit a span suggestion and fall back to help messages if we can't find a suitable span.
+///
+/// This helps finding backticks in huge macro-generated docs.
+fn suggest_insertion(
+ cx: &DocContext<'_>,
+ item: &Item,
+ dox: &str,
+ lint: &mut DiagnosticBuilder<'_, ()>,
+ insert_index: usize,
+ suggestion: char,
+ message: &str,
+) {
+ /// Maximum bytes of context to show around the insertion.
+ const CONTEXT_MAX_LEN: usize = 80;
+
+ if let Some(span) =
+ source_span_for_markdown_range(cx.tcx, &dox, &(insert_index..insert_index), &item.attrs)
+ {
+ lint.span_suggestion(span, message, suggestion, Applicability::MaybeIncorrect);
+ } else {
+ let line_start = dox[..insert_index].rfind('\n').map_or(0, |idx| idx + 1);
+ let line_end = dox[insert_index..].find('\n').map_or(dox.len(), |idx| idx + insert_index);
+
+ let context_before_max_len = if insert_index - line_start < CONTEXT_MAX_LEN / 2 {
+ insert_index - line_start
+ } else if line_end - insert_index < CONTEXT_MAX_LEN / 2 {
+ CONTEXT_MAX_LEN - (line_end - insert_index)
+ } else {
+ CONTEXT_MAX_LEN / 2
+ };
+ let context_after_max_len = CONTEXT_MAX_LEN - context_before_max_len;
+
+ let (prefix, context_start) = if insert_index - line_start <= context_before_max_len {
+ ("", line_start)
+ } else {
+ ("...", dox.ceil_char_boundary(insert_index - context_before_max_len))
+ };
+ let (suffix, context_end) = if line_end - insert_index <= context_after_max_len {
+ ("", line_end)
+ } else {
+ ("...", dox.floor_char_boundary(insert_index + context_after_max_len))
+ };
+
+ let context_full = &dox[context_start..context_end].trim_end();
+ let context_before = &dox[context_start..insert_index];
+ let context_after = &dox[insert_index..context_end].trim_end();
+ lint.help(format!(
+ "{message}\n change: {prefix}{context_full}{suffix}\nto this: {prefix}{context_before}{suggestion}{context_after}{suffix}"
+ ));
+ }
+}
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index a688aa148..972b0c5ec 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -1,5 +1,6 @@
//! Strip all doc(hidden) items from the output.
+use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
use std::mem;
@@ -29,6 +30,7 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
update_retained: true,
tcx: cx.tcx,
is_in_hidden_item: false,
+ last_reexport: None,
};
stripper.fold_crate(krate)
};
@@ -49,13 +51,24 @@ struct Stripper<'a, 'tcx> {
update_retained: bool,
tcx: TyCtxt<'tcx>,
is_in_hidden_item: bool,
+ last_reexport: Option<LocalDefId>,
}
impl<'a, 'tcx> Stripper<'a, 'tcx> {
+ fn set_last_reexport_then_fold_item(&mut self, i: Item) -> Item {
+ let prev_from_reexport = self.last_reexport;
+ if i.inline_stmt_id.is_some() {
+ self.last_reexport = i.item_id.as_def_id().and_then(|def_id| def_id.as_local());
+ }
+ let ret = self.fold_item_recur(i);
+ self.last_reexport = prev_from_reexport;
+ ret
+ }
+
fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item {
let prev = self.is_in_hidden_item;
self.is_in_hidden_item |= is_in_hidden_item;
- let ret = self.fold_item_recur(i);
+ let ret = self.set_last_reexport_then_fold_item(i);
self.is_in_hidden_item = prev;
ret
}
@@ -64,7 +77,7 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> {
/// of `is_in_hidden_item` to `true` because the impl children inherit its visibility.
fn recurse_in_impl_or_exported_macro(&mut self, i: Item) -> Item {
let prev = mem::replace(&mut self.is_in_hidden_item, false);
- let ret = self.fold_item_recur(i);
+ let ret = self.set_last_reexport_then_fold_item(i);
self.is_in_hidden_item = prev;
ret
}
@@ -86,13 +99,20 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
if !is_impl_or_exported_macro {
is_hidden = self.is_in_hidden_item || has_doc_hidden;
if !is_hidden && i.inline_stmt_id.is_none() {
- // We don't need to check if it's coming from a reexport since the reexport itself was
- // already checked.
+ // `i.inline_stmt_id` is `Some` if the item is directly reexported. If it is, we
+ // don't need to check it, because the reexport itself was already checked.
+ //
+ // If this item is the child of a reexported module, `self.last_reexport` will be
+ // `Some` even though `i.inline_stmt_id` is `None`. Hiddenness inheritance needs to
+ // account for the possibility that an item's true parent module is hidden, but it's
+ // inlined into a visible module true. This code shouldn't be reachable if the
+ // module's reexport is itself hidden, for the same reason it doesn't need to be
+ // checked if `i.inline_stmt_id` is Some: hidden reexports are never inlined.
is_hidden = i
.item_id
.as_def_id()
.and_then(|def_id| def_id.as_local())
- .map(|def_id| inherits_doc_hidden(self.tcx, def_id))
+ .map(|def_id| inherits_doc_hidden(self.tcx, def_id, self.last_reexport))
.unwrap_or(false);
}
}
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index cba55e5fe..73fc26a6b 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -194,7 +194,7 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
})
{
return None;
- } else if imp.items.is_empty() && i.doc_value().is_none() {
+ } else if imp.items.is_empty() && i.doc_value().is_empty() {
return None;
}
}
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index f28c164d6..d2fa7769b 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -286,7 +286,7 @@ pub(crate) fn run(
let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?;
// Collect CrateIds corresponding to provided target crates
- // If two different versions of the crate in the dependency tree, then examples will be collcted from both.
+ // If two different versions of the crate in the dependency tree, then examples will be collected from both.
let all_crates = tcx
.crates(())
.iter()
@@ -331,7 +331,7 @@ pub(crate) fn run(
};
if let Err(e) = inner() {
- tcx.sess.fatal(&e);
+ tcx.sess.fatal(e);
}
Ok(())
@@ -358,7 +358,7 @@ pub(crate) fn load_call_locations(
};
inner().map_err(|e: String| {
- diag.err(&format!("failed to load examples: {}", e));
+ diag.err(format!("failed to load examples: {}", e));
1
})
}
diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs
index e7a26cb34..722e01cd1 100644
--- a/src/librustdoc/theme.rs
+++ b/src/librustdoc/theme.rs
@@ -241,7 +241,7 @@ pub(crate) fn test_theme_against<P: AsRef<Path>>(
{
Ok(c) => c,
Err(e) => {
- diag.struct_err(&e).emit();
+ diag.struct_err(e).emit();
return (false, vec![]);
}
};
diff --git a/src/librustdoc/theme/tests.rs b/src/librustdoc/theme/tests.rs
index 08a174d27..2a28c19c3 100644
--- a/src/librustdoc/theme/tests.rs
+++ b/src/librustdoc/theme/tests.rs
@@ -13,11 +13,11 @@ rule d
// another line comment
e {}
-rule f/* a multine
+rule f/* a multiline
comment*/{}
-rule g/* another multine
+rule g/* another multiline
comment*/h
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index f54b70b41..6b7ad4cf2 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,11 +5,12 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
-use rustc_hir::intravisit::{walk_item, Visitor};
+use rustc_hir::intravisit::{walk_body, walk_item, Visitor};
use rustc_hir::{Node, CRATE_HIR_ID};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
@@ -26,6 +27,8 @@ pub(crate) struct Module<'hir> {
pub(crate) where_inner: Span,
pub(crate) mods: Vec<Module<'hir>>,
pub(crate) def_id: LocalDefId,
+ pub(crate) renamed: Option<Symbol>,
+ pub(crate) import_id: Option<LocalDefId>,
/// The key is the item `ItemId` and the value is: (item, renamed, import_id).
/// We use `FxIndexMap` to keep the insert order.
pub(crate) items: FxIndexMap<
@@ -36,11 +39,19 @@ pub(crate) struct Module<'hir> {
}
impl Module<'_> {
- pub(crate) fn new(name: Symbol, def_id: LocalDefId, where_inner: Span) -> Self {
+ pub(crate) fn new(
+ name: Symbol,
+ def_id: LocalDefId,
+ where_inner: Span,
+ renamed: Option<Symbol>,
+ import_id: Option<LocalDefId>,
+ ) -> Self {
Module {
name,
def_id,
where_inner,
+ renamed,
+ import_id,
mods: Vec::new(),
items: FxIndexMap::default(),
foreigns: Vec::new(),
@@ -59,9 +70,16 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<Symbol> {
std::iter::once(crate_name).chain(relative).collect()
}
-pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: LocalDefId) -> bool {
+pub(crate) fn inherits_doc_hidden(
+ tcx: TyCtxt<'_>,
+ mut def_id: LocalDefId,
+ stop_at: Option<LocalDefId>,
+) -> bool {
let hir = tcx.hir();
while let Some(id) = tcx.opt_local_parent(def_id) {
+ if let Some(stop_at) = stop_at && id == stop_at {
+ return false;
+ }
def_id = id;
if tcx.is_doc_hidden(def_id.to_def_id()) {
return true;
@@ -87,6 +105,8 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
inside_public_path: bool,
exact_paths: DefIdMap<Vec<Symbol>>,
modules: Vec<Module<'tcx>>,
+ is_importable_from_parent: bool,
+ inside_body: bool,
}
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -98,6 +118,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
cx.tcx.crate_name(LOCAL_CRATE),
CRATE_DEF_ID,
cx.tcx.hir().root_module().spans.inner_span,
+ None,
+ None,
);
RustdocVisitor {
@@ -107,6 +129,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
inside_public_path: true,
exact_paths: Default::default(),
modules: vec![om],
+ is_importable_from_parent: true,
+ inside_body: false,
}
}
@@ -133,14 +157,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
// is declared but also a reexport of itself producing two exports of the same
// macro in the same module.
let mut inserted = FxHashSet::default();
- for export in self.cx.tcx.module_children_reexports(CRATE_DEF_ID) {
- if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
+ for child in self.cx.tcx.module_children_local(CRATE_DEF_ID) {
+ if !child.reexport_chain.is_empty() &&
+ let Res::Def(DefKind::Macro(_), def_id) = child.res &&
let Some(local_def_id) = def_id.as_local() &&
self.cx.tcx.has_attr(def_id, sym::macro_export) &&
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 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));
}
}
@@ -255,9 +280,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
return false;
};
- let is_private =
- !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did);
- let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did);
+ let is_private = !self.cx.cache.effective_visibilities.is_directly_public(tcx, ori_res_did);
+ let is_hidden = inherits_doc_hidden(tcx, res_did, None);
// Only inline if requested or if the item would otherwise be stripped.
if (!please_inline && !is_private && !is_hidden) || is_no_inline {
@@ -265,7 +289,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
if !please_inline &&
- let Some(item_def_id) = reexport_chain(self.cx.tcx, def_id, res_did).iter()
+ let Some(item_def_id) = reexport_chain(tcx, def_id, res_did).iter()
.flat_map(|reexport| reexport.id()).map(|id| id.expect_local())
.chain(iter::once(res_did)).nth(1) &&
item_def_id != def_id &&
@@ -273,22 +297,38 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
.cx
.cache
.effective_visibilities
- .is_directly_public(self.cx.tcx, item_def_id.to_def_id()) &&
- !inherits_doc_hidden(self.cx.tcx, item_def_id)
+ .is_directly_public(tcx, item_def_id.to_def_id()) &&
+ !inherits_doc_hidden(tcx, item_def_id, None)
{
// The imported item is public and not `doc(hidden)` so no need to inline it.
return false;
}
- if !self.view_item_stack.insert(res_did) {
+ let is_bang_macro = matches!(
+ tcx.hir().get_by_def_id(res_did),
+ Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, MacroKind::Bang), .. })
+ );
+
+ if !self.view_item_stack.insert(res_did) && !is_bang_macro {
return false;
}
let ret = match tcx.hir().get_by_def_id(res_did) {
+ // Bang macros are handled a bit on their because of how they are handled by the
+ // compiler. If they have `#[doc(hidden)]` and the re-export doesn't have
+ // `#[doc(inline)]`, then we don't inline it.
+ Node::Item(_)
+ if is_bang_macro
+ && !please_inline
+ && renamed.is_some()
+ && self.cx.tcx.is_doc_hidden(ori_res_did) =>
+ {
+ return false;
+ }
Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
let prev = mem::replace(&mut self.inlining, true);
for &i in m.item_ids {
- let i = self.cx.tcx.hir().item(i);
+ let i = tcx.hir().item(i);
self.visit_item_inner(i, None, Some(def_id));
}
self.inlining = prev;
@@ -319,11 +359,23 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
renamed: Option<Symbol>,
parent_id: Option<LocalDefId>,
) {
- self.modules
- .last_mut()
- .unwrap()
- .items
- .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
+ if self.is_importable_from_parent
+ // If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export`
+ // attribute can still be visible.
+ || match item.kind {
+ hir::ItemKind::Impl(..) => true,
+ hir::ItemKind::Macro(_, MacroKind::Bang) => {
+ self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export)
+ }
+ _ => false,
+ }
+ {
+ self.modules
+ .last_mut()
+ .unwrap()
+ .items
+ .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
+ }
}
fn visit_item_inner(
@@ -331,8 +383,28 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
item: &'tcx hir::Item<'_>,
renamed: Option<Symbol>,
import_id: Option<LocalDefId>,
- ) -> bool {
+ ) {
debug!("visiting item {:?}", item);
+ if self.inside_body {
+ // Only impls can be "seen" outside a body. For example:
+ //
+ // ```
+ // struct Bar;
+ //
+ // fn foo() {
+ // impl Bar { fn bar() {} }
+ // }
+ // Bar::bar();
+ // ```
+ if let hir::ItemKind::Impl(impl_) = item.kind &&
+ // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
+ // them up regardless of where they're located.
+ impl_.of_trait.is_none()
+ {
+ self.add_to_current_mod(item, None, None);
+ }
+ return;
+ }
let name = renamed.unwrap_or(item.ident.name);
let tcx = self.cx.tcx;
@@ -411,7 +483,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
}
hir::ItemKind::Mod(ref m) => {
- self.enter_mod(item.owner_id.def_id, m, name);
+ self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id);
}
hir::ItemKind::Fn(..)
| hir::ItemKind::ExternCrate(..)
@@ -420,7 +492,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
| hir::ItemKind::Union(..)
| hir::ItemKind::TyAlias(..)
| hir::ItemKind::OpaqueTy(hir::OpaqueTy {
- origin: hir::OpaqueTyOrigin::TyAlias, ..
+ origin: hir::OpaqueTyOrigin::TyAlias { .. },
+ ..
})
| hir::ItemKind::Static(..)
| hir::ItemKind::Trait(..)
@@ -448,7 +521,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
}
}
- true
}
fn visit_foreign_item_inner(
@@ -465,8 +537,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
/// This method will create a new module and push it onto the "modules stack" then call
/// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
/// add into the list of modules of the current module.
- fn enter_mod(&mut self, id: LocalDefId, m: &'tcx hir::Mod<'tcx>, name: Symbol) {
- self.modules.push(Module::new(name, id, m.spans.inner_span));
+ fn enter_mod(
+ &mut self,
+ id: LocalDefId,
+ m: &'tcx hir::Mod<'tcx>,
+ name: Symbol,
+ renamed: Option<Symbol>,
+ import_id: Option<LocalDefId>,
+ ) {
+ self.modules.push(Module::new(name, id, m.spans.inner_span, renamed, import_id));
self.visit_mod_contents(id, m);
@@ -485,9 +564,18 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
}
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
- if self.visit_item_inner(i, None, None) {
- walk_item(self, i);
- }
+ self.visit_item_inner(i, None, None);
+ let new_value = self.is_importable_from_parent
+ && matches!(
+ i.kind,
+ hir::ItemKind::Mod(..)
+ | hir::ItemKind::ForeignMod { .. }
+ | hir::ItemKind::Impl(..)
+ | hir::ItemKind::Trait(..)
+ );
+ let prev = mem::replace(&mut self.is_importable_from_parent, new_value);
+ walk_item(self, i);
+ self.is_importable_from_parent = prev;
}
fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
@@ -513,4 +601,10 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
fn visit_lifetime(&mut self, _: &hir::Lifetime) {
// Unneeded.
}
+
+ fn visit_body(&mut self, b: &'tcx hir::Body<'tcx>) {
+ let prev = mem::replace(&mut self.inside_body, true);
+ walk_body(self, b);
+ self.inside_body = prev;
+ }
}
diff --git a/src/rustdoc-json-types/Cargo.toml b/src/rustdoc-json-types/Cargo.toml
index d63caa7ad..d3548036d 100644
--- a/src/rustdoc-json-types/Cargo.toml
+++ b/src/rustdoc-json-types/Cargo.toml
@@ -12,3 +12,4 @@ rustc-hash = "1.1.0"
[dev-dependencies]
serde_json = "1.0"
+bincode = "1"
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 3cf8ceed6..ba8eeaa66 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use std::path::PathBuf;
/// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 24;
+pub const FORMAT_VERSION: u32 = 26;
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
@@ -83,7 +83,6 @@ pub struct Item {
/// Stringified versions of the attributes on this item (e.g. `"#[inline]"`)
pub attrs: Vec<String>,
pub deprecation: Option<Deprecation>,
- #[serde(flatten)]
pub inner: ItemEnum,
}
@@ -222,7 +221,7 @@ pub enum ItemKind {
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-#[serde(tag = "kind", content = "inner", rename_all = "snake_case")]
+#[serde(rename_all = "snake_case")]
pub enum ItemEnum {
Module(Module),
ExternCrate {
@@ -543,7 +542,6 @@ pub enum Term {
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
-#[serde(tag = "kind", content = "inner")]
pub enum Type {
/// Structs, enums, and unions
ResolvedPath(Path),
@@ -581,13 +579,15 @@ pub enum Type {
#[serde(rename = "type")]
type_: Box<Type>,
},
- /// `<Type as Trait>::Name` or associated types like `T::Item` where `T: Iterator`
+ /// Associated types like `<Type as Trait>::Name` and `T::Item` where
+ /// `T: Iterator` or inherent associated types like `Struct::Name`.
QualifiedPath {
name: String,
args: Box<GenericArgs>,
self_type: Box<Type>,
+ /// `None` iff this is an *inherent* associated type.
#[serde(rename = "trait")]
- trait_: Path,
+ trait_: Option<Path>,
},
}
diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs
index 399ff54b2..1126d5f78 100644
--- a/src/rustdoc-json-types/tests.rs
+++ b/src/rustdoc-json-types/tests.rs
@@ -8,11 +8,15 @@ fn test_struct_info_roundtrip() {
impls: vec![],
});
+ // JSON
let struct_json = serde_json::to_string(&s).unwrap();
-
let de_s = serde_json::from_str(&struct_json).unwrap();
-
assert_eq!(s, de_s);
+
+ // Bincode
+ let encoded: Vec<u8> = bincode::serialize(&s).unwrap();
+ let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
+ assert_eq!(s, decoded);
}
#[test]
@@ -24,9 +28,13 @@ fn test_union_info_roundtrip() {
impls: vec![],
});
+ // JSON
let union_json = serde_json::to_string(&u).unwrap();
-
let de_u = serde_json::from_str(&union_json).unwrap();
-
assert_eq!(u, de_u);
+
+ // Bincode
+ let encoded: Vec<u8> = bincode::serialize(&u).unwrap();
+ let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
+ assert_eq!(u, decoded);
}
diff --git a/src/stage0.json b/src/stage0.json
index 0cb95bae7..762e01fed 100644
--- a/src/stage0.json
+++ b/src/stage0.json
@@ -17,298 +17,298 @@
"tool is executed."
],
"compiler": {
- "date": "2023-04-20",
- "version": "1.69.0"
+ "date": "2023-06-01",
+ "version": "1.70.0"
},
"rustfmt": null,
"checksums_sha256": {
- "dist/2023-04-20/cargo-1.69.0-aarch64-apple-darwin.tar.gz": "b185ea41a0ad76ac23b08744732c51e4811528291f7193d612a42e3e54ecd535",
- "dist/2023-04-20/cargo-1.69.0-aarch64-apple-darwin.tar.xz": "48e4f318dfcb3c61a010850a7a3ea11a1e4cacf0cc071bf1cd6ebdf7aaf0ec9e",
- "dist/2023-04-20/cargo-1.69.0-aarch64-pc-windows-msvc.tar.gz": "9e047a2ac5f0aea3ee0fb7ef59c5e29f1b90f698dbb1498a8c8ee79d9373a850",
- "dist/2023-04-20/cargo-1.69.0-aarch64-pc-windows-msvc.tar.xz": "82b93bb4491177c262fe3c2ed7b22e82e06727d39e72886159578f0c47ac5c45",
- "dist/2023-04-20/cargo-1.69.0-aarch64-unknown-linux-gnu.tar.gz": "6ba6e4a9295b03d01b7dac94b7941d71c029343dc3abfd6cc4733a99fc3c7976",
- "dist/2023-04-20/cargo-1.69.0-aarch64-unknown-linux-gnu.tar.xz": "b0ffb368d4e66a5808f96659cc598030761cb06966ae8d5299596b14fbc09364",
- "dist/2023-04-20/cargo-1.69.0-aarch64-unknown-linux-musl.tar.gz": "803303b02c7f40e3eb507d4096cc7abd591c32f2921cbfb98d17ab8b6dd7f83a",
- "dist/2023-04-20/cargo-1.69.0-aarch64-unknown-linux-musl.tar.xz": "8fb122605ae32f84b2eee261d2d00da35dfb34f776886f24b089293ce37e9e8b",
- "dist/2023-04-20/cargo-1.69.0-arm-unknown-linux-gnueabi.tar.gz": "0d93ea24db4e3fc7739c68661a466fa4fbe8e158c1f10ef06e8d9cee1f7de73f",
- "dist/2023-04-20/cargo-1.69.0-arm-unknown-linux-gnueabi.tar.xz": "bdae08c6209dc24a4c4dd1aa42ccb39b48b7743faadda99190c9ab4c5ec6425a",
- "dist/2023-04-20/cargo-1.69.0-arm-unknown-linux-gnueabihf.tar.gz": "dcc8d9dffc209bd665ad45586b271569a261795162426ffbab24336e04f7a3c6",
- "dist/2023-04-20/cargo-1.69.0-arm-unknown-linux-gnueabihf.tar.xz": "e2076c5386d0ae13be0a8e8d99096bab15e2bf0f749d0410c2d45376ff837aeb",
- "dist/2023-04-20/cargo-1.69.0-armv7-unknown-linux-gnueabihf.tar.gz": "8cd5ca78c7efebcd735b7264f8a926480f4bed334b9e031d68f75494e669ff60",
- "dist/2023-04-20/cargo-1.69.0-armv7-unknown-linux-gnueabihf.tar.xz": "f709ae6c7d92d95b9fdf27188b7fc04bbf95089091803ee7eb1c4e78d38fee7d",
- "dist/2023-04-20/cargo-1.69.0-i686-pc-windows-gnu.tar.gz": "363bea80afae170d9877754e185ad2af705b95099a5961176cac776824f3afda",
- "dist/2023-04-20/cargo-1.69.0-i686-pc-windows-gnu.tar.xz": "5bb26a69498295d2780eb690ea519d877aac24f93f2789da9f21ac9450b04c3f",
- "dist/2023-04-20/cargo-1.69.0-i686-pc-windows-msvc.tar.gz": "caae66efe790bf765c0b26943428481a4cf14f69c011bfc7e68a12a6adfcc0d1",
- "dist/2023-04-20/cargo-1.69.0-i686-pc-windows-msvc.tar.xz": "dcca36e98acd82ee356302f33ecdb451208f404efabd28a76c548e99b0fe3f52",
- "dist/2023-04-20/cargo-1.69.0-i686-unknown-linux-gnu.tar.gz": "45f966d2965e41e0598fa9dce780766163685935647c8de09610c73f5f85823f",
- "dist/2023-04-20/cargo-1.69.0-i686-unknown-linux-gnu.tar.xz": "4c9b1b2fb692bb0c81e524df6368723f061c8bb0d21a1f487eb8e5c2bdf323ab",
- "dist/2023-04-20/cargo-1.69.0-mips-unknown-linux-gnu.tar.gz": "7997f46aeaa844ac83a6f781c6bc7389594f2eac120f44163ca3c4a173fbe4e0",
- "dist/2023-04-20/cargo-1.69.0-mips-unknown-linux-gnu.tar.xz": "bdaef2f95b0485dc2a5cde74c08bd269174bbbb553226c5b5d2287e52841b061",
- "dist/2023-04-20/cargo-1.69.0-mips64-unknown-linux-gnuabi64.tar.gz": "d584fcced4891a16baa6013122a3d53e05f42ba7247d75c30f70219c7fc49519",
- "dist/2023-04-20/cargo-1.69.0-mips64-unknown-linux-gnuabi64.tar.xz": "e952b2dfe477a1768fd88383f65f82bd4be097f2f0582de42745c8fbad052cf5",
- "dist/2023-04-20/cargo-1.69.0-mips64el-unknown-linux-gnuabi64.tar.gz": "ca74d5cb2705e95763a5018677ac10bbd0a41dec324568c10fc0e03f587fd8cc",
- "dist/2023-04-20/cargo-1.69.0-mips64el-unknown-linux-gnuabi64.tar.xz": "07d73849ed1b469e4d81c9666dc9e4fcc6b6ece2025371fabb58fae9dd3c1bf9",
- "dist/2023-04-20/cargo-1.69.0-mipsel-unknown-linux-gnu.tar.gz": "0ba8a052eaf7877c75f3d1a22d102144138a9a3ed10a8c4b0ea724a805759a01",
- "dist/2023-04-20/cargo-1.69.0-mipsel-unknown-linux-gnu.tar.xz": "df114ac589fb50fcc3027e26c6e201fc530aadef1bcc8f6396c761a457ba7bbb",
- "dist/2023-04-20/cargo-1.69.0-powerpc-unknown-linux-gnu.tar.gz": "05167bc46932bd8de5eb95d5ed91c8ceddc0a0138cdf7765f981db3d920c784f",
- "dist/2023-04-20/cargo-1.69.0-powerpc-unknown-linux-gnu.tar.xz": "26c774db5e21ddf66107b677d5c6612d50611186feaa68ff11c34a61e4d5a57e",
- "dist/2023-04-20/cargo-1.69.0-powerpc64-unknown-linux-gnu.tar.gz": "2bfd3c9b0b384cf9e13180f29aee234a822a10dfcff132541f2da2ce72403932",
- "dist/2023-04-20/cargo-1.69.0-powerpc64-unknown-linux-gnu.tar.xz": "160692a0fc5fe1b48b617e063c6ce1d4546e108b32c0049dbde95602a30af133",
- "dist/2023-04-20/cargo-1.69.0-powerpc64le-unknown-linux-gnu.tar.gz": "23e66703392ea5ec4c1c793b51fef83cd244bc57d23ae42be5cf0b0888eb9758",
- "dist/2023-04-20/cargo-1.69.0-powerpc64le-unknown-linux-gnu.tar.xz": "9a3fe155d763b382ea18753133cb0e2186993e2850568134e2f7e468f2d07197",
- "dist/2023-04-20/cargo-1.69.0-riscv64gc-unknown-linux-gnu.tar.gz": "816deb02a3805bd0b3c3a91a7fec1a54543a55f3d490992cb0f612d3ecfa3e2f",
- "dist/2023-04-20/cargo-1.69.0-riscv64gc-unknown-linux-gnu.tar.xz": "9bc29f493c353313b968243fbdf5147c9ca401f7f8205aed63f180b5757161e2",
- "dist/2023-04-20/cargo-1.69.0-s390x-unknown-linux-gnu.tar.gz": "9b046efbf06aaa70cddc98138483feba77bd954e1b879ab4e7f02cb5c0806348",
- "dist/2023-04-20/cargo-1.69.0-s390x-unknown-linux-gnu.tar.xz": "812907846a454a182b05eab76658b49eabd8d06d2b5e8df56f29d73971f91b03",
- "dist/2023-04-20/cargo-1.69.0-x86_64-apple-darwin.tar.gz": "3ed0b5eaaf7e908f196b4882aad757cb2a623ca3c8e8e74471422df5e93ebfb0",
- "dist/2023-04-20/cargo-1.69.0-x86_64-apple-darwin.tar.xz": "8a01c5f5454708a60d39734e0688cadd83c9709412a02bdcd4984d246f8b299a",
- "dist/2023-04-20/cargo-1.69.0-x86_64-pc-windows-gnu.tar.gz": "8ab16b569ad8b1bf8c7b151acbe9d77c08e744ec2511502ea8d1a01ece1bf097",
- "dist/2023-04-20/cargo-1.69.0-x86_64-pc-windows-gnu.tar.xz": "6afc9b5b4192b66382ef428daf340fbed615024696c094d8f783b5782c8cad41",
- "dist/2023-04-20/cargo-1.69.0-x86_64-pc-windows-msvc.tar.gz": "9fef20492ad1e296f5f458b0b118e33b42a3c956ad20d9f5d683e0235f1d9d77",
- "dist/2023-04-20/cargo-1.69.0-x86_64-pc-windows-msvc.tar.xz": "992db17f28426d99d1a4f41e9b06df2c03464b3cda7c2121732a0a43cfc59c8d",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-freebsd.tar.gz": "797b9f3844d91323b42ec82fb6c06864b13cd70f0cae42c29a3d205e72ad2782",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-freebsd.tar.xz": "98f3157fe6ebef8d276e13a9f517ad3ccc59c62d3a13ba940c49d223c72f2836",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-illumos.tar.gz": "905e09513b9ea0af77257e5bb97bea77006f3d1323a33e1969d3f0cf2fb1dedd",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-illumos.tar.xz": "12530275246dcc8025b8f5359b7d97c3a51c8922132987e4a2433753d8d3ebca",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-linux-gnu.tar.gz": "7ee899206f592a86687478465970aa6b57772ccbe9a1f1b7695aa1237c2325a6",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-linux-gnu.tar.xz": "336eeabf231a7665c26c127a37b8aefffe28cb087c5c8d4ba0460419f5f8eff2",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-linux-musl.tar.gz": "c17cd0511c1b1b826d78533deeffffa0f7a4fa2d010ec660afa85bf24d977d9c",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-linux-musl.tar.xz": "17f5c6481a881599adb5f665480d9985073155eda9c9fdc1e5663563db51b970",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-netbsd.tar.gz": "9edfe8166acc4cf6e28f17290cea6ae87e8d6c983ef910fb3082c05363ee373e",
- "dist/2023-04-20/cargo-1.69.0-x86_64-unknown-netbsd.tar.xz": "e808fbe1391879376faa9e0001bef6a370d9ad533b31a0241da8465d58675e4e",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-apple-darwin.tar.gz": "00307d648acc269a0874ba8de4f8eb3bd3b85a0f10e3da59ba1ff8c840e92b34",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-apple-darwin.tar.xz": "fdb1f29341f51e8b119f69e98b657a12fa60f12edfccfa494ae282de0553d4fd",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-apple-ios-sim.tar.gz": "2291ac2949ca832ea6db3795f17e981d7c563fa5b102eaea39811482320374b2",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-apple-ios-sim.tar.xz": "105f15574591f3a297c0b755b8205ca8672aa6238da432ab59cb5422374e042d",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-apple-ios.tar.gz": "ef1a7dc02df8cbb0b22e897253cd22b7de33e7958031604bc9d0a8fb9fd6c9a8",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-apple-ios.tar.xz": "94cf2ba63b38addc81a9c75d3dfda0275bdafe20d3948b3c6b53f8c6f692da4c",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-linux-android.tar.gz": "0faba7a6b0789f19d16ae235d46fac30e89131df29ed382ed70218ccd57b4ddf",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-linux-android.tar.xz": "4ae8f5c8c1845f666115f26ab5bc8341986f8035fb93887b6ba01c090004ad69",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-pc-windows-msvc.tar.gz": "6bc44180bda86171560be7cecc36698a1eab5e8cba676a87d89c24d1f091d7a4",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-pc-windows-msvc.tar.xz": "2254b8272362837809e0b53f018973b3d016e079537230937c299f55fccadf99",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-fuchsia.tar.gz": "74d501377215c640cd30ee7e6cd444f30d90e01eccf7cc881cde276709eb535d",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-fuchsia.tar.xz": "44d2db28e20a490c68444516fa3eda623a9a541ab1c1848b6eaa86817b43346e",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-linux-gnu.tar.gz": "8f42b40c0a0658ee75ce758652c9821fac7db3fbd8d20f7fb2483ec2c57ee0ac",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-linux-gnu.tar.xz": "c3c5346b1e95ea9bd806b0dd9ff9aa618976fb38f4f3a615af4964bb4dd15633",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-linux-musl.tar.gz": "07788bc6a1d17e8f0791c3367734c3c65165ca806ee83d01dad303059690b19d",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-linux-musl.tar.xz": "729a22a51089b9a96ff7abf350ee963649bbb320e43e9ed511a47689fd80e17c",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-none-softfloat.tar.gz": "0ec4c2e2606553837fab6d13af656d3449653a9077a5bb83d52e43ccc51f1607",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-none-softfloat.tar.xz": "6371f7e2308d4021d4dbd2d468bc3ee7f83434765300e6c15bfa4de843ccfaf8",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-none.tar.gz": "793676cf620513684d6027faed70a30c51a265b730aa6f930d05e3c76043b20f",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-none.tar.xz": "4ec6982e74d01790a2cd167c7e84f8a859a3b0232a1f4275d13fc244fc49d096",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-uefi.tar.gz": "7e6e32252fd6d7f7e9f3d1fdfeedd67310d7cce0fe35e3e3f0f9a7df5379eb28",
- "dist/2023-04-20/rust-std-1.69.0-aarch64-unknown-uefi.tar.xz": "6aecf80e8216efce5d26421904015a41cae65eade2c9b744d343c2a848089b0d",
- "dist/2023-04-20/rust-std-1.69.0-arm-linux-androideabi.tar.gz": "66e2609bff426ce6dfc1c05639aa2aeebee1a0d0d5082dcacee73dab0d422f3c",
- "dist/2023-04-20/rust-std-1.69.0-arm-linux-androideabi.tar.xz": "9f821298c15cf7a2c58f21c27d6e9efca9a10e559e2478a03498d211605ff57e",
- "dist/2023-04-20/rust-std-1.69.0-arm-unknown-linux-gnueabi.tar.gz": "096aa203d690339f3831052b9dac52d91cc5dd63627c6c89688c16d7f70dca4a",
- "dist/2023-04-20/rust-std-1.69.0-arm-unknown-linux-gnueabi.tar.xz": "3c6f8fc7ccd747c85855944510b13166779f43926e970e40bfe7835252734c7f",
- "dist/2023-04-20/rust-std-1.69.0-arm-unknown-linux-gnueabihf.tar.gz": "f0630a13adf0f86f5db528291a838645e31ce63e1e052ef5284aecd8ae6cecca",
- "dist/2023-04-20/rust-std-1.69.0-arm-unknown-linux-gnueabihf.tar.xz": "c2f4a3332dfe1520a3761a9d072b8edcb6b5c0a84b1b24c3a7ac621e86b4e13e",
- "dist/2023-04-20/rust-std-1.69.0-arm-unknown-linux-musleabi.tar.gz": "7be1e4ee98a1e6adc233bf8ce5499fc5147345ca90c7bb120959ebb2254fb9a7",
- "dist/2023-04-20/rust-std-1.69.0-arm-unknown-linux-musleabi.tar.xz": "c0837c5f36381aaa8b297d478b935cdcbe9ee3af741f2891b9a75dc0dcb6a036",
- "dist/2023-04-20/rust-std-1.69.0-arm-unknown-linux-musleabihf.tar.gz": "ad6ae81c5ec8588d62257b45516ce49dcd395d27741a009c5beaf1a522dde8d4",
- "dist/2023-04-20/rust-std-1.69.0-arm-unknown-linux-musleabihf.tar.xz": "3d924216ba8f1c57f14578a254e3043256cc55211c18263eb2c1134a0021133f",
- "dist/2023-04-20/rust-std-1.69.0-armebv7r-none-eabi.tar.gz": "8b03c7898ec352726ead95bd8c8f8b55707de7528d58ffff3e835e345eade1af",
- "dist/2023-04-20/rust-std-1.69.0-armebv7r-none-eabi.tar.xz": "16797d6cd21aa3c4987727a4b89851ff1f9fc11870b40e70f87e42024adf0323",
- "dist/2023-04-20/rust-std-1.69.0-armebv7r-none-eabihf.tar.gz": "042eddf9c2a41a06cda2064737ca1bbd98deb7a8a806037bc1ef605df48f2013",
- "dist/2023-04-20/rust-std-1.69.0-armebv7r-none-eabihf.tar.xz": "2e48b2c1e0b2b60d1baf12bb282f6ff7fdc907745d2d819a43080b3f1a516f64",
- "dist/2023-04-20/rust-std-1.69.0-armv5te-unknown-linux-gnueabi.tar.gz": "2e6b90f114fb81cd8d746895560552d82c09c08bdac97116a29f336019ca3982",
- "dist/2023-04-20/rust-std-1.69.0-armv5te-unknown-linux-gnueabi.tar.xz": "e90362811e8cb7d8f4d9e850f57b6bf9b94ea9136de6501918f636c24d39ee55",
- "dist/2023-04-20/rust-std-1.69.0-armv5te-unknown-linux-musleabi.tar.gz": "e51d66540ac036582d8a84af72a5a6da27bc338ea42fcbc5ca7679a8abb4acbc",
- "dist/2023-04-20/rust-std-1.69.0-armv5te-unknown-linux-musleabi.tar.xz": "a348ed99e575c9e735bd8053b11a42408bf27dc690c4afdf5d25876813b403fe",
- "dist/2023-04-20/rust-std-1.69.0-armv7-linux-androideabi.tar.gz": "e2dbafb21fc6af9e9b2daa2139f3c4665cc38ad8ff56031f534b1334ceed7b08",
- "dist/2023-04-20/rust-std-1.69.0-armv7-linux-androideabi.tar.xz": "3e3a8346e665d5f7e2169be345130ba4ab4196c3a6a192a1bf6369b5abd26deb",
- "dist/2023-04-20/rust-std-1.69.0-armv7-unknown-linux-gnueabi.tar.gz": "fecd5d2244534451ed8ea3f901bfaaf6c2d10c77913caa1c3406a763b70b59af",
- "dist/2023-04-20/rust-std-1.69.0-armv7-unknown-linux-gnueabi.tar.xz": "cd9917a868a11489b0eaee928f082dcaf95f843ff52c894f72af1ace3c32408e",
- "dist/2023-04-20/rust-std-1.69.0-armv7-unknown-linux-gnueabihf.tar.gz": "08edc4547495299393a0e18f8eff740d7cf31e00ad2b31671688e5e4438abe16",
- "dist/2023-04-20/rust-std-1.69.0-armv7-unknown-linux-gnueabihf.tar.xz": "d0f5a2046354688e21cc10a8feeb35b2c5c05c8adf5c9cf474dc47eadf417fd5",
- "dist/2023-04-20/rust-std-1.69.0-armv7-unknown-linux-musleabi.tar.gz": "97294b981cb60fd1ad374bc24d8a90c80c62390dbed17f012d6b14c79be8b53a",
- "dist/2023-04-20/rust-std-1.69.0-armv7-unknown-linux-musleabi.tar.xz": "997954b5551eb5386dd66ffe7b9660e02b04e5336c172c0e65985cc5ad5afee6",
- "dist/2023-04-20/rust-std-1.69.0-armv7-unknown-linux-musleabihf.tar.gz": "fadb41835ada212a248f663caa0c727e32a3c8d9471bea25f63a948b760e3124",
- "dist/2023-04-20/rust-std-1.69.0-armv7-unknown-linux-musleabihf.tar.xz": "ac3594d012a194b9f1adeb8eada22e90aeb1e20c24eed295455caaeff3217dc0",
- "dist/2023-04-20/rust-std-1.69.0-armv7a-none-eabi.tar.gz": "e4d2220efeb177d8b8611cd5106e013b064184d409cc255b6cae6bae63102375",
- "dist/2023-04-20/rust-std-1.69.0-armv7a-none-eabi.tar.xz": "387ebdb7831aa33792dbb37122f3e1eba26fc6609dcd39ec55b7d40cb06c1d7b",
- "dist/2023-04-20/rust-std-1.69.0-armv7r-none-eabi.tar.gz": "9c84550b56e9df136c6901577cf793a736c18cd7bf8e208add18ad3a8bc205d5",
- "dist/2023-04-20/rust-std-1.69.0-armv7r-none-eabi.tar.xz": "45e2f46b15546611ce1f11fec827ea36cff3513ed0e56fea98aa3a1f3c0f63ad",
- "dist/2023-04-20/rust-std-1.69.0-armv7r-none-eabihf.tar.gz": "a027bf24f3bdc61541e3f968d72157a23ce4ed1d3034b26b2170d60dad36a336",
- "dist/2023-04-20/rust-std-1.69.0-armv7r-none-eabihf.tar.xz": "1f042663eb05563a00c62fe94f500f5d4b42dd96d736c916a43473e833a8c175",
- "dist/2023-04-20/rust-std-1.69.0-asmjs-unknown-emscripten.tar.gz": "b2ac5bdec00dc572128701a4f58ceb7047826f410fca523c33bd92fb523d3206",
- "dist/2023-04-20/rust-std-1.69.0-asmjs-unknown-emscripten.tar.xz": "c79a0ebcd78c1f4ef02dcdf5353b5d40b214cfe3078e8fd679e5fdcfc0dd953e",
- "dist/2023-04-20/rust-std-1.69.0-i586-pc-windows-msvc.tar.gz": "613ca46ef08adb9a17b75bc1a005ad60bc0891f82baaa74505e38fb794a1f067",
- "dist/2023-04-20/rust-std-1.69.0-i586-pc-windows-msvc.tar.xz": "b4fb87926419095bfe644e21800cb610784453d496529a905423493b91df1392",
- "dist/2023-04-20/rust-std-1.69.0-i586-unknown-linux-gnu.tar.gz": "613270943dd6a3dcfad6a9227089bc3bbb30984f3d6d45781da527823c143559",
- "dist/2023-04-20/rust-std-1.69.0-i586-unknown-linux-gnu.tar.xz": "a8125d72e06f2d866472a7aca3bd20a247160171d23a75c4207761a05e00ed5b",
- "dist/2023-04-20/rust-std-1.69.0-i586-unknown-linux-musl.tar.gz": "41c00fc1e8f6fbeed5edefcca626b7b349d950ba5893b2e6fe7653fbd0f2639c",
- "dist/2023-04-20/rust-std-1.69.0-i586-unknown-linux-musl.tar.xz": "97e5d07965f978a95f2e52040c9255014fe74f1d591f9b41ef66ee29fbdf3709",
- "dist/2023-04-20/rust-std-1.69.0-i686-linux-android.tar.gz": "3660b69a847330ef336773ae36acf327865c0eca7093e159e84d34741856fed7",
- "dist/2023-04-20/rust-std-1.69.0-i686-linux-android.tar.xz": "3ef1a76919d426ed7370585c6f3098ebd63e3b3ed5903830ad8124c69aa446ec",
- "dist/2023-04-20/rust-std-1.69.0-i686-pc-windows-gnu.tar.gz": "418e391397ee55e0310d940d36ae1150aaae6c02a8816a0199b9ccbaf2c8c7c2",
- "dist/2023-04-20/rust-std-1.69.0-i686-pc-windows-gnu.tar.xz": "baca4756366308de5f58bd6d29ac4812be88b7c18caae97ff6478f6775a86b2c",
- "dist/2023-04-20/rust-std-1.69.0-i686-pc-windows-msvc.tar.gz": "7305a813acd54621b8d82c372bea9c90e8a874c993c2a67bbb450d7048dbe707",
- "dist/2023-04-20/rust-std-1.69.0-i686-pc-windows-msvc.tar.xz": "64d48421916f1efca0c9013cba41ac7057360da3306476310aab0c957cf9cb0c",
- "dist/2023-04-20/rust-std-1.69.0-i686-unknown-freebsd.tar.gz": "feb636176841d919b700bb586f72476d4f5ad70c1dbcca28d4fa54c3a76e4cdc",
- "dist/2023-04-20/rust-std-1.69.0-i686-unknown-freebsd.tar.xz": "7f3e92d9ce81293f257e32047966b5513a404e8c072cefe45ccd0ee0121b0633",
- "dist/2023-04-20/rust-std-1.69.0-i686-unknown-linux-gnu.tar.gz": "d54849ab7168e16210107b812871bea7f282a3f50b4b34aa252f04f25f8a8bf9",
- "dist/2023-04-20/rust-std-1.69.0-i686-unknown-linux-gnu.tar.xz": "bef330af5bfb381a01349186e05402983495a3e2d4d1c35723a8443039d19a2d",
- "dist/2023-04-20/rust-std-1.69.0-i686-unknown-linux-musl.tar.gz": "9a5a1c439351b1327fc60e04d641fdb54fdecacda95ba1ec4fff202a805d4791",
- "dist/2023-04-20/rust-std-1.69.0-i686-unknown-linux-musl.tar.xz": "699286334b8a2c10c8676f8345b5589681e334bf6789a174947b6885faa78b85",
- "dist/2023-04-20/rust-std-1.69.0-i686-unknown-uefi.tar.gz": "3903ee3752a13fd5717aa1816363461f7bb8f72022da29559dfe0ac0168f79bc",
- "dist/2023-04-20/rust-std-1.69.0-i686-unknown-uefi.tar.xz": "e82cb58dc0c5640a0d7d8ddcea7c6245dbd596b0c9cc3d41157017e1308ff746",
- "dist/2023-04-20/rust-std-1.69.0-mips-unknown-linux-gnu.tar.gz": "032e5b35b2883a9a5fc29e191c1103be8ea33af90b35d26305da5bdb847dd65d",
- "dist/2023-04-20/rust-std-1.69.0-mips-unknown-linux-gnu.tar.xz": "89849b93af9d4922554c938bc1c7641498d13c3a8b2b464f3bb7a060eae7a580",
- "dist/2023-04-20/rust-std-1.69.0-mips-unknown-linux-musl.tar.gz": "968099776e6d19183cfb5e97d5f13daf69b24c1088af46d49378843049caf4af",
- "dist/2023-04-20/rust-std-1.69.0-mips-unknown-linux-musl.tar.xz": "6c5276f3821b4feb8a6de1b9c44e5b3ca312169f34a00d6d9302680bd2109b57",
- "dist/2023-04-20/rust-std-1.69.0-mips64-unknown-linux-gnuabi64.tar.gz": "2393e2cecb12fe20e2774fce2b52599b5082f93e7041c4f7816aad1e378d9d1d",
- "dist/2023-04-20/rust-std-1.69.0-mips64-unknown-linux-gnuabi64.tar.xz": "413527cb7b1b876013cc721aa8f93b78b7021d26f7673a1a9f568e5b51af42d9",
- "dist/2023-04-20/rust-std-1.69.0-mips64-unknown-linux-muslabi64.tar.gz": "7948c622a68fc4726d9c855f03eab0fab2b448cd7303f17f69c592e931184e58",
- "dist/2023-04-20/rust-std-1.69.0-mips64-unknown-linux-muslabi64.tar.xz": "0578d0efe7d09ea0edbaeea9b44822632ef4e7e2c210c7df47e8ff7fc141cb0f",
- "dist/2023-04-20/rust-std-1.69.0-mips64el-unknown-linux-gnuabi64.tar.gz": "72b17108862ff9740ee594f2eff517e08a02380903b4a9ea35aa5296a13aa5bb",
- "dist/2023-04-20/rust-std-1.69.0-mips64el-unknown-linux-gnuabi64.tar.xz": "738d2b7ef7683cef511252fea994594cfffdef6f6650dd457c9b312ddb17a807",
- "dist/2023-04-20/rust-std-1.69.0-mips64el-unknown-linux-muslabi64.tar.gz": "6d87304fcbc9e07a290d37317cd3c8e96469b4654e232daf66ae83eb9e6e7093",
- "dist/2023-04-20/rust-std-1.69.0-mips64el-unknown-linux-muslabi64.tar.xz": "37a7618464f2a0253dd3fb51037a8f42649a26f8240ddab77bd57f688b70a40a",
- "dist/2023-04-20/rust-std-1.69.0-mipsel-unknown-linux-gnu.tar.gz": "3101831757ce93c10b4c394e1f979176e8d1ca72492247d2a043f4a9fcceb24c",
- "dist/2023-04-20/rust-std-1.69.0-mipsel-unknown-linux-gnu.tar.xz": "22bb266cf4e6da4d6867144873579b0da47e59c8ec9cb1a329ee8a7f418e8ee3",
- "dist/2023-04-20/rust-std-1.69.0-mipsel-unknown-linux-musl.tar.gz": "e909ba817e0c5d5e90424bc7dfeb9b4a42c01871101dd5898a3243f9ff9d033f",
- "dist/2023-04-20/rust-std-1.69.0-mipsel-unknown-linux-musl.tar.xz": "c9bedee259b0cf93cd22fa7c7ece8a1cfdb1882efca2b04e18a16175d36a9519",
- "dist/2023-04-20/rust-std-1.69.0-nvptx64-nvidia-cuda.tar.gz": "0f61f851ac53581c569f2f7b43f8c088cea338fb8b5cc22be283af9bc04c33d1",
- "dist/2023-04-20/rust-std-1.69.0-nvptx64-nvidia-cuda.tar.xz": "e7238c3adf53ed42858b5ddd3936b5fca58e27df23f4feb920f6f81e64abfb97",
- "dist/2023-04-20/rust-std-1.69.0-powerpc-unknown-linux-gnu.tar.gz": "dd5c877591ad9df7a5cb541e23be18d1ca7ccc04850c20118b1eab35625845b0",
- "dist/2023-04-20/rust-std-1.69.0-powerpc-unknown-linux-gnu.tar.xz": "6303fc2be557467af0f1ff9cc756fd14ae2b9db7f17f42a1d2238ed934351e56",
- "dist/2023-04-20/rust-std-1.69.0-powerpc64-unknown-linux-gnu.tar.gz": "fad166839757b27d9078803c54ba46aed7688dd43dcbe2a14b5d05c21327c7aa",
- "dist/2023-04-20/rust-std-1.69.0-powerpc64-unknown-linux-gnu.tar.xz": "6a4b8b5307141c8207ed67d4fbaf9345c42fb3662e389b9dd3d9a4086c1b6efe",
- "dist/2023-04-20/rust-std-1.69.0-powerpc64le-unknown-linux-gnu.tar.gz": "f214837e0cf46dbe2be6652a518e49d7b24936fecc8f4cff01aa9fc63512ed1f",
- "dist/2023-04-20/rust-std-1.69.0-powerpc64le-unknown-linux-gnu.tar.xz": "c44bcf91a9d13412a59ba75e7f8bd14c7f60d44cdb7b21916e502c90b4b378ce",
- "dist/2023-04-20/rust-std-1.69.0-riscv32i-unknown-none-elf.tar.gz": "c0e8f8fe373f856fe543b82df887e9c2f2a36d8fe1bbbb00404c8f38e380a7c0",
- "dist/2023-04-20/rust-std-1.69.0-riscv32i-unknown-none-elf.tar.xz": "d06a27b43698dfdbf80db53e4cabad33f00aad5617c7374deb3802906fe4b62c",
- "dist/2023-04-20/rust-std-1.69.0-riscv32imac-unknown-none-elf.tar.gz": "69320d4b3225317367be4ea5a6625ae2cf391cfdb5d3f8bf3989e8f42f0ff110",
- "dist/2023-04-20/rust-std-1.69.0-riscv32imac-unknown-none-elf.tar.xz": "44a8c64837c311a9412b0a777f58d50f9c83f4d3f569b58ea7fdd5b16d1d25b9",
- "dist/2023-04-20/rust-std-1.69.0-riscv32imc-unknown-none-elf.tar.gz": "41d2fcce0ab65cda817fee363e7e569550bc011c0d86aa57bd6c80e1bc60184e",
- "dist/2023-04-20/rust-std-1.69.0-riscv32imc-unknown-none-elf.tar.xz": "547dea9f9d82916ecf33a4a0d9b604262c86b2368707deb39891be4a9fdeafaf",
- "dist/2023-04-20/rust-std-1.69.0-riscv64gc-unknown-linux-gnu.tar.gz": "b8b03db1ca7286976099fae83b972b320aa69ea50b94c8a1a4001e9a3b85c888",
- "dist/2023-04-20/rust-std-1.69.0-riscv64gc-unknown-linux-gnu.tar.xz": "8c32a848e2688b2900c3e073da8814ce5649ce6e0362be30d53517d7a9ef21ff",
- "dist/2023-04-20/rust-std-1.69.0-riscv64gc-unknown-none-elf.tar.gz": "d7258e46ea8744c38f01967c17c0a5a628820db94458286710aa6f68230fc519",
- "dist/2023-04-20/rust-std-1.69.0-riscv64gc-unknown-none-elf.tar.xz": "e9b8d1a80ca59d188d8654d031e9165920a02fae3baac7dddf4736c6585de7f8",
- "dist/2023-04-20/rust-std-1.69.0-riscv64imac-unknown-none-elf.tar.gz": "ef8c38f492fe2367757f5c70ca6c73d6a75cccfe7f22d32a41e588e4997c8040",
- "dist/2023-04-20/rust-std-1.69.0-riscv64imac-unknown-none-elf.tar.xz": "0eca0161d4d19ab8dd5159429760588b1f02626899a667b5c219ca74e2ff72d0",
- "dist/2023-04-20/rust-std-1.69.0-s390x-unknown-linux-gnu.tar.gz": "82dbdd45414afca9ac3a1c867a6819cf98ea27ddff7311fd5c83fdb7a041d362",
- "dist/2023-04-20/rust-std-1.69.0-s390x-unknown-linux-gnu.tar.xz": "5c98653199b89bff6f368bed61fca7860f7179364ce9e9474c90af38e2629baf",
- "dist/2023-04-20/rust-std-1.69.0-sparc64-unknown-linux-gnu.tar.gz": "51a0c52962998c429500fe1f7bb0fef6d911a1e4990080649704ec8bb60574bc",
- "dist/2023-04-20/rust-std-1.69.0-sparc64-unknown-linux-gnu.tar.xz": "7d50ff8499d8925ea973aa659e1a88190547615b3cfecb79e776ef8de953b755",
- "dist/2023-04-20/rust-std-1.69.0-sparcv9-sun-solaris.tar.gz": "6c21c66d2e398d0a5e80c706a15cc847722827b961e1f70411c1af27ea6112f6",
- "dist/2023-04-20/rust-std-1.69.0-sparcv9-sun-solaris.tar.xz": "30c2e8bb50cddcf083025c74b1b08eee146ac018244193fac93856207fc94ae2",
- "dist/2023-04-20/rust-std-1.69.0-thumbv6m-none-eabi.tar.gz": "47f9e2a194ace9189cb5188792c960beef16217dc13cb567831ad484cd2f93cd",
- "dist/2023-04-20/rust-std-1.69.0-thumbv6m-none-eabi.tar.xz": "94348fef7014cc2cc56fae5ff4272ae1bc6d25fd0d19d2f673cdaeab31cee2fc",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7em-none-eabi.tar.gz": "cfc1b8ef3055187692cca52b57999c41db006d220a51dec97733c1d1d8ba4ea0",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7em-none-eabi.tar.xz": "f4dccfcc825ca4c0808cdfb8decb178a6fae750dfd059cabffdbd20102ce7ecc",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7em-none-eabihf.tar.gz": "d185f87a0f9276c66c784152639ce4548116b159c9aa51a6024301f35a1bbe91",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7em-none-eabihf.tar.xz": "bbaed6340fa2484607798e2c036ec163bedd30f58e44ca589928dff2884da4bf",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7m-none-eabi.tar.gz": "9a9335ee62a18feb08d5c23f766e831e617db89cacfaa13e2903ab759b313838",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7m-none-eabi.tar.xz": "3ddb333fbac410c22ff1dc45f6472917322b868816639ec788c154747c3e1234",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7neon-linux-androideabi.tar.gz": "4ede5d3089ffa894ef2b27a124f0e2d58ebd4699b603ee2bb4904787824d324c",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7neon-linux-androideabi.tar.xz": "1c4e4d14807940674f8b23c2e85406e1fd59d73a9d51c64fdbb59e1a5b7bbe5b",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "6d9765056f095182a39e67f51fea587f445096307c77a46421c8eaeb8aec4ac4",
- "dist/2023-04-20/rust-std-1.69.0-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "527fc9fa5b19ecab8cce352070834063b2556b7d3c7c87e55915ca938cd2c2a4",
- "dist/2023-04-20/rust-std-1.69.0-thumbv8m.base-none-eabi.tar.gz": "980023ef9aa5f133a725cdedd1f3d1301ce7810bb130dc78253874d340c2090b",
- "dist/2023-04-20/rust-std-1.69.0-thumbv8m.base-none-eabi.tar.xz": "d122ae463680fd87bb72fab28f8705585dbfdd9b9821f36034fcb482ac18b93b",
- "dist/2023-04-20/rust-std-1.69.0-thumbv8m.main-none-eabi.tar.gz": "fd6513f30b105670bb6e511989db13e5d7503d725c77584d10751bc526343fb1",
- "dist/2023-04-20/rust-std-1.69.0-thumbv8m.main-none-eabi.tar.xz": "0d01c05009b6315c3087a1d30ba4d8c788d29fa47ca87b633666076fce39cf60",
- "dist/2023-04-20/rust-std-1.69.0-thumbv8m.main-none-eabihf.tar.gz": "5ac4be3ff3cc30533477d296b0cd3669b0c60abc0141c384667fdc19ca6f04a9",
- "dist/2023-04-20/rust-std-1.69.0-thumbv8m.main-none-eabihf.tar.xz": "37a96cf44a4623eddbf0e036933dfdc3c3d2094e9e7746c01e0fdf71491aa47a",
- "dist/2023-04-20/rust-std-1.69.0-wasm32-unknown-emscripten.tar.gz": "5caa0780daa7cba8db7e6ddef564e01c0ba44960879d5f25f0fe8256a07fdb2d",
- "dist/2023-04-20/rust-std-1.69.0-wasm32-unknown-emscripten.tar.xz": "2f1940260c06d1689a79219cde37f2cb23208f51b403a5e434ab9869c79adc97",
- "dist/2023-04-20/rust-std-1.69.0-wasm32-unknown-unknown.tar.gz": "895f79222ea5d9cc50a1257a8ac208c1525ccaf8f25dcc138183a6cd61be79d6",
- "dist/2023-04-20/rust-std-1.69.0-wasm32-unknown-unknown.tar.xz": "4ea9d3b776eb2831f79db0f2d14965343dab6c52103c2f48c3f0903acce85592",
- "dist/2023-04-20/rust-std-1.69.0-wasm32-wasi.tar.gz": "ff1700395e39d853ce28b867e17108d3c5fe3f276e3c210b08dc180438d6badb",
- "dist/2023-04-20/rust-std-1.69.0-wasm32-wasi.tar.xz": "72fbbbd50d46c22a0c0162c5535c36b18626b32f17a6760538e4fac02450b3c2",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-apple-darwin.tar.gz": "e44d71250dc5a238da0dc4784dad59d562862653adecd31ea52e0920b85c6a7c",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-apple-darwin.tar.xz": "20161f5c41856762d1ce946737feb833bb7acd2817a4068f4e3044b176e5f73c",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-apple-ios.tar.gz": "882a02c1fedff14cb4f7f09bd588386ab3f63e6b33fbf5ad5587af33886a9b51",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-apple-ios.tar.xz": "22d6d7a072ce523e79cfdce7ad09982b399d8baed0d810a2dceb01c261f2b85e",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-fortanix-unknown-sgx.tar.gz": "8fac6617253d245eb94361d96ec7284577384d169c5d93153696525d89dd91ba",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-fortanix-unknown-sgx.tar.xz": "9e5fe109092b8f172c96789ca058d9a01330ddba17aec1c23ef95d4547ba5210",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-linux-android.tar.gz": "8cb25ade421817865833a61114648e7765b69635c4d8b09d471a3e7e058aa272",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-linux-android.tar.xz": "c7ed56d9c4b3c03b532a409bf84bc8c676bb5b2504a969dc44078f2c40b74991",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-pc-solaris.tar.gz": "bd608aaea7615cb98a70afb8b9320849cdbe6329fb2dd6945539a9dbc67b9142",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-pc-solaris.tar.xz": "0c35e1e2a2abce437f7f15425bc607d7373eb7f11e058823b2450dfc639d7e1d",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-pc-windows-gnu.tar.gz": "09ded4a4c27c16aff9c9911640b1bdf6e1172237ce540ed4dc3e166e9438f0d7",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-pc-windows-gnu.tar.xz": "aa1d30f2f66d0198ea304047262f9142c406618a35acc466c7ad2b2c1469435d",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-pc-windows-msvc.tar.gz": "92716346a9049ae0dd826818dc280935e1af3010ecb779e3f6846efc579ec993",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-pc-windows-msvc.tar.xz": "0d1f0399d4d9dba7e9daf2e957c0e7a6107538810a3265ba4f4e04763b21f001",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-sun-solaris.tar.gz": "67282df0d68c1bcafa4bc91ee2dcd73162dbe6853e76d9e451e35b86cb59206c",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-sun-solaris.tar.xz": "e02525a18d1ba50b4ae01816f33404331ec60a793d2106296839726cd5ac3aed",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-freebsd.tar.gz": "eed4b3f3358a8887b0f6a62e021469878a8990af9b94c2fe87d3c1b0220913bb",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-freebsd.tar.xz": "2cb020438164d1bc40ab6e5909c0ae3a71ee2d549d3821bad1d99d2eb70b2f57",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-fuchsia.tar.gz": "cceaf7bfeb626618cf6a9515baf933bbe424f7b5880fa04d41afaa6cd4bfcc09",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-fuchsia.tar.xz": "03205a4e7b01b91fd689198c301af1456b4efc333021ab3e0e3ec1e0518bf557",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-illumos.tar.gz": "d736e1f9da70759c027614b998973b06f177e41be9a2fc3545b5e77d5db0c9c0",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-illumos.tar.xz": "7b8252e74c50479d43d14217b5a9cf3882f6ecd7b2ff9e7a133f2233065abd66",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-linux-gnu.tar.gz": "b6986b4042af7b17fc8f51127018617b32d45cd555c582efa816ac194d4b53df",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-linux-gnu.tar.xz": "4c95739e6f0f1d4defd937f6d60360b566e051dfb2fa71879d0f9751392f3709",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-linux-gnux32.tar.gz": "560e938f5dfed51bb9b99614cd3dd1a01a035670cb76760ccd96922a7a5bf53f",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-linux-gnux32.tar.xz": "0166c4a3df3e2d86f448daa46076e3201999f1be1cc54031b28e6e00445ead1b",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-linux-musl.tar.gz": "9eb5cd25b488bfae389fe205d447199127cbf87b00974e7f850e7f1df19d4485",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-linux-musl.tar.xz": "29d98c004629ab536bd2461f715f26ddce3b0f0212db85939c7bc66a8d234b2d",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-netbsd.tar.gz": "5b94230d2d7e6cb0c08fc1ac4604a35b5c57c7998bb5df4121bef54c340a28f1",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-netbsd.tar.xz": "9875615c721f6b5fa06f370bf8c1f44a2ec2890472a40a5b26206cac3185d35f",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-none.tar.gz": "067beff146e3426076d2426da98f6d8ff8ccb1aefb5afe96f816a786580304e7",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-none.tar.xz": "8947fd736a2204bacd7d5c6efa9f4210a45e279ed49a72a773dad34fcc7da0d3",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-redox.tar.gz": "cacdece6813823fdbb9967178c08ec8ceadb0ef41dd9913908437e5eedc77fcf",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-redox.tar.xz": "8bf860514dcc4d0f0d7f5c35f48d4aa6c5c9733af13fb9387f19d456c62b6708",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-uefi.tar.gz": "02c61dec4851d522d8aa754681cf37db81f893e5a2c40566975ee99139e9f748",
- "dist/2023-04-20/rust-std-1.69.0-x86_64-unknown-uefi.tar.xz": "631f840671a475824cd60206eccbd5ed743289b08b39f8d6f06c259a0bcea128",
- "dist/2023-04-20/rustc-1.69.0-aarch64-apple-darwin.tar.gz": "aaecbc9591591b42f02befedb5c4a04c8faeecfacbaffb5c9ee4ad1f77b0a3ed",
- "dist/2023-04-20/rustc-1.69.0-aarch64-apple-darwin.tar.xz": "4cabd9d45777ca0d5cf88e32391940f7983083727f136421385fdb60d4d00d6f",
- "dist/2023-04-20/rustc-1.69.0-aarch64-pc-windows-msvc.tar.gz": "d771891b523628d0eb46f40b4b612cc7772cfc81c90f07d8a716c143a51d3f4d",
- "dist/2023-04-20/rustc-1.69.0-aarch64-pc-windows-msvc.tar.xz": "71b56ad71e36350a9d43b1cdf607d488228fa53ac5ccf04e64f6661a0998b2c4",
- "dist/2023-04-20/rustc-1.69.0-aarch64-unknown-linux-gnu.tar.gz": "b240a2d8182adb0aa2978ba8ec4812014b3a93a1aa36f10ca2ef3b1f4d80a47f",
- "dist/2023-04-20/rustc-1.69.0-aarch64-unknown-linux-gnu.tar.xz": "d14166fa0b2832dd87b3f35c08d0bc829f83aa01a539b45df3d923469ee119be",
- "dist/2023-04-20/rustc-1.69.0-aarch64-unknown-linux-musl.tar.gz": "192e9ab084f82aa71acf40cab6a39752d8e301c78ce2303f773fee082e146765",
- "dist/2023-04-20/rustc-1.69.0-aarch64-unknown-linux-musl.tar.xz": "c8d318691ed0acfd7fc70713fc14b3ca34693cac68f1b593ea12e15cd3f175fb",
- "dist/2023-04-20/rustc-1.69.0-arm-unknown-linux-gnueabi.tar.gz": "6a32cf470f510d0882f9570524a5616db644df6a409c99922d5c74ed8bb8a42d",
- "dist/2023-04-20/rustc-1.69.0-arm-unknown-linux-gnueabi.tar.xz": "c6f226dd756836c88977591acadb4c41c4eb6e5e58aaa2042cfb9538e24d2732",
- "dist/2023-04-20/rustc-1.69.0-arm-unknown-linux-gnueabihf.tar.gz": "e5e5fa9ad8e7e5d455f515c8308e870b9916ad836f0ceb36897a16c3bab24924",
- "dist/2023-04-20/rustc-1.69.0-arm-unknown-linux-gnueabihf.tar.xz": "213183f703239b2fb489837be29e0f9b27681ae25ac9bd2f2e7960f133aa432c",
- "dist/2023-04-20/rustc-1.69.0-armv7-unknown-linux-gnueabihf.tar.gz": "53dc923efcfc8c6dffe8a635d24668d0146732228deeb6a560e1e3baedfa4fd8",
- "dist/2023-04-20/rustc-1.69.0-armv7-unknown-linux-gnueabihf.tar.xz": "257e049d561c71f1765bb72f1bfe98aa8407604dc85965ae178e110bc05948be",
- "dist/2023-04-20/rustc-1.69.0-i686-pc-windows-gnu.tar.gz": "09f6d97a1abe649462ce1ddd0b0a88aab3423c59966b6032847d52b78291813f",
- "dist/2023-04-20/rustc-1.69.0-i686-pc-windows-gnu.tar.xz": "1c4435d12c94c26ec46371e767f975d666b50b5e746f0b8218ee07bbb1cfebf0",
- "dist/2023-04-20/rustc-1.69.0-i686-pc-windows-msvc.tar.gz": "3125fe8d3787a714988fe4b42a2b708a58d176c355130df5ae87d8844ca82940",
- "dist/2023-04-20/rustc-1.69.0-i686-pc-windows-msvc.tar.xz": "48f63fef58e5c71b71156e3eec7de761df330fbbbe857ad2d6c1e5cea1d39d07",
- "dist/2023-04-20/rustc-1.69.0-i686-unknown-linux-gnu.tar.gz": "aca43ad204a3ced049e389f4187afbe14015acdd803bdf6269b0a6a45ab9ffa8",
- "dist/2023-04-20/rustc-1.69.0-i686-unknown-linux-gnu.tar.xz": "788ff61555857680d5ea7cf76023f74a7f4820dd1c26abf76536561d4de3cbe6",
- "dist/2023-04-20/rustc-1.69.0-mips-unknown-linux-gnu.tar.gz": "59905d9f35bce7b60cda2c63ea9190cc25b6b2f57685bc31d76ef84a1dce9106",
- "dist/2023-04-20/rustc-1.69.0-mips-unknown-linux-gnu.tar.xz": "ef17b364df355f7322c1fdd3b4cc4296d2d5d489b58fdd4b12374a1f2975a455",
- "dist/2023-04-20/rustc-1.69.0-mips64-unknown-linux-gnuabi64.tar.gz": "b8845364e72c5e4d443964e93a696bec03c4a4a4f678afbde919348c8f36a517",
- "dist/2023-04-20/rustc-1.69.0-mips64-unknown-linux-gnuabi64.tar.xz": "f9823eb52b271c7ac9a3558e0ce46af097129df9c93cd465969ffd1f8134fb56",
- "dist/2023-04-20/rustc-1.69.0-mips64el-unknown-linux-gnuabi64.tar.gz": "e96f6b9f06cffc4355699e68e53cb7aa3efaed9f51591432cc5abd51dfa2fa04",
- "dist/2023-04-20/rustc-1.69.0-mips64el-unknown-linux-gnuabi64.tar.xz": "d2087d9a0dbca57a56873ed93b7b09a113c2a46e4e3510d58bc5b1a84abe2bd9",
- "dist/2023-04-20/rustc-1.69.0-mipsel-unknown-linux-gnu.tar.gz": "171f6b39356f311d595a87bae356f7f6795dccc7c3f3909b50d23032fa610f4b",
- "dist/2023-04-20/rustc-1.69.0-mipsel-unknown-linux-gnu.tar.xz": "9df4110f716a309323a776952fcf0dccaae878e7abf0d148c14a2a03c5170850",
- "dist/2023-04-20/rustc-1.69.0-powerpc-unknown-linux-gnu.tar.gz": "9c392fadcf728fac7bee91434989980b7093a1f210a9815cf90bc76829bb9085",
- "dist/2023-04-20/rustc-1.69.0-powerpc-unknown-linux-gnu.tar.xz": "716e790b7658206c59dc8019c1b603f230c5ce945229463367fade862cea60b9",
- "dist/2023-04-20/rustc-1.69.0-powerpc64-unknown-linux-gnu.tar.gz": "31bd957c3c2af76d883f9ba60b71bbb508b8d59c317d703d2554186ab833ce43",
- "dist/2023-04-20/rustc-1.69.0-powerpc64-unknown-linux-gnu.tar.xz": "313d0944a1fc41c1c5ce0a054b3cebccd6f471ce8e8272e5e68f36b8d08e5bb1",
- "dist/2023-04-20/rustc-1.69.0-powerpc64le-unknown-linux-gnu.tar.gz": "e72b2b5729fc8f3dc5f6786d81e601fc6b367055c28a49f82fea842d4b27dbeb",
- "dist/2023-04-20/rustc-1.69.0-powerpc64le-unknown-linux-gnu.tar.xz": "1781b5be30fa4fadf7608cc9cd3a2de93b3671a09adfa98ae4d975f789ba2275",
- "dist/2023-04-20/rustc-1.69.0-riscv64gc-unknown-linux-gnu.tar.gz": "72e10b38b490c6c1ca970fe215ccb2b8794878e2e8165db3f3efe02c51bcf6df",
- "dist/2023-04-20/rustc-1.69.0-riscv64gc-unknown-linux-gnu.tar.xz": "03606f1ad3fd196e73e0d255ab6342e4e8fef2edaa1afcc577411aa8a68f0133",
- "dist/2023-04-20/rustc-1.69.0-s390x-unknown-linux-gnu.tar.gz": "21517868b8991366b07965d7daecd101f8e1ca8fb137f0ab90e4807bbe888263",
- "dist/2023-04-20/rustc-1.69.0-s390x-unknown-linux-gnu.tar.xz": "3cef208c0761bc83d156a14a5a94821cc9421772f0f376ea54765a6d00842b21",
- "dist/2023-04-20/rustc-1.69.0-x86_64-apple-darwin.tar.gz": "7b337037b7b7b2ec71cd369009cd94a32019466cdae56b6d6a8cfb74481a3de5",
- "dist/2023-04-20/rustc-1.69.0-x86_64-apple-darwin.tar.xz": "63136b7163226f41ec5ff14b5344b3b5741db85a412c6b1162a1da457a76cd2d",
- "dist/2023-04-20/rustc-1.69.0-x86_64-pc-windows-gnu.tar.gz": "8ee73321d9d4d9929aa034af513a8c8ca73fad7ee79a72fb590e728697a5f2f8",
- "dist/2023-04-20/rustc-1.69.0-x86_64-pc-windows-gnu.tar.xz": "086563a9b8fd7d31677bc3b091b7d015910b44aac74c6ce2cfcd8da42da819f5",
- "dist/2023-04-20/rustc-1.69.0-x86_64-pc-windows-msvc.tar.gz": "5b4baa74b0a078674ad9ce52725ac61343428b2f7de1dcee1a10041560f5d2d8",
- "dist/2023-04-20/rustc-1.69.0-x86_64-pc-windows-msvc.tar.xz": "438dd475deccdc78c7580eb0098b2864e6a329ac87bda1559440a7100cbbc47a",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-freebsd.tar.gz": "a8d03185ede0b020a6eaba16a077363c8524768a587b30899dcc497607698f75",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-freebsd.tar.xz": "c608b776adcb0a04edeb43a898e0803c4d4e285294cd21e692017531e51932f9",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-illumos.tar.gz": "f3dce28649299ea5d8ab234a82c52f6da5cc95aafdf622dc76f8aebfc3400c00",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-illumos.tar.xz": "5cf5f7e486dce727e559cb1dbb9518b981ccba4c1b5c488979e19d76964eff3e",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-linux-gnu.tar.gz": "edd616432207bee868bd585fdd7c7229699f8bc3ffdcfc90e5a7404aba0d30f4",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-linux-gnu.tar.xz": "70e97ab5b9600328b977268fc92ca4aa53064e4e97468df35215d4396e509279",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-linux-musl.tar.gz": "9a1fd85b9c69b98eb14a33d54e71d3f8708fd24ac09e4b54a3433c6a421a166d",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-linux-musl.tar.xz": "7d9e64850a79292d2cda6f4464dfd67d2cbd22ac8c7f3e170291396ef8be8041",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-netbsd.tar.gz": "6d9c4d3682627539fdbe1349c5f5c92606d47a222c02d701425c0dec0b7afceb",
- "dist/2023-04-20/rustc-1.69.0-x86_64-unknown-netbsd.tar.xz": "b7fcfbef784ad51286eae4eed5b70678b7ae9c8e52e56f31fd2ce03beeb445de"
+ "dist/2023-06-01/cargo-1.70.0-aarch64-apple-darwin.tar.gz": "42eee022368b143c45cd86905d1c9b5ac28fe0608288a805b508a0435c1433e6",
+ "dist/2023-06-01/cargo-1.70.0-aarch64-apple-darwin.tar.xz": "faa0c57eab1846f4220e0833a167b845799bfc2d43aee819db7e9f5fe7d5a031",
+ "dist/2023-06-01/cargo-1.70.0-aarch64-pc-windows-msvc.tar.gz": "f175065a97e33c1a12bffd255797db04b6187269315de235f918cf4d92f3de3f",
+ "dist/2023-06-01/cargo-1.70.0-aarch64-pc-windows-msvc.tar.xz": "64f6268735bc5b067a21c7eea10357c45c8d1d71c977caffcd23d1186a4ad08b",
+ "dist/2023-06-01/cargo-1.70.0-aarch64-unknown-linux-gnu.tar.gz": "b711859b9cc39c8c0aa5aa50559a2905d20fc229cfd5bbf9a7fdf02477d18e2b",
+ "dist/2023-06-01/cargo-1.70.0-aarch64-unknown-linux-gnu.tar.xz": "8fd2d9806f0601feab1485f79e46d1441af2158c68abf56788ff355d5c6b4ab5",
+ "dist/2023-06-01/cargo-1.70.0-aarch64-unknown-linux-musl.tar.gz": "022fd4d69923d5ed685cd2a4b4e17bcade6eed01ccb0a8b7326842d17a3a77df",
+ "dist/2023-06-01/cargo-1.70.0-aarch64-unknown-linux-musl.tar.xz": "9d09de7cb77372a53baa9e1a02bba96913b8192896a4207660dc760642b151a7",
+ "dist/2023-06-01/cargo-1.70.0-arm-unknown-linux-gnueabi.tar.gz": "186fed2acd8bf9424c9d76cb22350d058ceff7c3d606c901005779c2bd92aeeb",
+ "dist/2023-06-01/cargo-1.70.0-arm-unknown-linux-gnueabi.tar.xz": "4bfd3e6214c1c2582dfc6d6cbd4d1cbb55f083ea461d4ad004e76ffc4113ee6f",
+ "dist/2023-06-01/cargo-1.70.0-arm-unknown-linux-gnueabihf.tar.gz": "9fc820a9391388207500e507eb317d48be396f2b244cc6ee6ca4677a6be8d609",
+ "dist/2023-06-01/cargo-1.70.0-arm-unknown-linux-gnueabihf.tar.xz": "b932b2d562a1383b1fae5e2931f85fd5ea0cbb5da2c7605d5382d7d2680efd7f",
+ "dist/2023-06-01/cargo-1.70.0-armv7-unknown-linux-gnueabihf.tar.gz": "ce4de253a3fb1376701da5d2be4d1c338721695a9da027ac1d710f5d0a084ff0",
+ "dist/2023-06-01/cargo-1.70.0-armv7-unknown-linux-gnueabihf.tar.xz": "ed08b631d3c2de83eb820f88e95ffbb94a2ec48e73f4d316582b6ee807298d1a",
+ "dist/2023-06-01/cargo-1.70.0-i686-pc-windows-gnu.tar.gz": "2e5551a0827b9ff5d8faa0ea08096fc7f9d7b597c0084e427fe16d04d3ab36fa",
+ "dist/2023-06-01/cargo-1.70.0-i686-pc-windows-gnu.tar.xz": "504de4bb3218c474d2a2a3b0a084d360d9430473425d51c5b602404d634389ed",
+ "dist/2023-06-01/cargo-1.70.0-i686-pc-windows-msvc.tar.gz": "cc221209be51d30ffd484618c7d805e9a7a90de5aa6c584cd52ef0882741d9bb",
+ "dist/2023-06-01/cargo-1.70.0-i686-pc-windows-msvc.tar.xz": "3f81f3951654f1dc1ccd0d3af9cbb83c3de354bf4fbdf975d0f6581b80caa6cb",
+ "dist/2023-06-01/cargo-1.70.0-i686-unknown-linux-gnu.tar.gz": "c8a53cfd0537e33585c8b9cd65fd73db9991453cfda421c28832338cd4af87fb",
+ "dist/2023-06-01/cargo-1.70.0-i686-unknown-linux-gnu.tar.xz": "5d20e9b8e56f641c3ef4aef965563806aa220044397485ec56f784657451a329",
+ "dist/2023-06-01/cargo-1.70.0-mips-unknown-linux-gnu.tar.gz": "8518af371c34411b7a680a2b3a39b368e5298aae70cc71a8c160e9a58e81d709",
+ "dist/2023-06-01/cargo-1.70.0-mips-unknown-linux-gnu.tar.xz": "a272a2a34f03a89e1bc89d9bb11ec0dee08428f43b5103785a587091b3911c60",
+ "dist/2023-06-01/cargo-1.70.0-mips64-unknown-linux-gnuabi64.tar.gz": "a559c7ba37b195c647e33fd292c6fde0f50700fbcca573eac59cc432192b5aa6",
+ "dist/2023-06-01/cargo-1.70.0-mips64-unknown-linux-gnuabi64.tar.xz": "a55aa69bae509f752a92731ffc83fee4624f5010766521a2f80aa1f3d7c2ad31",
+ "dist/2023-06-01/cargo-1.70.0-mips64el-unknown-linux-gnuabi64.tar.gz": "a71d5424c1524f515d6e5f957d5fb48df6c4ff20d927f593bcae55492faa1415",
+ "dist/2023-06-01/cargo-1.70.0-mips64el-unknown-linux-gnuabi64.tar.xz": "e7fd7709883bebce0706d4ecff4ea7b0c2f64f22a21f5b4f9ba5ffe06f32e26e",
+ "dist/2023-06-01/cargo-1.70.0-mipsel-unknown-linux-gnu.tar.gz": "4fc41dd6a5e2ef17df0cae32ee01c514ea1b3d5ba6a7b0719598ba62c86cf152",
+ "dist/2023-06-01/cargo-1.70.0-mipsel-unknown-linux-gnu.tar.xz": "25d2aaad531403359c60ed3035005db782ba041549fdb60d3ef1a5b5a04b2970",
+ "dist/2023-06-01/cargo-1.70.0-powerpc-unknown-linux-gnu.tar.gz": "cfc169a4d58399cf2613b1bb66d4a063c5656412d520fd70dd5644bced4d42bf",
+ "dist/2023-06-01/cargo-1.70.0-powerpc-unknown-linux-gnu.tar.xz": "314ed27bbf7eed16f6ac0092b076a82782630c65927a241db921d1eff8b04759",
+ "dist/2023-06-01/cargo-1.70.0-powerpc64-unknown-linux-gnu.tar.gz": "ad2eda1e8938e40ce6ebaa7afada2b0e421a752874829d443dc058f2630231de",
+ "dist/2023-06-01/cargo-1.70.0-powerpc64-unknown-linux-gnu.tar.xz": "ccb5b4c03f4d359cbeb1739ba27b725b0fc9d0d55b22837b0d3904e778a7fdc9",
+ "dist/2023-06-01/cargo-1.70.0-powerpc64le-unknown-linux-gnu.tar.gz": "ea84732e31445c918d108cb5984d21f10b96b13eb6eab263f88288dfb255b669",
+ "dist/2023-06-01/cargo-1.70.0-powerpc64le-unknown-linux-gnu.tar.xz": "5f1751ab8d44a9c9e083d32a8039980d699a1224654e3f5aa0dfffbc4407f1c0",
+ "dist/2023-06-01/cargo-1.70.0-riscv64gc-unknown-linux-gnu.tar.gz": "599e36dacde553188c88b222341ca78cb1dbcb83e96fa84a3ac67e605d1c7345",
+ "dist/2023-06-01/cargo-1.70.0-riscv64gc-unknown-linux-gnu.tar.xz": "55c3a5c06b14c954df5318073c38a5b4b0ace3f9a32a24f0ef5514941f7c9502",
+ "dist/2023-06-01/cargo-1.70.0-s390x-unknown-linux-gnu.tar.gz": "dd6abba5dadbe482d415bde69b5b30a442f8c809950002da5a04042a65bafa99",
+ "dist/2023-06-01/cargo-1.70.0-s390x-unknown-linux-gnu.tar.xz": "dc4104e9e4b82dff14ffb20233d412ff57cea27e7bb2064b6a7e660fee6d2c4d",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-apple-darwin.tar.gz": "e8f67154ae8faefb81be06b8804658cdde39d96e8fbd6b5240a9ef9d95f49f57",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-apple-darwin.tar.xz": "0aa4661564be110614874812891d29b327eb343d2eb1eaf9862438aa2436f6b5",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-pc-windows-gnu.tar.gz": "f30050975bc9481ef1e4551c1e3f240e1f623d8dbc80e7763b8d4d5cfa98a88f",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-pc-windows-gnu.tar.xz": "1cac9d61249c6e77da888f3cbf067bbc6567fbd6007781e613dfc9fed67c3613",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-pc-windows-msvc.tar.gz": "7a60c81b92a0bcec5586d2878f3b6853d2cf2b27968ac7f5d8f9f26f1beeae78",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-pc-windows-msvc.tar.xz": "8081450d37db51e24fc30d4b89f8cdf2310c4696764dd08baead6022f35a39a4",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-freebsd.tar.gz": "cf9a5c8b2463a67723ace3d696d8a0d39deae8ebc88223c5d022606fee8a5ceb",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-freebsd.tar.xz": "91baa04632e97d7641f313801fd0ca2f42695a665548d505049c0a15614ceb7b",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-illumos.tar.gz": "dd524762e9c989acf9267ed4cf54928c1e579da66bf82b4700e203204263b6a9",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-illumos.tar.xz": "a76c2cdaf59017e0706dee94184916c2fa65f757834e361bbdf0e4864a4d3314",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-linux-gnu.tar.gz": "74e049e657f544d146013746e53ecf427f47f0d5f1185bef1b28c2c8ace43253",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-linux-gnu.tar.xz": "650e7a890a52869cd14e2305652bff775aec7fc2cf47fc62cf4a89ff07242333",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-linux-musl.tar.gz": "0bfa400bd24b49ff8511fefe37941805fd7af6a36181bbca7aa4f49c38e8265c",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-linux-musl.tar.xz": "4d7513e23b8710ebacb01ed333d00692331295e45191f5c0795aada00f291d19",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-netbsd.tar.gz": "86680ee268134b987d0ce0ea9d9e65d70b49f0a876f04f2e42a31c2e6fb7991c",
+ "dist/2023-06-01/cargo-1.70.0-x86_64-unknown-netbsd.tar.xz": "a3dcdf97c9c91d1b20e83088d184695d14aa88680889f515cc353e0c14bca45f",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-apple-darwin.tar.gz": "7fa4b1390784ab83cdef0b1dcacba9710024bb47867b72d09d6b9a711bebceb6",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-apple-darwin.tar.xz": "cea769733d661c25199ac200b3ec522e4e935c610fd8c3a55f24360f1b8ec616",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-apple-ios-sim.tar.gz": "4a8923a1357380b4b327f71f2ede0fed96926c78431175ed206f3cad588b9a30",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-apple-ios-sim.tar.xz": "5c1123492ba1fbf04df9bbc93c7b083c9ebbcbd2951d2c5df76f6bf538141fb7",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-apple-ios.tar.gz": "e90967bdd3294abe09058e4380e8a6be8921a00045f8cb495e6826f417e94391",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-apple-ios.tar.xz": "e7e7d8956960d13a80742418b84f72c153d4f09240b16e5aed7fde07ddb8829a",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-linux-android.tar.gz": "da51305740bcc127973eb0f99de2c359b4a5c1d83eee54621a27e10e89562d0f",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-linux-android.tar.xz": "cb9eda61bb6f5fdfe1fa4877d6efc09f75c47a4d25c7c3519ff3e351180e215e",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-pc-windows-msvc.tar.gz": "9690d19f74fed2a26128a448457304e1532dc33e75bb2cd9bb57ee749f7c49b2",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-pc-windows-msvc.tar.xz": "1c42af0f69c2c3896b7e08edbdbf07da4764b520b1aa862dd9cb1b86e6ad298f",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-fuchsia.tar.gz": "b17b9d12f866a42a346200dc5809ea5a55414880cc1f9c137a35b96a8c7bb674",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-fuchsia.tar.xz": "8acf89e4bd5ada1aae43875df592f338469615db939c9cab9b8d2e4e35d5ea73",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-linux-gnu.tar.gz": "78e8ce250a7ba30b7b9e55406915d42d160074c3a0e10540f13a69144c85a981",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-linux-gnu.tar.xz": "966e85187b6b76dc520b23aadc886c5fe54b209a21c68f959ff00ef8542b7f9f",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-linux-musl.tar.gz": "5a33fe20263781a6821d52d2b2712e5322d8c2e29311b70a9fb0d5d7449c2033",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-linux-musl.tar.xz": "277c2313f0ee420851c4009f15ba4d474000e0495deef38b0b636d6837e4f15f",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-none-softfloat.tar.gz": "0ebdd87e1891187ab0cd59d89ee92f87ecb07397afd235ac809a111650e3a353",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-none-softfloat.tar.xz": "6fcf96a7e1a96c8e9e509f1202df12cca3862b29a988145a3aca10cf49f8b258",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-none.tar.gz": "2513a665b9654ad998008637901ea2976b828a5eacd961036e27e976caca65c2",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-none.tar.xz": "572efe81c47de72097ab4f13df6c687734fd049b339cee8d3c18526ffc3fa026",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-uefi.tar.gz": "2e661193ec69453b971b75dbab7b87dc66a5fba793c6c13f2d8986c019453ccb",
+ "dist/2023-06-01/rust-std-1.70.0-aarch64-unknown-uefi.tar.xz": "9abdb94c7675dd2497d5ff893389877160c248bd59964c12b21b066e2aa6de1e",
+ "dist/2023-06-01/rust-std-1.70.0-arm-linux-androideabi.tar.gz": "98314996a3396024f6359fea03eb00293cdbbe5014ebe85479edbcbb9bb758f8",
+ "dist/2023-06-01/rust-std-1.70.0-arm-linux-androideabi.tar.xz": "2a2a426ceab00962973cf62a74758f12a5552add7374cf049225b1cbd331cc7f",
+ "dist/2023-06-01/rust-std-1.70.0-arm-unknown-linux-gnueabi.tar.gz": "0bd625326fa48ddba9a6d0de8a5a24eb9a415e599004875fec8edaea869aa468",
+ "dist/2023-06-01/rust-std-1.70.0-arm-unknown-linux-gnueabi.tar.xz": "a6bf20e4eb5b88cd193ea2a126efe1a33651dc0be47080488be2cfff41c29272",
+ "dist/2023-06-01/rust-std-1.70.0-arm-unknown-linux-gnueabihf.tar.gz": "ebe12136f46269365a291f742e69986eea6736718e3493e80444f4df5986e9a4",
+ "dist/2023-06-01/rust-std-1.70.0-arm-unknown-linux-gnueabihf.tar.xz": "6ad1231aeb34fef9c9db267859b0db3c6846bbade8227e6c9f456b6264c1278c",
+ "dist/2023-06-01/rust-std-1.70.0-arm-unknown-linux-musleabi.tar.gz": "9d168273c1d660908dca84355934c2f1cc1119dff7a30a443e449125ad9d8114",
+ "dist/2023-06-01/rust-std-1.70.0-arm-unknown-linux-musleabi.tar.xz": "f72c1983fcd90c338c62747b15964103518ec377530df2e71e35f7ea16eeede8",
+ "dist/2023-06-01/rust-std-1.70.0-arm-unknown-linux-musleabihf.tar.gz": "bcf04409b603b5fb4725981bb13dbf03a6c9e81af3790ce8f7095a00927c11ee",
+ "dist/2023-06-01/rust-std-1.70.0-arm-unknown-linux-musleabihf.tar.xz": "0b021ad310e638e90ae64b60c5a898f2f30ec77fcc1622e3775abb5476200de4",
+ "dist/2023-06-01/rust-std-1.70.0-armebv7r-none-eabi.tar.gz": "4ab272896ef991ec5683c002f67d0b4c944fdcc6c303dc5083d371698bbb5623",
+ "dist/2023-06-01/rust-std-1.70.0-armebv7r-none-eabi.tar.xz": "8624b97221d155f585dbb717cd15446e125ac086e070d8e4979518c3b11c8792",
+ "dist/2023-06-01/rust-std-1.70.0-armebv7r-none-eabihf.tar.gz": "659e7ef8308e32761043b11dbc1470504c399e323fd82c44c311194093480d53",
+ "dist/2023-06-01/rust-std-1.70.0-armebv7r-none-eabihf.tar.xz": "faafcb8562c48ca3a8512e21abe9ece3da9a3a824d331b776b60de213ca00c19",
+ "dist/2023-06-01/rust-std-1.70.0-armv5te-unknown-linux-gnueabi.tar.gz": "2ec260dfaeec9d14e15e48735ddc257431b35c89a0e5bfc5050483b1f2d2ad0a",
+ "dist/2023-06-01/rust-std-1.70.0-armv5te-unknown-linux-gnueabi.tar.xz": "93929160b961ea6feb0dd0c64aa0571e1e2dc3024a4e2d7ae9ab5f75b1950fd9",
+ "dist/2023-06-01/rust-std-1.70.0-armv5te-unknown-linux-musleabi.tar.gz": "8c34946c2e11e8755999374bb8dbb35f7279c3f6b55277328c029cdbc2485343",
+ "dist/2023-06-01/rust-std-1.70.0-armv5te-unknown-linux-musleabi.tar.xz": "4c4614c95bbd62665258248cc59d03d0d36e2034971892bd8f01659cdb953740",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-linux-androideabi.tar.gz": "bcc76e07fbcf106aac0d46fe1dda998da4d2cc947920f8bfe1524bdebcf36313",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-linux-androideabi.tar.xz": "1c20f48f0496aecb40a89edb04bc885fb80419b344b315a0a3d12842ce4b276d",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-unknown-linux-gnueabi.tar.gz": "4488a21b3278f0fbc70646485d900a185c9bbf6090bd08b5b636d79ddfa7c8cb",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-unknown-linux-gnueabi.tar.xz": "3edd71ce8102783c99b9b6661577ac1acf6a633156234ee220a20aa3d7190ebb",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-unknown-linux-gnueabihf.tar.gz": "3e3687fa87ce6549cc1f508d4888508531d70482fce210c19dad24b29b8e4e1e",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-unknown-linux-gnueabihf.tar.xz": "9baaca8ed2a71040480654a1ff3c9917e017ddfe78030b054ad82aed9b94c11e",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-unknown-linux-musleabi.tar.gz": "e861fd9a04af396afe35f3c61d1f64a26b30f1cadd63f53c5ece865a474e4a4d",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-unknown-linux-musleabi.tar.xz": "f9d5ce6b4bff635151579726ebf264b905679f42917283fa1268d86f7c82a55f",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-unknown-linux-musleabihf.tar.gz": "57d075caeac0ffdaa0c47accf7fdf6458f5b73fbd8cbe3c42937d348d422f056",
+ "dist/2023-06-01/rust-std-1.70.0-armv7-unknown-linux-musleabihf.tar.xz": "aaceb71de5268510cbfb59c356ef2f7fb539f89b57116a2d3a513d06c411bb35",
+ "dist/2023-06-01/rust-std-1.70.0-armv7a-none-eabi.tar.gz": "0e43c3ba4662fbb53ba23fd72249ba61f8b2e1942c98b181991651bd650619c1",
+ "dist/2023-06-01/rust-std-1.70.0-armv7a-none-eabi.tar.xz": "19fb24833ba3cb53c178e6c5ae93388cb5823cc8b2ffe569d8191cc436857a57",
+ "dist/2023-06-01/rust-std-1.70.0-armv7r-none-eabi.tar.gz": "56be0cff450aebd97618dac1ad95668007366b3377f702f8906056ed456eb4a2",
+ "dist/2023-06-01/rust-std-1.70.0-armv7r-none-eabi.tar.xz": "d77952b7516e64ea17b9aab5077a7e6c82801a7f72ff56ca23dd03c87040966a",
+ "dist/2023-06-01/rust-std-1.70.0-armv7r-none-eabihf.tar.gz": "85ba8bce13b66918dc38574273e6398d751e838e271ea3b4a755e873e87ad938",
+ "dist/2023-06-01/rust-std-1.70.0-armv7r-none-eabihf.tar.xz": "4090a0707364c1d93155def78a2a4ff0707873ebb1b798a760376bc2999038c4",
+ "dist/2023-06-01/rust-std-1.70.0-asmjs-unknown-emscripten.tar.gz": "1af5ed9f0b633c0e64eff30115ffcbf0f02cce2d53b6287a740ce10fee8e80c4",
+ "dist/2023-06-01/rust-std-1.70.0-asmjs-unknown-emscripten.tar.xz": "4d4aabfb6d73c05bec2728cdc2c9f39b4a5d2afd0821ec0f52b4fa6af0d6e2e0",
+ "dist/2023-06-01/rust-std-1.70.0-i586-pc-windows-msvc.tar.gz": "d579fffc528f65e0b0f5f53655aa0c45d941306c1dac4bded8794c02c099d969",
+ "dist/2023-06-01/rust-std-1.70.0-i586-pc-windows-msvc.tar.xz": "5247fbd7dafffbbf1fa1399c629ad15291542298224b2c97eebf210f9148353c",
+ "dist/2023-06-01/rust-std-1.70.0-i586-unknown-linux-gnu.tar.gz": "139677e14811f4a735cbf3b639f866ea48c153489e70ed021ee54d4840478182",
+ "dist/2023-06-01/rust-std-1.70.0-i586-unknown-linux-gnu.tar.xz": "f52e3ac35157e90f86e5ca6c177a43774425c24a51b15655ed61f6209c7db6f0",
+ "dist/2023-06-01/rust-std-1.70.0-i586-unknown-linux-musl.tar.gz": "02e758d78c0ea8dbf7f254c224d32d3806693bbf5c04597a77918308222b4929",
+ "dist/2023-06-01/rust-std-1.70.0-i586-unknown-linux-musl.tar.xz": "1a42665bb54eeff908f833dca12e917d6ce87140139ec56702b9d88cda61be79",
+ "dist/2023-06-01/rust-std-1.70.0-i686-linux-android.tar.gz": "f7a6c27128ef16f6fc5ff9d8cd5b8c93425e28f4abdbe750f2123a3212cdc04c",
+ "dist/2023-06-01/rust-std-1.70.0-i686-linux-android.tar.xz": "305f084e00f1c0ec0a3ed6162a0cfd59d4e2db03e1f5c63b0f1c9e54ebe93075",
+ "dist/2023-06-01/rust-std-1.70.0-i686-pc-windows-gnu.tar.gz": "33a3e0564bf5c03adee926bb7c709f5b3cab3d8b8c031b54308260d2f325f247",
+ "dist/2023-06-01/rust-std-1.70.0-i686-pc-windows-gnu.tar.xz": "d51dac4f4085f88a12e2d4967f7d81a31ec1c5376190dc63e644b32eddb538c1",
+ "dist/2023-06-01/rust-std-1.70.0-i686-pc-windows-msvc.tar.gz": "722d78650e81d68e4c1751f89e615381810445c0ba602aa0e135a44d00143f57",
+ "dist/2023-06-01/rust-std-1.70.0-i686-pc-windows-msvc.tar.xz": "0445c24888fc00a85c144c87dd98ea1a63dc4f2d62c2ecb1c994017000b03619",
+ "dist/2023-06-01/rust-std-1.70.0-i686-unknown-freebsd.tar.gz": "9db5315fa01cb9c693f6dac3a0967d5850bc43f7fefbf345bec1fbb6e3ba42a2",
+ "dist/2023-06-01/rust-std-1.70.0-i686-unknown-freebsd.tar.xz": "528a808cad2a032ef835031d43adbadadcb0eb6ba34206e1bc441a1cb98f7cbe",
+ "dist/2023-06-01/rust-std-1.70.0-i686-unknown-linux-gnu.tar.gz": "6cf40f9cd6efcf225fbd3a1da62fc589c4b946c6c3e25ab4fadaa4c948e10016",
+ "dist/2023-06-01/rust-std-1.70.0-i686-unknown-linux-gnu.tar.xz": "0e5543c35196ca5b08f1b7e49fa3f3b671444d75648504cdbcfd854e2e7efd2d",
+ "dist/2023-06-01/rust-std-1.70.0-i686-unknown-linux-musl.tar.gz": "094aeeef5741cdc3b293cd9b777ce6be1c64b98c0a4850c104aa35bad4f250fa",
+ "dist/2023-06-01/rust-std-1.70.0-i686-unknown-linux-musl.tar.xz": "19ef3b0f6e52f81cd17f0d98a692c48fe02e85570d1e36b6369a7294ae875e2a",
+ "dist/2023-06-01/rust-std-1.70.0-i686-unknown-uefi.tar.gz": "1e7b6ff0b7d8bf61721d5797cd44bc0edd88d8852d20a68e157c753da7550613",
+ "dist/2023-06-01/rust-std-1.70.0-i686-unknown-uefi.tar.xz": "6faae7be58a732d29419752f787d4d547fc217eddbca8e531ef6b176a5ef36b6",
+ "dist/2023-06-01/rust-std-1.70.0-mips-unknown-linux-gnu.tar.gz": "c1bc7f7b963da3288bf5fa624c0e0511d1da8983bbf5cac6c3e305688a83d3cf",
+ "dist/2023-06-01/rust-std-1.70.0-mips-unknown-linux-gnu.tar.xz": "0cd85a53e328b1c445a8ec13af87f74280c1d344744076b102227f626456caec",
+ "dist/2023-06-01/rust-std-1.70.0-mips-unknown-linux-musl.tar.gz": "0a876b1829df1ee2a17b5e062d3f718067fb2292435b7008d97bf0a19425376b",
+ "dist/2023-06-01/rust-std-1.70.0-mips-unknown-linux-musl.tar.xz": "5e1abc99236050e0371ffdce8f4924e7fe46957daa7509cabc21355f62ee05e7",
+ "dist/2023-06-01/rust-std-1.70.0-mips64-unknown-linux-gnuabi64.tar.gz": "c9563b063e71fd6fa18b988c9bd43dd7c37ab0d5657418dfc1c45625956169d4",
+ "dist/2023-06-01/rust-std-1.70.0-mips64-unknown-linux-gnuabi64.tar.xz": "9624b99d806b64e11916b78afac1fac7561578c23b1321486f73f22f5e7d8710",
+ "dist/2023-06-01/rust-std-1.70.0-mips64-unknown-linux-muslabi64.tar.gz": "12a845c7c3cc539de43aaf1127ea84e56814da56141b27f97c8a8e823346d954",
+ "dist/2023-06-01/rust-std-1.70.0-mips64-unknown-linux-muslabi64.tar.xz": "de3adfd43245dadff1fdb172250189f85dbcbc848badf29d5512d5bd10ff8e53",
+ "dist/2023-06-01/rust-std-1.70.0-mips64el-unknown-linux-gnuabi64.tar.gz": "f950be0cf98529da7e3c43b62e4c71c051e79e34ba10e84effe7c5e77604e968",
+ "dist/2023-06-01/rust-std-1.70.0-mips64el-unknown-linux-gnuabi64.tar.xz": "55153a84e1a00d8426b08bb745de7eae8bd34dc65ece529a46c2b76448404338",
+ "dist/2023-06-01/rust-std-1.70.0-mips64el-unknown-linux-muslabi64.tar.gz": "e06d196fbf51c2eaba743537abbf7c1e525edac84baafaa62d7dd28348ca325b",
+ "dist/2023-06-01/rust-std-1.70.0-mips64el-unknown-linux-muslabi64.tar.xz": "39edcc0d4cc184ec320c710b41cc7401ab6f2408da3d8a6bc9c1a836429d429f",
+ "dist/2023-06-01/rust-std-1.70.0-mipsel-unknown-linux-gnu.tar.gz": "248bf2b1e24d712cc20675d62ae5bc5564f1ac5825790cd95e2fa203da46b85d",
+ "dist/2023-06-01/rust-std-1.70.0-mipsel-unknown-linux-gnu.tar.xz": "58bf8a6407d92cd4786991f1cbdec7380001e07c057c3a8946c2e54593bb7f8c",
+ "dist/2023-06-01/rust-std-1.70.0-mipsel-unknown-linux-musl.tar.gz": "071f4878958487c2c8b0e5f0774e60f0ed0cb2916a449d6015c8855676b8fe2f",
+ "dist/2023-06-01/rust-std-1.70.0-mipsel-unknown-linux-musl.tar.xz": "4dd7f934ab4d21f933e5287b7ea194d34e36b6d5a17a5a7ef3bf0b705c59f8ca",
+ "dist/2023-06-01/rust-std-1.70.0-nvptx64-nvidia-cuda.tar.gz": "5ab96af5baba98c1444eb32c2b0490892f6d569bd0748f71f5b3bd43ba201461",
+ "dist/2023-06-01/rust-std-1.70.0-nvptx64-nvidia-cuda.tar.xz": "49cb39c2724a0988dc65e5de0af20999f52e89063c2003d4fe2297761f5b8363",
+ "dist/2023-06-01/rust-std-1.70.0-powerpc-unknown-linux-gnu.tar.gz": "27c10ad6ec6fea23980a5b28d51bcdf9e4b7206636e1570bc994c0581f950907",
+ "dist/2023-06-01/rust-std-1.70.0-powerpc-unknown-linux-gnu.tar.xz": "101f358b08381b9c37c2f061bac1ff3e60c6036be20059c451f322a55f72376b",
+ "dist/2023-06-01/rust-std-1.70.0-powerpc64-unknown-linux-gnu.tar.gz": "b20694e7aa8a8684f59d297d7b9ba35c6fa1cf47e48e6108a8c27847aa400ed4",
+ "dist/2023-06-01/rust-std-1.70.0-powerpc64-unknown-linux-gnu.tar.xz": "468672f84e5b140269e188b836ec82494d65c18bda8b7cf1f9bf6fce19f222ab",
+ "dist/2023-06-01/rust-std-1.70.0-powerpc64le-unknown-linux-gnu.tar.gz": "eedc1d961cac503f70b34570739052f17ab132cef41cc7e69bddabcf8dc191fa",
+ "dist/2023-06-01/rust-std-1.70.0-powerpc64le-unknown-linux-gnu.tar.xz": "bbd882f9ec7f01a732ecc60cf50b7d8a10cd52c3de41c205f62938b6dc2b4dbc",
+ "dist/2023-06-01/rust-std-1.70.0-riscv32i-unknown-none-elf.tar.gz": "833f30fc96ca3a0b79d36cabfc793e780865a672cb3b5a1073a19446d26f1143",
+ "dist/2023-06-01/rust-std-1.70.0-riscv32i-unknown-none-elf.tar.xz": "7e68f21c521a6b005ac65fe8db699758cd8a16dd50dffdcc4a4d834f901d63e2",
+ "dist/2023-06-01/rust-std-1.70.0-riscv32imac-unknown-none-elf.tar.gz": "a27b3e785b284308e2cd4fd99c6bbd443403dffb498474ab56ae72dba67e2ab2",
+ "dist/2023-06-01/rust-std-1.70.0-riscv32imac-unknown-none-elf.tar.xz": "c036809fdb39d2e0ba3e27cd0a47f5800263ba1d41348228c8d98912b9ffe025",
+ "dist/2023-06-01/rust-std-1.70.0-riscv32imc-unknown-none-elf.tar.gz": "69a105b558bd3bf947acb7fa56d58808bbf43fbbf77f66d68b8ea2d8155c4195",
+ "dist/2023-06-01/rust-std-1.70.0-riscv32imc-unknown-none-elf.tar.xz": "c79f9620cbc37171d1ffae00dfb23129608526eb9d4c383e12ba22c56b6cd01a",
+ "dist/2023-06-01/rust-std-1.70.0-riscv64gc-unknown-linux-gnu.tar.gz": "3a275431d0dca26d577f4acb54d797dc6b61f2d0b74d472efe3d0cf3b808e716",
+ "dist/2023-06-01/rust-std-1.70.0-riscv64gc-unknown-linux-gnu.tar.xz": "cdecf32e245898306a27a0b164451b2ee9a2122176ce3a65f2ec73c200986dc3",
+ "dist/2023-06-01/rust-std-1.70.0-riscv64gc-unknown-none-elf.tar.gz": "6a8e3060b95a2ef49ccfc049902e5b907bf6191eec89b34176daac2606501bfd",
+ "dist/2023-06-01/rust-std-1.70.0-riscv64gc-unknown-none-elf.tar.xz": "c335254fe0ecabc8c90c47dc6565c733a1f3e31ade48666ece4c9ffc791c9548",
+ "dist/2023-06-01/rust-std-1.70.0-riscv64imac-unknown-none-elf.tar.gz": "6aa7f5f344467a9d7d39522bb23852b055e6848fb4a4cf543737de2a553c7d06",
+ "dist/2023-06-01/rust-std-1.70.0-riscv64imac-unknown-none-elf.tar.xz": "ada4c5750dd4f11c381fe3a167bff4f09c5edf5d5e36fad1497a15058bd646b4",
+ "dist/2023-06-01/rust-std-1.70.0-s390x-unknown-linux-gnu.tar.gz": "ba659946575e478617049b49f5c12261fb86b5a38b0147969c3c056cba42fbf3",
+ "dist/2023-06-01/rust-std-1.70.0-s390x-unknown-linux-gnu.tar.xz": "7084afbe9fb1a0e8a0c3e760f45475ebba400b72030ae8359bdccef67cb48992",
+ "dist/2023-06-01/rust-std-1.70.0-sparc64-unknown-linux-gnu.tar.gz": "6e89be191a8491a58cb012ec2363704744e81eae99fae2b656a1da5c82c8e6b7",
+ "dist/2023-06-01/rust-std-1.70.0-sparc64-unknown-linux-gnu.tar.xz": "b06933f6f94cd30e1c2415b37db97a94533a727aa5d32a34ee80c6742ee418d2",
+ "dist/2023-06-01/rust-std-1.70.0-sparcv9-sun-solaris.tar.gz": "81027f48121c412a778ba6114ade411c4856671b5c842e854718a941c9690ee2",
+ "dist/2023-06-01/rust-std-1.70.0-sparcv9-sun-solaris.tar.xz": "3f908d3e59c1933118cf5610e48ccece1010519d59ef03aa0d2d90464941c47c",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv6m-none-eabi.tar.gz": "5839550c148a328e8e2ba3aceb3031052342d6bb2f245407df9a32c830102c14",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv6m-none-eabi.tar.xz": "2e2d217a9c9ab9c72d0fdd2c3067c7ea3208b60c2e11100434ee41eb15b8ae66",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7em-none-eabi.tar.gz": "8ebd1ed18801f61eeca2c5b92d649dc743145b4e12730fff50a921b7a7c404c5",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7em-none-eabi.tar.xz": "ddb44e71703a5b04adaf61ca6228bd5118bb3803b9715a1d679a676255f75403",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7em-none-eabihf.tar.gz": "7bc81093887aef2306b5edf05b3f03a260f154293d5f620d1c4d3cea5e5170ea",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7em-none-eabihf.tar.xz": "2c7cf2e53eee1b4881d003eb2a3195a18b493aabdede4624ba05199e12586265",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7m-none-eabi.tar.gz": "305155c3fa945be27786771927dcf0475e8c0375f78ceedab0bc8dbc6c879156",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7m-none-eabi.tar.xz": "ec61f8eedc7c8025d10ff82d4389f4af551ad9cce58b2611ced4a2f1c7a6d851",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7neon-linux-androideabi.tar.gz": "4973ec1e3528a240ed88f8ae4b08a56411b0f4e4f7d63ef912bbbe933270fd6c",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7neon-linux-androideabi.tar.xz": "dab5edf2c84fb46d3b95a5a34240677f3975eb941f4c90216c7d55ef574dfa37",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "edd19412e3704ae1688c6ac5af7ad948d6802711e9a04d52c0cc39379f40d230",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "bd36d29e3171cdc97ce425140dcd210fa2ed2fcfdbcd93e427aec01065732e79",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv8m.base-none-eabi.tar.gz": "36d6d8a53e15aa79948d244a45bc044fa6f4e40b1bcf8dca70559efc90f491b0",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv8m.base-none-eabi.tar.xz": "f28760e399da316a3e5118310af8f4f2b6394a130e40159de9a9afaa1e04b738",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv8m.main-none-eabi.tar.gz": "01b2a3ef92d7bad67bba0e4e4ff7bbfe65f11dc4396dad7cdba3fbfe63ac5917",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv8m.main-none-eabi.tar.xz": "95e98838c14eafb23f5f5b4c36fada458822ea812f90d04ba18461fe44dbac69",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv8m.main-none-eabihf.tar.gz": "f7260e989864e8064086dff1dd7a203e19da1590b1a7326d6da56b6796b6d1f3",
+ "dist/2023-06-01/rust-std-1.70.0-thumbv8m.main-none-eabihf.tar.xz": "877addee2f4c10524ed761c8c171c34a92b37ac2050d5e04c3f4d697b49b8fbc",
+ "dist/2023-06-01/rust-std-1.70.0-wasm32-unknown-emscripten.tar.gz": "b05019f22ce2608adde1317c58b7803c44955cfb9010286ebaec565e5f7bfe4c",
+ "dist/2023-06-01/rust-std-1.70.0-wasm32-unknown-emscripten.tar.xz": "efad3273dc11acf91a68e67dd0fcf00e59d480d22aa8768dbaca09fca6394574",
+ "dist/2023-06-01/rust-std-1.70.0-wasm32-unknown-unknown.tar.gz": "3e35a53e22810fd6beb2fd874cc9898724b473f85ffcfdf4a45aee1bd01da78c",
+ "dist/2023-06-01/rust-std-1.70.0-wasm32-unknown-unknown.tar.xz": "a33e6f39a4ea9df2576a7f1a3940f3926278c3930751d8b79f33d49cf7baa52d",
+ "dist/2023-06-01/rust-std-1.70.0-wasm32-wasi.tar.gz": "ac69d791b549dae699df8094cb092cfc1195acbb2838ee36a0ef5bfd3bd446b0",
+ "dist/2023-06-01/rust-std-1.70.0-wasm32-wasi.tar.xz": "9a3666fd0ac966b39507e5973822a3c0a31b8e617b51eeb1e664d2333ba562bb",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-apple-darwin.tar.gz": "0bce6e0abf5b7375ae4e78ec59d3036100267c300cb999dc6e665356bce6e3b2",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-apple-darwin.tar.xz": "bf15abbb701729483b710309fb71c65c8ec9c27423bd712299c255bd080ead42",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-apple-ios.tar.gz": "4225d118018d7a36dcbd39bb913d3421d25a03443c92b94dbed1f62d8f3697cf",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-apple-ios.tar.xz": "6b265d91889cf13c9769d15cbf8c76b9376734536c8bdc622067325419b44a7e",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-fortanix-unknown-sgx.tar.gz": "38a3a69866f51e4e580d1534c1e77c06370c5e02c1be0e887d7cec686d5299c9",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-fortanix-unknown-sgx.tar.xz": "6d4db6ef354e34e97e3e495308331709e6e9f77a1a0fd2a3a1dea83109f7ece1",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-linux-android.tar.gz": "070983431fd324d085d72497560a54473f0d86537214810661c2487d59c9056e",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-linux-android.tar.xz": "bb18817aee42167a0a39a99706a94d1d218ac80b3ab1d6c1b9d95afefb638a26",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-pc-solaris.tar.gz": "45f4a140939359133255d577b47dc9f3d18d094b51b2b94852551ff4b7dc9317",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-pc-solaris.tar.xz": "a278257c08a837ea2aa48b70f3502d6762f21f05c57f58cec8da6b8eb05a0866",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-pc-windows-gnu.tar.gz": "e6559a04e5c44721fdf6afe2e1863bf31b0d2164d06b9cf65807a5710beff42b",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-pc-windows-gnu.tar.xz": "a0a8e558db3ad663b4f993da72706bb14eec9d3ad9091ee648a4e07663666b57",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-pc-windows-msvc.tar.gz": "7012c830e9645571de90d67ea562e39decf9992650025751f4e80d6f04b05b20",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-pc-windows-msvc.tar.xz": "e6174a936377335331f95bc41419e2506fed859eb96d97cda0b6729712701dbf",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-sun-solaris.tar.gz": "38e840f7f090622abd291adcc814c176e4cf892ed7951bfbc6375b571a1948f1",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-sun-solaris.tar.xz": "e7996811d278163ff4bb8f5cf5c48361b72de83cfe64d6332916b43abdea4183",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-freebsd.tar.gz": "5cbf49c9a286f0bb9b30d20958fe102f1a54c93fc8832bea76b465ba66928719",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-freebsd.tar.xz": "88451b78421801463892d230f730af4af017dedc37d260ab05dffe56296fd0d9",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-fuchsia.tar.gz": "f1fad628ea3d2761e7c07f2e6d236b20beb7ed18a1fecaeeea793b02a5169ac7",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-fuchsia.tar.xz": "fad0a55e346be7b6c91f08ca3c7b8e50915de7c404d73c885c40d09b84d6c105",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-illumos.tar.gz": "8ac9a4dd237cdce47cba9aa2e5764e3bdb94ef31c57bd4fc149ad23e58e38ca2",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-illumos.tar.xz": "7736c8e1182e33c935dc8823a096f0e4d12d414029b244cd3021ff34426a3ab5",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-linux-gnu.tar.gz": "d921afdcf5218bfe144b74bd16b4c18d824bb6194e6ff92451f0ed749ca025f3",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-linux-gnu.tar.xz": "0c0129717da1e27ccf2c56da950d2fe56973f71beec9e80ae6904b282d2f0ee9",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-linux-gnux32.tar.gz": "7ce1077f3c10875e84cc89c84addb9abd422016a4b8e476a805e9799d6f7ec3c",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-linux-gnux32.tar.xz": "f29ac3981ff349e02e6ab9d534f5affcf55481e84f30e4ae7e9acc657ad03640",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-linux-musl.tar.gz": "68396314cf9fad4c0575aa8c0559e26e283d95106095cad59649a44bab8a9d57",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-linux-musl.tar.xz": "7ebaba08385d1ec87d0a27ca8b4e1eb454374da18ffa12621bd1578973754101",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-netbsd.tar.gz": "365631ae197b1761f15e42bbf3a08f4ea4761effb57e141b36019b1558bef911",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-netbsd.tar.xz": "40777fe8e9e78db0b175e9a4b4513f3b1a64d1ef29e6658646c8c64ce20a26e5",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-none.tar.gz": "97b094a4b154807858ad8b8c3732b8bf5f3461eec972d61192a0b89668d70243",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-none.tar.xz": "90c9e2568b978682712635dda549591b88230ca3319aa488a4c3b8e14fbdb8fb",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-redox.tar.gz": "b7af742124df889a2a39f5e44532ed951ff853ddd7ba7cdc25364e7ba8ad0ed0",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-redox.tar.xz": "3a4f9532a1b69c51ca6855b43aaaad7fd369e882a0187ac8c61b5c42ce1fa79d",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-uefi.tar.gz": "0d370784dfa4290d2a997185bd92fb42830936e36e50dc60b6f2a76137805478",
+ "dist/2023-06-01/rust-std-1.70.0-x86_64-unknown-uefi.tar.xz": "361ddfaf0c0ac9277399c4a90cdc0102791c64945bf1d20dfa2e7a1f93bb8dd5",
+ "dist/2023-06-01/rustc-1.70.0-aarch64-apple-darwin.tar.gz": "efad5373622c83dc301c4c045bc3b0ad5cb271409f89c839864f4c3af1510cc8",
+ "dist/2023-06-01/rustc-1.70.0-aarch64-apple-darwin.tar.xz": "cc5f1242e3aa8fe9af7245542d5e1a0edaad7cd4289db31836021ab60bbf91f4",
+ "dist/2023-06-01/rustc-1.70.0-aarch64-pc-windows-msvc.tar.gz": "548dbe009112ab3794300533a734bfaefc73a68518c9b734a456c76a3eb7b338",
+ "dist/2023-06-01/rustc-1.70.0-aarch64-pc-windows-msvc.tar.xz": "f1b2b6d2b7bb6ff36c200832892e82dc7d4cba5bcd6159efbf95e22eae7b603f",
+ "dist/2023-06-01/rustc-1.70.0-aarch64-unknown-linux-gnu.tar.gz": "4ede6cb7dd09415b7a75145397fe49023aec759e9f2435f8254b4d7aabc704bd",
+ "dist/2023-06-01/rustc-1.70.0-aarch64-unknown-linux-gnu.tar.xz": "71698cf444eef74050db821dc4df996c0f268615230099cde836e685e5b5465d",
+ "dist/2023-06-01/rustc-1.70.0-aarch64-unknown-linux-musl.tar.gz": "f92f6ac28eb43120a3df277b8d3df36086277a6b2ec102944e8bc60a89311a44",
+ "dist/2023-06-01/rustc-1.70.0-aarch64-unknown-linux-musl.tar.xz": "e9ca31fea461436b0327fae8777ebd8669bb6f80697a204b529b79a192b258c4",
+ "dist/2023-06-01/rustc-1.70.0-arm-unknown-linux-gnueabi.tar.gz": "5ca537ea37ae6789e740cf1ef5587d743b09a5d1ea1bea5f5256f9cf625f59b9",
+ "dist/2023-06-01/rustc-1.70.0-arm-unknown-linux-gnueabi.tar.xz": "2e151309f60e99a55e7fe9fe3ec7dec050816dc0599c5e954a6ce8c9ddf1ce31",
+ "dist/2023-06-01/rustc-1.70.0-arm-unknown-linux-gnueabihf.tar.gz": "d2ef2939d6fe1bc6c8941653285fb21ef3780b3b3126f8ac7cdd1cdce5661177",
+ "dist/2023-06-01/rustc-1.70.0-arm-unknown-linux-gnueabihf.tar.xz": "24158d5e153d13de9e0b78de27f3d0721e98dbc0e78b3abfcad89f02b0978302",
+ "dist/2023-06-01/rustc-1.70.0-armv7-unknown-linux-gnueabihf.tar.gz": "003c8cefb3d1c3abe087a7068b0cd4889d81784132697ccab24e81aa733a9935",
+ "dist/2023-06-01/rustc-1.70.0-armv7-unknown-linux-gnueabihf.tar.xz": "9dfaef5084bf82380e44f10a81beee7dbe77e95ec4dfa2105488434df92d169f",
+ "dist/2023-06-01/rustc-1.70.0-i686-pc-windows-gnu.tar.gz": "f742d6e7f34162f66e47463b2eb2f5311a272301716c3f35808925b8ef78313c",
+ "dist/2023-06-01/rustc-1.70.0-i686-pc-windows-gnu.tar.xz": "1b4654012f939d22f8fa75b81bf7a29906901158bb54b520fde708b213fda9c2",
+ "dist/2023-06-01/rustc-1.70.0-i686-pc-windows-msvc.tar.gz": "3b6a6acd8ff10ea9f518b6aa4466efd3eb777c9e278d181bec54dd9d86f3345b",
+ "dist/2023-06-01/rustc-1.70.0-i686-pc-windows-msvc.tar.xz": "8eb582439d3f2a61c08c94c5efeeaf81e06ab9f1bcbc065b924eab630996ece4",
+ "dist/2023-06-01/rustc-1.70.0-i686-unknown-linux-gnu.tar.gz": "d35087bbebed15f8573b7882e44982979ba4ced828ab0ff00e3b415b232c5fe3",
+ "dist/2023-06-01/rustc-1.70.0-i686-unknown-linux-gnu.tar.xz": "f89c90f80864f68e42b70d9c14984195629ed9894bb5cfe6c8a0f1140f7816ff",
+ "dist/2023-06-01/rustc-1.70.0-mips-unknown-linux-gnu.tar.gz": "fc1fdfb90f988743c651dc3893aa6265ea51d70639bfff2d2f36960ecec8e073",
+ "dist/2023-06-01/rustc-1.70.0-mips-unknown-linux-gnu.tar.xz": "c1f51717bcec5a9c799d57d8c80eff7760c11fc5af383700fb22c3508dd9450e",
+ "dist/2023-06-01/rustc-1.70.0-mips64-unknown-linux-gnuabi64.tar.gz": "973bd5286980a4b646e62ee7692ccd61f4d6c2894c0704c6e6f8e33cd0450d95",
+ "dist/2023-06-01/rustc-1.70.0-mips64-unknown-linux-gnuabi64.tar.xz": "28b0f6239eada812b1e0c43b49f9fa8782be8069b8c8e84cbf6680acc673d72a",
+ "dist/2023-06-01/rustc-1.70.0-mips64el-unknown-linux-gnuabi64.tar.gz": "badb4cafa97ef6d8301be5476b7347b1adb9c1570457eeb506aaac9a0ffa9e41",
+ "dist/2023-06-01/rustc-1.70.0-mips64el-unknown-linux-gnuabi64.tar.xz": "c76e5e485b6d5137a7189f9c3915287cd69c74d9ddc5b37e66cc4aeb55d09ea7",
+ "dist/2023-06-01/rustc-1.70.0-mipsel-unknown-linux-gnu.tar.gz": "282d8132c71c0fe5ae3ba0e811e6ff74b0911a26b1490334a2df8b2084f25d53",
+ "dist/2023-06-01/rustc-1.70.0-mipsel-unknown-linux-gnu.tar.xz": "0a6cf0eef9f1b67415ca5bbde1832cd3cd79560762251f3fb1b6f317ed5109bd",
+ "dist/2023-06-01/rustc-1.70.0-powerpc-unknown-linux-gnu.tar.gz": "f6d873153f1137768999d384662d0c8b514dc4886a673c76409d8d4275717cc1",
+ "dist/2023-06-01/rustc-1.70.0-powerpc-unknown-linux-gnu.tar.xz": "4e4fe3a8b2c0ea1f82e99a30c193b848464b7ac1ed802fddc100c11814a7b2ba",
+ "dist/2023-06-01/rustc-1.70.0-powerpc64-unknown-linux-gnu.tar.gz": "efdb58eac761ecc0f22837c1c15ad709ff4381001cfc297567a1ccbcfba99b5d",
+ "dist/2023-06-01/rustc-1.70.0-powerpc64-unknown-linux-gnu.tar.xz": "7891593a85ba231ca91505720a3535e9cff22700ee1f3e122bc33a5f10ddf705",
+ "dist/2023-06-01/rustc-1.70.0-powerpc64le-unknown-linux-gnu.tar.gz": "b67c547f7fa8e85530b11bd5eb8a2eb11c4149b5073945b71fd40caddfe1cc18",
+ "dist/2023-06-01/rustc-1.70.0-powerpc64le-unknown-linux-gnu.tar.xz": "7152b111cf91a2cfa1e7beb51d3c737561095ebdf75ec7e032ab1118639ea4ca",
+ "dist/2023-06-01/rustc-1.70.0-riscv64gc-unknown-linux-gnu.tar.gz": "b615624cf7aa172c173a00ba7724362b4ad5624ca1814cd0f89ca30c3dfa756a",
+ "dist/2023-06-01/rustc-1.70.0-riscv64gc-unknown-linux-gnu.tar.xz": "7fa4de4b7f8ab8b23a0f2ef3dc4886658d3bf90a97f6b215146b75b445a6131b",
+ "dist/2023-06-01/rustc-1.70.0-s390x-unknown-linux-gnu.tar.gz": "334ea075070c9b2261304d5238b601699352101c6aa69e5e3fa8b96ab2047f32",
+ "dist/2023-06-01/rustc-1.70.0-s390x-unknown-linux-gnu.tar.xz": "2c8421d95d575d33545b969ed5d200bbcbc69a2ae80d0ffeba4c516fc8a91356",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-apple-darwin.tar.gz": "b4b6fa6605dac66c38008020ea11b59a06bcc1cdbac66a17204ff38aa7115221",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-apple-darwin.tar.xz": "dd6708867b72a70f56efb3054d21c7f605be93f937b848ab17580857912a516a",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-pc-windows-gnu.tar.gz": "9940534fd213f5cb74f3abdd207197a587df0a77b5afbeb38f94a4018154cce8",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-pc-windows-gnu.tar.xz": "9a9e9c847702ca00c3af49cf14983610c2ebfe6d90369ef060e6c32062b82624",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-pc-windows-msvc.tar.gz": "c74883beebe7bacf75500d936ea57155b409a49b76bc1ddd8d166f897c87ddd1",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-pc-windows-msvc.tar.xz": "9af11cec423c96b3fdf76a81fbdf90df2b5f4a3fbf3f5c2cc432e103c54a1b8c",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-freebsd.tar.gz": "de009a7e23c8a218f0d740e21094caec50ed73adf9cec071d2e0d73dbad00574",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-freebsd.tar.xz": "3c1b99458547aa2b50eb09e5466e0177c0efc5fb75410661c0765920203ae07b",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-illumos.tar.gz": "1564e73dbfaa011608cdff39b82372ac27b8fefc61514d56052c3ec023adb4d1",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-illumos.tar.xz": "56db124c6c700bf31544137e4ae07f66e3d3d453c68c25ecb615d5a4e113a15c",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-linux-gnu.tar.gz": "532e773484a6df30996b3809bc2a000f1fbe3e5b966a09d3ec0133c57c25c0fa",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-linux-gnu.tar.xz": "7d891d3e9bc4f1151545c83cbe3bc6af9ed234388c45ca2e19641262f48615e2",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-linux-musl.tar.gz": "dca297aac0adc07af587d2e7f495fc0529f6adee130c8831368b86010ab3c6dc",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-linux-musl.tar.xz": "69a3ba1273aedaf7aadc91f6ccf59061eb00205c9c523f0b1f91ca14cfa2058c",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-netbsd.tar.gz": "fc114ba6e1ef3885b2ef27a9f8ee03f852aafb308de77903922112e296ef3743",
+ "dist/2023-06-01/rustc-1.70.0-x86_64-unknown-netbsd.tar.xz": "06a8ec190486ce7140c2f43cf7c82d2870fbae2a5ed83e73150863bf5f086c5a"
}
}
diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml
index c437bde5a..6c3b5bb00 100644
--- a/src/tools/build-manifest/Cargo.toml
+++ b/src/tools/build-manifest/Cargo.toml
@@ -9,6 +9,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0.32"
flate2 = "1.0.16"
+xz2 = "0.1.7"
tar = "0.4.29"
sha2 = "0.10.1"
rayon = "1.5.1"
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 21dad9eb7..8b28c68e0 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -24,6 +24,7 @@ static HOSTS: &[&str] = &[
"i686-pc-windows-gnu",
"i686-pc-windows-msvc",
"i686-unknown-linux-gnu",
+ "loongarch64-unknown-linux-gnu",
"mips-unknown-linux-gnu",
"mips64-unknown-linux-gnuabi64",
"mips64el-unknown-linux-gnuabi64",
@@ -97,6 +98,7 @@ static TARGETS: &[&str] = &[
"i686-unknown-linux-gnu",
"i686-unknown-linux-musl",
"i686-unknown-uefi",
+ "loongarch64-unknown-linux-gnu",
"m68k-unknown-linux-gnu",
"mips-unknown-linux-gnu",
"mips-unknown-linux-musl",
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index dde9745af..7a4c15d01 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -5,6 +5,7 @@ use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use tar::Archive;
+use xz2::read::XzDecoder;
const DEFAULT_TARGET: &str = "x86_64-unknown-linux-gnu";
@@ -175,9 +176,23 @@ impl Versions {
}
fn load_version_from_tarball(&mut self, package: &PkgType) -> Result<VersionInfo, Error> {
- let tarball_name = self.tarball_name(package, DEFAULT_TARGET)?;
- let tarball = self.dist_path.join(tarball_name);
+ for ext in ["xz", "gz"] {
+ let info =
+ self.load_version_from_tarball_inner(&self.dist_path.join(self.archive_name(
+ package,
+ DEFAULT_TARGET,
+ &format!("tar.{}", ext),
+ )?))?;
+ if info.present {
+ return Ok(info);
+ }
+ }
+
+ // If neither tarball is present, we fallback to returning the non-present info.
+ Ok(VersionInfo::default())
+ }
+ fn load_version_from_tarball_inner(&mut self, tarball: &Path) -> Result<VersionInfo, Error> {
let file = match File::open(&tarball) {
Ok(file) => file,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
@@ -187,7 +202,14 @@ impl Versions {
}
Err(err) => return Err(err.into()),
};
- let mut tar = Archive::new(GzDecoder::new(file));
+ let mut tar: Archive<Box<dyn std::io::Read>> =
+ Archive::new(if tarball.extension().map_or(false, |e| e == "gz") {
+ Box::new(GzDecoder::new(file))
+ } else if tarball.extension().map_or(false, |e| e == "xz") {
+ Box::new(XzDecoder::new(file))
+ } else {
+ unimplemented!("tarball extension not recognized: {}", tarball.display())
+ });
let mut version = None;
let mut git_commit = None;
diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs
index 9f113c72b..d2e9c324a 100644
--- a/src/tools/build_helper/src/ci.rs
+++ b/src/tools/build_helper/src/ci.rs
@@ -38,3 +38,27 @@ impl CiEnv {
}
}
}
+
+pub mod gha {
+ /// All github actions log messages from this call to the Drop of the return value
+ /// will be grouped and hidden by default in logs. Note that nesting these does
+ /// not really work.
+ pub fn group(name: impl std::fmt::Display) -> Group {
+ if std::env::var_os("GITHUB_ACTIONS").is_some() {
+ eprintln!("::group::{name}");
+ }
+ Group(())
+ }
+
+ /// A guard that closes the current github actions log group on drop.
+ #[must_use]
+ pub struct Group(());
+
+ impl Drop for Group {
+ fn drop(&mut self) {
+ if std::env::var_os("GITHUB_ACTIONS").is_some() {
+ eprintln!("::endgroup::");
+ }
+ }
+ }
+}
diff --git a/src/tools/cargo/.cargo/config.toml b/src/tools/cargo/.cargo/config.toml
new file mode 100644
index 000000000..c4a595b61
--- /dev/null
+++ b/src/tools/cargo/.cargo/config.toml
@@ -0,0 +1,4 @@
+[alias]
+build-man = "run --package xtask-build-man --"
+stale-label = "run --package xtask-stale-label --"
+unpublished = "run --package xtask-unpublished --"
diff --git a/src/tools/cargo/.github/ISSUE_TEMPLATE/bug_report.yml b/src/tools/cargo/.github/ISSUE_TEMPLATE/bug_report.yml
index f465e1240..5cee9c65c 100644
--- a/src/tools/cargo/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/src/tools/cargo/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,6 +1,6 @@
name: Bug Report
description: Create a report to help us improve
-labels: ["C-bug"]
+labels: ["C-bug", "S-triage"]
body:
- type: markdown
attributes:
diff --git a/src/tools/cargo/.github/ISSUE_TEMPLATE/feature_request.yml b/src/tools/cargo/.github/ISSUE_TEMPLATE/feature_request.yml
index bae2469d1..e6ed547f8 100644
--- a/src/tools/cargo/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/src/tools/cargo/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -1,6 +1,6 @@
name: Feature Request
description: Suggest an idea for enhancing Cargo
-labels: ["C-feature-request"]
+labels: ["C-feature-request", "S-triage"]
body:
- type: markdown
attributes:
diff --git a/src/tools/cargo/.github/workflows/main.yml b/src/tools/cargo/.github/workflows/main.yml
index 400e725e5..c522a19a1 100644
--- a/src/tools/cargo/.github/workflows/main.yml
+++ b/src/tools/cargo/.github/workflows/main.yml
@@ -24,12 +24,6 @@ jobs:
- run: rustup update stable && rustup default stable
- run: rustup component add rustfmt
- run: cargo fmt --all --check
- - run: |
- for manifest in `find crates benches/benchsuite benches/capture -name Cargo.toml`
- do
- echo check fmt for $manifest
- cargo fmt --all --manifest-path $manifest --check
- done
# Ensure there are no clippy warnings
clippy:
@@ -39,7 +33,35 @@ jobs:
- run: rustup update stable && rustup default stable
- run: rustup component add clippy
# Only check cargo lib for now
- - run: cargo clippy -p cargo --lib -- -D warnings
+ # TODO: check every members
+ - run: cargo clippy -p cargo --lib --no-deps -- -D warnings
+
+ stale-label:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - run: rustup update stable && rustup default stable
+ - run: cargo stale-label
+
+ # Ensure Cargo.lock is up-to-date
+ lockfile:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - run: rustup update stable && rustup default stable
+ - run: cargo update -p cargo --locked
+
+ check-version-bump:
+ runs-on: ubuntu-latest
+ env:
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
+ HEAD_SHA: ${{ github.sha }}
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0 # make `git diff` work
+ - run: rustup update stable && rustup default stable
+ - run: ci/validate-version-bump.sh
test:
runs-on: ${{ matrix.os }}
@@ -101,47 +123,39 @@ jobs:
run: echo CARGO_CONTAINER_TESTS=1 >> $GITHUB_ENV
if: matrix.os == 'ubuntu-latest'
- - run: cargo test
+ - run: cargo test -p cargo
- name: Clear intermediate test output
run: ci/clean-test-output.sh
- name: gitoxide tests (all git-related tests)
- run: cargo test git
+ run: cargo test -p cargo git
env:
__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2: 1
# The testsuite generates a huge amount of data, and fetch-smoke-test was
# running out of disk space.
- name: Clear test output
run: ci/clean-test-output.sh
+ # This only tests `cargo fix` because fix-proxy-mode is one of the most
+ # complicated subprocess management in Cargo.
- name: Check operability of rustc invocation with argfile
+ run: 'cargo test -p cargo --test testsuite -- fix::'
env:
__CARGO_TEST_FORCE_ARGFILE: 1
- run: |
- # This only tests `cargo fix` because fix-proxy-mode is one of the most
- # complicated subprocess management in Cargo.
- cargo test --test testsuite -- fix::
- - run: cargo test --manifest-path crates/cargo-test-support/Cargo.toml
- env:
- CARGO_TARGET_DIR: target
+ - run: cargo test -p cargo-test-support
- run: cargo test -p cargo-platform
- run: cargo test -p cargo-util
- - run: cargo test --manifest-path crates/home/Cargo.toml
- - run: cargo test --manifest-path crates/mdman/Cargo.toml
- - run: cargo build --manifest-path crates/credential/cargo-credential-1password/Cargo.toml
- - run: cargo build --manifest-path crates/credential/cargo-credential-gnome-secret/Cargo.toml
+ - run: cargo test -p home
+ - run: cargo test -p mdman
+ - run: cargo build -p cargo-credential-1password
+ - run: cargo build -p cargo-credential-macos-keychain
+ - run: cargo build -p cargo-credential-wincred
+ - run: cargo build -p cargo-credential-gnome-secret
if: matrix.os == 'ubuntu-latest'
- - run: cargo build --manifest-path crates/credential/cargo-credential-macos-keychain/Cargo.toml
- if: matrix.os == 'macos-latest'
- - run: cargo build --manifest-path crates/credential/cargo-credential-wincred/Cargo.toml
- if: matrix.os == 'windows-latest'
- name: Check benchmarks
- env:
- # Share the target dir to try to cache a few build-time deps.
- CARGO_TARGET_DIR: target
run: |
# This only tests one benchmark since it can take over 10 minutes to
# download all workspaces.
- cargo test --manifest-path benches/benchsuite/Cargo.toml --all-targets -- cargo
- cargo check --manifest-path benches/capture/Cargo.toml
+ cargo test -p benchsuite --all-targets -- cargo
+ cargo check -p capture
# The testsuite generates a huge amount of data, and fetch-smoke-test was
# running out of disk space.
- name: Clear benchmark output
@@ -154,7 +168,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: rustup update stable && rustup default stable
- - run: cargo test --manifest-path crates/resolver-tests/Cargo.toml
+ - run: cargo test -p resolver-tests
test_gitoxide:
runs-on: ubuntu-latest
@@ -164,7 +178,7 @@ jobs:
- run: rustup target add i686-unknown-linux-gnu
- run: sudo apt update -y && sudo apt install gcc-multilib libsecret-1-0 libsecret-1-dev -y
- run: rustup component add rustfmt || echo "rustfmt not available"
- - run: cargo test
+ - run: cargo test -p cargo
env:
__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2: 1
@@ -175,7 +189,7 @@ jobs:
- run: rustup update nightly && rustup default nightly
- run: rustup component add rust-src
- run: cargo build
- - run: cargo test --test build-std
+ - run: cargo test -p cargo --test build-std
env:
CARGO_RUN_BUILD_STD_TESTS: 1
docs:
@@ -187,26 +201,36 @@ jobs:
- run: rustup component add rust-docs
- run: ci/validate-man.sh
# This requires rustfmt, use stable.
- - run: cd src/doc/semver-check && cargo +stable run
- - run: |
+ - name: Run semver-check
+ run: cargo +stable run -p semver-check
+ - name: Ensure intradoc links are valid
+ run: cargo doc --workspace --document-private-items --no-deps
+ env:
+ RUSTDOCFLAGS: -D warnings
+ - name: Install mdbook
+ run: |
mkdir mdbook
curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.27/mdbook-v0.4.27-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
echo `pwd`/mdbook >> $GITHUB_PATH
- - run: cargo doc --document-private-items --no-deps
- env:
- RUSTDOCFLAGS: -D warnings
- run: cd src/doc && mdbook build --dest-dir ../../target/doc
- - run: |
- cd src/doc
- curl -sSLo linkcheck.sh \
- https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh
- sh linkcheck.sh --all cargo
+ - name: Run linkchecker.sh
+ run: |
+ cd target
+ curl -sSLO https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh
+ sh linkcheck.sh --all --path ../src/doc cargo
success:
permissions:
contents: none
name: bors build finished
- needs: [docs, rustfmt, test, resolver, build_std, test_gitoxide]
+ needs:
+ - build_std
+ - docs
+ - lockfile
+ - resolver
+ - rustfmt
+ - test
+ - test_gitoxide
runs-on: ubuntu-latest
if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto-cargo'"
steps:
@@ -215,7 +239,14 @@ jobs:
permissions:
contents: none
name: bors build finished
- needs: [docs, rustfmt, test, resolver, build_std]
+ needs:
+ - build_std
+ - docs
+ - lockfile
+ - resolver
+ - rustfmt
+ - test
+ - test_gitoxide
runs-on: ubuntu-latest
if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto-cargo'"
steps:
diff --git a/src/tools/cargo/CHANGELOG.md b/src/tools/cargo/CHANGELOG.md
index a3d488d92..5cb4d11c5 100644
--- a/src/tools/cargo/CHANGELOG.md
+++ b/src/tools/cargo/CHANGELOG.md
@@ -1,12 +1,75 @@
# Changelog
+## Cargo 1.71 (2023-07-13)
+[84b7041f...HEAD](https://github.com/rust-lang/cargo/compare/84b7041f...HEAD)
+
+### Added
+
+### Changed
+
+- ❗ Optimized the usage under `rustup`. When Cargo detects it will run `rustc`
+ pointing a rustup proxy, it'll try bypassing the proxy and use the underlying
+ binary directly. There are assumptions around the interaction with rustup and
+ `RUSTUP_TOOLCHAIN`. However, it's not expected to affect normal users.
+ [#11917](https://github.com/rust-lang/cargo/pull/11917)
+- ❗ When querying a package, Cargo tries only the original name, all hyphens,
+ and all underscores to handle misspellings. Previously, Cargo tried each
+ combination of hyphens and underscores, causing excessive requests to crates.io.
+ [#12083](https://github.com/rust-lang/cargo/pull/12083)
+- ❗ Disallow `RUSTUP_HOME` and `RUSTUP_TOOLCHAIN` in the `[env]` configuration
+ table. This is considered to be not a use case Cargo would like to support,
+ since it will likely cause problems or lead to confusion.
+ [#12101](https://github.com/rust-lang/cargo/pull/12101)
+ [#12107](https://github.com/rust-lang/cargo/pull/12107)
+- Better error message when getting an empty dependency table in Cargo.toml.
+ [#11997](https://github.com/rust-lang/cargo/pull/11997)
+- Use restricted Damerau-Levenshtein algorithm to provide typo suggestions.
+ [#11963](https://github.com/rust-lang/cargo/pull/11963)
+
+### Fixed
+
+- Corrected the bug report URL for `cargo clippy --fix`.
+ [#11882](https://github.com/rust-lang/cargo/pull/11882)
+
+### Nightly only
+
+- The `-Zbuild-std` breakage of missing features in `nightly-2023-05-04` has
+ been fixed in `nightly-2023-05-05`.
+ [#12088](https://github.com/rust-lang/cargo/pull/12088)
+- Recompile on profile rustflags changes.
+ [#11981](https://github.com/rust-lang/cargo/pull/11981)
+
+### Documentation
+
+### Internal
+
+- Cargo is now a Cargo workspace. We dogfood ourselves finally.
+ [#11851](https://github.com/rust-lang/cargo/pull/11851)
+ [#11994](https://github.com/rust-lang/cargo/pull/11994)
+ [#11996](https://github.com/rust-lang/cargo/pull/11996)
+- Allow win/mac credential managers to build on all platforms.
+ [#11993](https://github.com/rust-lang/cargo/pull/11993)
+- Use `openssl` only on non-Windows platforms.
+ [#11979](https://github.com/rust-lang/cargo/pull/11979)
+- A new, straightforward issue labels system for Cargo contributors.
+ [docs](https://doc.crates.io/contrib/issues.html)
+ [#11995](https://github.com/rust-lang/cargo/pull/11995)
+ [#12002](https://github.com/rust-lang/cargo/pull/12002)
+ [#12003](https://github.com/rust-lang/cargo/pull/12003)
+
## Cargo 1.70 (2023-06-01)
-[9880b408...HEAD](https://github.com/rust-lang/cargo/compare/9880b408...HEAD)
+[9880b408...rust-1.70.0](https://github.com/rust-lang/cargo/compare/9880b408...rust-1.70.0)
### Added
+- 🎉 Added `cargo logout` command for removing an API token from the registry locally.
+ [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-logout.html)
+ [#11919](https://github.com/rust-lang/cargo/pull/11919)
+ [#11950](https://github.com/rust-lang/cargo/pull/11950)
+- Added `--ignore-rust-version` flag to `cargo install`.
+ [#11859](https://github.com/rust-lang/cargo/pull/11859)
- The `CARGO_PKG_README` environment variable is now set to the path to the
- README file when compiling a crate.
+ README file when compiling a crate.
[#11645](https://github.com/rust-lang/cargo/pull/11645)
- Cargo now displays richer information of Cargo target failed to compile.
[#11636](https://github.com/rust-lang/cargo/pull/11636)
@@ -18,6 +81,20 @@
([docs](https://doc.rust-lang.org/nightly/cargo/reference/registries.html#registry-protocols))
[#11791](https://github.com/rust-lang/cargo/pull/11791)
[#11783](https://github.com/rust-lang/cargo/pull/11783)
+- ❗ `cargo login` and `cargo logout` now uses the registry specified in
+ `registry.default`. This was an unintentional regression.
+ [#11949](https://github.com/rust-lang/cargo/pull/11949)
+- `cargo update` accurately shows `Downgrading` status when downgrading dependencies.
+ [#11839](https://github.com/rust-lang/cargo/pull/11839)
+- Added more information to HTTP errors to help with debugging.
+ [#11878](https://github.com/rust-lang/cargo/pull/11878)
+- Added delays to network retries in Cargo.
+ [#11881](https://github.com/rust-lang/cargo/pull/11881)
+- Refined `cargo puslish` message when waiting for a publish complete.
+ [#11713](https://github.com/rust-lang/cargo/pull/11713)
+- Better error message when `cargo install` from a git repository but found
+ multiple packages.
+ [#11835](https://github.com/rust-lang/cargo/pull/11835)
### Fixed
@@ -29,6 +106,20 @@
[#11805](https://github.com/rust-lang/cargo/pull/11805)
- Don't panic when [`patch`] involved in dependency resolution results in a conflict.
[#11770](https://github.com/rust-lang/cargo/pull/11770)
+- Fixed credential token format validation.
+ [#11951](https://github.com/rust-lang/cargo/pull/11951)
+- Added the missing token format validation on publish.
+ [#11952](https://github.com/rust-lang/cargo/pull/11952)
+- Fixed case mismatches when looking up env vars in the Config snapshot.
+ [#11824](https://github.com/rust-lang/cargo/pull/11824)
+- `cargo new` generates the correct `.hgignore` aligning semantics with other
+ VCS ignore files.
+ [#11855](https://github.com/rust-lang/cargo/pull/11855)
+- Stopped doing unnecessary fuzzy registry index queries. This significantly
+ reduces the amount of HTTP requests to remote registries for crates
+ containing `-` or `_` in their names.
+ [#11936](https://github.com/rust-lang/cargo/pull/11936)
+ [#11937](https://github.com/rust-lang/cargo/pull/11937)
### Nightly only
@@ -42,6 +133,8 @@
([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html##gitoxide))
[#11448](https://github.com/rust-lang/cargo/pull/11448)
[#11800](https://github.com/rust-lang/cargo/pull/11800)
+ [#11822](https://github.com/rust-lang/cargo/pull/11822)
+ [#11830](https://github.com/rust-lang/cargo/pull/11830)
- Removed `-Zjobserver-per-rustc`. Its rustc counterpart never got landed.
[#11764](https://github.com/rust-lang/cargo/pull/11764)
@@ -51,16 +144,65 @@
[#11793](https://github.com/rust-lang/cargo/pull/11793)
- Enhanced the documentation of timing report with graphs.
[#11798](https://github.com/rust-lang/cargo/pull/11798)
+- Clarified requirements about the state of the registry index after publish.
+ [#11926](https://github.com/rust-lang/cargo/pull/11926)
+- Clarified docs on `-C` that it appears before the command.
+ [#11947](https://github.com/rust-lang/cargo/pull/11947)
+- Clarified working directory behaviour for `cargo test`, `cargo bench` and
+ `cargo run`.
+ [#11901](https://github.com/rust-lang/cargo/pull/11901)
+- Fixed the doc of `registries.name.index` configuration.
+ [#11880](https://github.com/rust-lang/cargo/pull/11880)
+- Notice for potential unexpected shell expansions in help text of `cargo-add`.
+ [#11826](https://github.com/rust-lang/cargo/pull/11826)
+- Updated external-tools JSON docs.
+ [#11918](https://github.com/rust-lang/cargo/pull/11918)
+- Call out the differences between the index JSON and the API or metadata.
+ [#11927](https://github.com/rust-lang/cargo/pull/11927)
+- Consistently use `@` when mentioning pkgid format.
+ [#11956](https://github.com/rust-lang/cargo/pull/11956)
+- Enhanced Cargo Contributor Guide.
+ [#11825](https://github.com/rust-lang/cargo/pull/11825)
+ [#11842](https://github.com/rust-lang/cargo/pull/11842)
+ [#11869](https://github.com/rust-lang/cargo/pull/11869)
+ [#11876](https://github.com/rust-lang/cargo/pull/11876)
+- Moved a part of Cargo Contributor Guide to Cargo API documentation.
+ [docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo)
+ [#11809](https://github.com/rust-lang/cargo/pull/11809)
+ [#11841](https://github.com/rust-lang/cargo/pull/11841)
+ [#11850](https://github.com/rust-lang/cargo/pull/11850)
+ [#11870](https://github.com/rust-lang/cargo/pull/11870)
+- Cargo team now arranges
+ [office hours](https://github.com/rust-lang/cargo/wiki/Office-Hours)!
+ [#11903](https://github.com/rust-lang/cargo/pull/11903)
### Internal
- Switched to `sha2` crate for SHA256 calculation.
[#11795](https://github.com/rust-lang/cargo/pull/11795)
[#11807](https://github.com/rust-lang/cargo/pull/11807)
-- Updated to `base64` v0.21.0.
+- Switched benchsuite to the index archive.
+ [#11933](https://github.com/rust-lang/cargo/pull/11933)
+- Updated to `base64` 0.21.0.
[#11796](https://github.com/rust-lang/cargo/pull/11796)
+- Updated to `curl-sys` 0.4.61, which corresponds to curl 8.0.1.
+ [#11871](https://github.com/rust-lang/cargo/pull/11871)
+- Updated to `proptest` 1.1.0.
+ [#11886](https://github.com/rust-lang/cargo/pull/11886)
+- Updated to `git2` 0.17.0, which corresponds to libgit2 1.6.3.
+ [#11928](https://github.com/rust-lang/cargo/pull/11928)
+- Updated to `clap` 4.2.
+ [#11904](https://github.com/rust-lang/cargo/pull/11904)
- Integrated `cargo-deny` in Cargo its own CI pipeline.
[#11761](https://github.com/rust-lang/cargo/pull/11761)
+- Made non-blocking IO calls more robust.
+ [#11624](https://github.com/rust-lang/cargo/pull/11624)
+- Dropped `derive` feature from `serde` in `cargo-platform`.
+ [#11915](https://github.com/rust-lang/cargo/pull/11915)
+- Replaced `std::fs::canonicalize` with a more robust `try_canonicalize`.
+ [#11866](https://github.com/rust-lang/cargo/pull/11866)
+- Enabled clippy warning on `disallowed_methods` for `std::env::var` and friends.
+ [#11828](https://github.com/rust-lang/cargo/pull/11828)
## Cargo 1.69 (2023-04-20)
[985d561f...rust-1.69.0](https://github.com/rust-lang/cargo/compare/985d561f...rust-1.69.0)
@@ -72,7 +214,7 @@
[#11558](https://github.com/rust-lang/cargo/pull/11558)
- Cargo now suggests `cargo add` if you try to install a library crate.
[#11410](https://github.com/rust-lang/cargo/pull/11410)
-- Cargo now sets `CARGO_BIN_NAME` environment variable also for binary examples.
+- Cargo now sets the `CARGO_BIN_NAME` environment variable also for binary examples.
[#11705](https://github.com/rust-lang/cargo/pull/11705)
### Changed
@@ -82,13 +224,12 @@
Cargo will enable default features of that dependency.
[#11409](https://github.com/rust-lang/cargo/pull/11409)
- ❗ Deny `CARGO_HOME` in `[env]` configuration table. Cargo itself doesn't
- pick up this value, but recursive calls to cargo will. We consider it as a
- wrong behavior to only pass it to recursive invocations.
+ pick up this value, but recursive calls to cargo would, which was not intended.
[#11644](https://github.com/rust-lang/cargo/pull/11644)
-- ❗ Debuginfo for build dependencies is now off if not explicit set. This is
- expected to boost the overall build time.
+- ❗ Debuginfo for build dependencies is now off if not explicitly set. This is
+ expected to improve the overall build time.
[#11252](https://github.com/rust-lang/cargo/pull/11252)
-- Cargo now emits errors on invalid alphanumeric token for crates.io.
+- Cargo now emits errors on invalid alphanumeric characters in a registry token.
[#11600](https://github.com/rust-lang/cargo/pull/11600)
- `cargo add` now checks only the order of `[dependencies]`
without considering `[dependencies.*]`.
diff --git a/src/tools/cargo/Cargo.lock b/src/tools/cargo/Cargo.lock
new file mode 100644
index 000000000..14fd1d056
--- /dev/null
+++ b/src/tools/cargo/Cargo.lock
@@ -0,0 +1,3755 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "ahash"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
+dependencies = [
+ "cfg-if",
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anstream"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-wincon",
+ "concolor-override",
+ "concolor-query",
+ "is-terminal",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
+
+[[package]]
+name = "arc-swap"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
+
+[[package]]
+name = "arrayvec"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi 0.1.19",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "base16ct"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+
+[[package]]
+name = "base64"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+
+[[package]]
+name = "base64ct"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+
+[[package]]
+name = "benchsuite"
+version = "0.0.0"
+dependencies = [
+ "cargo",
+ "criterion",
+ "flate2",
+ "tar",
+ "url",
+]
+
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813"
+
+[[package]]
+name = "bitmaps"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bstr"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09"
+dependencies = [
+ "memchr",
+ "once_cell",
+ "regex-automata",
+ "serde",
+]
+
+[[package]]
+name = "btoi"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd6407f73a9b8b6162d8a2ef999fe6afd7cc15902ebf42c5cd296addf17e0ad"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "bytes"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+
+[[package]]
+name = "bytesize"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38fcc2979eff34a4b84e1cf9a1e3da42a7d44b3b690a40cdcb23e3d556cfb2e5"
+
+[[package]]
+name = "camino"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "capture"
+version = "0.1.0"
+dependencies = [
+ "cargo_metadata",
+ "flate2",
+ "tar",
+ "toml",
+]
+
+[[package]]
+name = "cargo"
+version = "0.72.1"
+dependencies = [
+ "anyhow",
+ "base64",
+ "bytesize",
+ "cargo-platform 0.1.3",
+ "cargo-test-macro",
+ "cargo-test-support",
+ "cargo-util",
+ "clap 4.2.1",
+ "crates-io",
+ "curl",
+ "curl-sys",
+ "env_logger 0.10.0",
+ "filetime",
+ "flate2",
+ "fwdansi",
+ "git2",
+ "git2-curl",
+ "gix",
+ "gix-features",
+ "glob",
+ "hex",
+ "hmac",
+ "home 0.5.5",
+ "http-auth",
+ "humantime 2.1.0",
+ "ignore",
+ "im-rc",
+ "indexmap",
+ "is-terminal",
+ "itertools",
+ "jobserver",
+ "lazy_static",
+ "lazycell",
+ "libc",
+ "libgit2-sys",
+ "log",
+ "memchr",
+ "opener",
+ "openssl",
+ "os_info",
+ "pasetors",
+ "pathdiff",
+ "pretty_env_logger",
+ "rand",
+ "rustfix",
+ "same-file",
+ "semver",
+ "serde",
+ "serde-value",
+ "serde_ignored",
+ "serde_json",
+ "sha1",
+ "shell-escape",
+ "snapbox",
+ "strip-ansi-escapes",
+ "tar",
+ "tempfile",
+ "termcolor",
+ "time",
+ "toml",
+ "toml_edit",
+ "unicode-width",
+ "unicode-xid",
+ "url",
+ "walkdir",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "cargo-credential"
+version = "0.2.0"
+
+[[package]]
+name = "cargo-credential-1password"
+version = "0.2.0"
+dependencies = [
+ "cargo-credential",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "cargo-credential-gnome-secret"
+version = "0.2.0"
+dependencies = [
+ "cargo-credential",
+ "pkg-config",
+]
+
+[[package]]
+name = "cargo-credential-macos-keychain"
+version = "0.2.0"
+dependencies = [
+ "cargo-credential",
+ "security-framework",
+]
+
+[[package]]
+name = "cargo-credential-wincred"
+version = "0.2.0"
+dependencies = [
+ "cargo-credential",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.1.3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo-test-macro"
+version = "0.1.0"
+
+[[package]]
+name = "cargo-test-support"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "cargo-test-macro",
+ "cargo-util",
+ "crates-io",
+ "filetime",
+ "flate2",
+ "git2",
+ "glob",
+ "itertools",
+ "lazy_static",
+ "pasetors",
+ "serde",
+ "serde_json",
+ "snapbox",
+ "tar",
+ "termcolor",
+ "time",
+ "toml",
+ "url",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "cargo-util"
+version = "0.2.4"
+dependencies = [
+ "anyhow",
+ "core-foundation",
+ "filetime",
+ "hex",
+ "jobserver",
+ "libc",
+ "log",
+ "miow",
+ "same-file",
+ "sha2",
+ "shell-escape",
+ "tempfile",
+ "walkdir",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
+dependencies = [
+ "camino",
+ "cargo-platform 0.1.2",
+ "semver",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "cast"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+dependencies = [
+ "jobserver",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "bitflags 1.3.2",
+ "textwrap",
+ "unicode-width",
+]
+
+[[package]]
+name = "clap"
+version = "4.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3"
+dependencies = [
+ "clap_builder",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "bitflags 1.3.2",
+ "clap_lex",
+ "strsim",
+ "terminal_size",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
+
+[[package]]
+name = "clru"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807"
+
+[[package]]
+name = "concolor-override"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f"
+
+[[package]]
+name = "concolor-query"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf"
+dependencies = [
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "const-oid"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
+
+[[package]]
+name = "content_inspector"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crates-io"
+version = "0.37.0"
+dependencies = [
+ "anyhow",
+ "curl",
+ "percent-encoding",
+ "serde",
+ "serde_json",
+ "url",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "criterion"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
+dependencies = [
+ "atty",
+ "cast",
+ "clap 2.34.0",
+ "criterion-plot",
+ "csv",
+ "itertools",
+ "lazy_static",
+ "num-traits",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_cbor",
+ "serde_derive",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
+dependencies = [
+ "cast",
+ "itertools",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-bigint"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c2538c4e68e52548bacb3e83ac549f903d44f011ac9d5abb5e132e67d0808f7"
+dependencies = [
+ "generic-array",
+ "rand_core",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "csv"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad"
+dependencies = [
+ "csv-core",
+ "itoa 1.0.6",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "ct-codecs"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df"
+
+[[package]]
+name = "ctor"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "curl"
+version = "0.4.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22"
+dependencies = [
+ "curl-sys",
+ "libc",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "socket2",
+ "winapi",
+]
+
+[[package]]
+name = "curl-sys"
+version = "0.4.61+curl-8.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14d05c10f541ae6f3bc5b3d923c20001f47db7d5f0b2bc6ad16490133842db79"
+dependencies = [
+ "cc",
+ "libc",
+ "libnghttp2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+ "winapi",
+]
+
+[[package]]
+name = "der"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82b10af9f9f9f2134a42d3f8aa74658660f2e0234b0eb81bd171df8aa32779ed"
+dependencies = [
+ "const-oid",
+ "pem-rfc7468",
+ "zeroize",
+]
+
+[[package]]
+name = "diff"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
+
+[[package]]
+name = "digest"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+dependencies = [
+ "block-buffer",
+ "const-oid",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "dunce"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"
+
+[[package]]
+name = "ecdsa"
+version = "0.16.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a48e5d537b8a30c0b023116d981b16334be1485af7ca68db3a2b7024cbc957fd"
+dependencies = [
+ "der",
+ "digest",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+]
+
+[[package]]
+name = "ed25519-compact"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a3d382e8464107391c8706b4c14b087808ecb909f6c15c34114bc42e53a9e4c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "either"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+
+[[package]]
+name = "elliptic-curve"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "digest",
+ "ff",
+ "generic-array",
+ "group",
+ "hkdf",
+ "pem-rfc7468",
+ "pkcs8",
+ "rand_core",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
+dependencies = [
+ "atty",
+ "humantime 1.3.0",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
+dependencies = [
+ "humantime 2.1.0",
+ "is-terminal",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "ff"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+dependencies = [
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "fiat-crypto"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
+
+[[package]]
+name = "filetime"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.2.16",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+dependencies = [
+ "crc32fast",
+ "libz-sys",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "fwdansi"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08c1f5787fe85505d1f7777268db5103d80a7a374d2316a7ce262e57baf8f208"
+dependencies = [
+ "memchr",
+ "termcolor",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+ "zeroize",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "git2"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b7905cdfe33d31a88bb2e8419ddd054451f5432d1da9eaf2ac7804ee1ea12d5"
+dependencies = [
+ "bitflags 1.3.2",
+ "libc",
+ "libgit2-sys",
+ "log",
+ "openssl-probe",
+ "openssl-sys",
+ "url",
+]
+
+[[package]]
+name = "git2-curl"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8f8b7432b72928cff76f69e59ed5327f94a52763731e71274960dee72fe5f8c"
+dependencies = [
+ "curl",
+ "git2",
+ "log",
+ "url",
+]
+
+[[package]]
+name = "gix"
+version = "0.44.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bf41b61f7df395284f7a579c0fa1a7e012c5aede655174d4e91299ef1cac643"
+dependencies = [
+ "gix-actor",
+ "gix-attributes",
+ "gix-config",
+ "gix-credentials",
+ "gix-date",
+ "gix-diff",
+ "gix-discover",
+ "gix-features",
+ "gix-fs",
+ "gix-glob",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-ignore",
+ "gix-index",
+ "gix-lock",
+ "gix-mailmap",
+ "gix-object",
+ "gix-odb",
+ "gix-pack",
+ "gix-path",
+ "gix-prompt",
+ "gix-protocol",
+ "gix-ref",
+ "gix-refspec",
+ "gix-revision",
+ "gix-sec",
+ "gix-tempfile",
+ "gix-transport",
+ "gix-traverse",
+ "gix-url",
+ "gix-utils",
+ "gix-validate",
+ "gix-worktree",
+ "log",
+ "once_cell",
+ "prodash",
+ "signal-hook",
+ "smallvec",
+ "thiserror",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "gix-actor"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "848efa0f1210cea8638f95691c82a46f98a74b9e3524f01d4955ebc25a8f84f3"
+dependencies = [
+ "bstr",
+ "btoi",
+ "gix-date",
+ "itoa 1.0.6",
+ "nom",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-attributes"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3015baa01ad2122fbcaab7863c857a603eb7b7ec12ac8141207c42c6439805e2"
+dependencies = [
+ "bstr",
+ "gix-glob",
+ "gix-path",
+ "gix-quote",
+ "kstring",
+ "log",
+ "smallvec",
+ "thiserror",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-bitmap"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55a95f4942360766c3880bdb2b4b57f1ef73b190fc424755e7fdf480430af618"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "gix-chunk"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0d39583cab06464b8bf73b3f1707458270f0e7383cb24c3c9c1a16e6f792978"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "gix-command"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2c6f75c1e0f924de39e750880a6e21307194bb1ab773efe3c7d2d787277f8ab"
+dependencies = [
+ "bstr",
+]
+
+[[package]]
+name = "gix-config"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d252a0eddb6df74600d3d8872dc9fe98835a7da43110411d705b682f49d4ac1"
+dependencies = [
+ "bstr",
+ "gix-config-value",
+ "gix-features",
+ "gix-glob",
+ "gix-path",
+ "gix-ref",
+ "gix-sec",
+ "log",
+ "memchr",
+ "nom",
+ "once_cell",
+ "smallvec",
+ "thiserror",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-config-value"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "786861e84a5793ad5f863d846de5eb064cd23b87e61ad708c8c402608202e7be"
+dependencies = [
+ "bitflags 2.2.1",
+ "bstr",
+ "gix-path",
+ "libc",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-credentials"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4874a4fc11ffa844a3c2b87a66957bda30a73b577ef1acf15ac34df5745de5ff"
+dependencies = [
+ "bstr",
+ "gix-command",
+ "gix-config-value",
+ "gix-path",
+ "gix-prompt",
+ "gix-sec",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-date"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99056f37270715f5c7584fd8b46899a2296af9cae92463bf58b8bd1f5a78e553"
+dependencies = [
+ "bstr",
+ "itoa 1.0.6",
+ "thiserror",
+ "time",
+]
+
+[[package]]
+name = "gix-diff"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "644a0f2768bc42d7a69289ada80c9e15c589caefc6a315d2307202df83ed1186"
+dependencies = [
+ "gix-hash",
+ "gix-object",
+ "imara-diff",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-discover"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5012710ebdecf6193c6866d6409a3b702a4aa0d78c605bc343590b44ab9962a1"
+dependencies = [
+ "bstr",
+ "dunce",
+ "gix-hash",
+ "gix-path",
+ "gix-ref",
+ "gix-sec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-features"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf69b0f5c701cc3ae22d3204b671907668f6437ca88862d355eaf9bc47a4f897"
+dependencies = [
+ "bytes",
+ "crc32fast",
+ "crossbeam-channel",
+ "flate2",
+ "gix-hash",
+ "libc",
+ "once_cell",
+ "parking_lot",
+ "prodash",
+ "sha1_smol",
+ "thiserror",
+ "walkdir",
+]
+
+[[package]]
+name = "gix-fs"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b37a1832f691fdc09910bd267f9a2e413737c1f9ec68c6e31f9e802616278a9"
+dependencies = [
+ "gix-features",
+]
+
+[[package]]
+name = "gix-glob"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c07c98204529ac3f24b34754540a852593d2a4c7349008df389240266627a72a"
+dependencies = [
+ "bitflags 2.2.1",
+ "bstr",
+ "gix-features",
+ "gix-path",
+]
+
+[[package]]
+name = "gix-hash"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "078eec3ac2808cc03f0bddd2704cb661da5c5dc33b41a9d7947b141d499c7c42"
+dependencies = [
+ "hex",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-hashtable"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afebb85691c6a085b114e01a27f4a61364519298c5826cb87a45c304802299bc"
+dependencies = [
+ "gix-hash",
+ "hashbrown 0.13.2",
+ "parking_lot",
+]
+
+[[package]]
+name = "gix-ignore"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba205b6df563e2906768bb22834c82eb46c5fdfcd86ba2c347270bc8309a05b2"
+dependencies = [
+ "bstr",
+ "gix-glob",
+ "gix-path",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-index"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa282756760f79c401d4f4f42588fbb4aa27bbb4b0830f3b4d3480c21a4ac5a7"
+dependencies = [
+ "bitflags 2.2.1",
+ "bstr",
+ "btoi",
+ "filetime",
+ "gix-bitmap",
+ "gix-features",
+ "gix-hash",
+ "gix-lock",
+ "gix-object",
+ "gix-traverse",
+ "itoa 1.0.6",
+ "memmap2",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-lock"
+version = "5.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41b80172055c5d8017a48ddac5cc7a95421c00211047db0165c97853c4f05194"
+dependencies = [
+ "fastrand",
+ "gix-tempfile",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-mailmap"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8856cec3bdc3610c06970d28b6cb20a0c6621621cf9a8ec48cbd23f2630f362"
+dependencies = [
+ "bstr",
+ "gix-actor",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-object"
+version = "0.29.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9bb30ce0818d37096daa29efe361a4bc6dd0b51a5726598898be7e9a40a01e1"
+dependencies = [
+ "bstr",
+ "btoi",
+ "gix-actor",
+ "gix-features",
+ "gix-hash",
+ "gix-validate",
+ "hex",
+ "itoa 1.0.6",
+ "nom",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-odb"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bca2f324aa67672b6d0f2c0fa93f96eb6a7029d260e4c1df5dce3c015f5e5add"
+dependencies = [
+ "arc-swap",
+ "gix-features",
+ "gix-hash",
+ "gix-object",
+ "gix-pack",
+ "gix-path",
+ "gix-quote",
+ "parking_lot",
+ "tempfile",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-pack"
+version = "0.35.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "164a515900a83257ae4aa80e741655bee7a2e39113fb535d7a5ac623b445ff20"
+dependencies = [
+ "clru",
+ "gix-chunk",
+ "gix-diff",
+ "gix-features",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "gix-path",
+ "gix-tempfile",
+ "gix-traverse",
+ "memmap2",
+ "parking_lot",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-packetline"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51f53abaf1171d2fe99f80ac8ed6645904a1bfd706674749ac112bdd2d4f0777"
+dependencies = [
+ "bstr",
+ "hex",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-path"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fc78f47095a0c15aea0e66103838f0748f4494bf7a9555dfe0f00425400396c"
+dependencies = [
+ "bstr",
+ "home 0.5.5",
+ "once_cell",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-prompt"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "330d11fdf88fff3366c2491efde2f3e454958efe7d5ddf60272e8fb1d944bb01"
+dependencies = [
+ "gix-command",
+ "gix-config-value",
+ "parking_lot",
+ "rustix",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-protocol"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877e49417f1730f4dbc2f7d9a2ab0f8b2f49ef08f97270691403ecde3d961e3a"
+dependencies = [
+ "bstr",
+ "btoi",
+ "gix-credentials",
+ "gix-features",
+ "gix-hash",
+ "gix-transport",
+ "maybe-async",
+ "nom",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-quote"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a282f5a8d9ee0b09ec47390ac727350c48f2f5c76d803cd8da6b3e7ad56e0bcb"
+dependencies = [
+ "bstr",
+ "btoi",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-ref"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8212ecfe41815a2f1b059d82171d6276758cfac5506a5e0f04ad45ef0b1924a"
+dependencies = [
+ "gix-actor",
+ "gix-features",
+ "gix-fs",
+ "gix-hash",
+ "gix-lock",
+ "gix-object",
+ "gix-path",
+ "gix-tempfile",
+ "gix-validate",
+ "memmap2",
+ "nom",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-refspec"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6ea733820df67e4cd7797deb12727905824d8f5b7c59d943c456d314475892"
+dependencies = [
+ "bstr",
+ "gix-hash",
+ "gix-revision",
+ "gix-validate",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-revision"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "810f35e9afeccca999d5d348b239f9c162353127d2e13ff3240e31b919e35476"
+dependencies = [
+ "bstr",
+ "gix-date",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-sec"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "794520043d5a024dfeac335c6e520cb616f6963e30dab995892382e998c12897"
+dependencies = [
+ "bitflags 2.2.1",
+ "gix-path",
+ "libc",
+ "windows",
+]
+
+[[package]]
+name = "gix-tempfile"
+version = "5.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2ceb30a610e3f5f2d5f9a5114689fde507ba9417705a8cf3429604275b2153c"
+dependencies = [
+ "libc",
+ "once_cell",
+ "parking_lot",
+ "signal-hook",
+ "signal-hook-registry",
+ "tempfile",
+]
+
+[[package]]
+name = "gix-transport"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f01c2bf7b989c679695ef635fc7d9e80072e08101be4b53193c8e8b649900102"
+dependencies = [
+ "base64",
+ "bstr",
+ "curl",
+ "gix-command",
+ "gix-credentials",
+ "gix-features",
+ "gix-packetline",
+ "gix-quote",
+ "gix-sec",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-traverse"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5be1e807f288c33bb005075111886cceb43ed8a167b3182a0f62c186e2a0dd1"
+dependencies = [
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-url"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfc77f89054297cc81491e31f1bab4027e554b5ef742a44bd7035db9a0f78b76"
+dependencies = [
+ "bstr",
+ "gix-features",
+ "gix-path",
+ "home 0.5.5",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "gix-utils"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c10b69beac219acb8df673187a1f07dde2d74092f974fb3f9eb385aeb667c909"
+dependencies = [
+ "fastrand",
+]
+
+[[package]]
+name = "gix-validate"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bd629d3680773e1785e585d76fd4295b740b559cad9141517300d99a0c8c049"
+dependencies = [
+ "bstr",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-worktree"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10bf56a1f5037d84293ea6cece61d9f27c4866b1e13c1c95f37cf56b7da7af25"
+dependencies = [
+ "bstr",
+ "filetime",
+ "gix-attributes",
+ "gix-features",
+ "gix-fs",
+ "gix-glob",
+ "gix-hash",
+ "gix-ignore",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "io-close",
+ "thiserror",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "globset"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "fnv",
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "group"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+dependencies = [
+ "ff",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "half"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
+
+[[package]]
+name = "handlebars"
+version = "3.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3"
+dependencies = [
+ "log",
+ "pest",
+ "pest_derive",
+ "quick-error 2.0.1",
+ "serde",
+ "serde_json",
+ "walkdir",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "hashbrown"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hkdf"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "home"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "home"
+version = "0.5.6"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "http-auth"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5430cacd7a1f9a02fbeb350dfc81a0e5ed42d81f3398cb0ba184017f85bdcfbc"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+dependencies = [
+ "quick-error 1.2.3",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "idna"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "ignore"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
+dependencies = [
+ "globset",
+ "lazy_static",
+ "log",
+ "memchr",
+ "regex",
+ "same-file",
+ "thread_local",
+ "walkdir",
+ "winapi-util",
+]
+
+[[package]]
+name = "im-rc"
+version = "15.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
+dependencies = [
+ "bitmaps",
+ "rand_core",
+ "rand_xoshiro",
+ "sized-chunks",
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "imara-diff"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8"
+dependencies = [
+ "ahash",
+ "hashbrown 0.12.3",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown 0.12.3",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "io-close"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
+
+[[package]]
+name = "itoa"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+
+[[package]]
+name = "jobserver"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "kstring"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747"
+dependencies = [
+ "static_assertions",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "leb128"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
+
+[[package]]
+name = "libc"
+version = "0.2.144"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+
+[[package]]
+name = "libgit2-sys"
+version = "0.15.1+1.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb4577bde8cdfc7d6a2a4bcb7b049598597de33ffd337276e9c7db6cd4a2cee7"
+dependencies = [
+ "cc",
+ "libc",
+ "libssh2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "libm"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
+
+[[package]]
+name = "libnghttp2-sys"
+version = "0.1.7+1.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57ed28aba195b38d5ff02b9170cbff627e336a20925e43b4945390401c5dc93f"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "libssh2-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee"
+dependencies = [
+ "cc",
+ "libc",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "libz-sys"
+version = "1.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf"
+
+[[package]]
+name = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "maybe-async"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "mdman"
+version = "0.0.0"
+dependencies = [
+ "anyhow",
+ "handlebars",
+ "pretty_assertions",
+ "pulldown-cmark",
+ "same-file",
+ "serde_json",
+ "url",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "memmap2"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "miow"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52ffbca2f655e33c08be35d87278e5b18b89550a37dbd598c20db92f6a471123"
+dependencies = [
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "normalize-line-endings"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+ "libm",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "libc",
+]
+
+[[package]]
+name = "num_threads"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+
+[[package]]
+name = "oorandom"
+version = "11.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
+
+[[package]]
+name = "opener"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005"
+dependencies = [
+ "bstr",
+ "winapi",
+]
+
+[[package]]
+name = "openssl"
+version = "0.10.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1"
+dependencies = [
+ "bitflags 1.3.2",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.14",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "openssl-src"
+version = "111.25.3+1.1.1t"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "924757a6a226bf60da5f7dd0311a34d2b52283dd82ddeb103208ddc66362f80c"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.85"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0"
+dependencies = [
+ "cc",
+ "libc",
+ "openssl-src",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "ordered-float"
+version = "2.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "orion"
+version = "0.17.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbe74a766292f94f7e69db5a7bf010eadd944f24186c463fe578a7e637582066"
+dependencies = [
+ "fiat-crypto",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "os_info"
+version = "3.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e"
+dependencies = [
+ "log",
+ "serde",
+ "winapi",
+]
+
+[[package]]
+name = "output_vt100"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "p384"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "primeorder",
+ "sha2",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.2.16",
+ "smallvec",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "partial_ref"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f728bc9b1479656e40cba507034904a8c44027c0efdbbaf6a4bdc5f2d3a910c"
+dependencies = [
+ "partial_ref_derive",
+]
+
+[[package]]
+name = "partial_ref_derive"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "300e1d2cb5b898b5a5342e994e0d0c367dbfe69cbf717cd307045ec9fb057581"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "pasetors"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "824bf633b85dc1dece2eb07161627ba5d90a951597cd5dbf8d85f4d82b7aea69"
+dependencies = [
+ "ct-codecs",
+ "ed25519-compact",
+ "getrandom",
+ "orion",
+ "p384",
+ "rand_core",
+ "regex",
+ "serde",
+ "serde_json",
+ "sha2",
+ "subtle",
+ "time",
+ "zeroize",
+]
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "pem-rfc7468"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
+dependencies = [
+ "base64ct",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+
+[[package]]
+name = "pest"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122"
+dependencies = [
+ "thiserror",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.14",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e"
+dependencies = [
+ "once_cell",
+ "pest",
+ "sha2",
+]
+
+[[package]]
+name = "pkcs8"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+dependencies = [
+ "der",
+ "spki",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
+
+[[package]]
+name = "plotters"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
+dependencies = [
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
+dependencies = [
+ "plotters-backend",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "pretty_assertions"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
+dependencies = [
+ "ctor",
+ "diff",
+ "output_vt100",
+ "yansi",
+]
+
+[[package]]
+name = "pretty_env_logger"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
+dependencies = [
+ "env_logger 0.7.1",
+ "log",
+]
+
+[[package]]
+name = "primeorder"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf8d3875361e28f7753baefef104386e7aa47642c93023356d97fdef4003bfb5"
+dependencies = [
+ "elliptic-curve",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "prodash"
+version = "23.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9516b775656bc3e8985e19cd4b8c0c0de045095074e453d2c0a513b5f978392d"
+dependencies = [
+ "parking_lot",
+]
+
+[[package]]
+name = "proptest"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70"
+dependencies = [
+ "bit-set",
+ "bitflags 1.3.2",
+ "byteorder",
+ "lazy_static",
+ "num-traits",
+ "quick-error 2.0.1",
+ "rand",
+ "rand_chacha",
+ "rand_xorshift",
+ "regex-syntax",
+ "rusty-fork",
+ "tempfile",
+ "unarray",
+]
+
+[[package]]
+name = "pulldown-cmark"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
+dependencies = [
+ "bitflags 1.3.2",
+ "memchr",
+ "unicase",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quick-error"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
+
+[[package]]
+name = "quote"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_xorshift"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_xoshiro"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "regex"
+version = "1.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
+name = "resolver-tests"
+version = "0.0.0"
+dependencies = [
+ "cargo",
+ "cargo-util",
+ "is-terminal",
+ "lazy_static",
+ "proptest",
+ "varisat",
+]
+
+[[package]]
+name = "rfc6979"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
+dependencies = [
+ "hmac",
+ "subtle",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustfix"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecd2853d9e26988467753bd9912c3a126f642d05d229a4b53f5752ee36c56481"
+dependencies = [
+ "anyhow",
+ "log",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "rustix"
+version = "0.37.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece"
+dependencies = [
+ "bitflags 1.3.2",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "rusty-fork"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
+dependencies = [
+ "fnv",
+ "quick-error 1.2.3",
+ "tempfile",
+ "wait-timeout",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
+dependencies = [
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "sec1"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
+dependencies = [
+ "base16ct",
+ "der",
+ "generic-array",
+ "pkcs8",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "semver-check"
+version = "0.0.0"
+dependencies = [
+ "tempfile",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.160"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde-value"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
+dependencies = [
+ "ordered-float",
+ "serde",
+]
+
+[[package]]
+name = "serde_cbor"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
+dependencies = [
+ "half",
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.160"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.14",
+]
+
+[[package]]
+name = "serde_ignored"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94eb4a4087ba8bdf14a9208ac44fddbf55c01a6195f7edfc511ddaff6cae45a6"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744"
+dependencies = [
+ "itoa 1.0.6",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha1_smol"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
+
+[[package]]
+name = "sha2"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "shell-escape"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
+
+[[package]]
+name = "signal-hook"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "signature"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
+dependencies = [
+ "digest",
+ "rand_core",
+]
+
+[[package]]
+name = "similar"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf"
+
+[[package]]
+name = "sized-chunks"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
+dependencies = [
+ "bitmaps",
+ "typenum",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "snapbox"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9615402f9cff539301119bdf2c2f328739cf2b45c2116666618fb6ac399f75bb"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "content_inspector",
+ "dunce",
+ "filetime",
+ "normalize-line-endings",
+ "similar",
+ "snapbox-macros",
+ "tempfile",
+ "walkdir",
+]
+
+[[package]]
+name = "snapbox-macros"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8e40c667388ed1cb5060f545d0013bf0a23efdfa6c5c3e9ef592de391cd860f"
+dependencies = [
+ "anstream",
+]
+
+[[package]]
+name = "socket2"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "spki"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strip-ansi-escapes"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8"
+dependencies = [
+ "vte",
+]
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tar"
+version = "0.4.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96"
+dependencies = [
+ "filetime",
+ "libc",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "redox_syscall 0.3.5",
+ "rustix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
+dependencies = [
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.14",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "time"
+version = "0.3.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
+dependencies = [
+ "itoa 1.0.6",
+ "libc",
+ "num_threads",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+
+[[package]]
+name = "time-macros"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
+dependencies = [
+ "time-core",
+]
+
+[[package]]
+name = "tinytemplate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "toml"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.19.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
+
+[[package]]
+name = "unarray"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
+
+[[package]]
+name = "unicase"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
+
+[[package]]
+name = "unicode-bom"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
+[[package]]
+name = "url"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "varisat"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebe609851d1e9196674ac295f656bd8601200a1077343d22b345013497807caf"
+dependencies = [
+ "anyhow",
+ "itoa 0.4.8",
+ "leb128",
+ "log",
+ "ordered-float",
+ "partial_ref",
+ "rustc-hash",
+ "serde",
+ "thiserror",
+ "varisat-checker",
+ "varisat-dimacs",
+ "varisat-formula",
+ "varisat-internal-macros",
+ "varisat-internal-proof",
+ "vec_mut_scan",
+]
+
+[[package]]
+name = "varisat-checker"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "135c977c5913ed6e98f6b81b8e4d322211303b7d40dae773caef7ad1de6c763b"
+dependencies = [
+ "anyhow",
+ "log",
+ "partial_ref",
+ "rustc-hash",
+ "smallvec",
+ "thiserror",
+ "varisat-dimacs",
+ "varisat-formula",
+ "varisat-internal-proof",
+]
+
+[[package]]
+name = "varisat-dimacs"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d1dee4e21be1f04c0a939f7ae710cced47233a578de08a1b3c7d50848402636"
+dependencies = [
+ "anyhow",
+ "itoa 0.4.8",
+ "thiserror",
+ "varisat-formula",
+]
+
+[[package]]
+name = "varisat-formula"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "395c5543b9bfd9076d6d3af49d6c34a4b91b0b355998c0a5ec6ed7265d364520"
+
+[[package]]
+name = "varisat-internal-macros"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "602ece773543d066aa7848455486c6c0422a3f214da7a2b899100f3c4f12408d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "regex",
+ "syn 1.0.109",
+ "synstructure",
+]
+
+[[package]]
+name = "varisat-internal-proof"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6163bb7bc9018af077b76d64f976803d141c36a27d640f1437dddc4fd527d207"
+dependencies = [
+ "anyhow",
+ "varisat-formula",
+]
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "vec_mut_scan"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68ed610a8d5e63d9c0e31300e8fdb55104c5f21e422743a9dc74848fa8317fd2"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "vte"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983"
+dependencies = [
+ "arrayvec",
+ "utf8parse",
+ "vte_generate_state_changes",
+]
+
+[[package]]
+name = "vte_generate_state_changes"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "wait-timeout"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "walkdir"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+
+[[package]]
+name = "web-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
+name = "winnow"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "xtask-build-man"
+version = "0.0.0"
+
+[[package]]
+name = "xtask-stale-label"
+version = "0.0.0"
+dependencies = [
+ "toml_edit",
+]
+
+[[package]]
+name = "xtask-unpublished"
+version = "0.0.0"
+dependencies = [
+ "anyhow",
+ "cargo",
+ "clap 4.2.1",
+ "env_logger 0.10.0",
+ "log",
+]
+
+[[package]]
+name = "yansi"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+
+[[package]]
+name = "zeroize"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
diff --git a/src/tools/cargo/Cargo.toml b/src/tools/cargo/Cargo.toml
index 56c9827cb..05c95c727 100644
--- a/src/tools/cargo/Cargo.toml
+++ b/src/tools/cargo/Cargo.toml
@@ -1,41 +1,45 @@
-[package]
-name = "cargo"
-version = "0.71.0"
-edition = "2021"
-license = "MIT OR Apache-2.0"
-homepage = "https://crates.io"
-repository = "https://github.com/rust-lang/cargo"
-documentation = "https://docs.rs/cargo"
-readme = "README.md"
-description = """
-Cargo, a package manager for Rust.
-"""
-
-[lib]
-name = "cargo"
-path = "src/cargo/lib.rs"
+[workspace]
+resolver = "2"
+members = [
+ "crates/*",
+ "credential/*",
+ "benches/benchsuite",
+ "benches/capture",
+]
+exclude = [
+ "target/", # exclude bench testing
+]
-[dependencies]
+[workspace.dependencies]
anyhow = "1.0.47"
base64 = "0.21.0"
bytesize = "1.0"
-cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" }
-cargo-util = { path = "crates/cargo-util", version = "0.2.4" }
+cargo = { path = "" }
+cargo-credential = { version = "0.2.0", path = "credential/cargo-credential" }
+cargo-platform = { path = "crates/cargo-platform", version = "0.1.3" }
+cargo-test-macro = { path = "crates/cargo-test-macro" }
+cargo-test-support = { path = "crates/cargo-test-support" }
+cargo-util = { version = "0.2.4", path = "crates/cargo-util" }
+cargo_metadata = "0.14.0"
clap = "4.2.0"
-crates-io = { path = "crates/crates-io", version = "0.36.0" }
-curl = { version = "0.4.44", features = ["http2"] }
+core-foundation = { version = "0.9.0", features = ["mac_os_10_7_support"] }
+crates-io = { version = "0.37.0", path = "crates/crates-io" }
+criterion = { version = "0.3.5", features = ["html_reports"] }
+curl = "0.4.44"
curl-sys = "0.4.61"
env_logger = "0.10.0"
filetime = "0.2.9"
flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] }
-git2 = "0.17.0"
+fwdansi = "1.1.0"
+git2 = "0.17.1"
git2-curl = "0.18.0"
-gix = { version = "0.39.0", default-features = false, features = ["blocking-http-transport-curl", "progress-tree"] }
-gix-features-for-configuration-only = { version = "0.28.0", package = "gix-features", features = [ "parallel" ] }
+gix = { version = "0.44.1", default-features = false, features = ["blocking-http-transport-curl", "progress-tree"] }
+gix-features-for-configuration-only = { version = "0.29.0", package = "gix-features", features = [ "parallel" ] }
glob = "0.3.0"
-hex = "0.4"
+handlebars = { version = "3.2.1", features = ["dir_source"] }
+hex = "0.4.2"
hmac = "0.12.1"
-home = "0.5"
+home = "0.5.5"
http-auth = { version = "0.1.6", default-features = false }
humantime = "2.0.0"
ignore = "0.4.7"
@@ -44,49 +48,137 @@ indexmap = "1"
is-terminal = "0.4.4"
itertools = "0.10.0"
jobserver = "0.1.26"
-lazy_static = "1.2.0"
+lazy_static = "1.3.0"
lazycell = "1.2.0"
-libc = "0.2"
-libgit2-sys = "0.15.0"
-log = "0.4.6"
+libc = "0.2.144"
+libgit2-sys = "0.15.1"
+log = "0.4.17"
memchr = "2.1.3"
+miow = "0.5.0"
opener = "0.5"
-openssl = { version = '0.10.11', optional = true }
+openssl ="0.10.50"
os_info = "3.5.0"
pasetors = { version = "0.6.4", features = ["v3", "paserk", "std", "serde"] }
pathdiff = "0.2"
-pretty_env_logger = { version = "0.4", optional = true }
+percent-encoding = "2.0"
+pkg-config = "0.3.19"
+pretty_assertions = "1.3.0"
+pretty_env_logger = "0.4"
+proptest = "1.1.0"
+pulldown-cmark = { version = "0.9.2", default-features = false }
rand = "0.8.5"
rustfix = "0.6.0"
+same-file = "1.0.6"
+security-framework = "2.0.0"
semver = { version = "1.0.3", features = ["serde"] }
-serde = { version = "1.0.123", features = ["derive"] }
+serde = "1.0.123"
serde-value = "0.7.0"
serde_ignored = "0.1.0"
-serde_json = { version = "1.0.30", features = ["raw_value"] }
+serde_json = "1.0.59"
sha1 = "0.10.5"
+sha2 = "0.10.6"
shell-escape = "0.1.4"
+snapbox = { version = "0.4.0", features = ["diff", "path"] }
strip-ansi-escapes = "0.1.0"
-tar = { version = "0.4.38", default-features = false }
-tempfile = "3.0"
-termcolor = "1.1"
-time = { version = "0.3", features = ["parsing", "formatting"]}
+tar = { version = "0.4.39", default-features = false }
+tempfile = "3.1.0"
+termcolor = "1.1.2"
+time = { version = "0.3", features = ["parsing", "formatting"] }
toml = "0.7.0"
toml_edit = "0.19.0"
unicode-width = "0.1.5"
unicode-xid = "0.2.0"
url = "2.2.2"
-walkdir = "2.2"
+varisat = "0.2.1"
+walkdir = "2.3.1"
+windows-sys = "0.48"
-# A noop dependency that changes in the Rust repository, it's a bit of a hack.
-# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
-# for more information.
-rustc-workspace-hack = "1.0.0"
+[package]
+name = "cargo"
+version = "0.72.1"
+edition = "2021"
+license = "MIT OR Apache-2.0"
+homepage = "https://crates.io"
+repository = "https://github.com/rust-lang/cargo"
+documentation = "https://docs.rs/cargo"
+readme = "README.md"
+description = """
+Cargo, a package manager for Rust.
+"""
+
+[lib]
+name = "cargo"
+path = "src/cargo/lib.rs"
+
+[dependencies]
+anyhow.workspace = true
+base64.workspace = true
+bytesize.workspace = true
+cargo-platform.workspace = true
+cargo-util.workspace = true
+clap = { workspace = true, features = ["wrap_help"] }
+crates-io.workspace = true
+curl = { workspace = true, features = ["http2"] }
+curl-sys.workspace = true
+env_logger.workspace = true
+filetime.workspace = true
+flate2.workspace = true
+git2.workspace = true
+git2-curl.workspace = true
+gix.workspace = true
+gix-features-for-configuration-only.workspace = true
+glob.workspace = true
+hex.workspace = true
+hmac.workspace = true
+home.workspace = true
+http-auth.workspace = true
+humantime.workspace = true
+ignore.workspace = true
+im-rc.workspace = true
+indexmap.workspace = true
+is-terminal.workspace = true
+itertools.workspace = true
+jobserver.workspace = true
+lazy_static.workspace = true
+lazycell.workspace = true
+libc.workspace = true
+libgit2-sys.workspace = true
+log.workspace = true
+memchr.workspace = true
+opener.workspace = true
+os_info.workspace = true
+pasetors.workspace = true
+pathdiff.workspace = true
+pretty_env_logger = { workspace = true, optional = true }
+rand.workspace = true
+rustfix.workspace = true
+semver.workspace = true
+serde = { workspace = true, features = ["derive"] }
+serde-value.workspace = true
+serde_ignored.workspace = true
+serde_json = { workspace = true, features = ["raw_value"] }
+sha1.workspace = true
+shell-escape.workspace = true
+strip-ansi-escapes.workspace = true
+tar.workspace = true
+tempfile.workspace = true
+termcolor.workspace = true
+time.workspace = true
+toml.workspace = true
+toml_edit.workspace = true
+unicode-width.workspace = true
+unicode-xid.workspace = true
+url.workspace = true
+walkdir.workspace = true
+
+[target.'cfg(not(windows))'.dependencies]
+openssl = { workspace = true, optional = true }
[target.'cfg(windows)'.dependencies]
-fwdansi = "1.1.0"
+fwdansi.workspace = true
[target.'cfg(windows)'.dependencies.windows-sys]
-version = "0.45"
+workspace = true
features = [
"Win32_Foundation",
"Win32_Storage_FileSystem",
@@ -99,14 +191,14 @@ features = [
]
[dev-dependencies]
-cargo-test-macro = { path = "crates/cargo-test-macro" }
-cargo-test-support = { path = "crates/cargo-test-support" }
-same-file = "1.0.6"
-snapbox = { version = "0.4.0", features = ["diff", "path"] }
+cargo-test-macro.workspace = true
+cargo-test-support.workspace = true
+same-file.workspace = true
+snapbox.workspace = true
[build-dependencies]
-flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] }
-tar = { version = "0.4.38", default-features = false }
+flate2.workspace = true
+tar.workspace = true
[[bin]]
name = "cargo"
@@ -117,3 +209,5 @@ doc = false
vendored-openssl = ["openssl/vendored"]
vendored-libgit2 = ["libgit2-sys/vendored"]
pretty-env-logger = ["pretty_env_logger"]
+# This is primarily used by rust-lang/rust distributing cargo the executable.
+all-static = ['vendored-openssl', 'curl/static-curl', 'curl/force-system-lib-on-osx']
diff --git a/src/tools/cargo/benches/benchsuite/Cargo.toml b/src/tools/cargo/benches/benchsuite/Cargo.toml
index f4bc3583a..782e6c101 100644
--- a/src/tools/cargo/benches/benchsuite/Cargo.toml
+++ b/src/tools/cargo/benches/benchsuite/Cargo.toml
@@ -1,20 +1,19 @@
[package]
name = "benchsuite"
-version = "0.1.0"
+version = "0.0.0"
edition = "2021"
license = "MIT OR Apache-2.0"
homepage = "https://github.com/rust-lang/cargo"
repository = "https://github.com/rust-lang/cargo"
-documentation = "https://docs.rs/cargo-platform"
description = "Benchmarking suite for Cargo."
+publish = false
[dependencies]
-cargo = { path = "../.." }
-# Consider removing html_reports in 0.4 and switching to `cargo criterion`.
-criterion = { version = "0.3.5", features = ["html_reports"] }
-flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] }
-tar = { version = "0.4.38", default-features = false }
-url = "2.2.2"
+cargo.workspace = true
+criterion.workspace = true
+flate2.workspace = true
+tar.workspace = true
+url.workspace = true
[lib]
bench = false
diff --git a/src/tools/cargo/benches/capture/Cargo.toml b/src/tools/cargo/benches/capture/Cargo.toml
index 25a901777..6319a0130 100644
--- a/src/tools/cargo/benches/capture/Cargo.toml
+++ b/src/tools/cargo/benches/capture/Cargo.toml
@@ -4,9 +4,10 @@ version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Tool for capturing a real-world workspace for benchmarking."
+publish = false
[dependencies]
-cargo_metadata = "0.14.0"
-flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] }
-tar = { version = "0.4.38", default-features = false }
-toml = "0.7.0"
+cargo_metadata.workspace = true
+flate2.workspace = true
+tar.workspace = true
+toml.workspace = true
diff --git a/src/tools/cargo/ci/validate-man.sh b/src/tools/cargo/ci/validate-man.sh
index 92df49781..a3f114214 100755
--- a/src/tools/cargo/ci/validate-man.sh
+++ b/src/tools/cargo/ci/validate-man.sh
@@ -3,24 +3,25 @@
set -e
-cd src/doc
+cargo_man="src/doc"
+mdman_man="crates/mdman/doc"
-changes=$(git status --porcelain)
+changes=$(git status --porcelain -- $cargo_man $mdman_man)
if [ -n "$changes" ]
then
echo "git directory must be clean before running this script."
exit 1
fi
-./build-man.sh
+cargo build-man
-changes=$(git status --porcelain)
+changes=$(git status --porcelain -- $cargo_man $mdman_man)
if [ -n "$changes" ]
then
- echo "Detected changes in man pages:"
+ echo "Detected changes of man pages:"
echo "$changes"
echo
- echo "Please run './build-man.sh' in the src/doc directory to rebuild the"
- echo "man pages, and commit the changes."
+ echo 'Please run `cargo build-man` to rebuild the man pages'
+ echo "and commit the changes."
exit 1
fi
diff --git a/src/tools/cargo/ci/validate-version-bump.sh b/src/tools/cargo/ci/validate-version-bump.sh
new file mode 100755
index 000000000..9b54fdaaf
--- /dev/null
+++ b/src/tools/cargo/ci/validate-version-bump.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# This script checks if a crate needs a version bump.
+#
+# At the time of writing, it doesn't check what kind of bump is required.
+# In the future, we could take SemVer compatibliity into account, like
+# integrating `cargo-semver-checks` of else
+#
+# Inputs:
+# BASE_SHA The commit SHA of the branch where the PR wants to merge into.
+# HEAD_SHA The commit SHA that triggered the workflow.
+
+set -euo pipefail
+
+# When `BASE_SHA` is missing, we assume it is from bors merge commit,
+# so hope `HEAD~` to find the previous commit on master branch.
+base_sha=$(git rev-parse "${BASE_SHA:-HEAD~1}")
+head_sha=$(git rev-parse "${HEAD_SHA:-HEAD}")
+
+echo "Base branch is $base_sha"
+echo "Current head is $head_sha"
+
+# Gets crate names of members that has been changed from $bash_sha to $head_sha.
+changed_crates=$(
+ git diff --name-only "$base_sha" "$head_sha" -- crates/ credential/ benches/ \
+ | cut -d'/' -f2 \
+ | sort -u
+)
+
+if [ -z "$changed_crates" ]
+then
+ echo "No file changed in member crates."
+ exit 0
+fi
+
+# Checks publish status for only crates with code changes.
+publish_status_table=$(
+ echo "$changed_crates" \
+ | xargs printf -- '--package %s\n' \
+ | xargs cargo unpublished
+)
+
+# "yes" -> code changed but no version difference -> need a bump
+# Prints 2nd column (sep by space), which is the name of the crate.
+crates_need_bump=$(
+ echo "$publish_status_table" \
+ | { grep '| yes ' || true; } \
+ | awk '{print $2}'
+)
+
+if [ -z "$crates_need_bump" ]
+then
+ echo "No version bump needed for member crates."
+ exit 0
+fi
+
+echo "Detected changes in these crates but no version bump found:"
+echo "$crates_need_bump"
+echo
+echo "Please bump at least one patch version for each corresponding Cargo.toml:"
+echo 'Run "cargo unpublished" to read the publish status table for details.'
+exit 1
diff --git a/src/tools/cargo/crates/cargo-platform/Cargo.toml b/src/tools/cargo/crates/cargo-platform/Cargo.toml
index a5e51ee5d..423cf491d 100644
--- a/src/tools/cargo/crates/cargo-platform/Cargo.toml
+++ b/src/tools/cargo/crates/cargo-platform/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cargo-platform"
-version = "0.1.2"
+version = "0.1.3"
edition = "2021"
license = "MIT OR Apache-2.0"
homepage = "https://github.com/rust-lang/cargo"
@@ -9,4 +9,4 @@ documentation = "https://docs.rs/cargo-platform"
description = "Cargo's representation of a target platform."
[dependencies]
-serde = "1.0.82"
+serde.workspace = true
diff --git a/src/tools/cargo/crates/cargo-test-macro/Cargo.toml b/src/tools/cargo/crates/cargo-test-macro/Cargo.toml
index 04dafc028..e40602ae3 100644
--- a/src/tools/cargo/crates/cargo-test-macro/Cargo.toml
+++ b/src/tools/cargo/crates/cargo-test-macro/Cargo.toml
@@ -7,6 +7,7 @@ homepage = "https://github.com/rust-lang/cargo"
repository = "https://github.com/rust-lang/cargo"
documentation = "https://github.com/rust-lang/cargo"
description = "Helper proc-macro for Cargo's testsuite."
+publish = false
[lib]
proc-macro = true
diff --git a/src/tools/cargo/crates/cargo-test-support/Cargo.toml b/src/tools/cargo/crates/cargo-test-support/Cargo.toml
index 91e6e4e34..305c809a8 100644
--- a/src/tools/cargo/crates/cargo-test-support/Cargo.toml
+++ b/src/tools/cargo/crates/cargo-test-support/Cargo.toml
@@ -3,30 +3,31 @@ name = "cargo-test-support"
version = "0.1.0"
license = "MIT OR Apache-2.0"
edition = "2021"
+publish = false
[lib]
doctest = false
[dependencies]
-anyhow = "1.0.34"
-cargo-test-macro = { path = "../cargo-test-macro" }
-cargo-util = { path = "../cargo-util" }
-crates-io = { path = "../crates-io" }
-filetime = "0.2"
-flate2 = { version = "1.0", default-features = false, features = ["zlib"] }
-git2 = "0.17.0"
-glob = "0.3"
-itertools = "0.10.0"
-lazy_static = "1.0"
-pasetors = { version = "0.6.4", features = ["v3", "paserk", "std", "serde"] }
-serde = { version = "1.0.123", features = ["derive"] }
-serde_json = "1.0"
-snapbox = { version = "0.4.0", features = ["diff", "path"] }
-tar = { version = "0.4.38", default-features = false }
-termcolor = "1.1.2"
-time = { version = "0.3", features = ["parsing", "formatting"]}
-toml = "0.7.0"
-url = "2.2.2"
+anyhow.workspace = true
+cargo-test-macro.workspace = true
+cargo-util.workspace = true
+crates-io.workspace = true
+filetime.workspace = true
+flate2.workspace = true
+git2.workspace = true
+glob.workspace = true
+itertools.workspace = true
+lazy_static.workspace = true
+pasetors.workspace = true
+serde = { workspace = true, features = ["derive"] }
+serde_json.workspace = true
+snapbox.workspace = true
+tar.workspace = true
+termcolor.workspace = true
+time.workspace = true
+toml.workspace = true
+url.workspace = true
[target.'cfg(windows)'.dependencies]
-windows-sys = { version = "0.45.0", features = ["Win32_Storage_FileSystem"] }
+windows-sys = { workspace = true, features = ["Win32_Storage_FileSystem"] }
diff --git a/src/tools/cargo/crates/cargo-test-support/src/install.rs b/src/tools/cargo/crates/cargo-test-support/src/install.rs
index 478b482d2..02842ef7b 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/install.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/install.rs
@@ -4,8 +4,12 @@ use std::path::{Path, PathBuf};
/// Used by `cargo install` tests to assert an executable binary
/// has been installed. Example usage:
+/// ```no_run
+/// use cargo_test_support::install::assert_has_installed_exe;
+/// use cargo_test_support::install::cargo_home;
///
-/// assert_has_installed_exe(cargo_home(), "foo");
+/// assert_has_installed_exe(cargo_home(), "foo");
+/// ```
#[track_caller]
pub fn assert_has_installed_exe<P: AsRef<Path>>(path: P, name: &'static str) {
assert!(check_has_installed_exe(path, name));
diff --git a/src/tools/cargo/crates/cargo-test-support/src/lib.rs b/src/tools/cargo/crates/cargo-test-support/src/lib.rs
index 04d6ce9f8..d27aab44f 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/lib.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/lib.rs
@@ -59,8 +59,8 @@ pub fn panic_error(what: &str, err: impl Into<anyhow::Error>) -> ! {
fn pe(what: &str, err: anyhow::Error) -> ! {
let mut result = format!("{}\nerror: {}", what, err);
for cause in err.chain().skip(1) {
- drop(writeln!(result, "\nCaused by:"));
- drop(write!(result, "{}", cause));
+ let _ = writeln!(result, "\nCaused by:");
+ let _ = write!(result, "{}", cause);
}
panic!("\n{}", result);
}
@@ -517,6 +517,29 @@ pub fn cargo_exe() -> PathBuf {
snapbox::cmd::cargo_bin("cargo")
}
+/// A wrapper around `rustc` instead of calling `clippy`.
+pub fn wrapped_clippy_driver() -> PathBuf {
+ let clippy_driver = project()
+ .at(paths::global_root().join("clippy-driver"))
+ .file("Cargo.toml", &basic_manifest("clippy-driver", "0.0.1"))
+ .file(
+ "src/main.rs",
+ r#"
+ fn main() {
+ let mut args = std::env::args_os();
+ let _me = args.next().unwrap();
+ let rustc = args.next().unwrap();
+ let status = std::process::Command::new(rustc).args(args).status().unwrap();
+ std::process::exit(status.code().unwrap_or(1));
+ }
+ "#,
+ )
+ .build();
+ clippy_driver.cargo("build").run();
+
+ clippy_driver.bin("clippy-driver")
+}
+
/// This is the raw output from the process.
///
/// This is similar to `std::process::Output`, however the `status` is
@@ -677,13 +700,15 @@ impl Execs {
/// The substrings are matched as `contains`. Example:
///
/// ```no_run
- /// execs.with_stderr_line_without(
+ /// use cargo_test_support::execs;
+ ///
+ /// execs().with_stderr_line_without(
/// &[
/// "[RUNNING] `rustc --crate-name build_script_build",
/// "-C opt-level=3",
/// ],
/// &["-C debuginfo", "-C incremental"],
- /// )
+ /// );
/// ```
///
/// This will check that a build line includes `-C opt-level=3` but does
diff --git a/src/tools/cargo/crates/cargo-test-support/src/publish.rs b/src/tools/cargo/crates/cargo-test-support/src/publish.rs
index 64774bc43..dccc8356d 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/publish.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/publish.rs
@@ -165,6 +165,7 @@ pub(crate) fn create_index_line(
features: crate::registry::FeatureMap,
yanked: bool,
links: Option<String>,
+ rust_version: Option<&str>,
v: Option<u32>,
) -> String {
// This emulates what crates.io does to retain backwards compatibility.
@@ -185,6 +186,9 @@ pub(crate) fn create_index_line(
if let Some(v) = v {
json["v"] = serde_json::json!(v);
}
+ if let Some(rust_version) = rust_version {
+ json["rust_version"] = serde_json::json!(rust_version);
+ }
json.to_string()
}
diff --git a/src/tools/cargo/crates/cargo-test-support/src/registry.rs b/src/tools/cargo/crates/cargo-test-support/src/registry.rs
index 5faf23540..0cf82cb70 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/registry.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/registry.rs
@@ -450,7 +450,10 @@ impl RegistryBuilder {
/// `VendorPackage` which implements directory sources.
///
/// # Example
-/// ```
+/// ```no_run
+/// use cargo_test_support::registry::Package;
+/// use cargo_test_support::project;
+///
/// // Publish package "a" depending on "b".
/// Package::new("a", "1.0.0")
/// .dep("b", "1.0.0")
@@ -1144,6 +1147,7 @@ fn save_new_crate(
false,
new_crate.links,
None,
+ None,
);
write_to_index(registry_path, &new_crate.name, line, false);
@@ -1240,7 +1244,7 @@ impl Package {
}
/// Adds a normal dependency. Example:
- /// ```
+ /// ```toml
/// [dependencies]
/// foo = {version = "1.0"}
/// ```
@@ -1249,7 +1253,7 @@ impl Package {
}
/// Adds a dependency with the given feature. Example:
- /// ```
+ /// ```toml
/// [dependencies]
/// foo = {version = "1.0", "features": ["feat1", "feat2"]}
/// ```
@@ -1272,7 +1276,7 @@ impl Package {
}
/// Adds a dev-dependency. Example:
- /// ```
+ /// ```toml
/// [dev-dependencies]
/// foo = {version = "1.0"}
/// ```
@@ -1281,7 +1285,7 @@ impl Package {
}
/// Adds a build-dependency. Example:
- /// ```
+ /// ```toml
/// [build-dependencies]
/// foo = {version = "1.0"}
/// ```
@@ -1400,6 +1404,7 @@ impl Package {
self.features.clone(),
self.yanked,
self.links.clone(),
+ self.rust_version.as_deref(),
self.v,
);
diff --git a/src/tools/cargo/crates/cargo-util/Cargo.toml b/src/tools/cargo/crates/cargo-util/Cargo.toml
index 7427ceb1a..f01705fca 100644
--- a/src/tools/cargo/crates/cargo-util/Cargo.toml
+++ b/src/tools/cargo/crates/cargo-util/Cargo.toml
@@ -8,21 +8,21 @@ repository = "https://github.com/rust-lang/cargo"
description = "Miscellaneous support code used by Cargo."
[dependencies]
-anyhow = "1.0.34"
-sha2 = "0.10.6"
-filetime = "0.2.9"
-hex = "0.4.2"
-jobserver = "0.1.26"
-libc = "0.2.88"
-log = "0.4.6"
-same-file = "1.0.6"
-shell-escape = "0.1.4"
-tempfile = "3.1.0"
-walkdir = "2.3.1"
+anyhow.workspace = true
+sha2.workspace = true
+filetime.workspace = true
+hex.workspace = true
+jobserver.workspace = true
+libc.workspace = true
+log.workspace = true
+same-file.workspace = true
+shell-escape.workspace = true
+tempfile.workspace = true
+walkdir.workspace = true
[target.'cfg(target_os = "macos")'.dependencies]
-core-foundation = { version = "0.9.0", features = ["mac_os_10_7_support"] }
+core-foundation.workspace = true
[target.'cfg(windows)'.dependencies]
-miow = "0.5.0"
-windows-sys = { version = "0.45.0", features = ["Win32_Storage_FileSystem", "Win32_Foundation", "Win32_System_Console"] }
+miow.workspace = true
+windows-sys = { workspace = true, features = ["Win32_Storage_FileSystem", "Win32_Foundation", "Win32_System_Console"] }
diff --git a/src/tools/cargo/crates/crates-io/Cargo.toml b/src/tools/cargo/crates/crates-io/Cargo.toml
index 004e2daff..034c2fca5 100644
--- a/src/tools/cargo/crates/crates-io/Cargo.toml
+++ b/src/tools/cargo/crates/crates-io/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "crates-io"
-version = "0.36.0"
+version = "0.37.0"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/cargo"
@@ -13,9 +13,9 @@ name = "crates_io"
path = "lib.rs"
[dependencies]
-anyhow = "1.0.34"
-curl = "0.4"
-percent-encoding = "2.0"
-serde = { version = "1.0", features = ['derive'] }
-serde_json = "1.0"
-url = "2.0"
+anyhow.workspace = true
+curl.workspace = true
+percent-encoding.workspace = true
+serde = { workspace = true, features = ["derive"] }
+serde_json.workspace = true
+url.workspace = true
diff --git a/src/tools/cargo/crates/crates-io/lib.rs b/src/tools/cargo/crates/crates-io/lib.rs
index e0197568a..243808098 100644
--- a/src/tools/cargo/crates/crates-io/lib.rs
+++ b/src/tools/cargo/crates/crates-io/lib.rs
@@ -57,6 +57,7 @@ pub struct NewCrate {
pub repository: Option<String>,
pub badges: BTreeMap<String, BTreeMap<String, String>>,
pub links: Option<String>,
+ pub rust_version: Option<String>,
}
#[derive(Serialize, Deserialize)]
@@ -199,7 +200,7 @@ impl Registry {
/// let mut handle = Easy::new();
/// // If connecting to crates.io, a user-agent is required.
/// handle.useragent("my_crawler (example.com/info)");
- /// let mut reg = Registry::new_handle(String::from("https://crates.io"), None, handle);
+ /// let mut reg = Registry::new_handle(String::from("https://crates.io"), None, handle, true);
/// ```
pub fn new_handle(
host: String,
diff --git a/src/tools/cargo/crates/credential/cargo-credential-macos-keychain/src/main.rs b/src/tools/cargo/crates/credential/cargo-credential-macos-keychain/src/main.rs
deleted file mode 100644
index 3fef3f92a..000000000
--- a/src/tools/cargo/crates/credential/cargo-credential-macos-keychain/src/main.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-//! Cargo registry macos keychain credential process.
-
-use cargo_credential::{Credential, Error};
-use security_framework::os::macos::keychain::SecKeychain;
-
-struct MacKeychain;
-
-/// The account name is not used.
-const ACCOUNT: &'static str = "";
-
-fn registry(registry_name: &str) -> String {
- format!("cargo-registry:{}", registry_name)
-}
-
-impl Credential for MacKeychain {
- fn name(&self) -> &'static str {
- env!("CARGO_PKG_NAME")
- }
-
- fn get(&self, index_url: &str) -> Result<String, Error> {
- let keychain = SecKeychain::default().unwrap();
- let service_name = registry(index_url);
- let (pass, _item) = keychain.find_generic_password(&service_name, ACCOUNT)?;
- String::from_utf8(pass.as_ref().to_vec())
- .map_err(|_| "failed to convert token to UTF8".into())
- }
-
- fn store(&self, index_url: &str, token: &str, name: Option<&str>) -> Result<(), Error> {
- let keychain = SecKeychain::default().unwrap();
- let service_name = registry(name.unwrap_or(index_url));
- if let Ok((_pass, mut item)) = keychain.find_generic_password(&service_name, ACCOUNT) {
- item.set_password(token.as_bytes())?;
- } else {
- keychain.add_generic_password(&service_name, ACCOUNT, token.as_bytes())?;
- }
- Ok(())
- }
-
- fn erase(&self, index_url: &str) -> Result<(), Error> {
- let keychain = SecKeychain::default().unwrap();
- let service_name = registry(index_url);
- let (_pass, item) = keychain.find_generic_password(&service_name, ACCOUNT)?;
- item.delete();
- Ok(())
- }
-}
-
-fn main() {
- cargo_credential::main(MacKeychain);
-}
diff --git a/src/tools/cargo/crates/credential/cargo-credential-wincred/src/main.rs b/src/tools/cargo/crates/credential/cargo-credential-wincred/src/main.rs
deleted file mode 100644
index 8ae48f348..000000000
--- a/src/tools/cargo/crates/credential/cargo-credential-wincred/src/main.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-//! Cargo registry windows credential process.
-
-use cargo_credential::{Credential, Error};
-use std::ffi::OsStr;
-use std::os::windows::ffi::OsStrExt;
-
-use windows_sys::core::PWSTR;
-use windows_sys::Win32::Foundation::ERROR_NOT_FOUND;
-use windows_sys::Win32::Foundation::FILETIME;
-use windows_sys::Win32::Foundation::TRUE;
-use windows_sys::Win32::Security::Credentials::CredDeleteW;
-use windows_sys::Win32::Security::Credentials::CredReadW;
-use windows_sys::Win32::Security::Credentials::CredWriteW;
-use windows_sys::Win32::Security::Credentials::CREDENTIALW;
-use windows_sys::Win32::Security::Credentials::CRED_PERSIST_LOCAL_MACHINE;
-use windows_sys::Win32::Security::Credentials::CRED_TYPE_GENERIC;
-
-struct WindowsCredential;
-
-/// Converts a string to a nul-terminated wide UTF-16 byte sequence.
-fn wstr(s: &str) -> Vec<u16> {
- let mut wide: Vec<u16> = OsStr::new(s).encode_wide().collect();
- if wide.iter().any(|b| *b == 0) {
- panic!("nul byte in wide string");
- }
- wide.push(0);
- wide
-}
-
-fn target_name(registry_name: &str) -> Vec<u16> {
- wstr(&format!("cargo-registry:{}", registry_name))
-}
-
-impl Credential for WindowsCredential {
- fn name(&self) -> &'static str {
- env!("CARGO_PKG_NAME")
- }
-
- fn get(&self, index_url: &str) -> Result<String, Error> {
- let target_name = target_name(index_url);
- let p_credential: *mut CREDENTIALW = std::ptr::null_mut() as *mut _;
- unsafe {
- if CredReadW(
- target_name.as_ptr(),
- CRED_TYPE_GENERIC,
- 0,
- p_credential as *mut _ as *mut _,
- ) != TRUE
- {
- return Err(
- format!("failed to fetch token: {}", std::io::Error::last_os_error()).into(),
- );
- }
- let bytes = std::slice::from_raw_parts(
- (*p_credential).CredentialBlob,
- (*p_credential).CredentialBlobSize as usize,
- );
- String::from_utf8(bytes.to_vec()).map_err(|_| "failed to convert token to UTF8".into())
- }
- }
-
- fn store(&self, index_url: &str, token: &str, name: Option<&str>) -> Result<(), Error> {
- let token = token.as_bytes();
- let target_name = target_name(index_url);
- let comment = match name {
- Some(name) => wstr(&format!("Cargo registry token for {}", name)),
- None => wstr("Cargo registry token"),
- };
- let mut credential = CREDENTIALW {
- Flags: 0,
- Type: CRED_TYPE_GENERIC,
- TargetName: target_name.as_ptr() as PWSTR,
- Comment: comment.as_ptr() as PWSTR,
- LastWritten: FILETIME {
- dwLowDateTime: 0,
- dwHighDateTime: 0,
- },
- CredentialBlobSize: token.len() as u32,
- CredentialBlob: token.as_ptr() as *mut u8,
- Persist: CRED_PERSIST_LOCAL_MACHINE,
- AttributeCount: 0,
- Attributes: std::ptr::null_mut(),
- TargetAlias: std::ptr::null_mut(),
- UserName: std::ptr::null_mut(),
- };
- let result = unsafe { CredWriteW(&mut credential, 0) };
- if result != TRUE {
- let err = std::io::Error::last_os_error();
- return Err(format!("failed to store token: {}", err).into());
- }
- Ok(())
- }
-
- fn erase(&self, index_url: &str) -> Result<(), Error> {
- let target_name = target_name(index_url);
- let result = unsafe { CredDeleteW(target_name.as_ptr(), CRED_TYPE_GENERIC, 0) };
- if result != TRUE {
- let err = std::io::Error::last_os_error();
- if err.raw_os_error() == Some(ERROR_NOT_FOUND as i32) {
- eprintln!("not currently logged in to `{}`", index_url);
- return Ok(());
- }
- return Err(format!("failed to remove token: {}", err).into());
- }
- Ok(())
- }
-}
-
-fn main() {
- cargo_credential::main(WindowsCredential);
-}
diff --git a/src/tools/cargo/crates/home/CHANGELOG.md b/src/tools/cargo/crates/home/CHANGELOG.md
index 7674667c9..58f960cc3 100644
--- a/src/tools/cargo/crates/home/CHANGELOG.md
+++ b/src/tools/cargo/crates/home/CHANGELOG.md
@@ -4,7 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-<!-- ## [Unreleased] -->
+## 0.5.6
+- Fixed & enhanced documentation.
+ [#12047](https://github.com/rust-lang/cargo/pull/12047)
+
+## 0.5.5 - 2023-04-25
+- The `home` crate has migrated to the <https://github.com/rust-lang/cargo/> repository.
+ [#11359](https://github.com/rust-lang/cargo/pull/11359)
+- Replaced the winapi dependency with windows-sys.
+ [#11656](https://github.com/rust-lang/cargo/pull/11656)
## [0.5.4] - 2022-10-10
- Add `_with_env` variants of functions to support in-process threaded tests for
@@ -38,7 +46,6 @@ Use Rust 1.36.0 as minimum Rust version.
### Removed
- Remove support for `multirust` folder used in old version of `rustup`.
-[Unreleased]: https://github.com/brson/home/compare/v0.5.4...HEAD
[0.5.4]: https://github.com/brson/home/compare/v0.5.3...v0.5.4
[0.5.3]: https://github.com/brson/home/compare/v0.5.2...v0.5.3
[0.5.2]: https://github.com/brson/home/compare/v0.5.1...v0.5.2
diff --git a/src/tools/cargo/crates/home/Cargo.toml b/src/tools/cargo/crates/home/Cargo.toml
index 2c5b92bcb..6c65ecc18 100644
--- a/src/tools/cargo/crates/home/Cargo.toml
+++ b/src/tools/cargo/crates/home/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "home"
-version = "0.5.4" # also update `html_root_url` in `src/lib.rs`
+version = "0.5.6" # also update `html_root_url` in `src/lib.rs`
authors = ["Brian Anderson <andersrb@gmail.com>"]
documentation = "https://docs.rs/home"
edition = "2018"
@@ -17,4 +17,4 @@ repository = "https://github.com/rust-lang/cargo"
description = "Shared definitions of home directories."
[target.'cfg(windows)'.dependencies]
-windows-sys = { version = "0.45.0", features = ["Win32_Foundation", "Win32_UI_Shell"] }
+windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_UI_Shell"] }
diff --git a/src/tools/cargo/crates/home/src/env.rs b/src/tools/cargo/crates/home/src/env.rs
index e47273bc8..49fea5422 100644
--- a/src/tools/cargo/crates/home/src/env.rs
+++ b/src/tools/cargo/crates/home/src/env.rs
@@ -9,7 +9,7 @@ use std::{
/// Permits parameterizing the home functions via the _from variants - used for
/// in-process unit testing by rustup.
pub trait Env {
- /// Return the path to the the users home dir, or None if any error occurs:
+ /// Return the path to the users home dir, or None if any error occurs:
/// see home_inner.
fn home_dir(&self) -> Option<PathBuf>;
/// Return the current working directory.
diff --git a/src/tools/cargo/crates/home/src/lib.rs b/src/tools/cargo/crates/home/src/lib.rs
index 306026e40..0e1e975e4 100644
--- a/src/tools/cargo/crates/home/src/lib.rs
+++ b/src/tools/cargo/crates/home/src/lib.rs
@@ -1,14 +1,5 @@
//! Canonical definitions of `home_dir`, `cargo_home`, and `rustup_home`.
//!
-//! This provides the definition of `home_dir` used by Cargo and
-//! rustup, as well functions to find the correct value of
-//! `CARGO_HOME` and `RUSTUP_HOME`.
-//!
-//! See also the [`dirs`](https://docs.rs/dirs) crate.
-//!
-//! _Note that as of 2019/08/06 it appears that cargo uses this crate. And
-//! rustup has used this crate since 2019/08/21._
-//!
//! The definition of `home_dir` provided by the standard library is
//! incorrect because it considers the `HOME` environment variable on
//! Windows. This causes surprising situations where a Rust program
@@ -17,15 +8,17 @@
//! rustup use the standard libraries definition - they use the
//! definition here.
//!
-//! This crate further provides two functions, `cargo_home` and
+//! This crate provides two additional functions, `cargo_home` and
//! `rustup_home`, which are the canonical way to determine the
-//! location that Cargo and rustup store their data.
+//! location that Cargo and rustup use to store their data.
+//! The `env` module contains utilities for mocking the process environment
+//! by Cargo and rustup.
//!
//! See also this [discussion].
//!
//! [discussion]: https://github.com/rust-lang/rust/pull/46799#issuecomment-361156935
-#![doc(html_root_url = "https://docs.rs/home/0.5.4")]
+#![doc(html_root_url = "https://docs.rs/home/0.5.6")]
#![deny(rust_2018_idioms)]
pub mod env;
@@ -36,29 +29,34 @@ mod windows;
use std::io;
use std::path::{Path, PathBuf};
-/// Returns the path of the current user's home directory if known.
+/// Returns the path of the current user's home directory using environment
+/// variables or OS-specific APIs.
///
/// # Unix
///
/// Returns the value of the `HOME` environment variable if it is set
-/// and not equal to the empty string. Otherwise, it tries to determine the
-/// home directory by invoking the `getpwuid_r` function on the UID of the
-/// current user.
+/// **even** if it is an empty string. Otherwise, it tries to determine the
+/// home directory by invoking the [`getpwuid_r`][getpwuid] function with
+/// the UID of the current user.
+///
+/// [getpwuid]: https://linux.die.net/man/3/getpwuid_r
///
/// # Windows
///
-/// Returns the value of the `USERPROFILE` environment variable if it
-/// is set and not equal to the empty string. If both do not exist,
-/// [`SHGetFolderPathW`][msdn] is used to return the appropriate path.
+/// Returns the value of the `USERPROFILE` environment variable if it is set
+/// **and** it is not an empty string. Otherwise, it tries to determine the
+/// home directory by invoking the [`SHGetFolderPathW`][shgfp] function with
+/// [`CSIDL_PROFILE`][csidl].
///
-/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw
+/// [shgfp]: https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw
+/// [csidl]: https://learn.microsoft.com/en-us/windows/win32/shell/csidl
///
/// # Examples
///
/// ```
/// match home::home_dir() {
-/// Some(path) => println!("{}", path.display()),
-/// None => println!("Impossible to get your home dir!"),
+/// Some(path) if !path.as_os_str().is_empty() => println!("{}", path.display()),
+/// _ => println!("Unable to get your home dir!"),
/// }
/// ```
pub fn home_dir() -> Option<PathBuf> {
diff --git a/src/tools/cargo/crates/mdman/Cargo.lock b/src/tools/cargo/crates/mdman/Cargo.lock
deleted file mode 100644
index 51fe47a9c..000000000
--- a/src/tools/cargo/crates/mdman/Cargo.lock
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "anyhow"
-version = "1.0.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "block-buffer"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
-dependencies = [
- "block-padding",
- "byte-tools",
- "byteorder",
- "generic-array",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
-dependencies = [
- "byte-tools",
-]
-
-[[package]]
-name = "byte-tools"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
-
-[[package]]
-name = "byteorder"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "ctor"
-version = "0.1.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39858aa5bac06462d4dd4b9164848eb81ffc4aa5c479746393598fd193afa227"
-dependencies = [
- "quote",
- "syn",
-]
-
-[[package]]
-name = "diff"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
-
-[[package]]
-name = "digest"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "fake-simd"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
-
-[[package]]
-name = "form_urlencoded"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
-dependencies = [
- "matches",
- "percent-encoding",
-]
-
-[[package]]
-name = "generic-array"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
-dependencies = [
- "typenum",
-]
-
-[[package]]
-name = "handlebars"
-version = "3.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86dbc8a0746b08f363d2e00da48e6c9ceb75c198ac692d2715fcbb5bee74c87d"
-dependencies = [
- "log",
- "pest",
- "pest_derive",
- "quick-error",
- "serde",
- "serde_json",
- "walkdir",
-]
-
-[[package]]
-name = "idna"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
-dependencies = [
- "matches",
- "unicode-bidi",
- "unicode-normalization",
-]
-
-[[package]]
-name = "itoa"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
-
-[[package]]
-name = "log"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "maplit"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
-
-[[package]]
-name = "matches"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
-
-[[package]]
-name = "mdman"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "handlebars",
- "pretty_assertions",
- "pulldown-cmark",
- "same-file",
- "serde_json",
- "url",
-]
-
-[[package]]
-name = "memchr"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
-
-[[package]]
-name = "opaque-debug"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
-
-[[package]]
-name = "output_vt100"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "percent-encoding"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
-
-[[package]]
-name = "pest"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
-dependencies = [
- "ucd-trie",
-]
-
-[[package]]
-name = "pest_derive"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
-dependencies = [
- "pest",
- "pest_generator",
-]
-
-[[package]]
-name = "pest_generator"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
-dependencies = [
- "pest",
- "pest_meta",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "pest_meta"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
-dependencies = [
- "maplit",
- "pest",
- "sha-1",
-]
-
-[[package]]
-name = "pretty_assertions"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
-dependencies = [
- "ctor",
- "diff",
- "output_vt100",
- "yansi",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "pulldown-cmark"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
-dependencies = [
- "bitflags",
- "memchr",
- "unicase",
-]
-
-[[package]]
-name = "quick-error"
-version = "1.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
-
-[[package]]
-name = "quote"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.114"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
-
-[[package]]
-name = "serde_json"
-version = "1.0.57"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
-dependencies = [
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "sha-1"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
-dependencies = [
- "block-buffer",
- "digest",
- "fake-simd",
- "opaque-debug",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
-]
-
-[[package]]
-name = "tinyvec"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed"
-
-[[package]]
-name = "typenum"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
-
-[[package]]
-name = "ucd-trie"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
-
-[[package]]
-name = "unicase"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
-dependencies = [
- "version_check",
-]
-
-[[package]]
-name = "unicode-bidi"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
-dependencies = [
- "matches",
-]
-
-[[package]]
-name = "unicode-normalization"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
-dependencies = [
- "tinyvec",
-]
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
-
-[[package]]
-name = "url"
-version = "2.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
-dependencies = [
- "form_urlencoded",
- "idna",
- "matches",
- "percent-encoding",
-]
-
-[[package]]
-name = "version_check"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
-
-[[package]]
-name = "walkdir"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
-dependencies = [
- "same-file",
- "winapi",
- "winapi-util",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "yansi"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
diff --git a/src/tools/cargo/crates/mdman/Cargo.toml b/src/tools/cargo/crates/mdman/Cargo.toml
index 92cdf2eb6..812f1393a 100644
--- a/src/tools/cargo/crates/mdman/Cargo.toml
+++ b/src/tools/cargo/crates/mdman/Cargo.toml
@@ -1,17 +1,18 @@
[package]
name = "mdman"
-version = "0.1.0"
+version = "0.0.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Creates a man page page from markdown."
+publish = false
[dependencies]
-anyhow = "1.0.31"
-handlebars = { version = "3.2.1", features = ["dir_source"] }
-pulldown-cmark = { version = "0.9.2", default-features = false }
-same-file = "1.0.6"
-serde_json = "1.0.56"
-url = "2.2.2"
+anyhow.workspace = true
+handlebars.workspace = true
+pulldown-cmark.workspace = true
+same-file.workspace = true
+serde_json.workspace = true
+url.workspace = true
[dev-dependencies]
-pretty_assertions = "1.3.0"
+pretty_assertions.workspace = true
diff --git a/src/tools/cargo/crates/mdman/build-man.sh b/src/tools/cargo/crates/mdman/build-man.sh
deleted file mode 100755
index 9286b17c2..000000000
--- a/src/tools/cargo/crates/mdman/build-man.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-set -e
-
-cargo run -- -t md -o doc/out doc/*.md
-cargo run -- -t txt -o doc/out doc/*.md
-cargo run -- -t man -o doc/out doc/*.md
diff --git a/src/tools/cargo/crates/mdman/doc/mdman.md b/src/tools/cargo/crates/mdman/doc/mdman.md
index 2025c13dc..bfa394648 100644
--- a/src/tools/cargo/crates/mdman/doc/mdman.md
+++ b/src/tools/cargo/crates/mdman/doc/mdman.md
@@ -28,7 +28,7 @@ man page:
and `{{/options}}` tags. This tells the processor where the options start
and end.
- Each option must be expressed with a `{{#option}}` block. The parameters to
- the the block are a sequence of strings indicating the option. For example,
+ the block are a sequence of strings indicating the option. For example,
```{{#option "`-p` _spec_..." "`--package` _spec_..."}}``` is an option that
has two different forms. The text within the string is processed as markdown.
It is recommended to use formatting similar to this example.
diff --git a/src/tools/cargo/crates/mdman/doc/out/mdman.1 b/src/tools/cargo/crates/mdman/doc/out/mdman.1
index 0718d6ddb..b114715ae 100644
--- a/src/tools/cargo/crates/mdman/doc/out/mdman.1
+++ b/src/tools/cargo/crates/mdman/doc/out/mdman.1
@@ -6,7 +6,7 @@
.SH "NAME"
mdman \- Converts markdown to a man page
.SH "SYNOPSIS"
-\fBmdman\fR [\fIoptions\fR] \fB\-t\fR \fItype\fR \fB\-o\fR \fIoutdir\fR \fIsources...\fR
+\fBmdman\fR [\fIoptions\fR] \fB\-t\fR \fItype\fR \fB\-o\fR \fIoutdir\fR \fIsources\[u2026]\fR
.SH "DESCRIPTION"
Converts a markdown file to a man page.
.sp
@@ -29,7 +29,7 @@ and end.
.sp
.RS 4
\h'-04'\(bu\h'+02'Each option must be expressed with a \fB{{#option}}\fR block. The parameters to
-the the block are a sequence of strings indicating the option. For example,
+the block are a sequence of strings indicating the option. For example,
\fB{{#option "`\-p` _spec_..." "`\-\-package` _spec_..."}}\fR is an option that
has two different forms. The text within the string is processed as markdown.
It is recommended to use formatting similar to this example.
@@ -83,7 +83,7 @@ Outputs with the \fB\&.md\fR extension.
.RE
.sp
.RS 4
-\h'-04'\(bu\h'+02'\fBtxt\fR \[em] A text file, rendered for situations where a man page viewer isn't
+\h'-04'\(bu\h'+02'\fBtxt\fR \[em] A text file, rendered for situations where a man page viewer isn\[cq]t
available. Outputs with the \fB\&.txt\fR extension.
.RE
.RE
@@ -107,7 +107,7 @@ matching \fB\-\-man\fR entry, then a relative link to a file named \fIname\fR\fB
be used.
.RE
.sp
-\fIsources...\fR
+\fIsources\[u2026]\fR
.RS 4
The source input filename, may be specified multiple times.
.RE
diff --git a/src/tools/cargo/crates/mdman/doc/out/mdman.md b/src/tools/cargo/crates/mdman/doc/out/mdman.md
index d0dd34511..9d2fe9326 100644
--- a/src/tools/cargo/crates/mdman/doc/out/mdman.md
+++ b/src/tools/cargo/crates/mdman/doc/out/mdman.md
@@ -27,7 +27,7 @@ man page:
and `{{/options}}` tags. This tells the processor where the options start
and end.
- Each option must be expressed with a `{{#option}}` block. The parameters to
- the the block are a sequence of strings indicating the option. For example,
+ the block are a sequence of strings indicating the option. For example,
```{{#option "`-p` _spec_..." "`--package` _spec_..."}}``` is an option that
has two different forms. The text within the string is processed as markdown.
It is recommended to use formatting similar to this example.
@@ -61,7 +61,7 @@ man page:
<code>.1</code>) matching the man page section.</li>
<li><code>md</code> — A markdown file, after all handlebars processing has been finished.
Outputs with the <code>.md</code> extension.</li>
-<li><code>txt</code> — A text file, rendered for situations where a man page viewer isn't
+<li><code>txt</code> — A text file, rendered for situations where a man page viewer isn’t
available. Outputs with the <code>.txt</code> extension.</li>
</ul></dd>
@@ -82,7 +82,7 @@ matching <code>--man</code> entry, then a relative link to a file named <em>name
be used.</dd>
-<dt class="option-term" id="option-mdman-sources..."><a class="option-anchor" href="#option-mdman-sources..."></a><em>sources...</em></dt>
+<dt class="option-term" id="option-mdman-sources…"><a class="option-anchor" href="#option-mdman-sources…"></a><em>sources…</em></dt>
<dd class="option-desc">The source input filename, may be specified multiple times.</dd>
diff --git a/src/tools/cargo/crates/mdman/doc/out/mdman.txt b/src/tools/cargo/crates/mdman/doc/out/mdman.txt
index 83fa7de90..6c8dcd65d 100644
--- a/src/tools/cargo/crates/mdman/doc/out/mdman.txt
+++ b/src/tools/cargo/crates/mdman/doc/out/mdman.txt
@@ -4,7 +4,7 @@ NAME
mdman - Converts markdown to a man page
SYNOPSIS
- mdman [options] -t type -o outdir sources...
+ mdman [options] -t type -o outdir sources…
DESCRIPTION
Converts a markdown file to a man page.
@@ -25,7 +25,7 @@ DESCRIPTION
the options start and end.
o Each option must be expressed with a {{#option}} block. The
- parameters to the the block are a sequence of strings indicating the
+ parameters to the block are a sequence of strings indicating the
option. For example, {{#option "`-p` _spec_..." "`--package`
_spec_..."}} is an option that has two different forms. The text
within the string is processed as markdown. It is recommended to use
@@ -65,7 +65,7 @@ OPTIONS
finished. Outputs with the .md extension.
o txt — A text file, rendered for situations where a man page
- viewer isn't available. Outputs with the .txt extension.
+ viewer isn’t available. Outputs with the .txt extension.
-o outdir
Specifies the directory where to save the output.
@@ -81,7 +81,7 @@ OPTIONS
does not have a matching --man entry, then a relative link to a file
named name.md will be used.
- sources...
+ sources…
The source input filename, may be specified multiple times.
EXAMPLES
diff --git a/src/tools/cargo/crates/resolver-tests/Cargo.toml b/src/tools/cargo/crates/resolver-tests/Cargo.toml
index e4aab4325..8a7cab113 100644
--- a/src/tools/cargo/crates/resolver-tests/Cargo.toml
+++ b/src/tools/cargo/crates/resolver-tests/Cargo.toml
@@ -1,12 +1,13 @@
[package]
name = "resolver-tests"
-version = "0.1.0"
+version = "0.0.0"
edition = "2018"
+publish = false
[dependencies]
-cargo = { path = "../.." }
-cargo-util = { path = "../cargo-util" }
-is-terminal = "0.4.0"
-lazy_static = "1.3.0"
-proptest = "1.1.0"
-varisat = "0.2.1"
+cargo.workspace = true
+cargo-util.workspace = true
+is-terminal.workspace = true
+lazy_static.workspace = true
+proptest.workspace = true
+varisat.workspace = true
diff --git a/src/tools/cargo/crates/resolver-tests/src/lib.rs b/src/tools/cargo/crates/resolver-tests/src/lib.rs
index 3ffb6c5d2..01d9b5e6d 100644
--- a/src/tools/cargo/crates/resolver-tests/src/lib.rs
+++ b/src/tools/cargo/crates/resolver-tests/src/lib.rs
@@ -184,6 +184,7 @@ pub fn resolve_with_config_raw(
deps,
&BTreeMap::new(),
None::<&String>,
+ None::<&String>,
)
.unwrap();
let opts = ResolveOpts::everything();
@@ -585,6 +586,7 @@ pub fn pkg_dep<T: ToPkgId>(name: T, dep: Vec<Dependency>) -> Summary {
dep,
&BTreeMap::new(),
link,
+ None::<&String>,
)
.unwrap()
}
@@ -613,6 +615,7 @@ pub fn pkg_loc(name: &str, loc: &str) -> Summary {
Vec::new(),
&BTreeMap::new(),
link,
+ None::<&String>,
)
.unwrap()
}
@@ -627,6 +630,7 @@ pub fn remove_dep(sum: &Summary, ind: usize) -> Summary {
deps,
&BTreeMap::new(),
sum.links().map(|a| a.as_str()),
+ None::<&String>,
)
.unwrap()
}
diff --git a/src/tools/cargo/src/doc/semver-check/Cargo.toml b/src/tools/cargo/crates/semver-check/Cargo.toml
index bdfd8d7d7..f7b8c7d48 100644
--- a/src/tools/cargo/src/doc/semver-check/Cargo.toml
+++ b/src/tools/cargo/crates/semver-check/Cargo.toml
@@ -1,10 +1,11 @@
[package]
name = "semver-check"
-version = "0.1.0"
+version = "0.0.0"
authors = ["Eric Huss"]
edition = "2021"
+publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-tempfile = "3.1.0"
+tempfile.workspace = true
diff --git a/src/tools/cargo/src/doc/semver-check/src/main.rs b/src/tools/cargo/crates/semver-check/src/main.rs
index 51aacbe11..fa4639eb7 100644
--- a/src/tools/cargo/src/doc/semver-check/src/main.rs
+++ b/src/tools/cargo/crates/semver-check/src/main.rs
@@ -23,9 +23,13 @@ fn main() {
const SEPARATOR: &str = "///////////////////////////////////////////////////////////";
fn doit() -> Result<(), Box<dyn Error>> {
- let filename = std::env::args()
- .nth(1)
- .unwrap_or_else(|| "../src/reference/semver.md".to_string());
+ let filename = std::env::args().nth(1).unwrap_or_else(|| {
+ Path::new(env!("CARGO_MANIFEST_DIR"))
+ .join("../../src/doc/src/reference/semver.md")
+ .to_str()
+ .unwrap()
+ .to_string()
+ });
let contents = fs::read_to_string(filename)?;
let mut lines = contents.lines().enumerate();
diff --git a/src/tools/cargo/crates/xtask-build-man/Cargo.toml b/src/tools/cargo/crates/xtask-build-man/Cargo.toml
new file mode 100644
index 000000000..6d02aa2c3
--- /dev/null
+++ b/src/tools/cargo/crates/xtask-build-man/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "xtask-build-man"
+version = "0.0.0"
+edition = "2021"
+publish = false
+
+[dependencies]
diff --git a/src/tools/cargo/crates/xtask-build-man/src/main.rs b/src/tools/cargo/crates/xtask-build-man/src/main.rs
new file mode 100644
index 000000000..6680c3783
--- /dev/null
+++ b/src/tools/cargo/crates/xtask-build-man/src/main.rs
@@ -0,0 +1,108 @@
+//! ```text
+//! NAME
+//! build-man
+//!
+//! SYNOPSIS
+//! build-man
+//!
+//! DESCRIPTION
+//! Build the man pages for packages `mdman` and `cargo`.
+//! For more, read their doc comments.
+//! ```
+
+use std::fs;
+use std::io;
+use std::path::PathBuf;
+use std::process;
+use std::process::Command;
+
+fn main() -> io::Result<()> {
+ build_mdman()?;
+ build_cargo()?;
+ Ok(())
+}
+
+/// Builds the man pages for `mdman`.
+fn build_mdman() -> io::Result<()> {
+ cwd_to_workspace_root()?;
+
+ let src_paths = &["crates/mdman/doc/mdman.md".into()];
+ let dst_path = "crates/mdman/doc/out";
+ let outs = [("md", dst_path), ("txt", dst_path), ("man", dst_path)];
+
+ build_man("mdman", src_paths, &outs, &[])
+}
+
+/// Builds the man pages for Cargo.
+///
+/// The source for the man pages are located in src/doc/man/ in markdown format.
+/// These also are handlebars templates, see crates/mdman/README.md for details.
+///
+/// The generated man pages are placed in the src/etc/man/ directory. The pages
+/// are also expanded into markdown (after being expanded by handlebars) and
+/// saved in the src/doc/src/commands/ directory. These are included in the
+/// Cargo book, which is converted to HTML by mdbook.
+fn build_cargo() -> io::Result<()> {
+ // Find all `src/doc/man/cargo-*.md`
+ let src_paths = {
+ let mut src_paths = Vec::new();
+ for entry in fs::read_dir("src/doc/man")? {
+ let entry = entry?;
+ let file_name = entry.file_name();
+ let file_name = file_name.to_str().unwrap();
+ if file_name.starts_with("cargo-") && file_name.ends_with(".md") {
+ src_paths.push(entry.path());
+ }
+ }
+ src_paths
+ };
+ let outs = [
+ ("md", "src/doc/src/commands"),
+ ("txt", "src/doc/man/generated_txt"),
+ ("man", "src/etc/man"),
+ ];
+ let args = [
+ "--url",
+ "https://doc.rust-lang.org/cargo/commands/",
+ "--man",
+ "rustc:1=https://doc.rust-lang.org/rustc/index.html",
+ "--man",
+ "rustdoc:1=https://doc.rust-lang.org/rustdoc/index.html",
+ ];
+ build_man("cargo", &src_paths[..], &outs, &args)
+}
+
+/// Change to workspace root.
+///
+/// Assumed this xtask is located in `[WORKSPACE]/crates/xtask-build-man`.
+fn cwd_to_workspace_root() -> io::Result<()> {
+ let pkg_root = std::env!("CARGO_MANIFEST_DIR");
+ let ws_root = format!("{pkg_root}/../..");
+ std::env::set_current_dir(ws_root)
+}
+
+/// Builds the man pages.
+fn build_man(
+ pkg_name: &str,
+ src_paths: &[PathBuf],
+ outs: &[(&str, &str)],
+ extra_args: &[&str],
+) -> io::Result<()> {
+ for (format, dst_path) in outs {
+ eprintln!("Start converting `{format}` for package `{pkg_name}`...");
+ let mut cmd = Command::new(std::env!("CARGO"));
+ cmd.args(["run", "--package", "mdman", "--"])
+ .args(["-t", format, "-o", dst_path])
+ .args(src_paths)
+ .args(extra_args);
+
+ let status = cmd.status()?;
+ if !status.success() {
+ eprintln!("failed to build the man pages for package `{pkg_name}`");
+ eprintln!("failed command: `{cmd:?}`");
+ process::exit(status.code().unwrap_or(1));
+ }
+ }
+
+ Ok(())
+}
diff --git a/src/tools/cargo/crates/xtask-stale-label/Cargo.toml b/src/tools/cargo/crates/xtask-stale-label/Cargo.toml
new file mode 100644
index 000000000..af3218e96
--- /dev/null
+++ b/src/tools/cargo/crates/xtask-stale-label/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "xtask-stale-label"
+version = "0.0.0"
+edition = "2021"
+publish = false
+
+[dependencies]
+toml_edit.workspace = true
diff --git a/src/tools/cargo/crates/xtask-stale-label/src/main.rs b/src/tools/cargo/crates/xtask-stale-label/src/main.rs
new file mode 100644
index 000000000..37675979c
--- /dev/null
+++ b/src/tools/cargo/crates/xtask-stale-label/src/main.rs
@@ -0,0 +1,91 @@
+//! ```text
+//! NAME
+//! stale-label
+//!
+//! SYNOPSIS
+//! stale-label
+//!
+//! DESCRIPTION
+//! Detect stale paths in autolabel definitions in triagebot.toml.
+//! Probably autofix them in the future.
+//! ```
+
+use std::fmt::Write as _;
+use std::path::PathBuf;
+use std::process;
+use toml_edit::Document;
+
+fn main() {
+ let pkg_root = std::env!("CARGO_MANIFEST_DIR");
+ let ws_root = PathBuf::from(format!("{pkg_root}/../.."));
+ let path = {
+ let path = ws_root.join("triagebot.toml");
+ path.canonicalize().unwrap_or(path)
+ };
+
+ eprintln!("Checking file {path:?}\n");
+
+ let mut failed = 0;
+ let mut passed = 0;
+
+ let toml = std::fs::read_to_string(path).expect("read from file");
+ let doc = toml.parse::<Document>().expect("a toml");
+ let autolabel = doc["autolabel"].as_table().expect("a toml table");
+
+ for (label, value) in autolabel.iter() {
+ let Some(trigger_files) = value.get("trigger_files") else {
+ continue
+ };
+ let trigger_files = trigger_files.as_array().expect("an array");
+ let missing_files: Vec<_> = trigger_files
+ .iter()
+ // Hey TOML content is strict UTF-8.
+ .map(|v| v.as_str().unwrap())
+ .filter(|f| {
+ // triagebot checks with `starts_with` only.
+ // See https://github.com/rust-lang/triagebot/blob/0e4b48ca86ffede9cc70fb1611e658e4d013bce2/src/handlers/autolabel.rs#L45
+ let path = ws_root.join(f);
+ if path.exists() {
+ return false;
+ }
+ let Some(mut read_dir) = path.parent().and_then(|p| p.read_dir().ok()) else {
+ return true;
+ };
+ !read_dir.any(|e| {
+ e.unwrap()
+ .path()
+ .strip_prefix(&ws_root)
+ .unwrap()
+ .to_str()
+ .unwrap()
+ .starts_with(f)
+ })
+ })
+ .collect();
+
+ failed += missing_files.len();
+ passed += trigger_files.len() - missing_files.len();
+
+ if missing_files.is_empty() {
+ continue;
+ }
+
+ let mut msg = String::new();
+ writeln!(
+ &mut msg,
+ "missing files defined in `autolabel.{label}.trigger_files`:"
+ )
+ .unwrap();
+ for f in missing_files.iter() {
+ writeln!(&mut msg, "\t {f}").unwrap();
+ }
+ eprintln!("{msg}");
+ }
+
+ let result = if failed == 0 { "ok" } else { "FAILED" };
+ eprintln!("test result: {result}. {passed} passed; {failed} failed;");
+
+ if failed > 0 {
+ process::exit(1);
+ }
+}
diff --git a/src/tools/cargo/crates/xtask-unpublished/Cargo.toml b/src/tools/cargo/crates/xtask-unpublished/Cargo.toml
new file mode 100644
index 000000000..541a34dea
--- /dev/null
+++ b/src/tools/cargo/crates/xtask-unpublished/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "xtask-unpublished"
+version = "0.0.0"
+edition = "2021"
+publish = false
+
+[dependencies]
+anyhow.workspace = true
+cargo.workspace = true
+clap.workspace = true
+env_logger.workspace = true
+log.workspace = true
diff --git a/src/tools/cargo/crates/xtask-unpublished/src/main.rs b/src/tools/cargo/crates/xtask-unpublished/src/main.rs
new file mode 100644
index 000000000..1942a3621
--- /dev/null
+++ b/src/tools/cargo/crates/xtask-unpublished/src/main.rs
@@ -0,0 +1,15 @@
+mod xtask;
+
+fn main() {
+ env_logger::init_from_env("CARGO_LOG");
+ let cli = xtask::cli();
+ let matches = cli.get_matches();
+
+ let mut config = cargo::util::config::Config::default().unwrap_or_else(|e| {
+ let mut eval = cargo::core::shell::Shell::new();
+ cargo::exit_with_error(e.into(), &mut eval)
+ });
+ if let Err(e) = xtask::exec(&matches, &mut config) {
+ cargo::exit_with_error(e, &mut config.shell())
+ }
+}
diff --git a/src/tools/cargo/crates/xtask-unpublished/src/xtask.rs b/src/tools/cargo/crates/xtask-unpublished/src/xtask.rs
new file mode 100644
index 000000000..f1086951f
--- /dev/null
+++ b/src/tools/cargo/crates/xtask-unpublished/src/xtask.rs
@@ -0,0 +1,200 @@
+//! `xtask-unpublished` outputs a table with publish status --- a local version
+//! and a version on crates.io for comparisons.
+//!
+//! This aims to help developers check if there is any crate required a new
+//! publish, as well as detect if a version bump is needed in CI pipeline.
+
+use std::collections::HashSet;
+
+use cargo::core::registry::PackageRegistry;
+use cargo::core::QueryKind;
+use cargo::core::Registry;
+use cargo::core::SourceId;
+use cargo::ops::Packages;
+use cargo::util::command_prelude::*;
+
+pub fn cli() -> clap::Command {
+ clap::Command::new("xtask-unpublished")
+ .arg_package_spec_simple("Package to inspect the published status")
+ .arg(
+ opt(
+ "verbose",
+ "Use verbose output (-vv very verbose/build.rs output)",
+ )
+ .short('v')
+ .action(ArgAction::Count)
+ .global(true),
+ )
+ .arg_quiet()
+ .arg(
+ opt("color", "Coloring: auto, always, never")
+ .value_name("WHEN")
+ .global(true),
+ )
+ .arg(flag("frozen", "Require Cargo.lock and cache are up to date").global(true))
+ .arg(flag("locked", "Require Cargo.lock is up to date").global(true))
+ .arg(flag("offline", "Run without accessing the network").global(true))
+ .arg(multi_opt("config", "KEY=VALUE", "Override a configuration value").global(true))
+ .arg(
+ Arg::new("unstable-features")
+ .help("Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details")
+ .short('Z')
+ .value_name("FLAG")
+ .action(ArgAction::Append)
+ .global(true),
+ )
+}
+
+pub fn exec(args: &clap::ArgMatches, config: &mut cargo::util::Config) -> cargo::CliResult {
+ config_configure(config, args)?;
+
+ unpublished(args, config)?;
+
+ Ok(())
+}
+
+fn config_configure(config: &mut Config, args: &ArgMatches) -> CliResult {
+ let verbose = args.verbose();
+ // quiet is unusual because it is redefined in some subcommands in order
+ // to provide custom help text.
+ let quiet = args.flag("quiet");
+ let color = args.get_one::<String>("color").map(String::as_str);
+ let frozen = args.flag("frozen");
+ let locked = args.flag("locked");
+ let offline = args.flag("offline");
+ let mut unstable_flags = vec![];
+ if let Some(values) = args.get_many::<String>("unstable-features") {
+ unstable_flags.extend(values.cloned());
+ }
+ let mut config_args = vec![];
+ if let Some(values) = args.get_many::<String>("config") {
+ config_args.extend(values.cloned());
+ }
+ config.configure(
+ verbose,
+ quiet,
+ color,
+ frozen,
+ locked,
+ offline,
+ &None,
+ &unstable_flags,
+ &config_args,
+ )?;
+ Ok(())
+}
+
+fn unpublished(args: &clap::ArgMatches, config: &mut cargo::util::Config) -> cargo::CliResult {
+ let ws = args.workspace(config)?;
+
+ let members_to_inspect: HashSet<_> = {
+ let pkgs = args.packages_from_flags()?;
+ if let Packages::Packages(_) = pkgs {
+ HashSet::from_iter(pkgs.get_packages(&ws)?)
+ } else {
+ HashSet::from_iter(ws.members())
+ }
+ };
+
+ let mut results = Vec::new();
+ {
+ let mut registry = PackageRegistry::new(config)?;
+ let _lock = config.acquire_package_cache_lock()?;
+ registry.lock_patches();
+ let source_id = SourceId::crates_io(config)?;
+
+ for member in members_to_inspect {
+ let name = member.name();
+ let current = member.version();
+ if member.publish() == &Some(vec![]) {
+ log::trace!("skipping {name}, `publish = false`");
+ continue;
+ }
+
+ let version_req = format!("<={current}");
+ let query =
+ cargo::core::dependency::Dependency::parse(name, Some(&version_req), source_id)?;
+ let possibilities = loop {
+ // Exact to avoid returning all for path/git
+ match registry.query_vec(&query, QueryKind::Exact) {
+ std::task::Poll::Ready(res) => {
+ break res?;
+ }
+ std::task::Poll::Pending => registry.block_until_ready()?,
+ }
+ };
+ let (last, published) = possibilities
+ .iter()
+ .map(|s| s.version())
+ .max()
+ .map(|last| (last.to_string(), last == current))
+ .unwrap_or(("-".to_string(), false));
+
+ results.push(vec![
+ name.to_string(),
+ last,
+ current.to_string(),
+ if published { "yes" } else { "no" }.to_string(),
+ ]);
+ }
+ }
+ results.sort();
+
+ if results.is_empty() {
+ return Ok(());
+ }
+
+ results.insert(
+ 0,
+ vec![
+ "name".to_owned(),
+ "crates.io".to_owned(),
+ "local".to_owned(),
+ "published?".to_owned(),
+ ],
+ );
+
+ output_table(results);
+
+ Ok(())
+}
+
+/// Outputs a markdown table like this.
+///
+/// ```text
+/// | name | crates.io | local | published? |
+/// |------------------|-----------|--------|------------|
+/// | cargo | 0.70.1 | 0.72.0 | no |
+/// | cargo-platform | 0.1.2 | 0.1.2 | yes |
+/// | cargo-util | - | 0.2.4 | no |
+/// | crates-io | 0.36.0 | 0.36.0 | yes |
+/// | home | - | 0.5.6 | no |
+/// ```
+fn output_table(table: Vec<Vec<String>>) {
+ let header = table.first().unwrap();
+ let paddings = table.iter().fold(vec![0; header.len()], |mut widths, row| {
+ for (width, field) in widths.iter_mut().zip(row) {
+ *width = usize::max(*width, field.len());
+ }
+ widths
+ });
+
+ let print = |row: &[_]| {
+ for (field, pad) in row.iter().zip(&paddings) {
+ print!("| {field:pad$} ");
+ }
+ println!("|");
+ };
+
+ print(header);
+
+ paddings.iter().for_each(|fill| print!("|-{:-<fill$}-", ""));
+ println!("|");
+
+ table.iter().skip(1).for_each(|r| print(r));
+}
+
+#[test]
+fn verify_cli() {
+ cli().debug_assert();
+}
diff --git a/src/tools/cargo/crates/credential/README.md b/src/tools/cargo/credential/README.md
index 168cc71c3..168cc71c3 100644
--- a/src/tools/cargo/crates/credential/README.md
+++ b/src/tools/cargo/credential/README.md
diff --git a/src/tools/cargo/crates/credential/cargo-credential-1password/Cargo.toml b/src/tools/cargo/credential/cargo-credential-1password/Cargo.toml
index 093fde8e5..8db40e577 100644
--- a/src/tools/cargo/crates/credential/cargo-credential-1password/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential-1password/Cargo.toml
@@ -7,6 +7,6 @@ repository = "https://github.com/rust-lang/cargo"
description = "A Cargo credential process that stores tokens in a 1password vault."
[dependencies]
-cargo-credential = { version = "0.2.0", path = "../cargo-credential" }
-serde = { version = "1.0.117", features = ["derive"] }
-serde_json = "1.0.59"
+cargo-credential.workspace = true
+serde = { workspace = true, features = ["derive"] }
+serde_json.workspace = true
diff --git a/src/tools/cargo/crates/credential/cargo-credential-1password/src/main.rs b/src/tools/cargo/credential/cargo-credential-1password/src/main.rs
index 4f512b717..4f512b717 100644
--- a/src/tools/cargo/crates/credential/cargo-credential-1password/src/main.rs
+++ b/src/tools/cargo/credential/cargo-credential-1password/src/main.rs
diff --git a/src/tools/cargo/crates/credential/cargo-credential-gnome-secret/Cargo.toml b/src/tools/cargo/credential/cargo-credential-gnome-secret/Cargo.toml
index 12e25cfb6..63b3e95cc 100644
--- a/src/tools/cargo/crates/credential/cargo-credential-gnome-secret/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential-gnome-secret/Cargo.toml
@@ -7,7 +7,7 @@ repository = "https://github.com/rust-lang/cargo"
description = "A Cargo credential process that stores tokens with GNOME libsecret."
[dependencies]
-cargo-credential = { version = "0.2.0", path = "../cargo-credential" }
+cargo-credential.workspace = true
[build-dependencies]
-pkg-config = "0.3.19"
+pkg-config.workspace = true
diff --git a/src/tools/cargo/crates/credential/cargo-credential-gnome-secret/build.rs b/src/tools/cargo/credential/cargo-credential-gnome-secret/build.rs
index 9283535af..9283535af 100644
--- a/src/tools/cargo/crates/credential/cargo-credential-gnome-secret/build.rs
+++ b/src/tools/cargo/credential/cargo-credential-gnome-secret/build.rs
diff --git a/src/tools/cargo/crates/credential/cargo-credential-gnome-secret/src/main.rs b/src/tools/cargo/credential/cargo-credential-gnome-secret/src/main.rs
index 40972b05d..40972b05d 100644
--- a/src/tools/cargo/crates/credential/cargo-credential-gnome-secret/src/main.rs
+++ b/src/tools/cargo/credential/cargo-credential-gnome-secret/src/main.rs
diff --git a/src/tools/cargo/crates/credential/cargo-credential-macos-keychain/Cargo.toml b/src/tools/cargo/credential/cargo-credential-macos-keychain/Cargo.toml
index c2c22a425..6311b71de 100644
--- a/src/tools/cargo/crates/credential/cargo-credential-macos-keychain/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential-macos-keychain/Cargo.toml
@@ -7,5 +7,7 @@ repository = "https://github.com/rust-lang/cargo"
description = "A Cargo credential process that stores tokens in a macOS keychain."
[dependencies]
-cargo-credential = { version = "0.2.0", path = "../cargo-credential" }
-security-framework = "2.0.0"
+cargo-credential.workspace = true
+
+[target.'cfg(target_os = "macos")'.dependencies]
+security-framework.workspace = true
diff --git a/src/tools/cargo/credential/cargo-credential-macos-keychain/src/main.rs b/src/tools/cargo/credential/cargo-credential-macos-keychain/src/main.rs
new file mode 100644
index 000000000..4d6ea96d0
--- /dev/null
+++ b/src/tools/cargo/credential/cargo-credential-macos-keychain/src/main.rs
@@ -0,0 +1,58 @@
+//! Cargo registry macos keychain credential process.
+
+#[cfg(target_os = "macos")]
+mod macos {
+ use cargo_credential::{Credential, Error};
+ use security_framework::os::macos::keychain::SecKeychain;
+
+ pub(crate) struct MacKeychain;
+
+ /// The account name is not used.
+ const ACCOUNT: &'static str = "";
+
+ fn registry(registry_name: &str) -> String {
+ format!("cargo-registry:{}", registry_name)
+ }
+
+ impl Credential for MacKeychain {
+ fn name(&self) -> &'static str {
+ env!("CARGO_PKG_NAME")
+ }
+
+ fn get(&self, index_url: &str) -> Result<String, Error> {
+ let keychain = SecKeychain::default().unwrap();
+ let service_name = registry(index_url);
+ let (pass, _item) = keychain.find_generic_password(&service_name, ACCOUNT)?;
+ String::from_utf8(pass.as_ref().to_vec())
+ .map_err(|_| "failed to convert token to UTF8".into())
+ }
+
+ fn store(&self, index_url: &str, token: &str, name: Option<&str>) -> Result<(), Error> {
+ let keychain = SecKeychain::default().unwrap();
+ let service_name = registry(name.unwrap_or(index_url));
+ if let Ok((_pass, mut item)) = keychain.find_generic_password(&service_name, ACCOUNT) {
+ item.set_password(token.as_bytes())?;
+ } else {
+ keychain.add_generic_password(&service_name, ACCOUNT, token.as_bytes())?;
+ }
+ Ok(())
+ }
+
+ fn erase(&self, index_url: &str) -> Result<(), Error> {
+ let keychain = SecKeychain::default().unwrap();
+ let service_name = registry(index_url);
+ let (_pass, item) = keychain.find_generic_password(&service_name, ACCOUNT)?;
+ item.delete();
+ Ok(())
+ }
+ }
+}
+
+#[cfg(not(target_os = "macos"))]
+use cargo_credential::UnsupportedCredential as MacKeychain;
+#[cfg(target_os = "macos")]
+use macos::MacKeychain;
+
+fn main() {
+ cargo_credential::main(MacKeychain);
+}
diff --git a/src/tools/cargo/crates/credential/cargo-credential-wincred/Cargo.toml b/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml
index 83c38e80d..cd168a8a3 100644
--- a/src/tools/cargo/crates/credential/cargo-credential-wincred/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml
@@ -7,5 +7,8 @@ repository = "https://github.com/rust-lang/cargo"
description = "A Cargo credential process that stores tokens with Windows Credential Manager."
[dependencies]
-cargo-credential = { version = "0.2.0", path = "../cargo-credential" }
-windows-sys = { version = "0.45", features = ["Win32_Foundation", "Win32_Security_Credentials"] }
+cargo-credential.workspace = true
+
+[target.'cfg(windows)'.dependencies.windows-sys]
+features = ["Win32_Foundation", "Win32_Security_Credentials"]
+workspace = true
diff --git a/src/tools/cargo/credential/cargo-credential-wincred/src/main.rs b/src/tools/cargo/credential/cargo-credential-wincred/src/main.rs
new file mode 100644
index 000000000..4377172e8
--- /dev/null
+++ b/src/tools/cargo/credential/cargo-credential-wincred/src/main.rs
@@ -0,0 +1,122 @@
+//! Cargo registry windows credential process.
+
+#[cfg(windows)]
+mod win {
+ use cargo_credential::{Credential, Error};
+ use std::ffi::OsStr;
+ use std::os::windows::ffi::OsStrExt;
+
+ use windows_sys::core::PWSTR;
+ use windows_sys::Win32::Foundation::ERROR_NOT_FOUND;
+ use windows_sys::Win32::Foundation::FILETIME;
+ use windows_sys::Win32::Foundation::TRUE;
+ use windows_sys::Win32::Security::Credentials::CredDeleteW;
+ use windows_sys::Win32::Security::Credentials::CredReadW;
+ use windows_sys::Win32::Security::Credentials::CredWriteW;
+ use windows_sys::Win32::Security::Credentials::CREDENTIALW;
+ use windows_sys::Win32::Security::Credentials::CRED_PERSIST_LOCAL_MACHINE;
+ use windows_sys::Win32::Security::Credentials::CRED_TYPE_GENERIC;
+
+ pub(crate) struct WindowsCredential;
+
+ /// Converts a string to a nul-terminated wide UTF-16 byte sequence.
+ fn wstr(s: &str) -> Vec<u16> {
+ let mut wide: Vec<u16> = OsStr::new(s).encode_wide().collect();
+ if wide.iter().any(|b| *b == 0) {
+ panic!("nul byte in wide string");
+ }
+ wide.push(0);
+ wide
+ }
+
+ fn target_name(registry_name: &str) -> Vec<u16> {
+ wstr(&format!("cargo-registry:{}", registry_name))
+ }
+
+ impl Credential for WindowsCredential {
+ fn name(&self) -> &'static str {
+ env!("CARGO_PKG_NAME")
+ }
+
+ fn get(&self, index_url: &str) -> Result<String, Error> {
+ let target_name = target_name(index_url);
+ let p_credential: *mut CREDENTIALW = std::ptr::null_mut() as *mut _;
+ unsafe {
+ if CredReadW(
+ target_name.as_ptr(),
+ CRED_TYPE_GENERIC,
+ 0,
+ p_credential as *mut _ as *mut _,
+ ) != TRUE
+ {
+ return Err(format!(
+ "failed to fetch token: {}",
+ std::io::Error::last_os_error()
+ )
+ .into());
+ }
+ let bytes = std::slice::from_raw_parts(
+ (*p_credential).CredentialBlob,
+ (*p_credential).CredentialBlobSize as usize,
+ );
+ String::from_utf8(bytes.to_vec())
+ .map_err(|_| "failed to convert token to UTF8".into())
+ }
+ }
+
+ fn store(&self, index_url: &str, token: &str, name: Option<&str>) -> Result<(), Error> {
+ let token = token.as_bytes();
+ let target_name = target_name(index_url);
+ let comment = match name {
+ Some(name) => wstr(&format!("Cargo registry token for {}", name)),
+ None => wstr("Cargo registry token"),
+ };
+ let mut credential = CREDENTIALW {
+ Flags: 0,
+ Type: CRED_TYPE_GENERIC,
+ TargetName: target_name.as_ptr() as PWSTR,
+ Comment: comment.as_ptr() as PWSTR,
+ LastWritten: FILETIME {
+ dwLowDateTime: 0,
+ dwHighDateTime: 0,
+ },
+ CredentialBlobSize: token.len() as u32,
+ CredentialBlob: token.as_ptr() as *mut u8,
+ Persist: CRED_PERSIST_LOCAL_MACHINE,
+ AttributeCount: 0,
+ Attributes: std::ptr::null_mut(),
+ TargetAlias: std::ptr::null_mut(),
+ UserName: std::ptr::null_mut(),
+ };
+ let result = unsafe { CredWriteW(&mut credential, 0) };
+ if result != TRUE {
+ let err = std::io::Error::last_os_error();
+ return Err(format!("failed to store token: {}", err).into());
+ }
+ Ok(())
+ }
+
+ fn erase(&self, index_url: &str) -> Result<(), Error> {
+ let target_name = target_name(index_url);
+ let result = unsafe { CredDeleteW(target_name.as_ptr(), CRED_TYPE_GENERIC, 0) };
+ if result != TRUE {
+ let err = std::io::Error::last_os_error();
+ if err.raw_os_error() == Some(ERROR_NOT_FOUND as i32) {
+ eprintln!("not currently logged in to `{}`", index_url);
+ return Ok(());
+ }
+ return Err(format!("failed to remove token: {}", err).into());
+ }
+ Ok(())
+ }
+ }
+}
+
+#[cfg(not(windows))]
+use cargo_credential::UnsupportedCredential as WindowsCredential;
+#[cfg(windows)]
+use win::WindowsCredential;
+
+fn main() {
+ cargo_credential::main(WindowsCredential);
+}
diff --git a/src/tools/cargo/crates/credential/cargo-credential/Cargo.toml b/src/tools/cargo/credential/cargo-credential/Cargo.toml
index 2addaf5af..2addaf5af 100644
--- a/src/tools/cargo/crates/credential/cargo-credential/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential/Cargo.toml
diff --git a/src/tools/cargo/crates/credential/cargo-credential/README.md b/src/tools/cargo/credential/cargo-credential/README.md
index 1f75e598a..53dc8e6b7 100644
--- a/src/tools/cargo/crates/credential/cargo-credential/README.md
+++ b/src/tools/cargo/credential/cargo-credential/README.md
@@ -8,7 +8,7 @@ Documentation about credential processes may be found at
https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process
Example implementations may be found at
-https://github.com/rust-lang/cargo/tree/master/crates/credential
+https://github.com/rust-lang/cargo/tree/master/credential
## Usage
diff --git a/src/tools/cargo/crates/credential/cargo-credential/src/lib.rs b/src/tools/cargo/credential/cargo-credential/src/lib.rs
index 3baf42d77..c75172242 100644
--- a/src/tools/cargo/crates/credential/cargo-credential/src/lib.rs
+++ b/src/tools/cargo/credential/cargo-credential/src/lib.rs
@@ -34,6 +34,26 @@ pub trait Credential {
fn erase(&self, index_url: &str) -> Result<(), Error>;
}
+pub struct UnsupportedCredential;
+
+impl Credential for UnsupportedCredential {
+ fn name(&self) -> &'static str {
+ "unsupported"
+ }
+
+ fn get(&self, _index_url: &str) -> Result<String, Error> {
+ Err("unsupported".into())
+ }
+
+ fn store(&self, _index_url: &str, _token: &str, _name: Option<&str>) -> Result<(), Error> {
+ Err("unsupported".into())
+ }
+
+ fn erase(&self, _index_url: &str) -> Result<(), Error> {
+ Err("unsupported".into())
+ }
+}
+
/// Runs the credential interaction by processing the command-line and
/// environment variables.
pub fn main(credential: impl Credential) {
diff --git a/src/tools/cargo/src/bin/cargo/cli.rs b/src/tools/cargo/src/bin/cargo/cli.rs
index 17120a656..946816571 100644
--- a/src/tools/cargo/src/bin/cargo/cli.rs
+++ b/src/tools/cargo/src/bin/cargo/cli.rs
@@ -440,6 +440,9 @@ pub fn cli() -> Command {
"cargo [OPTIONS] [COMMAND]"
};
Command::new("cargo")
+ // Subcommands all count their args' display order independently (from 0),
+ // which makes their args interspersed with global args. This puts global args last.
+ .next_display_order(1000)
.allow_external_subcommands(true)
// Doesn't mix well with our list of common cargo commands. See clap-rs/clap#3108 for
// opening clap up to allow us to style our help template
diff --git a/src/tools/cargo/src/bin/cargo/commands/add.rs b/src/tools/cargo/src/bin/cargo/commands/add.rs
index 39f0e189e..90c4f4dd5 100644
--- a/src/tools/cargo/src/bin/cargo/commands/add.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/add.rs
@@ -72,6 +72,10 @@ The package will be removed from your features.")
Example uses:
- Depending on multiple versions of a crate
- Depend on crates with the same name from different registries"),
+ flag(
+ "ignore-rust-version",
+ "Ignore `rust-version` specification in packages (unstable)"
+ ),
])
.arg_manifest_path()
.arg_package("Package to modify")
@@ -188,12 +192,24 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let dependencies = parse_dependencies(config, args)?;
+ let ignore_rust_version = args.flag("ignore-rust-version");
+ if ignore_rust_version && !config.cli_unstable().msrv_policy {
+ return Err(CliError::new(
+ anyhow::format_err!(
+ "`--ignore-rust-version` is unstable; pass `-Zmsrv-policy` to enable support for it"
+ ),
+ 101,
+ ));
+ }
+ let honor_rust_version = !ignore_rust_version;
+
let options = AddOptions {
config,
spec,
dependencies,
section,
dry_run,
+ honor_rust_version,
};
add(&ws, &options)?;
diff --git a/src/tools/cargo/src/bin/cargo/main.rs b/src/tools/cargo/src/bin/cargo/main.rs
index 55da2997f..9fb6635ea 100644
--- a/src/tools/cargo/src/bin/cargo/main.rs
+++ b/src/tools/cargo/src/bin/cargo/main.rs
@@ -293,10 +293,6 @@ fn init_git(config: &Config) {
/// configured to use libcurl instead of the built-in networking support so
/// that those configuration settings can be used.
fn init_git_transports(config: &Config) {
- // Only use a custom transport if any HTTP options are specified,
- // such as proxies or custom certificate authorities. The custom
- // transport, however, is not as well battle-tested.
-
match cargo::ops::needs_custom_http_transport(config) {
Ok(true) => {}
_ => return,
diff --git a/src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs b/src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs
index bf8bb1578..e6e41c522 100644
--- a/src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs
@@ -7,6 +7,7 @@
//! * [`RustcTargetData::info`] to get a [`TargetInfo`] for an in-depth query.
//! * [`TargetInfo::rustc_outputs`] to get a list of supported file types.
+use crate::core::compiler::apply_env_config;
use crate::core::compiler::{
BuildOutput, CompileKind, CompileMode, CompileTarget, Context, CrateType,
};
@@ -38,7 +39,7 @@ pub struct TargetInfo {
///
/// The key is the crate type name (like `cdylib`) and the value is
/// `Some((prefix, suffix))`, for example `libcargo.so` would be
- /// `Some(("lib", ".so")). The value is `None` if the crate type is not
+ /// `Some(("lib", ".so"))`. The value is `None` if the crate type is not
/// supported.
crate_types: RefCell<HashMap<CrateType, Option<(String, String)>>>,
/// `cfg` information extracted from `rustc --print=cfg`.
@@ -175,6 +176,7 @@ impl TargetInfo {
//
// Search `--print` to see what we query so far.
let mut process = rustc.workspace_process();
+ apply_env_config(config, &mut process)?;
process
.arg("-")
.arg("--crate-name")
diff --git a/src/tools/cargo/src/cargo/core/compiler/compilation.rs b/src/tools/cargo/src/cargo/core/compiler/compilation.rs
index 29642f13d..b263119b0 100644
--- a/src/tools/cargo/src/cargo/core/compiler/compilation.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/compilation.rs
@@ -7,7 +7,8 @@ use std::path::PathBuf;
use cargo_platform::CfgExpr;
use cargo_util::{paths, ProcessBuilder};
-use super::BuildContext;
+use crate::core::compiler::apply_env_config;
+use crate::core::compiler::BuildContext;
use crate::core::compiler::{CompileKind, Metadata, Unit};
use crate::core::Package;
use crate::util::{config, CargoResult, Config};
@@ -349,17 +350,7 @@ impl<'cfg> Compilation<'cfg> {
)
.cwd(pkg.root());
- // Apply any environment variables from the config
- for (key, value) in self.config.env_config()?.iter() {
- // never override a value that has already been set by cargo
- if cmd.get_envs().contains_key(key) {
- continue;
- }
-
- if value.is_force() || self.config.get_env_os(key).is_none() {
- cmd.env(key, value.resolve(self.config));
- }
- }
+ apply_env_config(self.config, &mut cmd)?;
Ok(cmd)
}
diff --git a/src/tools/cargo/src/cargo/core/compiler/custom_build.rs b/src/tools/cargo/src/cargo/core/compiler/custom_build.rs
index 5728d0c85..01890e542 100644
--- a/src/tools/cargo/src/cargo/core/compiler/custom_build.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/custom_build.rs
@@ -1,3 +1,36 @@
+//! How to execute a build script and parse its output.
+//!
+//! ## Preparing a build script run
+//!
+//! A [build script] is an optional Rust script Cargo will run before building
+//! your package. As of this writing, two kinds of special [`Unit`]s will be
+//! constructed when there is a build script in a package.
+//!
+//! * Build script compilation --- This unit is generally the same as units
+//! that would compile other Cargo targets. It will recursively creates units
+//! of its dependencies. One biggest difference is that the [`Unit`] of
+//! compiling a build script is flagged as [`TargetKind::CustomBuild`].
+//! * Build script executaion --- During the construction of the [`UnitGraph`],
+//! Cargo inserts a [`Unit`] with [`CompileMode::RunCustomBuild`]. This unit
+//! depends on the unit of compiling the associated build script, to ensure
+//! the executable is available before running. The [`Work`] of running the
+//! build script is prepared in the function [`prepare`].
+//!
+//! ## Running a build script
+//!
+//! When running a build script, Cargo is aware of the progress and the result
+//! of a build script. Standard output is the chosen interprocess communication
+//! between Cargo and build script processes. A set of strings is defined for
+//! that purpose. These strings, a.k.a. instructions, are interpreted by
+//! [`BuildOutput::parse`] and stored in [`Context::build_script_outputs`].
+//! The entire execution work is constructed by [`build_work`].
+//!
+//! [build script]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html
+//! [`TargetKind::CustomBuild`]: crate::core::manifest::TargetKind::CustomBuild
+//! [`UnitGraph`]: super::unit_graph::UnitGraph
+//! [`CompileMode::RunCustomBuild`]: super::CompileMode
+//! [instructions]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script
+
use super::{fingerprint, Context, Job, LinkType, Unit, Work};
use crate::core::compiler::artifact;
use crate::core::compiler::context::Metadata;
@@ -15,6 +48,10 @@ use std::path::{Path, PathBuf};
use std::str;
use std::sync::{Arc, Mutex};
+/// A build script instruction that tells Cargo to display a warning after the
+/// build script has finished running. Read [the doc] for more.
+///
+/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-warning
const CARGO_WARNING: &str = "cargo:warning=";
/// Contains the parsed output of a custom build script.
@@ -63,7 +100,7 @@ pub struct BuildScriptOutputs {
/// Linking information for a `Unit`.
///
-/// See `build_map` for more details.
+/// See [`build_map`] for more details.
#[derive(Default)]
pub struct BuildScripts {
/// List of build script outputs this Unit needs to include for linking. Each
@@ -96,7 +133,8 @@ pub struct BuildScripts {
pub plugins: BTreeSet<(PackageId, Metadata)>,
}
-/// Dependency information as declared by a build script.
+/// Dependency information as declared by a build script that might trigger
+/// a recompile of itself.
#[derive(Debug)]
pub struct BuildDeps {
/// Absolute path to the file in the target directory that stores the
@@ -130,6 +168,8 @@ pub fn prepare(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
}
}
+/// Emits the output of a build script as a [`machine_message::BuildScript`]
+/// JSON string to standard output.
fn emit_build_output(
state: &JobState<'_, '_>,
output: &BuildOutput,
@@ -155,6 +195,14 @@ fn emit_build_output(
Ok(())
}
+/// Constructs the unit of work of running a build script.
+///
+/// The construction includes:
+///
+/// * Set environment varibles for the build script run.
+/// * Create the output dir (`OUT_DIR`) for the build script output.
+/// * Determine if the build script needs a re-run.
+/// * Run the build script and store its output.
fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
assert!(unit.mode.is_run_custom_build());
let bcx = &cx.bcx;
@@ -517,6 +565,8 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
Ok(job)
}
+/// When a build script run fails, store only warnings and nuke other outputs,
+/// as they are likely broken.
fn insert_warnings_in_build_outputs(
build_script_outputs: Arc<Mutex<BuildScriptOutputs>>,
id: PackageId,
@@ -534,6 +584,7 @@ fn insert_warnings_in_build_outputs(
}
impl BuildOutput {
+ /// Like [`BuildOutput::parse`] but from a file path.
pub fn parse_file(
path: &Path,
library_name: Option<String>,
@@ -557,9 +608,13 @@ impl BuildOutput {
)
}
- // Parses the output of a script.
- // The `pkg_descr` is used for error messages.
- // The `library_name` is used for determining if RUSTC_BOOTSTRAP should be allowed.
+ /// Parses the output instructions of a build script.
+ ///
+ /// * `pkg_descr` --- for error messages
+ /// * `library_name` --- for determining if `RUSTC_BOOTSTRAP` should be allowed
+ /// * `extra_check_cfg` --- for unstable feature [`-Zcheck-cfg`]
+ ///
+ /// [`-Zcheck-cfg`]: https://doc.rust-lang.org/cargo/reference/unstable.html#check-cfg
pub fn parse(
input: &[u8],
// Takes String instead of InternedString so passing `unit.pkg.name()` will give a compile error.
@@ -781,6 +836,9 @@ impl BuildOutput {
})
}
+ /// Parses [`cargo:rustc-flags`] instruction.
+ ///
+ /// [`cargo:rustc-flags`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-flagsflags
pub fn parse_rustc_flags(
value: &str,
whence: &str,
@@ -826,6 +884,9 @@ impl BuildOutput {
Ok((library_paths, library_links))
}
+ /// Parses [`cargo:rustc-env`] instruction.
+ ///
+ /// [`cargo:rustc-env`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-env
pub fn parse_rustc_env(value: &str, whence: &str) -> CargoResult<(String, String)> {
let mut iter = value.splitn(2, '=');
let name = iter.next();
@@ -837,6 +898,9 @@ impl BuildOutput {
}
}
+/// Prepares the Rust script for the unstable feature [metabuild].
+///
+/// [metabuild]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#metabuild
fn prepare_metabuild(cx: &Context<'_, '_>, unit: &Unit, deps: &[String]) -> CargoResult<()> {
let mut output = Vec::new();
let available_deps = cx.unit_deps(unit);
@@ -866,6 +930,8 @@ fn prepare_metabuild(cx: &Context<'_, '_>, unit: &Unit, deps: &[String]) -> Carg
}
impl BuildDeps {
+ /// Creates a build script dependency information from a previous
+ /// build script output path and the content.
pub fn new(output_file: &Path, output: Option<&BuildOutput>) -> BuildDeps {
BuildDeps {
build_script_output: output_file.to_path_buf(),
@@ -881,22 +947,27 @@ impl BuildDeps {
}
}
-/// Computes several maps in `Context`:
-/// - `build_scripts`: A map that tracks which build scripts each package
+/// Computes several maps in [`Context`].
+///
+/// - [`build_scripts`]: A map that tracks which build scripts each package
/// depends on.
-/// - `build_explicit_deps`: Dependency statements emitted by build scripts
+/// - [`build_explicit_deps`]: Dependency statements emitted by build scripts
/// from a previous run.
-/// - `build_script_outputs`: Pre-populates this with any overridden build
+/// - [`build_script_outputs`]: Pre-populates this with any overridden build
/// scripts.
///
-/// The important one here is `build_scripts`, which for each `(package,
-/// metadata)` stores a `BuildScripts` object which contains a list of
-/// dependencies with build scripts that the unit should consider when
-/// linking. For example this lists all dependencies' `-L` flags which need to
-/// be propagated transitively.
+/// The important one here is [`build_scripts`], which for each `(package,
+/// metadata)` stores a [`BuildScripts`] object which contains a list of
+/// dependencies with build scripts that the unit should consider when linking.
+/// For example this lists all dependencies' `-L` flags which need to be
+/// propagated transitively.
///
/// The given set of units to this function is the initial set of
/// targets/profiles which are being built.
+///
+/// [`build_scripts`]: Context::build_scripts
+/// [`build_explicit_deps`]: Context::build_explicit_deps
+/// [`build_script_outputs`]: Context::build_script_outputs
pub fn build_map(cx: &mut Context<'_, '_>) -> CargoResult<()> {
let mut ret = HashMap::new();
for unit in &cx.bcx.roots {
@@ -943,7 +1014,6 @@ pub fn build_map(cx: &mut Context<'_, '_>) -> CargoResult<()> {
add_to_link(&mut ret, unit.pkg.package_id(), script_meta);
}
- // Load any dependency declarations from a previous run.
if unit.mode.is_run_custom_build() {
parse_previous_explicit_deps(cx, unit);
}
@@ -982,6 +1052,7 @@ pub fn build_map(cx: &mut Context<'_, '_>) -> CargoResult<()> {
}
}
+ /// Load any dependency declarations from a previous build script run.
fn parse_previous_explicit_deps(cx: &mut Context<'_, '_>, unit: &Unit) {
let script_run_dir = cx.files().build_script_run_dir(unit);
let output_file = script_run_dir.join("output");
diff --git a/src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs b/src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs
index 7401afebc..a3523110b 100644
--- a/src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs
@@ -75,6 +75,7 @@
//! [`Lto`] flags | ✓ | ✓
//! config settings[^5] | ✓ |
//! is_std | | ✓
+//! `[lints]` table[^6] | ✓ |
//!
//! [^1]: Build script and bin dependencies are not included.
//!
@@ -86,6 +87,8 @@
//! [^5]: Config settings that are not otherwise captured anywhere else.
//! Currently, this is only `doc.extern-map`.
//!
+//! [^6]: Via [`Manifest::lint_rustflags`][crate::core::Manifest::lint_rustflags]
+//!
//! When deciding what should go in the Metadata vs the Fingerprint, consider
//! that some files (like dylibs) do not have a hash in their filename. Thus,
//! if a value changes, only the fingerprint will detect the change (consider,
@@ -1414,6 +1417,7 @@ fn calculate_normal(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Finger
unit.mode,
cx.bcx.extra_args_for(unit),
cx.lto[unit],
+ unit.pkg.manifest().lint_rustflags(),
));
// Include metadata since it is exposed as environment variables.
let m = unit.pkg.manifest().metadata();
diff --git a/src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs b/src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs
index 38ab0fe49..6e8866b2b 100644
--- a/src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs
@@ -487,7 +487,7 @@ impl<'cfg> JobQueue<'cfg> {
timings: self.timings,
tokens: Vec::new(),
pending_queue: Vec::new(),
- print: DiagnosticPrinter::new(cx.bcx.config),
+ print: DiagnosticPrinter::new(cx.bcx.config, &cx.bcx.rustc().workspace_wrapper),
finished: 0,
per_package_future_incompat_reports: Vec::new(),
};
@@ -812,7 +812,7 @@ impl<'cfg> DrainState<'cfg> {
);
if !cx.bcx.build_config.build_plan {
// It doesn't really matter if this fails.
- drop(cx.bcx.config.shell().status("Finished", message));
+ let _ = cx.bcx.config.shell().status("Finished", message);
future_incompat::save_and_display_report(
cx.bcx,
&self.per_package_future_incompat_reports,
@@ -836,7 +836,7 @@ impl<'cfg> DrainState<'cfg> {
if new_err.print_always || err_state.count == 0 {
crate::display_error(&new_err.error, shell);
if err_state.count == 0 && !self.active.is_empty() {
- drop(shell.warn("build failed, waiting for other jobs to finish..."));
+ let _ = shell.warn("build failed, waiting for other jobs to finish...");
}
err_state.count += 1;
} else {
@@ -863,11 +863,11 @@ impl<'cfg> DrainState<'cfg> {
.values()
.map(|u| self.name_for_progress(u))
.collect::<Vec<_>>();
- drop(self.progress.tick_now(
+ let _ = self.progress.tick_now(
self.finished,
self.total_units,
&format!(": {}", active_names.join(", ")),
- ));
+ );
}
fn name_for_progress(&self, unit: &Unit) -> String {
@@ -1005,12 +1005,16 @@ impl<'cfg> DrainState<'cfg> {
message.push_str(" generated ");
match count.total {
1 => message.push_str("1 warning"),
- n => drop(write!(message, "{} warnings", n)),
+ n => {
+ let _ = write!(message, "{} warnings", n);
+ }
};
match count.duplicates {
0 => {}
1 => message.push_str(" (1 duplicate)"),
- n => drop(write!(message, " ({} duplicates)", n)),
+ n => {
+ let _ = write!(message, " ({} duplicates)", n);
+ }
}
// Only show the `cargo fix` message if its a local `Unit`
if unit.is_local() {
@@ -1045,16 +1049,16 @@ impl<'cfg> DrainState<'cfg> {
if fixable > 1 {
suggestions.push_str("s")
}
- drop(write!(
+ let _ = write!(
message,
" (run `{command} --{args}` to apply {suggestions})"
- ))
+ );
}
}
}
// Errors are ignored here because it is tricky to handle them
// correctly, and they aren't important.
- drop(config.shell().warn(message));
+ let _ = config.shell().warn(message);
}
fn finish(
diff --git a/src/tools/cargo/src/cargo/core/compiler/mod.rs b/src/tools/cargo/src/cargo/core/compiler/mod.rs
index 7b43fd27d..7e49f0079 100644
--- a/src/tools/cargo/src/cargo/core/compiler/mod.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/mod.rs
@@ -92,6 +92,7 @@ use crate::core::{Feature, PackageId, Target, Verbosity};
use crate::util::errors::{CargoResult, VerboseError};
use crate::util::interning::InternedString;
use crate::util::machine_message::{self, Message};
+use crate::util::toml::TomlDebugInfo;
use crate::util::{add_path_args, internal, iter_join_onto, profile};
use cargo_util::{paths, ProcessBuilder, ProcessError};
use rustfix::diagnostics::Applicability;
@@ -603,9 +604,20 @@ fn link_targets(cx: &mut Context<'_, '_>, unit: &Unit, fresh: bool) -> CargoResu
}
if json_messages {
+ let debuginfo = profile.debuginfo.to_option().map(|d| match d {
+ TomlDebugInfo::None => machine_message::ArtifactDebuginfo::Int(0),
+ TomlDebugInfo::Limited => machine_message::ArtifactDebuginfo::Int(1),
+ TomlDebugInfo::Full => machine_message::ArtifactDebuginfo::Int(2),
+ TomlDebugInfo::LineDirectivesOnly => {
+ machine_message::ArtifactDebuginfo::Named("line-directives-only")
+ }
+ TomlDebugInfo::LineTablesOnly => {
+ machine_message::ArtifactDebuginfo::Named("line-tables-only")
+ }
+ });
let art_profile = machine_message::ArtifactProfile {
opt_level: profile.opt_level.as_str(),
- debuginfo: profile.debuginfo.to_option(),
+ debuginfo,
debug_assertions: profile.debug_assertions,
overflow_checks: profile.overflow_checks,
test: unit_mode.is_any_test(),
@@ -750,6 +762,7 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
add_error_format_and_color(cx, &mut rustdoc);
add_allow_features(cx, &mut rustdoc);
+ rustdoc.args(unit.pkg.manifest().lint_rustflags());
if let Some(args) = cx.bcx.extra_args_for(unit) {
rustdoc.args(args);
}
@@ -1028,10 +1041,6 @@ fn build_base_args(
cmd.arg("-C").arg(&format!("opt-level={}", opt_level));
}
- if !rustflags.is_empty() {
- cmd.args(&rustflags);
- }
-
if *panic != PanicStrategy::Unwind {
cmd.arg("-C").arg(format!("panic={}", panic));
}
@@ -1066,6 +1075,10 @@ fn build_base_args(
cmd.arg("-C").arg(format!("debuginfo={}", debuginfo));
}
+ cmd.args(unit.pkg.manifest().lint_rustflags());
+ if !rustflags.is_empty() {
+ cmd.args(&rustflags);
+ }
if let Some(args) = cx.bcx.extra_args_for(unit) {
cmd.args(args);
}
@@ -1793,3 +1806,18 @@ fn descriptive_pkg_name(name: &str, target: &Target, mode: &CompileMode) -> Stri
};
format!("`{name}` ({desc_name}{mode})")
}
+
+/// Applies environment variables from config `[env]` to [`ProcessBuilder`].
+fn apply_env_config(config: &crate::Config, cmd: &mut ProcessBuilder) -> CargoResult<()> {
+ for (key, value) in config.env_config()?.iter() {
+ // never override a value that has already been set by cargo
+ if cmd.get_envs().contains_key(key) {
+ continue;
+ }
+
+ if value.is_force() || config.get_env_os(key).is_none() {
+ cmd.env(key, value.resolve(config));
+ }
+ }
+ Ok(())
+}
diff --git a/src/tools/cargo/src/cargo/core/compiler/standard_lib.rs b/src/tools/cargo/src/cargo/core/compiler/standard_lib.rs
index b5ac0c997..c456c58d5 100644
--- a/src/tools/cargo/src/cargo/core/compiler/standard_lib.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/standard_lib.rs
@@ -92,7 +92,7 @@ pub fn resolve_std<'cfg>(
String::from("library/std"),
String::from("library/core"),
String::from("library/alloc"),
- String::from("library/test"),
+ String::from("library/sysroot"),
];
let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new(
&src_path,
@@ -114,13 +114,13 @@ pub fn resolve_std<'cfg>(
let config = ws.config();
// This is a delicate hack. In order for features to resolve correctly,
// the resolver needs to run a specific "current" member of the workspace.
- // Thus, in order to set the features for `std`, we need to set `libtest`
- // to be the "current" member. `libtest` is the root, and all other
+ // Thus, in order to set the features for `std`, we need to set `sysroot`
+ // to be the "current" member. `sysroot` is the root, and all other
// standard library crates are dependencies from there. Since none of the
// other crates need to alter their features, this should be fine, for
// now. Perhaps in the future features will be decoupled from the resolver
// and it will be easier to control feature selection.
- let current_manifest = src_path.join("library/test/Cargo.toml");
+ let current_manifest = src_path.join("library/sysroot/Cargo.toml");
// TODO: Consider doing something to enforce --locked? Or to prevent the
// lock file from being written, such as setting ephemeral.
let mut std_ws = Workspace::new_virtual(src_path, current_manifest, virtual_manifest, config)?;
@@ -128,10 +128,10 @@ pub fn resolve_std<'cfg>(
// `[dev-dependencies]`. No need for us to generate a `Resolve` which has
// those included because we'll never use them anyway.
std_ws.set_require_optional_deps(false);
- // `test` is not in the default set because it is optional, but it needs
- // to be part of the resolve in case we do need it.
+ // `sysroot` is not in the default set because it is optional, but it needs
+ // to be part of the resolve in case we do need it or `libtest`.
let mut spec_pkgs = Vec::from(crates);
- spec_pkgs.push("test".to_string());
+ spec_pkgs.push("sysroot".to_string());
let spec = Packages::Packages(spec_pkgs);
let specs = spec.to_package_id_specs(&std_ws)?;
let features = match &config.cli_unstable().build_std_features {
diff --git a/src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs b/src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs
index 68fc1e519..3bf8b0c77 100644
--- a/src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs
@@ -149,7 +149,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
/// Compute all the dependencies for the standard library.
fn calc_deps_of_std(
- mut state: &mut State<'_, '_>,
+ state: &mut State<'_, '_>,
std_roots: &HashMap<CompileKind, Vec<Unit>>,
) -> CargoResult<Option<UnitGraph>> {
if std_roots.is_empty() {
diff --git a/src/tools/cargo/src/cargo/core/features.rs b/src/tools/cargo/src/cargo/core/features.rs
index 7f16e79cf..d56054a0a 100644
--- a/src/tools/cargo/src/cargo/core/features.rs
+++ b/src/tools/cargo/src/cargo/core/features.rs
@@ -585,19 +585,19 @@ impl Features {
feature_name, feature.version
);
if self.is_local {
- drop(writeln!(
+ let _ = writeln!(
msg,
"Remove the feature from Cargo.toml to remove this error."
- ));
+ );
} else {
- drop(writeln!(
+ let _ = writeln!(
msg,
"This package cannot be used with this version of Cargo, \
as the unstable feature `{}` is no longer supported.",
feature_name
- ));
+ );
}
- drop(writeln!(msg, "{}", see_docs()));
+ let _ = writeln!(msg, "{}", see_docs());
bail!(msg);
}
}
@@ -629,32 +629,29 @@ impl Features {
if self.nightly_features_allowed {
if self.is_local {
- drop(writeln!(
+ let _ = writeln!(
msg,
"Consider adding `cargo-features = [\"{}\"]` \
to the top of Cargo.toml (above the [package] table) \
to tell Cargo you are opting in to use this unstable feature.",
feature_name
- ));
+ );
} else {
- drop(writeln!(
- msg,
- "Consider trying a more recent nightly release."
- ));
+ let _ = writeln!(msg, "Consider trying a more recent nightly release.");
}
} else {
- drop(writeln!(
+ let _ = writeln!(
msg,
"Consider trying a newer version of Cargo \
(this may require the nightly release)."
- ));
+ );
}
- drop(writeln!(
+ let _ = writeln!(
msg,
"See https://doc.rust-lang.org/nightly/cargo/{} for more information \
about the status of this feature.",
feature.docs
- ));
+ );
bail!("{}", msg);
}
@@ -733,6 +730,8 @@ unstable_cli_options!(
unstable_options: bool = ("Allow the usage of unstable options"),
skip_rustdoc_fingerprint: bool = (HIDDEN),
rustdoc_scrape_examples: bool = ("Allows Rustdoc to scrape code examples from reverse-dependencies"),
+ msrv_policy: bool = ("Enable rust-version aware policy within cargo"),
+ lints: bool = ("Pass `[lints]` to the linting tools"),
);
const STABILIZED_COMPILE_PROGRESS: &str = "The progress bar is now always \
@@ -1095,6 +1094,8 @@ impl CliUnstable {
"timings" => stabilized_warn(k, "1.60", STABILIZED_TIMINGS),
"codegen-backend" => self.codegen_backend = parse_empty(k, v)?,
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,
+ "msrv-policy" => self.msrv_policy = parse_empty(k, v)?,
+ "lints" => self.lints = parse_empty(k, v)?,
_ => bail!("unknown `-Z` flag specified: {}", k),
}
diff --git a/src/tools/cargo/src/cargo/core/manifest.rs b/src/tools/cargo/src/cargo/core/manifest.rs
index 182882dad..98498ead8 100644
--- a/src/tools/cargo/src/cargo/core/manifest.rs
+++ b/src/tools/cargo/src/cargo/core/manifest.rs
@@ -63,6 +63,7 @@ pub struct Manifest {
default_run: Option<String>,
metabuild: Option<Vec<String>>,
resolve_behavior: Option<ResolveBehavior>,
+ lint_rustflags: Vec<String>,
}
/// When parsing `Cargo.toml`, some warnings should silenced
@@ -110,6 +111,7 @@ pub struct ManifestMetadata {
pub documentation: Option<String>, // URL
pub badges: BTreeMap<String, BTreeMap<String, String>>,
pub links: Option<String>,
+ pub rust_version: Option<String>,
}
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
@@ -404,6 +406,7 @@ impl Manifest {
original: Rc<TomlManifest>,
metabuild: Option<Vec<String>>,
resolve_behavior: Option<ResolveBehavior>,
+ lint_rustflags: Vec<String>,
) -> Manifest {
Manifest {
summary,
@@ -429,6 +432,7 @@ impl Manifest {
default_run,
metabuild,
resolve_behavior,
+ lint_rustflags,
}
}
@@ -513,6 +517,11 @@ impl Manifest {
self.resolve_behavior
}
+ /// `RUSTFLAGS` from the `[lints]` table
+ pub fn lint_rustflags(&self) -> &[String] {
+ self.lint_rustflags.as_slice()
+ }
+
pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Manifest {
Manifest {
summary: self.summary.map_source(to_replace, replace_with),
diff --git a/src/tools/cargo/src/cargo/core/package_id_spec.rs b/src/tools/cargo/src/cargo/core/package_id_spec.rs
index 29043b963..267ea3ffd 100644
--- a/src/tools/cargo/src/cargo/core/package_id_spec.rs
+++ b/src/tools/cargo/src/cargo/core/package_id_spec.rs
@@ -7,9 +7,9 @@ use serde::{de, ser};
use url::Url;
use crate::core::PackageId;
+use crate::util::edit_distance;
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
-use crate::util::lev_distance;
use crate::util::{validate_package_name, IntoUrl, ToSemver};
/// Some or all of the data required to identify a package:
@@ -88,7 +88,7 @@ impl PackageIdSpec {
{
let i: Vec<_> = i.into_iter().collect();
let spec = PackageIdSpec::parse(spec).with_context(|| {
- let suggestion = lev_distance::closest_msg(spec, i.iter(), |id| id.name().as_str());
+ let suggestion = edit_distance::closest_msg(spec, i.iter(), |id| id.name().as_str());
format!("invalid package ID specification: `{}`{}", spec, suggestion)
})?;
spec.query(i)
@@ -229,7 +229,7 @@ impl PackageIdSpec {
);
}
if suggestion.is_empty() {
- suggestion.push_str(&lev_distance::closest_msg(
+ suggestion.push_str(&edit_distance::closest_msg(
&self.name,
all_ids.iter(),
|id| id.name().as_str(),
diff --git a/src/tools/cargo/src/cargo/core/profiles.rs b/src/tools/cargo/src/cargo/core/profiles.rs
index 51d19e32e..3831f18c2 100644
--- a/src/tools/cargo/src/cargo/core/profiles.rs
+++ b/src/tools/cargo/src/cargo/core/profiles.rs
@@ -26,7 +26,9 @@ use crate::core::dependency::Artifact;
use crate::core::resolver::features::FeaturesFor;
use crate::core::{PackageId, PackageIdSpec, Resolve, Shell, Target, Workspace};
use crate::util::interning::InternedString;
-use crate::util::toml::{ProfilePackageSpec, StringOrBool, TomlProfile, TomlProfiles, U32OrBool};
+use crate::util::toml::{
+ ProfilePackageSpec, StringOrBool, TomlDebugInfo, TomlProfile, TomlProfiles,
+};
use crate::util::{closest_msg, config, CargoResult, Config};
use anyhow::{bail, Context as _};
use std::collections::{BTreeMap, HashMap, HashSet};
@@ -276,15 +278,13 @@ impl Profiles {
// platform which has a stable `-Csplit-debuginfo` option for rustc,
// and it's typically much faster than running `dsymutil` on all builds
// in incremental cases.
- if let Some(debug) = profile.debuginfo.to_option() {
- if profile.split_debuginfo.is_none() && debug > 0 {
- let target = match &kind {
- CompileKind::Host => self.rustc_host.as_str(),
- CompileKind::Target(target) => target.short_name(),
- };
- if target.contains("-apple-") {
- profile.split_debuginfo = Some(InternedString::new("unpacked"));
- }
+ if profile.debuginfo.is_turned_on() && profile.split_debuginfo.is_none() {
+ let target = match &kind {
+ CompileKind::Host => self.rustc_host.as_str(),
+ CompileKind::Target(target) => target.short_name(),
+ };
+ if target.contains("-apple-") {
+ profile.split_debuginfo = Some(InternedString::new("unpacked"));
}
}
@@ -528,11 +528,8 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) {
if toml.codegen_units.is_some() {
profile.codegen_units = toml.codegen_units;
}
- match toml.debug {
- Some(U32OrBool::U32(debug)) => profile.debuginfo = DebugInfo::Explicit(debug),
- Some(U32OrBool::Bool(true)) => profile.debuginfo = DebugInfo::Explicit(2),
- Some(U32OrBool::Bool(false)) => profile.debuginfo = DebugInfo::None,
- None => {}
+ if let Some(debuginfo) = toml.debug {
+ profile.debuginfo = DebugInfo::Explicit(debuginfo);
}
if let Some(debug_assertions) = toml.debug_assertions {
profile.debug_assertions = debug_assertions;
@@ -683,7 +680,7 @@ impl Profile {
Profile {
name: InternedString::new("dev"),
root: ProfileRoot::Debug,
- debuginfo: DebugInfo::Explicit(2),
+ debuginfo: DebugInfo::Explicit(TomlDebugInfo::Full),
debug_assertions: true,
overflow_checks: true,
incremental: true,
@@ -704,7 +701,7 @@ impl Profile {
/// Compares all fields except `name`, which doesn't affect compilation.
/// This is necessary for `Unit` deduplication for things like "test" and
/// "dev" which are essentially the same.
- fn comparable(&self) -> impl Hash + Eq {
+ fn comparable(&self) -> impl Hash + Eq + '_ {
(
self.opt_level,
self.lto,
@@ -715,9 +712,8 @@ impl Profile {
self.debug_assertions,
self.overflow_checks,
self.rpath,
- self.incremental,
- self.panic,
- self.strip,
+ (self.incremental, self.panic, self.strip),
+ &self.rustflags,
)
}
}
@@ -743,7 +739,7 @@ pub enum DebugInfo {
/// No debuginfo level was set.
None,
/// A debuginfo level that is explicitly set, by a profile or a user.
- Explicit(u32),
+ Explicit(TomlDebugInfo),
/// For internal purposes: a deferred debuginfo level that can be optimized
/// away, but has this value otherwise.
///
@@ -753,22 +749,22 @@ pub enum DebugInfo {
/// faster to build (see [DebugInfo::weaken]).
///
/// In all other situations, this level value will be the one to use.
- Deferred(u32),
+ Deferred(TomlDebugInfo),
}
impl DebugInfo {
/// The main way to interact with this debuginfo level, turning it into an Option.
- pub fn to_option(&self) -> Option<u32> {
+ pub fn to_option(self) -> Option<TomlDebugInfo> {
match self {
DebugInfo::None => None,
- DebugInfo::Explicit(v) | DebugInfo::Deferred(v) => Some(*v),
+ DebugInfo::Explicit(v) | DebugInfo::Deferred(v) => Some(v),
}
}
- /// Returns true if the debuginfo level is high enough (at least 1). Helper
+ /// Returns true if any debuginfo will be generated. Helper
/// for a common operation on the usual `Option` representation.
pub(crate) fn is_turned_on(&self) -> bool {
- self.to_option().unwrap_or(0) != 0
+ !matches!(self.to_option(), None | Some(TomlDebugInfo::None))
}
pub(crate) fn is_deferred(&self) -> bool {
@@ -784,8 +780,12 @@ impl DebugInfo {
}
/// Reset to the lowest level: no debuginfo.
+ /// If it is explicitly set, keep it explicit.
pub(crate) fn weaken(self) -> Self {
- DebugInfo::None
+ match self {
+ DebugInfo::None => DebugInfo::None,
+ _ => DebugInfo::Explicit(TomlDebugInfo::None),
+ }
}
}
diff --git a/src/tools/cargo/src/cargo/core/resolver/dep_cache.rs b/src/tools/cargo/src/cargo/core/resolver/dep_cache.rs
index 4fd275385..54b0ce97f 100644
--- a/src/tools/cargo/src/cargo/core/resolver/dep_cache.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/dep_cache.rs
@@ -455,7 +455,12 @@ impl Requirements<'_> {
.iter()
.any(|dep| dep.name_in_toml() == package && dep.is_optional())
{
- self.require_feature(package)?;
+ // This optional dependency may not have an implicit feature of
+ // the same name if the `dep:` syntax is used to avoid creating
+ // that implicit feature.
+ if self.summary.features().contains_key(&package) {
+ self.require_feature(package)?;
+ }
}
self.deps.entry(package).or_default().insert(feat);
Ok(())
diff --git a/src/tools/cargo/src/cargo/core/resolver/errors.rs b/src/tools/cargo/src/cargo/core/resolver/errors.rs
index d75240df6..ca5c833f4 100644
--- a/src/tools/cargo/src/cargo/core/resolver/errors.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/errors.rs
@@ -2,7 +2,7 @@ use std::fmt;
use std::task::Poll;
use crate::core::{Dependency, PackageId, QueryKind, Registry, Summary};
-use crate::util::lev_distance::lev_distance;
+use crate::util::edit_distance::edit_distance;
use crate::util::{Config, VersionExt};
use anyhow::Error;
@@ -308,8 +308,7 @@ pub(super) fn activation_error(
candidates.dedup_by(|a, b| a.name() == b.name());
let mut candidates: Vec<_> = candidates
.iter()
- .map(|n| (lev_distance(&*new_dep.package_name(), &*n.name()), n))
- .filter(|&(d, _)| d < 4)
+ .filter_map(|n| Some((edit_distance(&*new_dep.package_name(), &*n.name(), 3)?, n)))
.collect();
candidates.sort_by_key(|o| o.0);
let mut msg: String;
diff --git a/src/tools/cargo/src/cargo/core/resolver/features.rs b/src/tools/cargo/src/cargo/core/resolver/features.rs
index e2f2bd5c5..6b79722ca 100644
--- a/src/tools/cargo/src/cargo/core/resolver/features.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/features.rs
@@ -717,7 +717,15 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
// The old behavior before weak dependencies were
// added is to also enables a feature of the same
// name.
- self.activate_rec(pkg_id, fk, dep_name)?;
+ //
+ // Don't enable if the implicit optional dependency
+ // feature wasn't created due to `dep:` hiding.
+ // See rust-lang/cargo#10788 and rust-lang/cargo#12130
+ let summary = self.resolve.summary(pkg_id);
+ let feature_map = summary.features();
+ if feature_map.contains_key(&dep_name) {
+ self.activate_rec(pkg_id, fk, dep_name)?;
+ }
}
}
// Activate the feature on the dependency.
diff --git a/src/tools/cargo/src/cargo/core/resolver/version_prefs.rs b/src/tools/cargo/src/cargo/core/resolver/version_prefs.rs
index 73cce5db8..002f11ff8 100644
--- a/src/tools/cargo/src/cargo/core/resolver/version_prefs.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/version_prefs.rs
@@ -100,7 +100,15 @@ mod test {
let pkg_id = pkgid(name, version);
let config = Config::default().unwrap();
let features = BTreeMap::new();
- Summary::new(&config, pkg_id, Vec::new(), &features, None::<&String>).unwrap()
+ Summary::new(
+ &config,
+ pkg_id,
+ Vec::new(),
+ &features,
+ None::<&String>,
+ None::<&String>,
+ )
+ .unwrap()
}
fn describe(summaries: &Vec<Summary>) -> String {
diff --git a/src/tools/cargo/src/cargo/core/shell.rs b/src/tools/cargo/src/cargo/core/shell.rs
index fdae617c4..f74bde257 100644
--- a/src/tools/cargo/src/cargo/core/shell.rs
+++ b/src/tools/cargo/src/cargo/core/shell.rs
@@ -563,13 +563,13 @@ mod imp {
use windows_sys::core::PCSTR;
use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
+ use windows_sys::Win32::Foundation::{GENERIC_READ, GENERIC_WRITE};
use windows_sys::Win32::Storage::FileSystem::{
CreateFileA, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,
};
use windows_sys::Win32::System::Console::{
GetConsoleScreenBufferInfo, GetStdHandle, CONSOLE_SCREEN_BUFFER_INFO, STD_ERROR_HANDLE,
};
- use windows_sys::Win32::System::SystemServices::{GENERIC_READ, GENERIC_WRITE};
pub(super) use super::{default_err_erase_line as err_erase_line, TtyWidth};
diff --git a/src/tools/cargo/src/cargo/core/source/mod.rs b/src/tools/cargo/src/cargo/core/source/mod.rs
index dca71b64e..6ca614d34 100644
--- a/src/tools/cargo/src/cargo/core/source/mod.rs
+++ b/src/tools/cargo/src/cargo/core/source/mod.rs
@@ -1,3 +1,18 @@
+//! Fundamental types and traits for sources of Cargo packages.
+//!
+//! A source is a provider that contains source files and metadata of packages.
+//! It provides a number of methods to fetch those package informations, for
+//! example, querying metadata or downloading files for a package. These
+//! informations then can be used as dependencies for other Cargo packages.
+//!
+//! Notably, this module contains
+//!
+//! * [`Source`] trait as an abstraction of different sources
+//! * [`SourceMap`] struct as a map of all available sources
+//! * [`SourceId`] struct as an unique identifier for a certain source
+//!
+//! For implementations of `Source` trait, see [`crate::sources`].
+
use std::collections::hash_map::HashMap;
use std::fmt;
use std::task::Poll;
@@ -10,25 +25,48 @@ mod source_id;
pub use self::source_id::{GitReference, SourceId};
-/// Something that finds and downloads remote packages based on names and versions.
+/// An abstraction of different sources of Cargo packages.
+///
+/// The [`Source`] trait generalizes the API to interact with these providers.
+/// For example,
+///
+/// * [`Source::query`] is for querying package metadata on a given
+/// [`Dependency`] requested by a Cargo manifest.
+/// * [`Source::download`] is for fetching the full package information on
+/// given names and versions.
+/// * [`Source::source_id`] is for defining an unique identifier of a source to
+/// distinguish one source from another, keeping Cargo safe from [dependency
+/// confusion attack].
+///
+/// Normally, developers don't need to implement their own [`Source`]s. Cargo
+/// provides several kinds of sources implementations that should cover almost
+/// all use cases. See [`crate::sources`] for implementations provided by Cargo.
+///
+/// [dependency confusion attack]: https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610
pub trait Source {
- /// Returns the `SourceId` corresponding to this source.
+ /// Returns the [`SourceId`] corresponding to this source.
fn source_id(&self) -> SourceId;
- /// Returns the replaced `SourceId` corresponding to this source.
+ /// Returns the replaced [`SourceId`] corresponding to this source.
fn replaced_source_id(&self) -> SourceId {
self.source_id()
}
- /// Returns whether or not this source will return summaries with
+ /// Returns whether or not this source will return [`Summary`] items with
/// checksums listed.
fn supports_checksums(&self) -> bool;
- /// Returns whether or not this source will return summaries with
- /// the `precise` field in the source id listed.
+ /// Returns whether or not this source will return [`Summary`] items with
+ /// the `precise` field in the [`SourceId`] listed.
fn requires_precise(&self) -> bool;
/// Attempts to find the packages that match a dependency request.
+ ///
+ /// Usually you should call [`Source::block_until_ready`] somewhere and
+ /// wait until package informations become available. Otherwise any query
+ /// may return a [`Poll::Pending`].
+ ///
+ /// The `f` argument is expected to get called when any [`Summary`] becomes available.
fn query(
&mut self,
dep: &Dependency,
@@ -36,6 +74,8 @@ pub trait Source {
f: &mut dyn FnMut(Summary),
) -> Poll<CargoResult<()>>;
+ /// Gathers the result from [`Source::query`] as a list of [`Summary`] items
+ /// when they become available.
fn query_vec(&mut self, dep: &Dependency, kind: QueryKind) -> Poll<CargoResult<Vec<Summary>>> {
let mut ret = Vec::new();
self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|_| ret)
@@ -50,6 +90,7 @@ pub trait Source {
/// Fetches the full package for each name and version specified.
fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage>;
+ /// Fetches the full package **immediately** for each name and version specified.
fn download_now(self: Box<Self>, package: PackageId, config: &Config) -> CargoResult<Package>
where
Self: std::marker::Sized,
@@ -61,7 +102,8 @@ pub trait Source {
Ok(Package::clone(pkg))
}
- fn finish_download(&mut self, package: PackageId, contents: Vec<u8>) -> CargoResult<Package>;
+ /// Finalizes the download contents of the given [`PackageId`] to a [`Package`].
+ fn finish_download(&mut self, pkg_id: PackageId, contents: Vec<u8>) -> CargoResult<Package>;
/// Generates a unique string which represents the fingerprint of the
/// current state of the source.
@@ -103,56 +145,67 @@ pub trait Source {
/// as yanked. This ignores the yanked whitelist.
fn is_yanked(&mut self, _pkg: PackageId) -> Poll<CargoResult<bool>>;
- /// Block until all outstanding Poll::Pending requests are `Poll::Ready`.
+ /// Block until all outstanding [`Poll::Pending`] requests are [`Poll::Ready`].
///
/// After calling this function, the source should return `Poll::Ready` for
/// any queries that previously returned `Poll::Pending`.
///
- /// If no queries previously returned `Poll::Pending`, and `invalidate_cache`
+ /// If no queries previously returned `Poll::Pending`, and [`Source::invalidate_cache`]
/// was not called, this function should be a no-op.
fn block_until_ready(&mut self) -> CargoResult<()>;
}
+/// Defines how a dependency query will be performed for a [`Source`].
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum QueryKind {
+ /// A query for packages exactly matching the given dependency requirement.
+ ///
+ /// Each source gets to define what `exact` means for it.
Exact,
+ /// A query for packages close to the given dependency requirement.
+ ///
/// Each source gets to define what `close` means for it.
+ ///
/// Path/Git sources may return all dependencies that are at that URI,
- /// whereas an `Index` source may return dependencies that have the same canonicalization.
+ /// whereas an `Registry` source may return dependencies that have the same
+ /// canonicalization.
Fuzzy,
}
+/// A download status that represents if a [`Package`] has already been
+/// downloaded, or if not then a location to download.
pub enum MaybePackage {
+ /// The [`Package`] is already downloaded.
Ready(Package),
+ /// Not yet downloaded. Here is the URL to download the [`Package`] from.
Download {
+ /// URL to download the content.
url: String,
+ /// Text to display to the user of what is being downloaded.
descriptor: String,
+ /// Authorization data that may be required to attach when downloading.
authorization: Option<String>,
},
}
+/// A blanket implementation forwards all methods to [`Source`].
impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
- /// Forwards to `Source::source_id`.
fn source_id(&self) -> SourceId {
(**self).source_id()
}
- /// Forwards to `Source::replaced_source_id`.
fn replaced_source_id(&self) -> SourceId {
(**self).replaced_source_id()
}
- /// Forwards to `Source::supports_checksums`.
fn supports_checksums(&self) -> bool {
(**self).supports_checksums()
}
- /// Forwards to `Source::requires_precise`.
fn requires_precise(&self) -> bool {
(**self).requires_precise()
}
- /// Forwards to `Source::query`.
fn query(
&mut self,
dep: &Dependency,
@@ -170,7 +223,6 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
(**self).set_quiet(quiet)
}
- /// Forwards to `Source::download`.
fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
(**self).download(id)
}
@@ -179,12 +231,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
(**self).finish_download(id, data)
}
- /// Forwards to `Source::fingerprint`.
fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
(**self).fingerprint(pkg)
}
- /// Forwards to `Source::verify`.
fn verify(&self, pkg: PackageId) -> CargoResult<()> {
(**self).verify(pkg)
}
@@ -210,6 +260,7 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
}
}
+/// A blanket implementation forwards all methods to [`Source`].
impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
fn source_id(&self) -> SourceId {
(**self).source_id()
@@ -281,7 +332,7 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
}
}
-/// A `HashMap` of `SourceId` -> `Box<Source>`.
+/// A [`HashMap`] of [`SourceId`] to `Box<Source>`.
#[derive(Default)]
pub struct SourceMap<'src> {
map: HashMap<SourceId, Box<dyn Source + 'src>>,
@@ -313,7 +364,7 @@ impl<'src> SourceMap<'src> {
self.map.get_mut(&id).map(|s| s.as_mut())
}
- /// Like `HashMap::insert`, but derives the `SourceId` key from the `Source`.
+ /// Like `HashMap::insert`, but derives the [`SourceId`] key from the [`Source`].
pub fn insert(&mut self, source: Box<dyn Source + 'src>) {
let id = source.source_id();
self.map.insert(id, source);
diff --git a/src/tools/cargo/src/cargo/core/source/source_id.rs b/src/tools/cargo/src/cargo/core/source/source_id.rs
index 034d7ed59..c369dab16 100644
--- a/src/tools/cargo/src/cargo/core/source/source_id.rs
+++ b/src/tools/cargo/src/cargo/core/source/source_id.rs
@@ -20,16 +20,31 @@ lazy_static::lazy_static! {
}
/// Unique identifier for a source of packages.
+///
+/// Cargo uniquely identifies packages using [`PackageId`], a combination of the
+/// package name, version, and the code source. `SourceId` exactly represents
+/// the "code source" in `PackageId`. See [`SourceId::hash`] to learn what are
+/// taken into account for the uniqueness of a source.
+///
+/// `SourceId` is usually associated with an instance of [`Source`], which is
+/// supposed to provide a `SourceId` via [`Source::source_id`] method.
+///
+/// [`Source`]: super::Source
+/// [`Source::source_id`]: super::Source::source_id
+/// [`PackageId`]: super::super::PackageId
#[derive(Clone, Copy, Eq, Debug)]
pub struct SourceId {
inner: &'static SourceIdInner,
}
+/// The interned version of [`SourceId`] to avoid excessive clones and borrows.
+/// Values are cached in `SOURCE_ID_CACHE` once created.
#[derive(Eq, Clone, Debug)]
struct SourceIdInner {
/// The source URL.
url: Url,
- /// The canonical version of the above url
+ /// The canonical version of the above url. See [`CanonicalUrl`] to learn
+ /// why it is needed and how it normalizes a URL.
canonical_url: CanonicalUrl,
/// The source kind.
kind: SourceKind,
@@ -45,8 +60,8 @@ struct SourceIdInner {
alt_registry_key: Option<String>,
}
-/// The possible kinds of code source. Along with `SourceIdInner`, this fully defines the
-/// source.
+/// The possible kinds of code source.
+/// Along with [`SourceIdInner`], this fully defines the source.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum SourceKind {
/// A git repository.
@@ -70,7 +85,8 @@ pub enum GitReference {
Tag(String),
/// From a branch.
Branch(String),
- /// From a specific revision.
+ /// From a specific revision. Can be a commit hash (either short or full),
+ /// or a named reference like `refs/pull/493/head`.
Rev(String),
/// The default branch of the repository, the reference named `HEAD`.
DefaultBranch,
@@ -100,6 +116,7 @@ impl SourceId {
Ok(source_id)
}
+ /// Interns the value and returns the wrapped type.
fn wrap(inner: SourceIdInner) -> SourceId {
let mut cache = SOURCE_ID_CACHE.lock().unwrap();
let inner = cache.get(&inner).cloned().unwrap_or_else(|| {
@@ -172,7 +189,7 @@ impl SourceId {
}
}
- /// A view of the `SourceId` that can be `Display`ed as a URL.
+ /// A view of the [`SourceId`] that can be `Display`ed as a URL.
pub fn as_url(&self) -> SourceIdAsUrl<'_> {
SourceIdAsUrl {
inner: &*self.inner,
@@ -208,7 +225,7 @@ impl SourceId {
SourceId::new(kind, url.to_owned(), Some(name))
}
- /// Creates a SourceId from a local registry path.
+ /// Creates a `SourceId` from a local registry path.
pub fn for_local_registry(path: &Path) -> CargoResult<SourceId> {
let url = path.into_url()?;
SourceId::new(SourceKind::LocalRegistry, url, None)
@@ -287,6 +304,7 @@ impl SourceId {
&self.inner.canonical_url
}
+ /// Displays the text "crates.io index" for Cargo shell status output.
pub fn display_index(self) -> String {
if self.is_crates_io() {
format!("{} index", CRATES_IO_DOMAIN)
@@ -295,6 +313,7 @@ impl SourceId {
}
}
+ /// Displays the name of a registry if it has one. Otherwise just the URL.
pub fn display_registry_name(self) -> String {
if self.is_crates_io() {
CRATES_IO_REGISTRY.to_string()
@@ -360,6 +379,8 @@ impl SourceId {
}
/// Creates an implementation of `Source` corresponding to this ID.
+ ///
+ /// * `yanked_whitelist` --- Packages allowed to be used, even if they are yanked.
pub fn load<'a>(
self,
config: &'a Config,
@@ -434,7 +455,7 @@ impl SourceId {
/// Hashes `self`.
///
/// For paths, remove the workspace prefix so the same source will give the
- /// same hash in different locations.
+ /// same hash in different locations, helping reproducible builds.
pub fn stable_hash<S: hash::Hasher>(self, workspace: &Path, into: &mut S) {
if self.is_path() {
if let Ok(p) = self
@@ -563,9 +584,9 @@ impl fmt::Display for SourceId {
}
}
-// The hash of SourceId is used in the name of some Cargo folders, so shouldn't
-// vary. `as_str` gives the serialisation of a url (which has a spec) and so
-// insulates against possible changes in how the url crate does hashing.
+/// The hash of SourceId is used in the name of some Cargo folders, so shouldn't
+/// vary. `as_str` gives the serialisation of a url (which has a spec) and so
+/// insulates against possible changes in how the url crate does hashing.
impl Hash for SourceId {
fn hash<S: hash::Hasher>(&self, into: &mut S) {
self.inner.kind.hash(into);
@@ -576,13 +597,14 @@ impl Hash for SourceId {
}
}
+/// The hash of `SourceIdInner` is used to retrieve its interned value from
+/// `SOURCE_ID_CACHE`. We only care about fields that make `SourceIdInner`
+/// unique. Optional fields not affecting the uniqueness must be excluded,
+/// such as [`name`] and [`alt_registry_key`]. That's why this is not derived.
+///
+/// [`name`]: SourceIdInner::name
+/// [`alt_registry_key`]: SourceIdInner::alt_registry_key
impl Hash for SourceIdInner {
- /// The hash of `SourceIdInner` is used to retrieve its interned value. We
- /// only care about fields that make `SourceIdInner` unique, which are:
- ///
- /// - `kind`
- /// - `precise`
- /// - `canonical_url`
fn hash<S: hash::Hasher>(&self, into: &mut S) {
self.kind.hash(into);
self.precise.hash(into);
@@ -590,8 +612,8 @@ impl Hash for SourceIdInner {
}
}
+/// This implementation must be synced with [`SourceIdInner::hash`].
impl PartialEq for SourceIdInner {
- /// This implementation must be synced with [`SourceIdInner::hash`].
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind
&& self.precise == other.precise
@@ -599,66 +621,66 @@ impl PartialEq for SourceIdInner {
}
}
-// forward to `Ord`
+/// Forwards to `Ord`
impl PartialOrd for SourceKind {
fn partial_cmp(&self, other: &SourceKind) -> Option<Ordering> {
Some(self.cmp(other))
}
}
-// Note that this is specifically not derived on `SourceKind` although the
-// implementation here is very similar to what it might look like if it were
-// otherwise derived.
-//
-// The reason for this is somewhat obtuse. First of all the hash value of
-// `SourceKind` makes its way into `~/.cargo/registry/index/github.com-XXXX`
-// which means that changes to the hash means that all Rust users need to
-// redownload the crates.io index and all their crates. If possible we strive to
-// not change this to make this redownloading behavior happen as little as
-// possible. How is this connected to `Ord` you might ask? That's a good
-// question!
-//
-// Since the beginning of time `SourceKind` has had `#[derive(Hash)]`. It for
-// the longest time *also* derived the `Ord` and `PartialOrd` traits. In #8522,
-// however, the implementation of `Ord` changed. This handwritten implementation
-// forgot to sync itself with the originally derived implementation, namely
-// placing git dependencies as sorted after all other dependencies instead of
-// first as before.
-//
-// This regression in #8522 (Rust 1.47) went unnoticed. When we switched back
-// to a derived implementation in #9133 (Rust 1.52 beta) we only then ironically
-// saw an issue (#9334). In #9334 it was observed that stable Rust at the time
-// (1.51) was sorting git dependencies last, whereas Rust 1.52 beta would sort
-// git dependencies first. This is because the `PartialOrd` implementation in
-// 1.51 used #8522, the buggy implementation, which put git deps last. In 1.52
-// it was (unknowingly) restored to the pre-1.47 behavior with git dependencies
-// first.
-//
-// Because the breakage was only witnessed after the original breakage, this
-// trait implementation is preserving the "broken" behavior. Put a different way:
-//
-// * Rust pre-1.47 sorted git deps first.
-// * Rust 1.47 to Rust 1.51 sorted git deps last, a breaking change (#8522) that
-// was never noticed.
-// * Rust 1.52 restored the pre-1.47 behavior (#9133, without knowing it did
-// so), and breakage was witnessed by actual users due to difference with
-// 1.51.
-// * Rust 1.52 (the source as it lives now) was fixed to match the 1.47-1.51
-// behavior (#9383), which is now considered intentionally breaking from the
-// pre-1.47 behavior.
-//
-// Note that this was all discovered when Rust 1.53 was in nightly and 1.52 was
-// in beta. #9133 was in both beta and nightly at the time of discovery. For
-// 1.52 #9383 reverted #9133, meaning 1.52 is the same as 1.51. On nightly
-// (1.53) #9397 was created to fix the regression introduced by #9133 relative
-// to the current stable (1.51).
-//
-// That's all a long winded way of saying "it's weird that git deps hash first
-// and are sorted last, but it's the way it is right now". The author of this
-// comment chose to handwrite the `Ord` implementation instead of the `Hash`
-// implementation, but it's only required that at most one of them is
-// hand-written because the other can be derived. Perhaps one day in
-// the future someone can figure out how to remove this behavior.
+/// Note that this is specifically not derived on `SourceKind` although the
+/// implementation here is very similar to what it might look like if it were
+/// otherwise derived.
+///
+/// The reason for this is somewhat obtuse. First of all the hash value of
+/// `SourceKind` makes its way into `~/.cargo/registry/index/github.com-XXXX`
+/// which means that changes to the hash means that all Rust users need to
+/// redownload the crates.io index and all their crates. If possible we strive
+/// to not change this to make this redownloading behavior happen as little as
+/// possible. How is this connected to `Ord` you might ask? That's a good
+/// question!
+///
+/// Since the beginning of time `SourceKind` has had `#[derive(Hash)]`. It for
+/// the longest time *also* derived the `Ord` and `PartialOrd` traits. In #8522,
+/// however, the implementation of `Ord` changed. This handwritten implementation
+/// forgot to sync itself with the originally derived implementation, namely
+/// placing git dependencies as sorted after all other dependencies instead of
+/// first as before.
+///
+/// This regression in #8522 (Rust 1.47) went unnoticed. When we switched back
+/// to a derived implementation in #9133 (Rust 1.52 beta) we only then ironically
+/// saw an issue (#9334). In #9334 it was observed that stable Rust at the time
+/// (1.51) was sorting git dependencies last, whereas Rust 1.52 beta would sort
+/// git dependencies first. This is because the `PartialOrd` implementation in
+/// 1.51 used #8522, the buggy implementation, which put git deps last. In 1.52
+/// it was (unknowingly) restored to the pre-1.47 behavior with git dependencies
+/// first.
+///
+/// Because the breakage was only witnessed after the original breakage, this
+/// trait implementation is preserving the "broken" behavior. Put a different way:
+///
+/// * Rust pre-1.47 sorted git deps first.
+/// * Rust 1.47 to Rust 1.51 sorted git deps last, a breaking change (#8522) that
+/// was never noticed.
+/// * Rust 1.52 restored the pre-1.47 behavior (#9133, without knowing it did
+/// so), and breakage was witnessed by actual users due to difference with
+/// 1.51.
+/// * Rust 1.52 (the source as it lives now) was fixed to match the 1.47-1.51
+/// behavior (#9383), which is now considered intentionally breaking from the
+/// pre-1.47 behavior.
+///
+/// Note that this was all discovered when Rust 1.53 was in nightly and 1.52 was
+/// in beta. #9133 was in both beta and nightly at the time of discovery. For
+/// 1.52 #9383 reverted #9133, meaning 1.52 is the same as 1.51. On nightly
+/// (1.53) #9397 was created to fix the regression introduced by #9133 relative
+/// to the current stable (1.51).
+///
+/// That's all a long winded way of saying "it's weird that git deps hash first
+/// and are sorted last, but it's the way it is right now". The author of this
+/// comment chose to handwrite the `Ord` implementation instead of the `Hash`
+/// implementation, but it's only required that at most one of them is
+/// hand-written because the other can be derived. Perhaps one day in
+/// the future someone can figure out how to remove this behavior.
impl Ord for SourceKind {
fn cmp(&self, other: &SourceKind) -> Ordering {
match (self, other) {
diff --git a/src/tools/cargo/src/cargo/core/summary.rs b/src/tools/cargo/src/cargo/core/summary.rs
index 8a7238e4a..2535c4482 100644
--- a/src/tools/cargo/src/cargo/core/summary.rs
+++ b/src/tools/cargo/src/cargo/core/summary.rs
@@ -25,6 +25,7 @@ struct Inner {
features: Rc<FeatureMap>,
checksum: Option<String>,
links: Option<InternedString>,
+ rust_version: Option<InternedString>,
}
impl Summary {
@@ -34,6 +35,7 @@ impl Summary {
dependencies: Vec<Dependency>,
features: &BTreeMap<InternedString, Vec<InternedString>>,
links: Option<impl Into<InternedString>>,
+ rust_version: Option<impl Into<InternedString>>,
) -> CargoResult<Summary> {
// ****CAUTION**** If you change anything here that may raise a new
// error, be sure to coordinate that change with either the index
@@ -55,6 +57,7 @@ impl Summary {
features: Rc::new(feature_map),
checksum: None,
links: links.map(|l| l.into()),
+ rust_version: rust_version.map(|l| l.into()),
}),
})
}
@@ -85,6 +88,10 @@ impl Summary {
self.inner.links
}
+ pub fn rust_version(&self) -> Option<InternedString> {
+ self.inner.rust_version
+ }
+
pub fn override_id(mut self, id: PackageId) -> Summary {
Rc::make_mut(&mut self.inner).package_id = id;
self
diff --git a/src/tools/cargo/src/cargo/core/workspace.rs b/src/tools/cargo/src/cargo/core/workspace.rs
index 12b78a69c..9922d6d33 100644
--- a/src/tools/cargo/src/cargo/core/workspace.rs
+++ b/src/tools/cargo/src/cargo/core/workspace.rs
@@ -19,9 +19,9 @@ use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec};
use crate::core::{EitherManifest, Package, SourceId, VirtualManifest};
use crate::ops;
use crate::sources::{PathSource, CRATES_IO_INDEX, CRATES_IO_REGISTRY};
+use crate::util::edit_distance;
use crate::util::errors::{CargoResult, ManifestError};
use crate::util::interning::InternedString;
-use crate::util::lev_distance;
use crate::util::toml::{read_manifest, InheritableFields, TomlDependency, TomlProfiles};
use crate::util::{config::ConfigRelativePath, Config, Filesystem, IntoUrl};
use cargo_util::paths;
@@ -1245,8 +1245,9 @@ impl<'cfg> Workspace<'cfg> {
optional_dependency_names_per_member.insert(member, optional_dependency_names_raw);
}
- let levenshtein_test =
- |a: InternedString, b: InternedString| lev_distance(a.as_str(), b.as_str()) < 4;
+ let edit_distance_test = |a: InternedString, b: InternedString| {
+ edit_distance(a.as_str(), b.as_str(), 3).is_some()
+ };
let suggestions: Vec<_> = cli_features
.features
@@ -1257,12 +1258,12 @@ impl<'cfg> Workspace<'cfg> {
// Finds member features which are similar to the requested feature.
let summary_features = summary_features
.iter()
- .filter(move |feature| levenshtein_test(**feature, *typo));
+ .filter(move |feature| edit_distance_test(**feature, *typo));
// Finds optional dependencies which name is similar to the feature
let optional_dependency_features = optional_dependency_names
.iter()
- .filter(move |feature| levenshtein_test(**feature, *typo));
+ .filter(move |feature| edit_distance_test(**feature, *typo));
summary_features
.chain(optional_dependency_features)
@@ -1278,13 +1279,13 @@ impl<'cfg> Workspace<'cfg> {
// Finds set of `pkg/feat` that are very similar to current `pkg/feat`.
let pkg_feat_similar = dependencies_features
.iter()
- .filter(|(name, _)| levenshtein_test(**name, *dep_name))
+ .filter(|(name, _)| edit_distance_test(**name, *dep_name))
.map(|(name, features)| {
(
name,
features
.iter()
- .filter(|feature| levenshtein_test(**feature, *dep_feature))
+ .filter(|feature| edit_distance_test(**feature, *dep_feature))
.collect::<Vec<_>>(),
)
})
@@ -1298,12 +1299,12 @@ impl<'cfg> Workspace<'cfg> {
// Finds set of `member/optional_dep` features which name is similar to current `pkg/feat`.
let optional_dependency_features = optional_dependency_names_per_member
.iter()
- .filter(|(package, _)| levenshtein_test(package.name(), *dep_name))
+ .filter(|(package, _)| edit_distance_test(package.name(), *dep_name))
.map(|(package, optional_dependencies)| {
optional_dependencies
.into_iter()
.filter(|optional_dependency| {
- levenshtein_test(**optional_dependency, *dep_name)
+ edit_distance_test(**optional_dependency, *dep_name)
})
.map(move |optional_dependency| {
format!("{}/{}", package.name(), optional_dependency)
@@ -1314,12 +1315,12 @@ impl<'cfg> Workspace<'cfg> {
// Finds set of `member/feat` features which name is similar to current `pkg/feat`.
let summary_features = summary_features_per_member
.iter()
- .filter(|(package, _)| levenshtein_test(package.name(), *dep_name))
+ .filter(|(package, _)| edit_distance_test(package.name(), *dep_name))
.map(|(package, summary_features)| {
summary_features
.into_iter()
.filter(|summary_feature| {
- levenshtein_test(**summary_feature, *dep_feature)
+ edit_distance_test(**summary_feature, *dep_feature)
})
.map(move |summary_feature| {
format!("{}/{}", package.name(), summary_feature)
diff --git a/src/tools/cargo/src/cargo/lib.rs b/src/tools/cargo/src/cargo/lib.rs
index f4c671fd3..31d03ad25 100644
--- a/src/tools/cargo/src/cargo/lib.rs
+++ b/src/tools/cargo/src/cargo/lib.rs
@@ -37,7 +37,7 @@
//! - [`core::compiler`]:
//! This is the code responsible for running `rustc` and `rustdoc`.
//! - [`core::compiler::build_context`]:
-//! The [`BuildContext`]['core::compiler::BuildContext] is the result of the "front end" of the
+//! The [`BuildContext`][core::compiler::BuildContext] is the result of the "front end" of the
//! build process. This contains the graph of work to perform and any settings necessary for
//! `rustc`. After this is built, the next stage of building is handled in
//! [`Context`][core::compiler::Context].
@@ -86,7 +86,7 @@
//! - [`cargo-test-macro`](https://github.com/rust-lang/cargo/tree/master/crates/cargo-test-macro)
//! ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo_test_macro/index.html)):
//! This is the `#[cargo_test]` proc-macro used by the test suite to define tests.
-//! - [`credential`](https://github.com/rust-lang/cargo/tree/master/crates/credential)
+//! - [`credential`](https://github.com/rust-lang/cargo/tree/master/credential)
//! This subdirectory contains several packages for implementing the
//! experimental
//! [credential-process](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process)
diff --git a/src/tools/cargo/src/cargo/ops/cargo_add/mod.rs b/src/tools/cargo/src/cargo/ops/cargo_add/mod.rs
index 5c519ac09..11ca282ee 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_add/mod.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_add/mod.rs
@@ -51,6 +51,8 @@ pub struct AddOptions<'a> {
pub section: DepTable,
/// Act as if dependencies will be added
pub dry_run: bool,
+ /// Whether the minimum supported Rust version should be considered during resolution
+ pub honor_rust_version: bool,
}
/// Add dependencies to a manifest
@@ -86,7 +88,9 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<(
&manifest,
raw,
workspace,
+ &options.spec,
&options.section,
+ options.honor_rust_version,
options.config,
&mut registry,
)
@@ -256,7 +260,9 @@ fn resolve_dependency(
manifest: &LocalManifest,
arg: &DepOp,
ws: &Workspace<'_>,
+ spec: &Package,
section: &DepTable,
+ honor_rust_version: bool,
config: &Config,
registry: &mut PackageRegistry<'_>,
) -> CargoResult<DependencyUI> {
@@ -368,7 +374,14 @@ fn resolve_dependency(
}
dependency = dependency.set_source(src);
} else {
- let latest = get_latest_dependency(&dependency, false, config, registry)?;
+ let latest = get_latest_dependency(
+ spec,
+ &dependency,
+ false,
+ honor_rust_version,
+ config,
+ registry,
+ )?;
if dependency.name != latest.name {
config.shell().warn(format!(
@@ -518,8 +531,10 @@ fn get_existing_dependency(
}
fn get_latest_dependency(
+ spec: &Package,
dependency: &Dependency,
_flag_allow_prerelease: bool,
+ honor_rust_version: bool,
config: &Config,
registry: &mut PackageRegistry<'_>,
) -> CargoResult<Dependency> {
@@ -529,7 +544,7 @@ fn get_latest_dependency(
unreachable!("registry dependencies required, found a workspace dependency");
}
MaybeWorkspace::Other(query) => {
- let possibilities = loop {
+ let mut possibilities = loop {
match registry.query_vec(&query, QueryKind::Fuzzy) {
std::task::Poll::Ready(res) => {
break res?;
@@ -537,19 +552,79 @@ fn get_latest_dependency(
std::task::Poll::Pending => registry.block_until_ready()?,
}
};
- let latest = possibilities
- .iter()
- .max_by_key(|s| {
- // Fallback to a pre-release if no official release is available by sorting them as
- // less.
- let stable = s.version().pre.is_empty();
- (stable, s.version())
- })
- .ok_or_else(|| {
- anyhow::format_err!(
- "the crate `{dependency}` could not be found in registry index."
- )
- })?;
+
+ possibilities.sort_by_key(|s| {
+ // Fallback to a pre-release if no official release is available by sorting them as
+ // less.
+ let stable = s.version().pre.is_empty();
+ (stable, s.version().clone())
+ });
+
+ let mut latest = possibilities.last().ok_or_else(|| {
+ anyhow::format_err!(
+ "the crate `{dependency}` could not be found in registry index."
+ )
+ })?;
+
+ if config.cli_unstable().msrv_policy && honor_rust_version {
+ fn parse_msrv(rust_version: impl AsRef<str>) -> (u64, u64, u64) {
+ // HACK: `rust-version` is a subset of the `VersionReq` syntax that only ever
+ // has one comparator with a required minor and optional patch, and uses no
+ // other features. If in the future this syntax is expanded, this code will need
+ // to be updated.
+ let version_req = semver::VersionReq::parse(rust_version.as_ref()).unwrap();
+ assert!(version_req.comparators.len() == 1);
+ let comp = &version_req.comparators[0];
+ assert_eq!(comp.op, semver::Op::Caret);
+ assert_eq!(comp.pre, semver::Prerelease::EMPTY);
+ (comp.major, comp.minor.unwrap_or(0), comp.patch.unwrap_or(0))
+ }
+
+ if let Some(req_msrv) = spec.rust_version().map(parse_msrv) {
+ let msrvs = possibilities
+ .iter()
+ .map(|s| (s, s.rust_version().map(parse_msrv)))
+ .collect::<Vec<_>>();
+
+ // Find the latest version of the dep which has a compatible rust-version. To
+ // determine whether or not one rust-version is compatible with another, we
+ // compare the lowest possible versions they could represent, and treat
+ // candidates without a rust-version as compatible by default.
+ let (latest_msrv, _) = msrvs
+ .iter()
+ .filter(|(_, v)| v.map(|msrv| req_msrv >= msrv).unwrap_or(true))
+ .last()
+ .ok_or_else(|| {
+ // Failing that, try to find the highest version with the lowest
+ // rust-version to report to the user.
+ let lowest_candidate = msrvs
+ .iter()
+ .min_set_by_key(|(_, v)| v)
+ .iter()
+ .map(|(s, _)| s)
+ .max_by_key(|s| s.version());
+ rust_version_incompat_error(
+ &dependency.name,
+ spec.rust_version().unwrap(),
+ lowest_candidate.copied(),
+ )
+ })?;
+
+ if latest_msrv.version() < latest.version() {
+ config.shell().warn(format_args!(
+ "ignoring `{dependency}@{latest_version}` (which has a rust-version of \
+ {latest_rust_version}) to satisfy this package's rust-version of \
+ {rust_version} (use `--ignore-rust-version` to override)",
+ latest_version = latest.version(),
+ latest_rust_version = latest.rust_version().unwrap(),
+ rust_version = spec.rust_version().unwrap(),
+ ))?;
+
+ latest = latest_msrv;
+ }
+ }
+ }
+
let mut dep = Dependency::from(latest);
if let Some(reg_name) = dependency.registry.as_deref() {
dep = dep.set_registry(reg_name);
@@ -559,6 +634,31 @@ fn get_latest_dependency(
}
}
+fn rust_version_incompat_error(
+ dep: &str,
+ rust_version: &str,
+ lowest_rust_version: Option<&Summary>,
+) -> anyhow::Error {
+ let mut error_msg = format!(
+ "could not find version of crate `{dep}` that satisfies this package's rust-version of \
+ {rust_version}\n\
+ help: use `--ignore-rust-version` to override this behavior"
+ );
+
+ if let Some(lowest) = lowest_rust_version {
+ // rust-version must be present for this candidate since it would have been selected as
+ // compatible previously if it weren't.
+ let version = lowest.version();
+ let rust_version = lowest.rust_version().unwrap();
+ error_msg.push_str(&format!(
+ "\nnote: the lowest rust-version available for `{dep}` is {rust_version}, used in \
+ version {version}"
+ ));
+ }
+
+ anyhow::format_err!(error_msg)
+}
+
fn select_package(
dependency: &Dependency,
config: &Config,
diff --git a/src/tools/cargo/src/cargo/ops/cargo_clean.rs b/src/tools/cargo/src/cargo/ops/cargo_clean.rs
index b3e1bf483..de3139c99 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_clean.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_clean.rs
@@ -2,9 +2,9 @@ use crate::core::compiler::{CompileKind, CompileMode, Layout, RustcTargetData};
use crate::core::profiles::Profiles;
use crate::core::{PackageIdSpec, TargetKind, Workspace};
use crate::ops;
+use crate::util::edit_distance;
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
-use crate::util::lev_distance;
use crate::util::{Config, Progress, ProgressStyle};
use anyhow::Context as _;
@@ -118,7 +118,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
let matches: Vec<_> = resolve.iter().filter(|id| spec.matches(*id)).collect();
if matches.is_empty() {
let mut suggestion = String::new();
- suggestion.push_str(&lev_distance::closest_msg(
+ suggestion.push_str(&edit_distance::closest_msg(
&spec.name(),
resolve.iter(),
|id| id.name().as_str(),
diff --git a/src/tools/cargo/src/cargo/ops/cargo_install.rs b/src/tools/cargo/src/cargo/ops/cargo_install.rs
index 53c3e72f7..5f843e8c7 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_install.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_install.rs
@@ -4,7 +4,9 @@ use std::sync::Arc;
use std::{env, fs};
use crate::core::compiler::{CompileKind, DefaultExecutor, Executor, UnitOutput};
-use crate::core::{Dependency, Edition, Package, PackageId, Source, SourceId, Target, Workspace};
+use crate::core::{
+ Dependency, Edition, Package, PackageId, PackageIdSpec, Source, SourceId, Target, Workspace,
+};
use crate::ops::{common_for_install_and_uninstall::*, FilterRule};
use crate::ops::{CompileFilter, Packages};
use crate::sources::{GitSource, PathSource, SourceConfigMap};
@@ -168,14 +170,8 @@ impl<'cfg, 'a> InstallablePackage<'cfg, 'a> {
}
};
- // When we build this package, we want to build the *specified* package only,
- // and avoid building e.g. workspace default-members instead. Do so by constructing
- // specialized compile options specific to the identified package.
- // See test `path_install_workspace_root_despite_default_members`.
- let mut opts = original_opts.clone();
- opts.spec = Packages::Packages(vec![pkg.name().to_string()]);
-
- let (ws, rustc, target) = make_ws_rustc_target(config, &opts, &source_id, pkg.clone())?;
+ let (ws, rustc, target) =
+ make_ws_rustc_target(config, &original_opts, &source_id, pkg.clone())?;
// If we're installing in --locked mode and there's no `Cargo.lock` published
// ie. the bin was published before https://github.com/rust-lang/cargo/pull/7026
if config.locked() && !ws.root().join("Cargo.lock").exists() {
@@ -192,6 +188,17 @@ impl<'cfg, 'a> InstallablePackage<'cfg, 'a> {
ws.current()?.clone()
};
+ // When we build this package, we want to build the *specified* package only,
+ // and avoid building e.g. workspace default-members instead. Do so by constructing
+ // specialized compile options specific to the identified package.
+ // See test `path_install_workspace_root_despite_default_members`.
+ let mut opts = original_opts.clone();
+ // For cargo install tracking, we retain the source git url in `pkg`, but for the build spec
+ // we need to unconditionally use `ws.current()` to correctly address the path where we
+ // locally cloned that repo.
+ let pkgidspec = PackageIdSpec::from_package_id(ws.current()?.package_id());
+ opts.spec = Packages::Packages(vec![pkgidspec.to_string()]);
+
if from_cwd {
if pkg.manifest().edition() == Edition::Edition2015 {
config.shell().warn(
diff --git a/src/tools/cargo/src/cargo/ops/cargo_new.rs b/src/tools/cargo/src/cargo/ops/cargo_new.rs
index caa1d2fa8..697798c0c 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_new.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_new.rs
@@ -1,5 +1,6 @@
use crate::core::{Edition, Shell, Workspace};
use crate::util::errors::CargoResult;
+use crate::util::important_paths::find_root_manifest_for_wd;
use crate::util::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo};
use crate::util::{restricted_names, Config};
use anyhow::{anyhow, Context as _};
@@ -759,69 +760,72 @@ fn mk(config: &Config, opts: &MkOptions<'_>) -> CargoResult<()> {
init_vcs(path, vcs, config)?;
write_ignore_file(path, &ignore, vcs)?;
- let mut cargotoml_path_specifier = String::new();
+ // Create `Cargo.toml` file with necessary `[lib]` and `[[bin]]` sections, if needed.
+ let mut manifest = toml_edit::Document::new();
+ manifest["package"] = toml_edit::Item::Table(toml_edit::Table::new());
+ manifest["package"]["name"] = toml_edit::value(name);
+ manifest["package"]["version"] = toml_edit::value("0.1.0");
+ let edition = match opts.edition {
+ Some(edition) => edition.to_string(),
+ None => Edition::LATEST_STABLE.to_string(),
+ };
+ manifest["package"]["edition"] = toml_edit::value(edition);
+ if let Some(registry) = opts.registry {
+ let mut array = toml_edit::Array::default();
+ array.push(registry);
+ manifest["package"]["publish"] = toml_edit::value(array);
+ }
+ let mut dep_table = toml_edit::Table::default();
+ dep_table.decor_mut().set_prefix("\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n");
+ manifest["dependencies"] = toml_edit::Item::Table(dep_table);
// Calculate what `[lib]` and `[[bin]]`s we need to append to `Cargo.toml`.
-
for i in &opts.source_files {
if i.bin {
if i.relative_path != "src/main.rs" {
- cargotoml_path_specifier.push_str(&format!(
- r#"
-[[bin]]
-name = "{}"
-path = {}
-"#,
- i.target_name,
- toml::Value::String(i.relative_path.clone())
- ));
+ let mut bin = toml_edit::Table::new();
+ bin["name"] = toml_edit::value(i.target_name.clone());
+ bin["path"] = toml_edit::value(i.relative_path.clone());
+ manifest["bin"]
+ .or_insert(toml_edit::Item::ArrayOfTables(
+ toml_edit::ArrayOfTables::new(),
+ ))
+ .as_array_of_tables_mut()
+ .expect("bin is an array of tables")
+ .push(bin);
}
} else if i.relative_path != "src/lib.rs" {
- cargotoml_path_specifier.push_str(&format!(
- r#"
-[lib]
-name = "{}"
-path = {}
-"#,
- i.target_name,
- toml::Value::String(i.relative_path.clone())
- ));
+ let mut lib = toml_edit::Table::new();
+ lib["name"] = toml_edit::value(i.target_name.clone());
+ lib["path"] = toml_edit::value(i.relative_path.clone());
+ manifest["lib"] = toml_edit::Item::Table(lib);
}
}
- // Create `Cargo.toml` file with necessary `[lib]` and `[[bin]]` sections, if needed.
+ let manifest_path = path.join("Cargo.toml");
+ if let Ok(root_manifest_path) = find_root_manifest_for_wd(&manifest_path) {
+ let root_manifest = paths::read(&root_manifest_path)?;
+ // Sometimes the root manifest is not a valid manifest, so we only try to parse it if it is.
+ // This should not block the creation of the new project. It is only a best effort to
+ // inherit the workspace package keys.
+ if let Ok(workspace_document) = root_manifest.parse::<toml_edit::Document>() {
+ if let Some(workspace_package_keys) = workspace_document
+ .get("workspace")
+ .and_then(|workspace| workspace.get("package"))
+ .and_then(|package| package.as_table())
+ {
+ update_manifest_with_inherited_workspace_package_keys(
+ opts,
+ &mut manifest,
+ workspace_package_keys,
+ )
+ }
+ }
+ }
- paths::write(
- &path.join("Cargo.toml"),
- format!(
- r#"[package]
-name = "{}"
-version = "0.1.0"
-edition = {}
-{}
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-{}"#,
- name,
- match opts.edition {
- Some(edition) => toml::Value::String(edition.to_string()),
- None => toml::Value::String(Edition::LATEST_STABLE.to_string()),
- },
- match opts.registry {
- Some(registry) => format!(
- "publish = {}\n",
- toml::Value::Array(vec!(toml::Value::String(registry.to_string())))
- ),
- None => "".to_string(),
- },
- cargotoml_path_specifier
- )
- .as_bytes(),
- )?;
+ paths::write(&manifest_path, manifest.to_string())?;
// Create all specified source files (with respective parent directories) if they don't exist.
-
for i in &opts.source_files {
let path_of_source_file = path.join(i.relative_path.clone());
@@ -878,3 +882,40 @@ mod tests {
Ok(())
}
+
+// Update the manifest with the inherited workspace package keys.
+// If the option is not set, the key is removed from the manifest.
+// If the option is set, keep the value from the manifest.
+fn update_manifest_with_inherited_workspace_package_keys(
+ opts: &MkOptions<'_>,
+ manifest: &mut toml_edit::Document,
+ workspace_package_keys: &toml_edit::Table,
+) {
+ if workspace_package_keys.is_empty() {
+ return;
+ }
+
+ let try_remove_and_inherit_package_key = |key: &str, manifest: &mut toml_edit::Document| {
+ let package = manifest["package"]
+ .as_table_mut()
+ .expect("package is a table");
+ package.remove(key);
+ let mut table = toml_edit::Table::new();
+ table.set_dotted(true);
+ table["workspace"] = toml_edit::value(true);
+ package.insert(key, toml_edit::Item::Table(table));
+ };
+
+ // Inherit keys from the workspace.
+ // Only keep the value from the manifest if the option is set.
+ for (key, _) in workspace_package_keys {
+ if key == "edition" && opts.edition.is_some() {
+ continue;
+ }
+ if key == "publish" && opts.registry.is_some() {
+ continue;
+ }
+
+ try_remove_and_inherit_package_key(key, manifest);
+ }
+}
diff --git a/src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs b/src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs
index 9d52fa09a..c0a63aa75 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs
@@ -43,6 +43,7 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo
Ok(ExportInfo {
packages,
workspace_members: ws.members().map(|pkg| pkg.package_id()).collect(),
+ workspace_default_members: ws.default_members().map(|pkg| pkg.package_id()).collect(),
resolve,
target_directory: ws.target_dir().into_path_unlocked(),
version: VERSION,
@@ -58,6 +59,7 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo
pub struct ExportInfo {
packages: Vec<SerializedPackage>,
workspace_members: Vec<PackageId>,
+ workspace_default_members: Vec<PackageId>,
resolve: Option<MetadataResolve>,
target_directory: PathBuf,
version: u32,
diff --git a/src/tools/cargo/src/cargo/ops/cargo_package.rs b/src/tools/cargo/src/cargo/ops/cargo_package.rs
index 35b213361..f80848c75 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_package.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_package.rs
@@ -281,7 +281,7 @@ fn build_ar_list(
if let Some(license_file) = &pkg.manifest().metadata().license_file {
let license_path = Path::new(license_file);
let abs_file_path = paths::normalize_path(&pkg.root().join(license_path));
- if abs_file_path.exists() {
+ if abs_file_path.is_file() {
check_for_file_and_add(
"license-file",
license_path,
@@ -291,26 +291,16 @@ fn build_ar_list(
ws,
)?;
} else {
- let rel_msg = if license_path.is_absolute() {
- "".to_string()
- } else {
- format!(" (relative to `{}`)", pkg.root().display())
- };
- ws.config().shell().warn(&format!(
- "license-file `{}` does not appear to exist{}.\n\
- Please update the license-file setting in the manifest at `{}`\n\
- This may become a hard error in the future.",
- license_path.display(),
- rel_msg,
- pkg.manifest_path().display()
- ))?;
+ warn_on_nonexistent_file(&pkg, &license_path, "license-file", &ws)?;
}
}
if let Some(readme) = &pkg.manifest().metadata().readme {
let readme_path = Path::new(readme);
let abs_file_path = paths::normalize_path(&pkg.root().join(readme_path));
- if abs_file_path.exists() {
+ if abs_file_path.is_file() {
check_for_file_and_add("readme", readme_path, abs_file_path, pkg, &mut result, ws)?;
+ } else {
+ warn_on_nonexistent_file(&pkg, &readme_path, "readme", &ws)?;
}
}
result.sort_unstable_by(|a, b| a.rel_path.cmp(&b.rel_path));
@@ -342,10 +332,7 @@ fn check_for_file_and_add(
Err(_) => {
// The file exists somewhere outside of the package.
let file_name = file_path.file_name().unwrap();
- if result
- .iter()
- .any(|ar| ar.rel_path.file_name().unwrap() == file_name)
- {
+ if result.iter().any(|ar| ar.rel_path == file_name) {
ws.config().shell().warn(&format!(
"{} `{}` appears to be a path outside of the package, \
but there is already a file named `{}` in the root of the package. \
@@ -369,6 +356,27 @@ fn check_for_file_and_add(
Ok(())
}
+fn warn_on_nonexistent_file(
+ pkg: &Package,
+ path: &Path,
+ manifest_key_name: &'static str,
+ ws: &Workspace<'_>,
+) -> CargoResult<()> {
+ let rel_msg = if path.is_absolute() {
+ "".to_string()
+ } else {
+ format!(" (relative to `{}`)", pkg.root().display())
+ };
+ ws.config().shell().warn(&format!(
+ "{manifest_key_name} `{}` does not appear to exist{}.\n\
+ Please update the {manifest_key_name} setting in the manifest at `{}`\n\
+ This may become a hard error in the future.",
+ path.display(),
+ rel_msg,
+ pkg.manifest_path().display()
+ ))
+}
+
/// Construct `Cargo.lock` for the package to be published.
fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult<String> {
let config = ws.config();
diff --git a/src/tools/cargo/src/cargo/ops/registry.rs b/src/tools/cargo/src/cargo/ops/registry.rs
index e04f7ba2c..a8efb5492 100644
--- a/src/tools/cargo/src/cargo/ops/registry.rs
+++ b/src/tools/cargo/src/cargo/ops/registry.rs
@@ -35,6 +35,7 @@ use crate::util::auth::{
use crate::util::config::{Config, SslVersionConfig, SslVersionConfigRange};
use crate::util::errors::CargoResult;
use crate::util::important_paths::find_root_manifest_for_wd;
+use crate::util::network;
use crate::util::{truncate_with_ellipsis, IntoUrl};
use crate::util::{Progress, ProgressStyle};
use crate::{drop_print, drop_println, version};
@@ -345,6 +346,7 @@ fn transmit(
ref categories,
ref badges,
ref links,
+ ref rust_version,
} = *manifest.metadata();
let readme_content = readme
.as_ref()
@@ -398,6 +400,7 @@ fn transmit(
license_file: license_file.clone(),
badges: badges.clone(),
links: links.clone(),
+ rust_version: rust_version.clone(),
},
tarball,
)
@@ -609,16 +612,22 @@ pub fn http_handle_and_timeout(config: &Config) -> CargoResult<(Easy, HttpTimeou
Ok((handle, timeout))
}
+// Only use a custom transport if any HTTP options are specified,
+// such as proxies or custom certificate authorities.
+//
+// The custom transport, however, is not as well battle-tested.
pub fn needs_custom_http_transport(config: &Config) -> CargoResult<bool> {
- Ok(http_proxy_exists(config)?
- || *config.http_config()? != Default::default()
- || config.get_env_os("HTTP_TIMEOUT").is_some())
+ Ok(
+ network::proxy::http_proxy_exists(config.http_config()?, config)
+ || *config.http_config()? != Default::default()
+ || config.get_env_os("HTTP_TIMEOUT").is_some(),
+ )
}
/// Configure a libcurl http handle with the defaults options for Cargo
pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<HttpTimeout> {
let http = config.http_config()?;
- if let Some(proxy) = http_proxy(config)? {
+ if let Some(proxy) = network::proxy::http_proxy(http) {
handle.proxy(&proxy)?;
}
if let Some(cainfo) = &http.cainfo {
@@ -702,12 +711,17 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<
InfoType::SslDataIn | InfoType::SslDataOut => return,
_ => return,
};
+ let starts_with_ignore_case = |line: &str, text: &str| -> bool {
+ line[..line.len().min(text.len())].eq_ignore_ascii_case(text)
+ };
match str::from_utf8(data) {
Ok(s) => {
for mut line in s.lines() {
- if line.starts_with("Authorization:") {
+ if starts_with_ignore_case(line, "authorization:") {
line = "Authorization: [REDACTED]";
- } else if line[..line.len().min(10)].eq_ignore_ascii_case("set-cookie") {
+ } else if starts_with_ignore_case(line, "h2h3 [authorization:") {
+ line = "h2h3 [Authorization: [REDACTED]]";
+ } else if starts_with_ignore_case(line, "set-cookie") {
line = "set-cookie: [REDACTED]";
}
log!(level, "http-debug: {} {}", prefix, line);
@@ -766,43 +780,6 @@ impl HttpTimeout {
}
}
-/// Finds an explicit HTTP proxy if one is available.
-///
-/// Favor cargo's `http.proxy`, then git's `http.proxy`. Proxies specified
-/// via environment variables are picked up by libcurl.
-fn http_proxy(config: &Config) -> CargoResult<Option<String>> {
- let http = config.http_config()?;
- if let Some(s) = &http.proxy {
- return Ok(Some(s.clone()));
- }
- if let Ok(cfg) = git2::Config::open_default() {
- if let Ok(s) = cfg.get_string("http.proxy") {
- return Ok(Some(s));
- }
- }
- Ok(None)
-}
-
-/// Determine if an http proxy exists.
-///
-/// Checks the following for existence, in order:
-///
-/// * cargo's `http.proxy`
-/// * git's `http.proxy`
-/// * `http_proxy` env var
-/// * `HTTP_PROXY` env var
-/// * `https_proxy` env var
-/// * `HTTPS_PROXY` env var
-fn http_proxy_exists(config: &Config) -> CargoResult<bool> {
- if http_proxy(config)?.is_some() {
- Ok(true)
- } else {
- Ok(["http_proxy", "HTTP_PROXY", "https_proxy", "HTTPS_PROXY"]
- .iter()
- .any(|v| config.get_env(v).is_ok()))
- }
-}
-
pub fn registry_login(
config: &Config,
token: Option<Secret<&str>>,
diff --git a/src/tools/cargo/src/cargo/ops/tree/graph.rs b/src/tools/cargo/src/cargo/ops/tree/graph.rs
index 20a9ca0b6..d01d07f1a 100644
--- a/src/tools/cargo/src/cargo/ops/tree/graph.rs
+++ b/src/tools/cargo/src/cargo/ops/tree/graph.rs
@@ -362,6 +362,10 @@ fn add_pkg(
if !opts.edge_kinds.contains(&EdgeKind::Dep(dep.kind())) {
return false;
}
+ // Filter out proc-macrcos if requested.
+ if opts.no_proc_macro && graph.package_for_id(dep_id).proc_macro() {
+ return false;
+ }
if dep.is_optional() {
// If the new feature resolver does not enable this
// optional dep, then don't use it.
diff --git a/src/tools/cargo/src/cargo/ops/tree/mod.rs b/src/tools/cargo/src/cargo/ops/tree/mod.rs
index 02459f78f..f397b95af 100644
--- a/src/tools/cargo/src/cargo/ops/tree/mod.rs
+++ b/src/tools/cargo/src/cargo/ops/tree/mod.rs
@@ -267,7 +267,6 @@ fn print(
opts.prefix,
opts.no_dedupe,
opts.max_display_depth,
- opts.no_proc_macro,
&mut visited_deps,
&mut levels_continue,
&mut print_stack,
@@ -288,7 +287,6 @@ fn print_node<'a>(
prefix: Prefix,
no_dedupe: bool,
max_display_depth: u32,
- no_proc_macro: bool,
visited_deps: &mut HashSet<usize>,
levels_continue: &mut Vec<bool>,
print_stack: &mut Vec<usize>,
@@ -348,7 +346,6 @@ fn print_node<'a>(
prefix,
no_dedupe,
max_display_depth,
- no_proc_macro,
visited_deps,
levels_continue,
print_stack,
@@ -369,7 +366,6 @@ fn print_dependencies<'a>(
prefix: Prefix,
no_dedupe: bool,
max_display_depth: u32,
- no_proc_macro: bool,
visited_deps: &mut HashSet<usize>,
levels_continue: &mut Vec<bool>,
print_stack: &mut Vec<usize>,
@@ -406,19 +402,6 @@ fn print_dependencies<'a>(
let mut it = deps
.iter()
.filter(|dep| {
- // Filter out proc-macro dependencies.
- if no_proc_macro {
- match graph.node(**dep) {
- &Node::Package { package_id, .. } => {
- !graph.package_for_id(package_id).proc_macro()
- }
- _ => true,
- }
- } else {
- true
- }
- })
- .filter(|dep| {
// Filter out packages to prune.
match graph.node(**dep) {
Node::Package { package_id, .. } => {
@@ -441,7 +424,6 @@ fn print_dependencies<'a>(
prefix,
no_dedupe,
max_display_depth,
- no_proc_macro,
visited_deps,
levels_continue,
print_stack,
diff --git a/src/tools/cargo/src/cargo/sources/config.rs b/src/tools/cargo/src/cargo/sources/config.rs
index 97a23a0b4..5d5a4e8db 100644
--- a/src/tools/cargo/src/cargo/sources/config.rs
+++ b/src/tools/cargo/src/cargo/sources/config.rs
@@ -1,4 +1,4 @@
-//! Implementation of configuration for various sources
+//! Implementation of configuration for various sources.
//!
//! This module will parse the various `source.*` TOML configuration keys into a
//! structure usable by Cargo itself. Currently this is primarily used to map
@@ -14,11 +14,12 @@ use log::debug;
use std::collections::{HashMap, HashSet};
use url::Url;
+/// Represents the entire `[source]` table in Cargo configuration.
#[derive(Clone)]
pub struct SourceConfigMap<'cfg> {
/// Mapping of source name to the toml configuration.
cfgs: HashMap<String, SourceConfig>,
- /// Mapping of `SourceId` to the source name.
+ /// Mapping of [`SourceId`] to the source name.
id2name: HashMap<SourceId, String>,
config: &'cfg Config,
}
@@ -67,6 +68,8 @@ struct SourceConfig {
}
impl<'cfg> SourceConfigMap<'cfg> {
+ /// Like [`SourceConfigMap::empty`] but includes sources from source
+ /// replacement configurations.
pub fn new(config: &'cfg Config) -> CargoResult<SourceConfigMap<'cfg>> {
let mut base = SourceConfigMap::empty(config)?;
let sources: Option<HashMap<String, SourceConfigDef>> = config.get("source")?;
@@ -78,6 +81,8 @@ impl<'cfg> SourceConfigMap<'cfg> {
Ok(base)
}
+ /// Creates the default set of sources that doesn't take `[source]`
+ /// replacement into account.
pub fn empty(config: &'cfg Config) -> CargoResult<SourceConfigMap<'cfg>> {
let mut base = SourceConfigMap {
cfgs: HashMap::new(),
@@ -112,11 +117,14 @@ impl<'cfg> SourceConfigMap<'cfg> {
Ok(base)
}
+ /// Returns the `Config` this source config map is associated with.
pub fn config(&self) -> &'cfg Config {
self.config
}
- /// Get the `Source` for a given `SourceId`.
+ /// Gets the [`Source`] for a given [`SourceId`].
+ ///
+ /// * `yanked_whitelist` --- Packages allowed to be used, even if they are yanked.
pub fn load(
&self,
id: SourceId,
@@ -208,6 +216,7 @@ restore the source replacement configuration to continue the build
Ok(Box::new(ReplacedSource::new(id, new_id, new_src)))
}
+ /// Adds a source config with an associated name.
fn add(&mut self, name: &str, cfg: SourceConfig) -> CargoResult<()> {
if let Some(old_name) = self.id2name.insert(cfg.id, name.to_string()) {
// The user is allowed to redefine the built-in crates-io
@@ -226,6 +235,7 @@ restore the source replacement configuration to continue the build
Ok(())
}
+ /// Adds a source config from TOML definition.
fn add_config(&mut self, name: String, def: SourceConfigDef) -> CargoResult<()> {
let mut srcs = Vec::new();
if let Some(registry) = def.registry {
diff --git a/src/tools/cargo/src/cargo/sources/directory.rs b/src/tools/cargo/src/cargo/sources/directory.rs
index 46acb9f86..a527c6dd7 100644
--- a/src/tools/cargo/src/cargo/sources/directory.rs
+++ b/src/tools/cargo/src/cargo/sources/directory.rs
@@ -13,17 +13,64 @@ use anyhow::Context as _;
use cargo_util::{paths, Sha256};
use serde::Deserialize;
+/// `DirectorySource` contains a number of crates on the file system. It was
+/// designed for representing vendored dependencies for `cargo vendor`.
+///
+/// `DirectorySource` at this moment is just a root directory containing other
+/// directories, which contain the source files of packages. Assumptions would
+/// be made to determine if a directory should be included as a package of a
+/// directory source's:
+///
+/// * Ignore directories starting with dot `.` (tend to be hidden).
+/// * Only when a `Cargo.toml` exists in a directory will it be included as
+/// a package. `DirectorySource` at this time only looks at one level of
+/// directories and never went deeper.
+/// * There must be a [`Checksum`] file `.cargo-checksum.json` file at the same
+/// level of `Cargo.toml` to ensure the integrity when a directory source was
+/// created (usually by `cargo vendor`). A failure to find or parse a single
+/// checksum results in a denial of loading any package in this source.
+/// * Otherwise, there is no other restrction of the name of directories. At
+/// this moment, it is `cargo vendor` that defines the layout and the name of
+/// each directory.
+///
+/// The file tree of a directory source may look like:
+///
+/// ```text
+/// [source root]
+/// ├── a-valid-crate/
+/// │ ├── src/
+/// │ ├── .cargo-checksum.json
+/// │ └── Cargo.toml
+/// ├── .ignored-a-dot-crate/
+/// │ ├── src/
+/// │ ├── .cargo-checksum.json
+/// │ └── Cargo.toml
+/// ├── skipped-no-manifest/
+/// │ ├── src/
+/// │ └── .cargo-checksum.json
+/// └── no-checksum-so-fails-the-entire-source-reading/
+/// └── Cargo.toml
+/// ```
pub struct DirectorySource<'cfg> {
+ /// The unique identifier of this source.
source_id: SourceId,
+ /// The root path of this source.
root: PathBuf,
+ /// Packages that this sources has discovered.
packages: HashMap<PackageId, (Package, Checksum)>,
config: &'cfg Config,
updated: bool,
}
+/// The checksum file to ensure the integrity of a package in a directory source.
+///
+/// The file name is simply `.cargo-checksum.json`. The checksum algorithm as
+/// of now is SHA256.
#[derive(Deserialize)]
struct Checksum {
+ /// Checksum of the package. Normally it is computed from the `.crate` file.
package: Option<String>,
+ /// Checksums of each source file.
files: HashMap<String, String>,
}
diff --git a/src/tools/cargo/src/cargo/sources/git/mod.rs b/src/tools/cargo/src/cargo/sources/git/mod.rs
index 6c230be93..47827f267 100644
--- a/src/tools/cargo/src/cargo/sources/git/mod.rs
+++ b/src/tools/cargo/src/cargo/sources/git/mod.rs
@@ -6,5 +6,46 @@ mod source;
mod utils;
pub mod fetch {
+ use crate::core::features::GitoxideFeatures;
+ use crate::Config;
+
+ /// The kind remote repository to fetch.
+ #[derive(Debug, Copy, Clone)]
+ pub enum RemoteKind {
+ /// A repository belongs to a git dependency.
+ GitDependency,
+ /// A repository belongs to a Cargo registry.
+ Registry,
+ }
+
+ impl RemoteKind {
+ /// Obtain the kind of history we would want for a fetch from our remote knowing if the target repo is already shallow
+ /// via `repo_is_shallow` along with gitoxide-specific feature configuration via `config`.
+ /// `rev_and_ref` is additional information that affects whether or not we may be shallow.
+ pub(crate) fn to_shallow_setting(
+ &self,
+ repo_is_shallow: bool,
+ config: &Config,
+ ) -> gix::remote::fetch::Shallow {
+ let has_feature = |cb: &dyn Fn(GitoxideFeatures) -> bool| {
+ config
+ .cli_unstable()
+ .gitoxide
+ .map_or(false, |features| cb(features))
+ };
+
+ // maintain shallow-ness and keep downloading single commits, or see if we can do shallow clones
+ if !repo_is_shallow {
+ match self {
+ RemoteKind::GitDependency if has_feature(&|git| git.shallow_deps) => {}
+ RemoteKind::Registry if has_feature(&|git| git.shallow_index) => {}
+ _ => return gix::remote::fetch::Shallow::NoChange,
+ }
+ };
+
+ gix::remote::fetch::Shallow::DepthAtRemote(1.try_into().expect("non-zero"))
+ }
+ }
+
pub type Error = gix::env::collate::fetch::Error<gix::refspec::parse::Error>;
}
diff --git a/src/tools/cargo/src/cargo/sources/git/oxide.rs b/src/tools/cargo/src/cargo/sources/git/oxide.rs
index 0270579da..c8d0a4ecd 100644
--- a/src/tools/cargo/src/cargo/sources/git/oxide.rs
+++ b/src/tools/cargo/src/cargo/sources/git/oxide.rs
@@ -29,6 +29,10 @@ pub fn with_retry_and_progress(
) -> CargoResult<()> {
std::thread::scope(|s| {
let mut progress_bar = Progress::new("Fetch", config);
+ let is_shallow = config
+ .cli_unstable()
+ .gitoxide
+ .map_or(false, |gix| gix.shallow_deps || gix.shallow_index);
network::retry::with_retry(config, || {
let progress_root: Arc<gix::progress::tree::Root> =
gix::progress::tree::root::Options {
@@ -50,7 +54,7 @@ pub fn with_retry_and_progress(
);
amend_authentication_hints(res, urls.get_mut().take())
});
- translate_progress_to_bar(&mut progress_bar, root)?;
+ translate_progress_to_bar(&mut progress_bar, root, is_shallow)?;
thread.join().expect("no panic in scoped thread")
})
})
@@ -59,7 +63,9 @@ pub fn with_retry_and_progress(
fn translate_progress_to_bar(
progress_bar: &mut Progress<'_>,
root: Weak<gix::progress::tree::Root>,
+ is_shallow: bool,
) -> CargoResult<()> {
+ let remote_progress: gix::progress::Id = gix::remote::fetch::ProgressId::RemoteProgress.into();
let read_pack_bytes: gix::progress::Id =
gix::odb::pack::bundle::write::ProgressId::ReadPackBytes.into();
let delta_index_objects: gix::progress::Id =
@@ -88,6 +94,7 @@ fn translate_progress_to_bar(
"progress should be smoother by keeping these as multiples of each other"
);
+ let num_phases = if is_shallow { 3 } else { 2 }; // indexing + delta-resolution, both with same amount of objects to handle
while let Some(root) = root.upgrade() {
std::thread::sleep(sleep_interval);
let needs_update = last_fast_update.elapsed() >= fast_check_interval;
@@ -102,31 +109,37 @@ fn translate_progress_to_bar(
fn progress_by_id(
id: gix::progress::Id,
task: &gix::progress::Task,
- ) -> Option<&gix::progress::Value> {
- (task.id == id).then(|| task.progress.as_ref()).flatten()
+ ) -> Option<(&str, &gix::progress::Value)> {
+ (task.id == id)
+ .then(|| task.progress.as_ref())
+ .flatten()
+ .map(|value| (task.name.as_str(), value))
}
fn find_in<K>(
tasks: &[(K, gix::progress::Task)],
- cb: impl Fn(&gix::progress::Task) -> Option<&gix::progress::Value>,
- ) -> Option<&gix::progress::Value> {
+ cb: impl Fn(&gix::progress::Task) -> Option<(&str, &gix::progress::Value)>,
+ ) -> Option<(&str, &gix::progress::Value)> {
tasks.iter().find_map(|(_, t)| cb(t))
}
- const NUM_PHASES: usize = 2; // indexing + delta-resolution, both with same amount of objects to handle
- if let Some(objs) = find_in(&tasks, |t| progress_by_id(resolve_objects, t)) {
- // Resolving deltas.
+ if let Some((_, objs)) = find_in(&tasks, |t| progress_by_id(resolve_objects, t)) {
+ // Phase 3: Resolving deltas.
let objects = objs.step.load(Ordering::Relaxed);
let total_objects = objs.done_at.expect("known amount of objects");
let msg = format!(", ({objects}/{total_objects}) resolving deltas");
- progress_bar.tick(total_objects + objects, total_objects * NUM_PHASES, &msg)?;
+ progress_bar.tick(
+ (total_objects * (num_phases - 1)) + objects,
+ total_objects * num_phases,
+ &msg,
+ )?;
} else if let Some((objs, read_pack)) =
find_in(&tasks, |t| progress_by_id(read_pack_bytes, t)).and_then(|read| {
find_in(&tasks, |t| progress_by_id(delta_index_objects, t))
- .map(|delta| (delta, read))
+ .map(|delta| (delta.1, read.1))
})
{
- // Receiving objects.
+ // Phase 2: Receiving objects.
let objects = objs.step.load(Ordering::Relaxed);
let total_objects = objs.done_at.expect("known amount of objects");
let received_bytes = read_pack.step.load(Ordering::Relaxed);
@@ -139,7 +152,25 @@ fn translate_progress_to_bar(
let (rate, unit) = human_readable_bytes(counter.rate() as u64);
let msg = format!(", {rate:.2}{unit}/s");
- progress_bar.tick(objects, total_objects * NUM_PHASES, &msg)?;
+ progress_bar.tick(
+ (total_objects * (num_phases - 2)) + objects,
+ total_objects * num_phases,
+ &msg,
+ )?;
+ } else if let Some((action, remote)) =
+ find_in(&tasks, |t| progress_by_id(remote_progress, t))
+ {
+ if !is_shallow {
+ continue;
+ }
+ // phase 1: work on the remote side
+
+ // Resolving deltas.
+ let objects = remote.step.load(Ordering::Relaxed);
+ if let Some(total_objects) = remote.done_at {
+ let msg = format!(", ({objects}/{total_objects}) {action}");
+ progress_bar.tick(objects, total_objects * num_phases, &msg)?;
+ }
}
}
Ok(())
@@ -232,7 +263,7 @@ pub fn open_repo(
) -> Result<gix::Repository, gix::open::Error> {
gix::open_opts(repo_path, {
let mut opts = gix::open::Options::default();
- opts.permissions.config = gix::permissions::Config::all();
+ opts.permissions.config = gix::open::permissions::Config::all();
opts.permissions.config.git_binary = purpose.needs_git_binary_config();
opts.with(gix::sec::Trust::Full)
.config_overrides(config_overrides)
diff --git a/src/tools/cargo/src/cargo/sources/git/source.rs b/src/tools/cargo/src/cargo/sources/git/source.rs
index 90c47093d..4cdb8983b 100644
--- a/src/tools/cargo/src/cargo/sources/git/source.rs
+++ b/src/tools/cargo/src/cargo/sources/git/source.rs
@@ -29,17 +29,26 @@ impl<'cfg> GitSource<'cfg> {
assert!(source_id.is_git(), "id is not git, id={}", source_id);
let remote = GitRemote::new(source_id.url());
- let ident = ident(&source_id);
-
- let source = GitSource {
- remote,
- manifest_reference: source_id.git_reference().unwrap().clone(),
- locked_rev: match source_id.precise() {
+ let manifest_reference = source_id.git_reference().unwrap().clone();
+ let locked_rev =
+ match source_id.precise() {
Some(s) => Some(git2::Oid::from_str(s).with_context(|| {
format!("precise value for git is not a git revision: {}", s)
})?),
None => None,
- },
+ };
+ let ident = ident_shallow(
+ &source_id,
+ config
+ .cli_unstable()
+ .gitoxide
+ .map_or(false, |gix| gix.fetch && gix.shallow_deps),
+ );
+
+ let source = GitSource {
+ remote,
+ manifest_reference,
+ locked_rev,
source_id,
path_source: None,
ident,
@@ -63,6 +72,7 @@ impl<'cfg> GitSource<'cfg> {
}
}
+/// Create an identifier from a URL, essentially turning `proto://host/path/repo` into `repo-<hash-of-url>`.
fn ident(id: &SourceId) -> String {
let ident = id
.canonical_url()
@@ -76,6 +86,18 @@ fn ident(id: &SourceId) -> String {
format!("{}-{}", ident, short_hash(id.canonical_url()))
}
+/// Like `ident()`, but appends `-shallow` to it, turning `proto://host/path/repo` into `repo-<hash-of-url>-shallow`.
+///
+/// It's important to separate shallow from non-shallow clones for reasons of backwards compatibility - older
+/// cargo's aren't necessarily handling shallow clones correctly.
+fn ident_shallow(id: &SourceId, is_shallow: bool) -> String {
+ let mut ident = ident(id);
+ if is_shallow {
+ ident.push_str("-shallow");
+ }
+ ident
+}
+
impl<'cfg> Debug for GitSource<'cfg> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "git repo at {}", self.remote.url())?;
diff --git a/src/tools/cargo/src/cargo/sources/git/utils.rs b/src/tools/cargo/src/cargo/sources/git/utils.rs
index a7ffccf79..c14d1daf3 100644
--- a/src/tools/cargo/src/cargo/sources/git/utils.rs
+++ b/src/tools/cargo/src/cargo/sources/git/utils.rs
@@ -2,6 +2,7 @@
//! authentication/cloning.
use crate::core::{GitReference, Verbosity};
+use crate::sources::git::fetch::RemoteKind;
use crate::sources::git::oxide;
use crate::sources::git::oxide::cargo_config_to_gitoxide_overrides;
use crate::util::errors::CargoResult;
@@ -96,20 +97,24 @@ impl GitRemote {
// if we can. If that can successfully load our revision then we've
// populated the database with the latest version of `reference`, so
// return that database and the rev we resolve to.
+ let locked_ref = locked_rev.map(|oid| GitReference::Rev(oid.to_string()));
+ let reference = locked_ref.as_ref().unwrap_or(reference);
if let Some(mut db) = db {
- fetch(&mut db.repo, self.url.as_str(), reference, cargo_config)
- .context(format!("failed to fetch into: {}", into.display()))?;
- match locked_rev {
- Some(rev) => {
- if db.contains(rev) {
- return Ok((db, rev));
- }
- }
- None => {
- if let Ok(rev) = reference.resolve(&db.repo) {
- return Ok((db, rev));
- }
- }
+ fetch(
+ &mut db.repo,
+ self.url.as_str(),
+ reference,
+ cargo_config,
+ RemoteKind::GitDependency,
+ )
+ .with_context(|| format!("failed to fetch into: {}", into.display()))?;
+
+ let resolved_commit_hash = match locked_rev {
+ Some(rev) => db.contains(rev).then_some(rev),
+ None => reference.resolve(&db.repo).ok(),
+ };
+ if let Some(rev) = resolved_commit_hash {
+ return Ok((db, rev));
}
}
@@ -121,8 +126,14 @@ impl GitRemote {
}
paths::create_dir_all(into)?;
let mut repo = init(into, true)?;
- fetch(&mut repo, self.url.as_str(), reference, cargo_config)
- .context(format!("failed to clone into: {}", into.display()))?;
+ fetch(
+ &mut repo,
+ self.url.as_str(),
+ reference,
+ cargo_config,
+ RemoteKind::GitDependency,
+ )
+ .with_context(|| format!("failed to clone into: {}", into.display()))?;
let rev = match locked_rev {
Some(rev) => rev,
None => reference.resolve(&repo)?,
@@ -282,6 +293,16 @@ impl<'a> GitCheckout<'a> {
.with_checkout(checkout)
.fetch_options(fopts)
.clone(url.as_str(), into)?;
+ // `git2` doesn't seem to handle shallow repos correctly when doing a local clone.
+ // Fortunately all that's needed is the copy of the one file that defines the
+ // shallow boundary, the commits which have their parents omitted as part of the
+ // shallow clone.
+ if database.repo.is_shallow() {
+ std::fs::copy(
+ database.repo.path().join("shallow"),
+ r.path().join("shallow"),
+ )?;
+ }
repo = Some(r);
Ok(())
})?;
@@ -432,7 +453,14 @@ impl<'a> GitCheckout<'a> {
cargo_config
.shell()
.status("Updating", format!("git submodule `{}`", url))?;
- fetch(&mut repo, &url, &reference, cargo_config).with_context(|| {
+ fetch(
+ &mut repo,
+ &url,
+ &reference,
+ cargo_config,
+ RemoteKind::GitDependency,
+ )
+ .with_context(|| {
format!(
"failed to fetch submodule `{}` from {}",
child.name().unwrap_or(""),
@@ -803,11 +831,15 @@ pub fn with_fetch_options(
})
}
+/// Note that `history` is a complex computed value to determine whether it's acceptable to perform shallow clones
+/// at all. It's needed to allow the caller to determine the correct position of the destination repository or move it
+/// into place should its position change.
pub fn fetch(
repo: &mut git2::Repository,
orig_url: &str,
reference: &GitReference,
config: &Config,
+ remote_kind: RemoteKind,
) -> CargoResult<()> {
if config.frozen() {
anyhow::bail!(
@@ -819,8 +851,10 @@ pub fn fetch(
anyhow::bail!("can't update a git repository in the offline mode")
}
+ let shallow = remote_kind.to_shallow_setting(repo.is_shallow(), config);
+
// If we're fetching from GitHub, attempt GitHub's special fast path for
- // testing if we've already got an up-to-date copy of the repository
+ // testing if we've already got an up-to-date copy of the repository.
let oid_to_fetch = match github_fast_path(repo, orig_url, reference, config) {
Ok(FastPathRev::UpToDate) => return Ok(()),
Ok(FastPathRev::NeedsFetch(rev)) => Some(rev),
@@ -852,6 +886,7 @@ pub fn fetch(
GitReference::Branch(b) => {
refspecs.push(format!("+refs/heads/{0}:refs/remotes/origin/{0}", b));
}
+
GitReference::Tag(t) => {
refspecs.push(format!("+refs/tags/{0}:refs/remotes/origin/tags/{0}", t));
}
@@ -865,6 +900,16 @@ pub fn fetch(
refspecs.push(format!("+{0}:{0}", rev));
} else if let Some(oid_to_fetch) = oid_to_fetch {
refspecs.push(format!("+{0}:refs/commit/{0}", oid_to_fetch));
+ } else if !matches!(shallow, gix::remote::fetch::Shallow::NoChange)
+ && rev.parse::<Oid>().is_ok()
+ {
+ // There is a specific commit to fetch and we will do so in shallow-mode only
+ // to not disturb the previous logic.
+ // Note that with typical settings for shallowing, we will just fetch a single `rev`
+ // as single commit.
+ // The reason we write to `refs/remotes/origin/HEAD` is that it's of special significance
+ // when during `GitReference::resolve()`, but otherwise it shouldn't matter.
+ refspecs.push(format!("+{0}:refs/remotes/origin/HEAD", rev));
} else {
// We don't know what the rev will point to. To handle this
// situation we fetch all branches and tags, and then we pray
@@ -936,8 +981,7 @@ pub fn fetch(
.url(gix::remote::Direction::Fetch)
.expect("set at init")
.to_owned();
- let connection =
- remote.connect(gix::remote::Direction::Fetch, &mut progress)?;
+ let connection = remote.connect(gix::remote::Direction::Fetch)?;
let mut authenticate = connection.configured_credentials(url)?;
let connection = connection.with_credentials(
move |action: gix::protocol::credentials::helper::Action| {
@@ -951,8 +995,9 @@ pub fn fetch(
},
);
let outcome = connection
- .prepare_fetch(gix::remote::ref_map::Options::default())?
- .receive(should_interrupt)?;
+ .prepare_fetch(&mut progress, gix::remote::ref_map::Options::default())?
+ .with_shallow(shallow.clone().into())
+ .receive(&mut progress, should_interrupt)?;
Ok(outcome)
});
let err = match res {
@@ -967,6 +1012,7 @@ pub fn fetch(
// folder before writing files into it, or else not even open a directory as git repository (which is
// also handled here).
&& err.is_corrupted()
+ || has_shallow_lock_file(&err)
{
repo_reinitialized.store(true, Ordering::Relaxed);
debug!(
@@ -1036,6 +1082,17 @@ pub fn fetch(
}
}
+/// `gitoxide` uses shallow locks to assure consistency when fetching to and to avoid races, and to write
+/// files atomically.
+/// Cargo has its own lock files and doesn't need that mechanism for race protection, so a stray lock means
+/// a signal interrupted a previous shallow fetch and doesn't mean a race is happening.
+fn has_shallow_lock_file(err: &crate::sources::git::fetch::Error) -> bool {
+ matches!(
+ err,
+ gix::env::collate::fetch::Error::Fetch(gix::remote::fetch::Error::LockShallowFile(_))
+ )
+}
+
fn fetch_with_cli(
repo: &mut git2::Repository,
url: &str,
diff --git a/src/tools/cargo/src/cargo/sources/mod.rs b/src/tools/cargo/src/cargo/sources/mod.rs
index 7d238d47d..81eda24ca 100644
--- a/src/tools/cargo/src/cargo/sources/mod.rs
+++ b/src/tools/cargo/src/cargo/sources/mod.rs
@@ -1,3 +1,24 @@
+//! Implementations of `Source` trait.
+//!
+//! Cargo provides several built-in implementations of [`Source`] trait. Namely,
+//!
+//! * [`RegistrySource`] --- A source that provides an index for people to query
+//! a crate's metadata, and fetch files for a certain crate. crates.io falls
+//! into this category. So do local registry and sparse registry.
+//! * [`DirectorySource`] --- Files are downloaded ahead of time. Primarily
+//! designed for crates generated from `cargo vendor`.
+//! * [`GitSource`] --- This gets crate information from a git repository.
+//! * [`PathSource`] --- This gets crate information from a local path on the
+//! filesystem.
+//! * [`ReplacedSource`] --- This manages the [source replacement] feature,
+//! redirecting operations on the original source to the replacement.
+//!
+//! This module also contains [`SourceConfigMap`], which is effectively the
+//! representation of the `[source.*]` value in Cargo configuration.
+//!
+//! [`Source`]: crate::core::Source
+//! [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html
+
pub use self::config::SourceConfigMap;
pub use self::directory::DirectorySource;
pub use self::git::GitSource;
diff --git a/src/tools/cargo/src/cargo/sources/path.rs b/src/tools/cargo/src/cargo/sources/path.rs
index 37e1e1f0f..2f147b19e 100644
--- a/src/tools/cargo/src/cargo/sources/path.rs
+++ b/src/tools/cargo/src/cargo/sources/path.rs
@@ -14,13 +14,28 @@ use ignore::gitignore::GitignoreBuilder;
use log::{trace, warn};
use walkdir::WalkDir;
+/// A source represents one or multiple packages gathering from a given root
+/// path on the filesystem.
+///
+/// It's the cornerstone of every other source --- other implementations
+/// eventually need to call `PathSource` to read local packages somewhere on
+/// the filesystem.
+///
+/// It also provides convenient methods like [`PathSource::list_files`] to
+/// list all files in a package, given its ability to walk the filesystem.
pub struct PathSource<'cfg> {
+ /// The unique identifier of this source.
source_id: SourceId,
+ /// The root path of this source.
path: PathBuf,
+ /// Whether this source has updated all package informations it may contain.
updated: bool,
+ /// Packages that this sources has discovered.
packages: Vec<Package>,
- config: &'cfg Config,
+ /// Whether this source should discover nested packages recursively.
+ /// See [`PathSource::new_recursive`] for more.
recursive: bool,
+ config: &'cfg Config,
}
impl<'cfg> PathSource<'cfg> {
@@ -41,9 +56,9 @@ impl<'cfg> PathSource<'cfg> {
/// Creates a new source which is walked recursively to discover packages.
///
- /// This is similar to the `new` method except that instead of requiring a
- /// valid package to be present at `root` the folder is walked entirely to
- /// crawl for packages.
+ /// This is similar to the [`PathSource::new`] method except that instead
+ /// of requiring a valid package to be present at `root` the folder is
+ /// walked entirely to crawl for packages.
///
/// Note that this should be used with care and likely shouldn't be chosen
/// by default!
@@ -54,6 +69,8 @@ impl<'cfg> PathSource<'cfg> {
}
}
+ /// Preloads a package for this source. The source is assumed that it has
+ /// yet loaded any other packages.
pub fn preload_with(&mut self, pkg: Package) {
assert!(!self.updated);
assert!(!self.recursive);
@@ -62,6 +79,7 @@ impl<'cfg> PathSource<'cfg> {
self.packages.push(pkg);
}
+ /// Gets the package on the root path.
pub fn root_package(&mut self) -> CargoResult<Package> {
trace!("root_package; source={:?}", self);
@@ -76,6 +94,8 @@ impl<'cfg> PathSource<'cfg> {
}
}
+ /// Returns the packages discovered by this source. It may walk the
+ /// the filesystem if package informations haven't yet updated.
pub fn read_packages(&self) -> CargoResult<Vec<Package>> {
if self.updated {
Ok(self.packages.clone())
@@ -96,7 +116,8 @@ impl<'cfg> PathSource<'cfg> {
///
/// The basic assumption of this method is that all files in the directory
/// are relevant for building this package, but it also contains logic to
- /// use other methods like .gitignore to filter the list of files.
+ /// use other methods like `.gitignore`, `package.include`, or
+ /// `package.exclude` to filter the list of files.
pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<PathBuf>> {
self._list_files(pkg).with_context(|| {
format!(
@@ -106,6 +127,7 @@ impl<'cfg> PathSource<'cfg> {
})
}
+ /// See [`PathSource::list_files`].
fn _list_files(&self, pkg: &Package) -> CargoResult<Vec<PathBuf>> {
let root = pkg.root();
let no_include_option = pkg.manifest().include().is_empty();
@@ -218,6 +240,11 @@ impl<'cfg> PathSource<'cfg> {
Ok(None)
}
+ /// Lists files relevant to building this package inside this source by
+ /// consulting both Git index (tracked) or status (untracked) under
+ /// a given Git repository.
+ ///
+ /// This looks into Git submodules as well.
fn list_files_git(
&self,
pkg: &Package,
@@ -373,6 +400,11 @@ impl<'cfg> PathSource<'cfg> {
}
}
+ /// Lists files relevant to building this package inside this source by
+ /// walking the filesystem from the package root path.
+ ///
+ /// This is a fallback for [`PathSource::list_files_git`] when the package
+ /// is not tracked under a Git repository.
fn list_files_walk(
&self,
pkg: &Package,
@@ -383,6 +415,7 @@ impl<'cfg> PathSource<'cfg> {
Ok(ret)
}
+ /// Helper recursive function for [`PathSource::list_files_walk`].
fn walk(
&self,
path: &Path,
@@ -448,6 +481,7 @@ impl<'cfg> PathSource<'cfg> {
Ok(())
}
+ /// Gets the last modified file in a package.
pub fn last_modified_file(&self, pkg: &Package) -> CargoResult<(FileTime, PathBuf)> {
if !self.updated {
return Err(internal(format!(
@@ -479,10 +513,12 @@ impl<'cfg> PathSource<'cfg> {
Ok((max, max_path))
}
+ /// Returns the root path of this source.
pub fn path(&self) -> &Path {
&self.path
}
+ /// Discovers packages inside this source if it hasn't yet done.
pub fn update(&mut self) -> CargoResult<()> {
if !self.updated {
let packages = self.read_packages()?;
diff --git a/src/tools/cargo/src/cargo/sources/registry/index.rs b/src/tools/cargo/src/cargo/sources/registry/index.rs
index a21511434..d857a053e 100644
--- a/src/tools/cargo/src/cargo/sources/registry/index.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/index.rs
@@ -81,91 +81,6 @@ use std::path::Path;
use std::str;
use std::task::{ready, Poll};
-/// Crates.io treats hyphen and underscores as interchangeable, but the index and old Cargo do not.
-/// Therefore, the index must store uncanonicalized version of the name so old Cargo's can find it.
-/// This loop tries all possible combinations of switching hyphen and underscores to find the
-/// uncanonicalized one. As all stored inputs have the correct spelling, we start with the spelling
-/// as-provided.
-pub struct UncanonicalizedIter<'s> {
- input: &'s str,
- num_hyphen_underscore: u32,
- hyphen_combination_num: u16,
-}
-
-impl<'s> UncanonicalizedIter<'s> {
- pub fn new(input: &'s str) -> Self {
- let num_hyphen_underscore = input.chars().filter(|&c| c == '_' || c == '-').count() as u32;
- UncanonicalizedIter {
- input,
- num_hyphen_underscore,
- hyphen_combination_num: 0,
- }
- }
-}
-
-impl<'s> Iterator for UncanonicalizedIter<'s> {
- type Item = String;
-
- fn next(&mut self) -> Option<Self::Item> {
- if self.hyphen_combination_num > 0
- && self.hyphen_combination_num.trailing_zeros() >= self.num_hyphen_underscore
- {
- return None;
- }
-
- let ret = Some(
- self.input
- .chars()
- .scan(0u16, |s, c| {
- // the check against 15 here's to prevent
- // shift overflow on inputs with more than 15 hyphens
- if (c == '_' || c == '-') && *s <= 15 {
- let switch = (self.hyphen_combination_num & (1u16 << *s)) > 0;
- let out = if (c == '_') ^ switch { '_' } else { '-' };
- *s += 1;
- Some(out)
- } else {
- Some(c)
- }
- })
- .collect(),
- );
- self.hyphen_combination_num += 1;
- ret
- }
-}
-
-#[test]
-fn no_hyphen() {
- assert_eq!(
- UncanonicalizedIter::new("test").collect::<Vec<_>>(),
- vec!["test".to_string()]
- )
-}
-
-#[test]
-fn two_hyphen() {
- assert_eq!(
- UncanonicalizedIter::new("te-_st").collect::<Vec<_>>(),
- vec![
- "te-_st".to_string(),
- "te__st".to_string(),
- "te--st".to_string(),
- "te_-st".to_string()
- ]
- )
-}
-
-#[test]
-fn overflow_hyphen() {
- assert_eq!(
- UncanonicalizedIter::new("te-_-_-_-_-_-_-_-_-st")
- .take(100)
- .count(),
- 100
- )
-}
-
/// Manager for handling the on-disk index.
///
/// Note that local and remote registries store the index differently. Local
@@ -814,6 +729,7 @@ impl IndexSummary {
features2,
yanked,
links,
+ rust_version,
v,
} = serde_json::from_slice(line)?;
let v = v.unwrap_or(1);
@@ -828,7 +744,7 @@ impl IndexSummary {
features.entry(name).or_default().extend(values);
}
}
- let mut summary = Summary::new(config, pkgid, deps, &features, links)?;
+ let mut summary = Summary::new(config, pkgid, deps, &features, links, rust_version)?;
summary.set_checksum(cksum);
Ok(IndexSummary {
summary,
diff --git a/src/tools/cargo/src/cargo/sources/registry/mod.rs b/src/tools/cargo/src/cargo/sources/registry/mod.rs
index aa3f5dc5f..c76ee6142 100644
--- a/src/tools/cargo/src/cargo/sources/registry/mod.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/mod.rs
@@ -161,8 +161,11 @@
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::HashSet;
+use std::fs;
use std::fs::{File, OpenOptions};
-use std::io::{self, Write};
+use std::io;
+use std::io::Read;
+use std::io::Write;
use std::path::{Path, PathBuf};
use std::task::{ready, Poll};
@@ -172,6 +175,7 @@ use flate2::read::GzDecoder;
use log::debug;
use semver::Version;
use serde::Deserialize;
+use serde::Serialize;
use tar::Archive;
use crate::core::dependency::{DepKind, Dependency};
@@ -199,6 +203,14 @@ const CHECKSUM_TEMPLATE: &str = "{sha256-checksum}";
const MAX_UNPACK_SIZE: u64 = 512 * 1024 * 1024;
const MAX_COMPRESSION_RATIO: usize = 20; // 20:1
+/// The content inside `.cargo-ok`.
+/// See [`RegistrySource::unpack_package`] for more.
+#[derive(Deserialize, Serialize)]
+struct LockMetadata {
+ /// The version of `.cargo-ok` file
+ v: u32,
+}
+
/// A "source" for a local (see `local::LocalRegistry`) or remote (see
/// `remote::RemoteRegistry`) registry.
///
@@ -241,7 +253,7 @@ pub struct RegistryConfig {
/// crate's sha256 checksum.
///
/// For backwards compatibility, if the string does not contain any
- /// markers (`{crate}`, `{version}`, `{prefix}`, or ``{lowerprefix}`), it
+ /// markers (`{crate}`, `{version}`, `{prefix}`, or `{lowerprefix}`), it
/// will be extended with `/{crate}/{version}/download` to
/// support registries like crates.io which were created before the
/// templating setup was created.
@@ -287,6 +299,13 @@ pub struct RegistryPackage<'a> {
/// Added early 2018 (see <https://github.com/rust-lang/cargo/pull/4978>),
/// can be `None` if published before then.
links: Option<InternedString>,
+ /// Required version of rust
+ ///
+ /// Corresponds to `package.rust-version`.
+ ///
+ /// Added in 2023 (see <https://github.com/rust-lang/crates.io/pull/6267>),
+ /// can be `None` if published before then or if not set in the manifest.
+ rust_version: Option<InternedString>,
/// The schema version for this entry.
///
/// If this is None, it defaults to version 1. Entries with unknown
@@ -549,10 +568,14 @@ mod index;
mod local;
mod remote;
-fn short_name(id: SourceId) -> String {
+fn short_name(id: SourceId, is_shallow: bool) -> String {
let hash = hex::short_hash(&id);
let ident = id.url().host_str().unwrap_or("").to_string();
- format!("{}-{}", ident, hash)
+ let mut name = format!("{}-{}", ident, hash);
+ if is_shallow {
+ name.push_str("-shallow");
+ }
+ name
}
impl<'cfg> RegistrySource<'cfg> {
@@ -562,7 +585,14 @@ impl<'cfg> RegistrySource<'cfg> {
config: &'cfg Config,
) -> CargoResult<RegistrySource<'cfg>> {
assert!(source_id.is_remote_registry());
- let name = short_name(source_id);
+ let name = short_name(
+ source_id,
+ config
+ .cli_unstable()
+ .gitoxide
+ .map_or(false, |gix| gix.fetch && gix.shallow_index)
+ && !source_id.is_sparse(),
+ );
let ops = if source_id.is_sparse() {
Box::new(http_remote::HttpRegistry::new(source_id, config, &name)?) as Box<_>
} else {
@@ -584,7 +614,7 @@ impl<'cfg> RegistrySource<'cfg> {
yanked_whitelist: &HashSet<PackageId>,
config: &'cfg Config,
) -> RegistrySource<'cfg> {
- let name = short_name(source_id);
+ let name = short_name(source_id, false);
let ops = local::LocalRegistry::new(path, config, &name);
RegistrySource::new(source_id, config, &name, Box::new(ops), yanked_whitelist)
}
@@ -617,6 +647,50 @@ impl<'cfg> RegistrySource<'cfg> {
/// compiled.
///
/// No action is taken if the source looks like it's already unpacked.
+ ///
+ /// # History of interruption detection with `.cargo-ok` file
+ ///
+ /// Cargo has always included a `.cargo-ok` file ([`PACKAGE_SOURCE_LOCK`])
+ /// to detect if extraction was interrupted, but it was originally empty.
+ ///
+ /// In 1.34, Cargo was changed to create the `.cargo-ok` file before it
+ /// started extraction to implement fine-grained locking. After it was
+ /// finished extracting, it wrote two bytes to indicate it was complete.
+ /// It would use the length check to detect if it was possibly interrupted.
+ ///
+ /// In 1.36, Cargo changed to not use fine-grained locking, and instead used
+ /// a global lock. The use of `.cargo-ok` was no longer needed for locking
+ /// purposes, but was kept to detect when extraction was interrupted.
+ ///
+ /// In 1.49, Cargo changed to not create the `.cargo-ok` file before it
+ /// started extraction to deal with `.crate` files that inexplicably had
+ /// a `.cargo-ok` file in them.
+ ///
+ /// In 1.64, Cargo changed to detect `.crate` files with `.cargo-ok` files
+ /// in them in response to [CVE-2022-36113], which dealt with malicious
+ /// `.crate` files making `.cargo-ok` a symlink causing cargo to write "ok"
+ /// to any arbitrary file on the filesystem it has permission to.
+ ///
+ /// In 1.71, `.cargo-ok` changed to contain a JSON `{ v: 1 }` to indicate
+ /// the version of it. A failure of parsing will result in a heavy-hammer
+ /// approach that unpacks the `.crate` file again. This is in response to a
+ /// security issue that the unpacking didn't respect umask on Unix systems.
+ ///
+ /// This is all a long-winded way of explaining the circumstances that might
+ /// cause a directory to contain a `.cargo-ok` file that is empty or
+ /// otherwise corrupted. Either this was extracted by a version of Rust
+ /// before 1.34, in which case everything should be fine. However, an empty
+ /// file created by versions 1.36 to 1.49 indicates that the extraction was
+ /// interrupted and that we need to start again.
+ ///
+ /// Another possibility is that the filesystem is simply corrupted, in
+ /// which case deleting the directory might be the safe thing to do. That
+ /// is probably unlikely, though.
+ ///
+ /// To be safe, we deletes the directory and starts over again if an empty
+ /// `.cargo-ok` file is found.
+ ///
+ /// [CVE-2022-36113]: https://blog.rust-lang.org/2022/09/14/cargo-cves.html#arbitrary-file-corruption-cve-2022-36113
fn unpack_package(&self, pkg: PackageId, tarball: &File) -> CargoResult<PathBuf> {
// The `.cargo-ok` file is used to track if the source is already
// unpacked.
@@ -625,62 +699,32 @@ impl<'cfg> RegistrySource<'cfg> {
let path = dst.join(PACKAGE_SOURCE_LOCK);
let path = self.config.assert_package_cache_locked(&path);
let unpack_dir = path.parent().unwrap();
- match path.metadata() {
- Ok(meta) if meta.len() > 0 => return Ok(unpack_dir.to_path_buf()),
- Ok(_meta) => {
- // The `.cargo-ok` file is not in a state we expect it to be
- // (with two bytes containing "ok").
- //
- // Cargo has always included a `.cargo-ok` file to detect if
- // extraction was interrupted, but it was originally empty.
- //
- // In 1.34, Cargo was changed to create the `.cargo-ok` file
- // before it started extraction to implement fine-grained
- // locking. After it was finished extracting, it wrote two
- // bytes to indicate it was complete. It would use the length
- // check to detect if it was possibly interrupted.
- //
- // In 1.36, Cargo changed to not use fine-grained locking, and
- // instead used a global lock. The use of `.cargo-ok` was no
- // longer needed for locking purposes, but was kept to detect
- // when extraction was interrupted.
- //
- // In 1.49, Cargo changed to not create the `.cargo-ok` file
- // before it started extraction to deal with `.crate` files
- // that inexplicably had a `.cargo-ok` file in them.
- //
- // In 1.64, Cargo changed to detect `.crate` files with
- // `.cargo-ok` files in them in response to CVE-2022-36113,
- // which dealt with malicious `.crate` files making
- // `.cargo-ok` a symlink causing cargo to write "ok" to any
- // arbitrary file on the filesystem it has permission to.
- //
- // This is all a long-winded way of explaining the
- // circumstances that might cause a directory to contain a
- // `.cargo-ok` file that is empty or otherwise corrupted.
- // Either this was extracted by a version of Rust before 1.34,
- // in which case everything should be fine. However, an empty
- // file created by versions 1.36 to 1.49 indicates that the
- // extraction was interrupted and that we need to start again.
- //
- // Another possibility is that the filesystem is simply
- // corrupted, in which case deleting the directory might be
- // the safe thing to do. That is probably unlikely, though.
- //
- // To be safe, this deletes the directory and starts over
- // again.
- log::warn!("unexpected length of {path:?}, clearing cache");
- paths::remove_dir_all(dst.as_path_unlocked())?;
- }
+ match fs::read_to_string(path) {
+ Ok(ok) => match serde_json::from_str::<LockMetadata>(&ok) {
+ Ok(lock_meta) if lock_meta.v == 1 => {
+ return Ok(unpack_dir.to_path_buf());
+ }
+ _ => {
+ if ok == "ok" {
+ log::debug!("old `ok` content found, clearing cache");
+ } else {
+ log::warn!("unrecognized .cargo-ok content, clearing cache: {ok}");
+ }
+ // See comment of `unpack_package` about why removing all stuff.
+ paths::remove_dir_all(dst.as_path_unlocked())?;
+ }
+ },
Err(e) if e.kind() == io::ErrorKind::NotFound => {}
- Err(e) => anyhow::bail!("failed to access package completion {path:?}: {e}"),
+ Err(e) => anyhow::bail!("unable to read .cargo-ok file at {path:?}: {e}"),
}
dst.create_dir()?;
let mut tar = {
let size_limit = max_unpack_size(self.config, tarball.metadata()?.len());
let gz = GzDecoder::new(tarball);
let gz = LimitErrorReader::new(gz, size_limit);
- Archive::new(gz)
+ let mut tar = Archive::new(gz);
+ set_mask(&mut tar);
+ tar
};
let prefix = unpack_dir.file_name().unwrap();
let parent = unpack_dir.parent().unwrap();
@@ -735,7 +779,9 @@ impl<'cfg> RegistrySource<'cfg> {
.write(true)
.open(&path)
.with_context(|| format!("failed to open `{}`", path.display()))?;
- write!(ok, "ok")?;
+
+ let lock_meta = LockMetadata { v: 1 };
+ write!(ok, "{}", serde_json::to_string(&lock_meta).unwrap())?;
Ok(unpack_dir.to_path_buf())
}
@@ -832,9 +878,15 @@ impl<'cfg> Source for RegistrySource<'cfg> {
// names to the original name. The resolver will later
// reject any candidates that have the wrong name, and with this it'll
// along the way produce helpful "did you mean?" suggestions.
- for name_permutation in
- index::UncanonicalizedIter::new(&dep.package_name()).take(1024)
- {
+ // For now we only try the canonical lysing `-` to `_` and vice versa.
+ // More advanced fuzzy searching become in the future.
+ for name_permutation in [
+ dep.package_name().replace('-', "_"),
+ dep.package_name().replace('_', "-"),
+ ] {
+ if name_permutation.as_str() == dep.package_name().as_str() {
+ continue;
+ }
any_pending |= self
.index
.query_inner(
@@ -945,7 +997,7 @@ impl<'cfg> Source for RegistrySource<'cfg> {
}
/// Get the maximum upack size that Cargo permits
-/// based on a given `size of your compressed file.
+/// based on a given `size` of your compressed file.
///
/// Returns the larger one between `size * max compression ratio`
/// and a fixed max unpacked size.
@@ -1012,3 +1064,16 @@ mod tests {
assert_eq!(make_dep_prefix("aBcDe"), "aB/cD");
}
}
+
+/// Set the current [`umask`] value for the given tarball. No-op on non-Unix
+/// platforms.
+///
+/// On Windows, tar only looks at user permissions and tries to set the "read
+/// only" attribute, so no-op as well.
+///
+/// [`umask`]: https://man7.org/linux/man-pages/man2/umask.2.html
+#[allow(unused_variables)]
+fn set_mask<R: Read>(tar: &mut Archive<R>) {
+ #[cfg(unix)]
+ tar.set_mask(crate::util::get_umask());
+}
diff --git a/src/tools/cargo/src/cargo/sources/registry/remote.rs b/src/tools/cargo/src/cargo/sources/registry/remote.rs
index 3e5029144..f4df4e86b 100644
--- a/src/tools/cargo/src/cargo/sources/registry/remote.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/remote.rs
@@ -1,5 +1,6 @@
use crate::core::{GitReference, PackageId, SourceId};
use crate::sources::git;
+use crate::sources::git::fetch::RemoteKind;
use crate::sources::registry::download;
use crate::sources::registry::MaybeLock;
use crate::sources::registry::{LoadResponse, RegistryConfig, RegistryData};
@@ -304,8 +305,14 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
// checkout.
let url = self.source_id.url();
let repo = self.repo.borrow_mut().unwrap();
- git::fetch(repo, url.as_str(), &self.index_git_ref, self.config)
- .with_context(|| format!("failed to fetch `{}`", url))?;
+ git::fetch(
+ repo,
+ url.as_str(),
+ &self.index_git_ref,
+ self.config,
+ RemoteKind::Registry,
+ )
+ .with_context(|| format!("failed to fetch `{}`", url))?;
// Create a dummy file to record the mtime for when we updated the
// index.
diff --git a/src/tools/cargo/src/cargo/sources/replaced.rs b/src/tools/cargo/src/cargo/sources/replaced.rs
index 13191d223..eef30e80c 100644
--- a/src/tools/cargo/src/cargo/sources/replaced.rs
+++ b/src/tools/cargo/src/cargo/sources/replaced.rs
@@ -5,13 +5,24 @@ use std::task::Poll;
use anyhow::Context as _;
+/// A source that replaces one source with the other. This manages the [source
+/// replacement] feature.
+///
+/// The implementation is merely redirecting from the original to the replacement.
+///
+/// [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html
pub struct ReplacedSource<'cfg> {
+ /// The identifier of the original source.
to_replace: SourceId,
+ /// The identifier of the new replacement source.
replace_with: SourceId,
inner: Box<dyn Source + 'cfg>,
}
impl<'cfg> ReplacedSource<'cfg> {
+ /// Creates a replaced source.
+ ///
+ /// The `src` argument is the new replacement source.
pub fn new(
to_replace: SourceId,
replace_with: SourceId,
diff --git a/src/tools/cargo/src/cargo/util/command_prelude.rs b/src/tools/cargo/src/cargo/util/command_prelude.rs
index 2145dbdee..c18785c66 100644
--- a/src/tools/cargo/src/cargo/util/command_prelude.rs
+++ b/src/tools/cargo/src/cargo/util/command_prelude.rs
@@ -91,10 +91,10 @@ pub trait CommandExt: Sized {
all: &'static str,
) -> Self {
self.arg_targets_lib_bin_example(lib, bin, bins, example, examples)
- ._arg(optional_multi_opt("test", "NAME", test))
._arg(flag("tests", tests))
- ._arg(optional_multi_opt("bench", "NAME", bench))
+ ._arg(optional_multi_opt("test", "NAME", test))
._arg(flag("benches", benches))
+ ._arg(optional_multi_opt("bench", "NAME", bench))
._arg(flag("all-targets", all))
}
@@ -107,10 +107,10 @@ pub trait CommandExt: Sized {
examples: &'static str,
) -> Self {
self._arg(flag("lib", lib))
- ._arg(optional_multi_opt("bin", "NAME", bin))
._arg(flag("bins", bins))
- ._arg(optional_multi_opt("example", "NAME", example))
+ ._arg(optional_multi_opt("bin", "NAME", bin))
._arg(flag("examples", examples))
+ ._arg(optional_multi_opt("example", "NAME", example))
}
fn arg_targets_bins_examples(
diff --git a/src/tools/cargo/src/cargo/util/config/mod.rs b/src/tools/cargo/src/cargo/util/config/mod.rs
index dad7e9c72..076b78299 100644
--- a/src/tools/cargo/src/cargo/util/config/mod.rs
+++ b/src/tools/cargo/src/cargo/util/config/mod.rs
@@ -388,7 +388,7 @@ impl Config {
/// Gets the path to the `rustdoc` executable.
pub fn rustdoc(&self) -> CargoResult<&Path> {
self.rustdoc
- .try_borrow_with(|| Ok(self.get_tool("rustdoc", &self.build_config()?.rustdoc)))
+ .try_borrow_with(|| Ok(self.get_tool(Tool::Rustdoc, &self.build_config()?.rustdoc)))
.map(AsRef::as_ref)
}
@@ -406,7 +406,7 @@ impl Config {
);
Rustc::new(
- self.get_tool("rustc", &self.build_config()?.rustc),
+ self.get_tool(Tool::Rustc, &self.build_config()?.rustc),
wrapper,
rustc_workspace_wrapper,
&self
@@ -1640,11 +1640,63 @@ impl Config {
}
}
- /// Looks for a path for `tool` in an environment variable or config path, defaulting to `tool`
- /// as a path.
- fn get_tool(&self, tool: &str, from_config: &Option<ConfigRelativePath>) -> PathBuf {
- self.maybe_get_tool(tool, from_config)
- .unwrap_or_else(|| PathBuf::from(tool))
+ /// Returns the path for the given tool.
+ ///
+ /// This will look for the tool in the following order:
+ ///
+ /// 1. From an environment variable matching the tool name (such as `RUSTC`).
+ /// 2. From the given config value (which is usually something like `build.rustc`).
+ /// 3. Finds the tool in the PATH environment variable.
+ ///
+ /// This is intended for tools that are rustup proxies. If you need to get
+ /// a tool that is not a rustup proxy, use `maybe_get_tool` instead.
+ fn get_tool(&self, tool: Tool, from_config: &Option<ConfigRelativePath>) -> PathBuf {
+ let tool_str = tool.as_str();
+ self.maybe_get_tool(tool_str, from_config)
+ .or_else(|| {
+ // This is an optimization to circumvent the rustup proxies
+ // which can have a significant performance hit. The goal here
+ // is to determine if calling `rustc` from PATH would end up
+ // calling the proxies.
+ //
+ // This is somewhat cautious trying to determine if it is safe
+ // to circumvent rustup, because there are some situations
+ // where users may do things like modify PATH, call cargo
+ // directly, use a custom rustup toolchain link without a
+ // cargo executable, etc. However, there is still some risk
+ // this may make the wrong decision in unusual circumstances.
+ //
+ // First, we must be running under rustup in the first place.
+ let toolchain = self.get_env_os("RUSTUP_TOOLCHAIN")?;
+ // This currently does not support toolchain paths.
+ // This also enforces UTF-8.
+ if toolchain.to_str()?.contains(&['/', '\\']) {
+ return None;
+ }
+ // If the tool on PATH is the same as `rustup` on path, then
+ // there is pretty good evidence that it will be a proxy.
+ let tool_resolved = paths::resolve_executable(Path::new(tool_str)).ok()?;
+ let rustup_resolved = paths::resolve_executable(Path::new("rustup")).ok()?;
+ let tool_meta = tool_resolved.metadata().ok()?;
+ let rustup_meta = rustup_resolved.metadata().ok()?;
+ // This works on the assumption that rustup and its proxies
+ // use hard links to a single binary. If rustup ever changes
+ // that setup, then I think the worst consequence is that this
+ // optimization will not work, and it will take the slow path.
+ if tool_meta.len() != rustup_meta.len() {
+ return None;
+ }
+ // Try to find the tool in rustup's toolchain directory.
+ let tool_exe = Path::new(tool_str).with_extension(env::consts::EXE_EXTENSION);
+ let toolchain_exe = home::rustup_home()
+ .ok()?
+ .join("toolchains")
+ .join(&toolchain)
+ .join("bin")
+ .join(&tool_exe);
+ toolchain_exe.exists().then_some(toolchain_exe)
+ })
+ .unwrap_or_else(|| PathBuf::from(tool_str))
}
pub fn jobserver_from_env(&self) -> Option<&jobserver::Client> {
@@ -1665,8 +1717,12 @@ impl Config {
}
pub fn http_config(&self) -> CargoResult<&CargoHttpConfig> {
- self.http_config
- .try_borrow_with(|| self.get::<CargoHttpConfig>("http"))
+ self.http_config.try_borrow_with(|| {
+ let mut http = self.get::<CargoHttpConfig>("http")?;
+ let curl_v = curl::Version::get();
+ disables_multiplexing_for_bad_curl(curl_v.version(), &mut http, self);
+ Ok(http)
+ })
}
pub fn future_incompat_config(&self) -> CargoResult<&CargoFutureIncompatConfig> {
@@ -1693,8 +1749,28 @@ impl Config {
.env_config
.try_borrow_with(|| self.get::<EnvConfig>("env"))?;
- if env_config.get("CARGO_HOME").is_some() {
- bail!("setting the `CARGO_HOME` environment variable is not supported in the `[env]` configuration table")
+ // Reasons for disallowing these values:
+ //
+ // - CARGO_HOME: The initial call to cargo does not honor this value
+ // from the [env] table. Recursive calls to cargo would use the new
+ // value, possibly behaving differently from the outer cargo.
+ //
+ // - RUSTUP_HOME and RUSTUP_TOOLCHAIN: Under normal usage with rustup,
+ // this will have no effect because the rustup proxy sets
+ // RUSTUP_HOME and RUSTUP_TOOLCHAIN, and that would override the
+ // [env] table. If the outer cargo is executed directly
+ // circumventing the rustup proxy, then this would affect calls to
+ // rustc (assuming that is a proxy), which could potentially cause
+ // problems with cargo and rustc being from different toolchains. We
+ // consider this to be not a use case we would like to support,
+ // since it will likely cause problems or lead to confusion.
+ for disallowed in &["CARGO_HOME", "RUSTUP_HOME", "RUSTUP_TOOLCHAIN"] {
+ if env_config.contains_key(*disallowed) {
+ bail!(
+ "setting the `{disallowed}` environment variable is not supported \
+ in the `[env]` configuration table"
+ );
+ }
}
Ok(env_config)
@@ -2645,3 +2721,90 @@ macro_rules! drop_eprint {
$crate::__shell_print!($config, err, false, $($arg)*)
);
}
+
+enum Tool {
+ Rustc,
+ Rustdoc,
+}
+
+impl Tool {
+ fn as_str(&self) -> &str {
+ match self {
+ Tool::Rustc => "rustc",
+ Tool::Rustdoc => "rustdoc",
+ }
+ }
+}
+
+/// Disable HTTP/2 multiplexing for some broken versions of libcurl.
+///
+/// In certain versions of libcurl when proxy is in use with HTTP/2
+/// multiplexing, connections will continue stacking up. This was
+/// fixed in libcurl 8.0.0 in curl/curl@821f6e2a89de8aec1c7da3c0f381b92b2b801efc
+///
+/// However, Cargo can still link against old system libcurl if it is from a
+/// custom built one or on macOS. For those cases, multiplexing needs to be
+/// disabled when those versions are detected.
+fn disables_multiplexing_for_bad_curl(
+ curl_version: &str,
+ http: &mut CargoHttpConfig,
+ config: &Config,
+) {
+ use crate::util::network;
+
+ if network::proxy::http_proxy_exists(http, config) && http.multiplexing.is_none() {
+ let bad_curl_versions = ["7.87.0", "7.88.0", "7.88.1"];
+ if bad_curl_versions
+ .iter()
+ .any(|v| curl_version.starts_with(v))
+ {
+ log::info!("disabling multiplexing with proxy, curl version is {curl_version}");
+ http.multiplexing = Some(false);
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::disables_multiplexing_for_bad_curl;
+ use super::CargoHttpConfig;
+ use super::Config;
+ use super::Shell;
+
+ #[test]
+ fn disables_multiplexing() {
+ let mut config = Config::new(Shell::new(), "".into(), "".into());
+ config.set_search_stop_path(std::path::PathBuf::new());
+ config.set_env(Default::default());
+
+ let mut http = CargoHttpConfig::default();
+ http.proxy = Some("127.0.0.1:3128".into());
+ disables_multiplexing_for_bad_curl("7.88.1", &mut http, &config);
+ assert_eq!(http.multiplexing, Some(false));
+
+ let cases = [
+ (None, None, "7.87.0", None),
+ (None, None, "7.88.0", None),
+ (None, None, "7.88.1", None),
+ (None, None, "8.0.0", None),
+ (Some("".into()), None, "7.87.0", Some(false)),
+ (Some("".into()), None, "7.88.0", Some(false)),
+ (Some("".into()), None, "7.88.1", Some(false)),
+ (Some("".into()), None, "8.0.0", None),
+ (Some("".into()), Some(false), "7.87.0", Some(false)),
+ (Some("".into()), Some(false), "7.88.0", Some(false)),
+ (Some("".into()), Some(false), "7.88.1", Some(false)),
+ (Some("".into()), Some(false), "8.0.0", Some(false)),
+ ];
+
+ for (proxy, multiplexing, curl_v, result) in cases {
+ let mut http = CargoHttpConfig {
+ multiplexing,
+ proxy,
+ ..Default::default()
+ };
+ disables_multiplexing_for_bad_curl(curl_v, &mut http, &config);
+ assert_eq!(http.multiplexing, result);
+ }
+ }
+}
diff --git a/src/tools/cargo/src/cargo/util/diagnostic_server.rs b/src/tools/cargo/src/cargo/util/diagnostic_server.rs
index cc5314260..36215735b 100644
--- a/src/tools/cargo/src/cargo/util/diagnostic_server.rs
+++ b/src/tools/cargo/src/cargo/util/diagnostic_server.rs
@@ -4,6 +4,7 @@
use std::collections::HashSet;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
+use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread::{self, JoinHandle};
@@ -18,16 +19,6 @@ use crate::util::errors::CargoResult;
use crate::util::Config;
const DIAGNOSTICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
-const PLEASE_REPORT_THIS_BUG: &str =
- "This likely indicates a bug in either rustc or cargo itself,\n\
- and we would appreciate a bug report! You're likely to see \n\
- a number of compiler warnings after this message which cargo\n\
- attempted to fix but failed. If you could open an issue at\n\
- https://github.com/rust-lang/rust/issues\n\
- quoting the full output of this command we'd be very appreciative!\n\
- Note that you may be able to make some more progress in the near-term\n\
- fixing code with the `--broken-code` flag\n\n\
- ";
#[derive(Deserialize, Serialize, Hash, Eq, PartialEq, Clone)]
pub enum Message {
@@ -83,15 +74,27 @@ impl Message {
}
}
+/// A printer that will print diagnostics messages to the shell.
pub struct DiagnosticPrinter<'a> {
+ /// The config to get the shell to print to.
config: &'a Config,
+ /// An optional wrapper to be used in addition to `rustc.wrapper` for workspace crates.
+ /// This is used to get the correct bug report URL. For instance,
+ /// if `clippy-driver` is set as the value for the wrapper,
+ /// then the correct bug report URL for `clippy` can be obtained.
+ workspace_wrapper: &'a Option<PathBuf>,
+ // A set of messages that have already been printed.
dedupe: HashSet<Message>,
}
impl<'a> DiagnosticPrinter<'a> {
- pub fn new(config: &'a Config) -> DiagnosticPrinter<'a> {
+ pub fn new(
+ config: &'a Config,
+ workspace_wrapper: &'a Option<PathBuf>,
+ ) -> DiagnosticPrinter<'a> {
DiagnosticPrinter {
config,
+ workspace_wrapper,
dedupe: HashSet::new(),
}
}
@@ -128,7 +131,12 @@ impl<'a> DiagnosticPrinter<'a> {
"The full error message was:\n\n> {}\n\n",
message,
)?;
- write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
+ let issue_link = get_bug_report_url(self.workspace_wrapper);
+ write!(
+ self.config.shell().err(),
+ "{}",
+ gen_please_report_this_bug_text(issue_link)
+ )?;
Ok(())
}
Message::FixFailed {
@@ -159,7 +167,12 @@ impl<'a> DiagnosticPrinter<'a> {
}
writeln!(self.config.shell().err())?;
}
- write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
+ let issue_link = get_bug_report_url(self.workspace_wrapper);
+ write!(
+ self.config.shell().err(),
+ "{}",
+ gen_please_report_this_bug_text(issue_link)
+ )?;
if !errors.is_empty() {
writeln!(
self.config.shell().err(),
@@ -218,6 +231,31 @@ https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-proje
}
}
+fn gen_please_report_this_bug_text(url: &str) -> String {
+ format!(
+ "This likely indicates a bug in either rustc or cargo itself,\n\
+ and we would appreciate a bug report! You're likely to see \n\
+ a number of compiler warnings after this message which cargo\n\
+ attempted to fix but failed. If you could open an issue at\n\
+ {}\n\
+ quoting the full output of this command we'd be very appreciative!\n\
+ Note that you may be able to make some more progress in the near-term\n\
+ fixing code with the `--broken-code` flag\n\n\
+ ",
+ url
+ )
+}
+
+fn get_bug_report_url(rustc_workspace_wrapper: &Option<PathBuf>) -> &str {
+ let clippy = std::ffi::OsStr::new("clippy-driver");
+ let issue_link = match rustc_workspace_wrapper.as_ref().and_then(|x| x.file_stem()) {
+ Some(wrapper) if wrapper == clippy => "https://github.com/rust-lang/rust-clippy/issues",
+ _ => "https://github.com/rust-lang/rust/issues",
+ };
+
+ issue_link
+}
+
#[derive(Debug)]
pub struct RustfixDiagnosticServer {
listener: TcpListener,
diff --git a/src/tools/cargo/src/cargo/util/edit_distance.rs b/src/tools/cargo/src/cargo/util/edit_distance.rs
new file mode 100644
index 000000000..f77e48b44
--- /dev/null
+++ b/src/tools/cargo/src/cargo/util/edit_distance.rs
@@ -0,0 +1,143 @@
+use std::{cmp, mem};
+
+/// Finds the [edit distance] between two strings.
+///
+/// Returns `None` if the distance exceeds the limit.
+///
+/// [edit distance]: https://en.wikipedia.org/wiki/Edit_distance
+pub fn edit_distance(a: &str, b: &str, limit: usize) -> Option<usize> {
+ // Comparing the strings lowercased will result in a difference in capitalization being less distance away
+ // than being a completely different letter. Otherwise `CHECK` is as far away from `check` as it
+ // is from `build` (both with a distance of 5). For a single letter shortcut (e.g. `b` or `c`), they will
+ // all be as far away from any capital single letter entry (all with a distance of 1).
+ // By first lowercasing the strings, `C` and `c` are closer than `C` and `b`, for example.
+ let a = a.to_lowercase();
+ let b = b.to_lowercase();
+
+ let mut a = &a.chars().collect::<Vec<_>>()[..];
+ let mut b = &b.chars().collect::<Vec<_>>()[..];
+
+ // Ensure that `b` is the shorter string, minimizing memory use.
+ if a.len() < b.len() {
+ mem::swap(&mut a, &mut b);
+ }
+
+ let min_dist = a.len() - b.len();
+ // If we know the limit will be exceeded, we can return early.
+ if min_dist > limit {
+ return None;
+ }
+
+ // Strip common prefix.
+ while let Some(((b_char, b_rest), (a_char, a_rest))) = b.split_first().zip(a.split_first()) {
+ if a_char != b_char {
+ break;
+ }
+ a = a_rest;
+ b = b_rest;
+ }
+ // Strip common suffix.
+ while let Some(((b_char, b_rest), (a_char, a_rest))) = b.split_last().zip(a.split_last()) {
+ if a_char != b_char {
+ break;
+ }
+ a = a_rest;
+ b = b_rest;
+ }
+
+ // If either string is empty, the distance is the length of the other.
+ // We know that `b` is the shorter string, so we don't need to check `a`.
+ if b.len() == 0 {
+ return Some(min_dist);
+ }
+
+ let mut prev_prev = vec![usize::MAX; b.len() + 1];
+ let mut prev = (0..=b.len()).collect::<Vec<_>>();
+ let mut current = vec![0; b.len() + 1];
+
+ // row by row
+ for i in 1..=a.len() {
+ current[0] = i;
+ let a_idx = i - 1;
+
+ // column by column
+ for j in 1..=b.len() {
+ let b_idx = j - 1;
+
+ // There is no cost to substitute a character with itself.
+ let substitution_cost = if a[a_idx] == b[b_idx] { 0 } else { 1 };
+
+ current[j] = cmp::min(
+ // deletion
+ prev[j] + 1,
+ cmp::min(
+ // insertion
+ current[j - 1] + 1,
+ // substitution
+ prev[j - 1] + substitution_cost,
+ ),
+ );
+
+ if (i > 1) && (j > 1) && (a[a_idx] == b[b_idx - 1]) && (a[a_idx - 1] == b[b_idx]) {
+ // transposition
+ current[j] = cmp::min(current[j], prev_prev[j - 2] + 1);
+ }
+ }
+
+ // Rotate the buffers, reusing the memory.
+ [prev_prev, prev, current] = [prev, current, prev_prev];
+ }
+
+ // `prev` because we already rotated the buffers.
+ let distance = prev[b.len()];
+ (distance <= limit).then_some(distance)
+}
+
+/// Find the closest element from `iter` matching `choice`. The `key` callback
+/// is used to select a `&str` from the iterator to compare against `choice`.
+pub fn closest<'a, T>(
+ choice: &str,
+ iter: impl Iterator<Item = T>,
+ key: impl Fn(&T) -> &'a str,
+) -> Option<T> {
+ // Only consider candidates with an edit distance of 3 or less so we don't
+ // suggest out-of-the-blue options.
+ iter.filter_map(|e| Some((edit_distance(choice, key(&e), 3)?, e)))
+ .min_by_key(|t| t.0)
+ .map(|t| t.1)
+}
+
+/// Version of `closest` that returns a common "suggestion" that can be tacked
+/// onto the end of an error message.
+pub fn closest_msg<'a, T>(
+ choice: &str,
+ iter: impl Iterator<Item = T>,
+ key: impl Fn(&T) -> &'a str,
+) -> String {
+ match closest(choice, iter, &key) {
+ Some(e) => format!("\n\n\tDid you mean `{}`?", key(&e)),
+ None => String::new(),
+ }
+}
+
+#[test]
+fn test_edit_distance() {
+ use std::char::{from_u32, MAX};
+ // Test bytelength agnosticity
+ for c in (0u32..MAX as u32)
+ .filter_map(from_u32)
+ .map(|i| i.to_string())
+ {
+ assert_eq!(edit_distance(&c, &c, usize::MAX), Some(0));
+ }
+
+ let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
+ let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
+ let c = "Mary häd ä little lämb\n\nLittle lämb\n";
+ assert_eq!(edit_distance(a, b, usize::MAX), Some(1));
+ assert_eq!(edit_distance(b, a, usize::MAX), Some(1));
+ assert_eq!(edit_distance(a, c, usize::MAX), Some(2));
+ assert_eq!(edit_distance(c, a, usize::MAX), Some(2));
+ assert_eq!(edit_distance(b, c, usize::MAX), Some(1));
+ assert_eq!(edit_distance(c, b, usize::MAX), Some(1));
+}
diff --git a/src/tools/cargo/src/cargo/util/lev_distance.rs b/src/tools/cargo/src/cargo/util/lev_distance.rs
deleted file mode 100644
index 8dcef4a89..000000000
--- a/src/tools/cargo/src/cargo/util/lev_distance.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-use std::cmp;
-
-pub fn lev_distance(me: &str, t: &str) -> usize {
- // Comparing the strings lowercased will result in a difference in capitalization being less distance away
- // than being a completely different letter. Otherwise `CHECK` is as far away from `check` as it
- // is from `build` (both with a distance of 5). For a single letter shortcut (e.g. `b` or `c`), they will
- // all be as far away from any capital single letter entry (all with a distance of 1).
- // By first lowercasing the strings, `C` and `c` are closer than `C` and `b`, for example.
- let me = me.to_lowercase();
- let t = t.to_lowercase();
-
- let t_len = t.chars().count();
- if me.is_empty() {
- return t_len;
- }
- if t.is_empty() {
- return me.chars().count();
- }
-
- let mut dcol = (0..=t_len).collect::<Vec<_>>();
- let mut t_last = 0;
-
- for (i, sc) in me.chars().enumerate() {
- let mut current = i;
- dcol[0] = current + 1;
-
- for (j, tc) in t.chars().enumerate() {
- let next = dcol[j + 1];
-
- if sc == tc {
- dcol[j + 1] = current;
- } else {
- dcol[j + 1] = cmp::min(current, next);
- dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
- }
-
- current = next;
- t_last = j;
- }
- }
-
- dcol[t_last + 1]
-}
-
-/// Find the closest element from `iter` matching `choice`. The `key` callback
-/// is used to select a `&str` from the iterator to compare against `choice`.
-pub fn closest<'a, T>(
- choice: &str,
- iter: impl Iterator<Item = T>,
- key: impl Fn(&T) -> &'a str,
-) -> Option<T> {
- // Only consider candidates with a lev_distance of 3 or less so we don't
- // suggest out-of-the-blue options.
- iter.map(|e| (lev_distance(choice, key(&e)), e))
- .filter(|&(d, _)| d < 4)
- .min_by_key(|t| t.0)
- .map(|t| t.1)
-}
-
-/// Version of `closest` that returns a common "suggestion" that can be tacked
-/// onto the end of an error message.
-pub fn closest_msg<'a, T>(
- choice: &str,
- iter: impl Iterator<Item = T>,
- key: impl Fn(&T) -> &'a str,
-) -> String {
- match closest(choice, iter, &key) {
- Some(e) => format!("\n\n\tDid you mean `{}`?", key(&e)),
- None => String::new(),
- }
-}
-
-#[test]
-fn test_lev_distance() {
- use std::char::{from_u32, MAX};
- // Test bytelength agnosticity
- for c in (0u32..MAX as u32)
- .filter_map(from_u32)
- .map(|i| i.to_string())
- {
- assert_eq!(lev_distance(&c, &c), 0);
- }
-
- let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
- let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
- let c = "Mary häd ä little lämb\n\nLittle lämb\n";
- assert_eq!(lev_distance(a, b), 1);
- assert_eq!(lev_distance(b, a), 1);
- assert_eq!(lev_distance(a, c), 2);
- assert_eq!(lev_distance(c, a), 2);
- assert_eq!(lev_distance(b, c), 1);
- assert_eq!(lev_distance(c, b), 1);
-}
diff --git a/src/tools/cargo/src/cargo/util/machine_message.rs b/src/tools/cargo/src/cargo/util/machine_message.rs
index baef5167b..f1602ae57 100644
--- a/src/tools/cargo/src/cargo/util/machine_message.rs
+++ b/src/tools/cargo/src/cargo/util/machine_message.rs
@@ -55,12 +55,20 @@ impl<'a> Message for Artifact<'a> {
#[derive(Serialize)]
pub struct ArtifactProfile {
pub opt_level: &'static str,
- pub debuginfo: Option<u32>,
+ pub debuginfo: Option<ArtifactDebuginfo>,
pub debug_assertions: bool,
pub overflow_checks: bool,
pub test: bool,
}
+/// Internally this is an enum with different variants, but keep using 0/1/2 as integers for compatibility.
+#[derive(Serialize)]
+#[serde(untagged)]
+pub enum ArtifactDebuginfo {
+ Int(u32),
+ Named(&'static str),
+}
+
#[derive(Serialize)]
pub struct BuildScript<'a> {
pub package_id: PackageId,
diff --git a/src/tools/cargo/src/cargo/util/mod.rs b/src/tools/cargo/src/cargo/util/mod.rs
index 12b152018..df8dcb0ac 100644
--- a/src/tools/cargo/src/cargo/util/mod.rs
+++ b/src/tools/cargo/src/cargo/util/mod.rs
@@ -7,6 +7,7 @@ pub use self::config::{homedir, Config, ConfigValue};
pub(crate) use self::counter::MetricsCounter;
pub use self::dependency_queue::DependencyQueue;
pub use self::diagnostic_server::RustfixDiagnosticServer;
+pub use self::edit_distance::{closest, closest_msg, edit_distance};
pub use self::errors::CliError;
pub use self::errors::{internal, CargoResult, CliResult};
pub use self::flock::{FileLock, Filesystem};
@@ -16,7 +17,6 @@ pub use self::hex::{hash_u64, short_hash, to_hex};
pub use self::into_url::IntoUrl;
pub use self::into_url_with_base::IntoUrlWithBase;
pub(crate) use self::io::LimitErrorReader;
-pub use self::lev_distance::{closest, closest_msg, lev_distance};
pub use self::lockserver::{LockServer, LockServerClient, LockServerStarted};
pub use self::progress::{Progress, ProgressStyle};
pub use self::queue::Queue;
@@ -38,6 +38,7 @@ mod counter;
pub mod cpu;
mod dependency_queue;
pub mod diagnostic_server;
+pub mod edit_distance;
pub mod errors;
mod flock;
pub mod graph;
@@ -49,7 +50,6 @@ pub mod into_url;
mod into_url_with_base;
mod io;
pub mod job;
-pub mod lev_distance;
mod lockserver;
pub mod machine_message;
pub mod network;
@@ -207,6 +207,24 @@ pub fn try_canonicalize<P: AsRef<Path>>(path: P) -> std::io::Result<PathBuf> {
})
}
+/// Get the current [`umask`] value.
+///
+/// [`umask`]: https://man7.org/linux/man-pages/man2/umask.2.html
+#[cfg(unix)]
+pub fn get_umask() -> u32 {
+ use std::sync::OnceLock;
+ static UMASK: OnceLock<libc::mode_t> = OnceLock::new();
+ // SAFETY: Syscalls are unsafe. Calling `umask` twice is even unsafer for
+ // multithreading program, since it doesn't provide a way to retrive the
+ // value without modifications. We use a static `OnceLock` here to ensure
+ // it only gets call once during the entire program lifetime.
+ *UMASK.get_or_init(|| unsafe {
+ let umask = libc::umask(0o022);
+ libc::umask(umask);
+ umask
+ }) as u32 // it is u16 on macos
+}
+
#[cfg(test)]
mod test {
use super::*;
diff --git a/src/tools/cargo/src/cargo/util/network/mod.rs b/src/tools/cargo/src/cargo/util/network/mod.rs
index 60a380343..2006bb65f 100644
--- a/src/tools/cargo/src/cargo/util/network/mod.rs
+++ b/src/tools/cargo/src/cargo/util/network/mod.rs
@@ -2,6 +2,7 @@
use std::task::Poll;
+pub mod proxy;
pub mod retry;
pub mod sleep;
diff --git a/src/tools/cargo/src/cargo/util/network/proxy.rs b/src/tools/cargo/src/cargo/util/network/proxy.rs
new file mode 100644
index 000000000..e305cf1ff
--- /dev/null
+++ b/src/tools/cargo/src/cargo/util/network/proxy.rs
@@ -0,0 +1,42 @@
+//! Utilities for network proxies.
+
+use crate::util::config::CargoHttpConfig;
+use crate::util::config::Config;
+
+/// Proxy environment variables that are picked up by libcurl.
+const LIBCURL_HTTP_PROXY_ENVS: [&str; 4] =
+ ["http_proxy", "HTTP_PROXY", "https_proxy", "HTTPS_PROXY"];
+
+/// Finds an explicit HTTP proxy if one is available.
+///
+/// Favor [Cargo's `http.proxy`], then [Git's `http.proxy`].
+/// Proxies specified via environment variables are picked up by libcurl.
+/// See [`LIBCURL_HTTP_PROXY_ENVS`].
+///
+/// [Cargo's `http.proxy`]: https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpproxy
+/// [Git's `http.proxy`]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-httpproxy
+pub fn http_proxy(http: &CargoHttpConfig) -> Option<String> {
+ if let Some(s) = &http.proxy {
+ return Some(s.into());
+ }
+ git2::Config::open_default()
+ .and_then(|cfg| cfg.get_string("http.proxy"))
+ .ok()
+}
+
+/// Determine if an http proxy exists.
+///
+/// Checks the following for existence, in order:
+///
+/// * Cargo's `http.proxy`
+/// * Git's `http.proxy`
+/// * `http_proxy` env var
+/// * `HTTP_PROXY` env var
+/// * `https_proxy` env var
+/// * `HTTPS_PROXY` env var
+pub fn http_proxy_exists(http: &CargoHttpConfig, config: &Config) -> bool {
+ http_proxy(http).is_some()
+ || LIBCURL_HTTP_PROXY_ENVS
+ .iter()
+ .any(|v| config.get_env(v).is_ok())
+}
diff --git a/src/tools/cargo/src/cargo/util/toml/mod.rs b/src/tools/cargo/src/cargo/util/toml/mod.rs
index 9e7c6f63e..2c213b7f5 100644
--- a/src/tools/cargo/src/cargo/util/toml/mod.rs
+++ b/src/tools/cargo/src/cargo/util/toml/mod.rs
@@ -1,5 +1,5 @@
use std::collections::{BTreeMap, BTreeSet, HashMap};
-use std::fmt;
+use std::fmt::{self, Display, Write};
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::rc::Rc;
@@ -12,8 +12,8 @@ use itertools::Itertools;
use lazycell::LazyCell;
use log::{debug, trace};
use semver::{self, VersionReq};
-use serde::de;
use serde::de::IntoDeserializer as _;
+use serde::de::{self, Unexpected};
use serde::ser;
use serde::{Deserialize, Serialize};
use url::Url;
@@ -355,6 +355,7 @@ pub struct TomlManifest {
patch: Option<BTreeMap<String, BTreeMap<String, TomlDependency>>>,
workspace: Option<TomlWorkspace>,
badges: Option<MaybeWorkspaceBtreeMap>,
+ lints: Option<toml::Value>,
}
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
@@ -442,11 +443,100 @@ impl ser::Serialize for TomlOptLevel {
}
}
-#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
-#[serde(untagged, expecting = "expected a boolean or an integer")]
-pub enum U32OrBool {
- U32(u32),
- Bool(bool),
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
+pub enum TomlDebugInfo {
+ None,
+ LineDirectivesOnly,
+ LineTablesOnly,
+ Limited,
+ Full,
+}
+
+impl ser::Serialize for TomlDebugInfo {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: ser::Serializer,
+ {
+ match self {
+ Self::None => 0.serialize(serializer),
+ Self::LineDirectivesOnly => "line-directives-only".serialize(serializer),
+ Self::LineTablesOnly => "line-tables-only".serialize(serializer),
+ Self::Limited => 1.serialize(serializer),
+ Self::Full => 2.serialize(serializer),
+ }
+ }
+}
+
+impl<'de> de::Deserialize<'de> for TomlDebugInfo {
+ fn deserialize<D>(d: D) -> Result<TomlDebugInfo, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ struct Visitor;
+
+ impl<'de> de::Visitor<'de> for Visitor {
+ type Value = TomlDebugInfo;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str(
+ "a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"",
+ )
+ }
+
+ fn visit_i64<E>(self, value: i64) -> Result<TomlDebugInfo, E>
+ where
+ E: de::Error,
+ {
+ let debuginfo = match value {
+ 0 => TomlDebugInfo::None,
+ 1 => TomlDebugInfo::Limited,
+ 2 => TomlDebugInfo::Full,
+ _ => return Err(de::Error::invalid_value(Unexpected::Signed(value), &self)),
+ };
+ Ok(debuginfo)
+ }
+
+ fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(if v {
+ TomlDebugInfo::Full
+ } else {
+ TomlDebugInfo::None
+ })
+ }
+
+ fn visit_str<E>(self, value: &str) -> Result<TomlDebugInfo, E>
+ where
+ E: de::Error,
+ {
+ let debuginfo = match value {
+ "none" => TomlDebugInfo::None,
+ "limited" => TomlDebugInfo::Limited,
+ "full" => TomlDebugInfo::Full,
+ "line-directives-only" => TomlDebugInfo::LineDirectivesOnly,
+ "line-tables-only" => TomlDebugInfo::LineTablesOnly,
+ _ => return Err(de::Error::invalid_value(Unexpected::Str(value), &self)),
+ };
+ Ok(debuginfo)
+ }
+ }
+
+ d.deserialize_any(Visitor)
+ }
+}
+
+impl Display for TomlDebugInfo {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ TomlDebugInfo::None => f.write_char('0'),
+ TomlDebugInfo::Limited => f.write_char('1'),
+ TomlDebugInfo::Full => f.write_char('2'),
+ TomlDebugInfo::LineDirectivesOnly => f.write_str("line-directives-only"),
+ TomlDebugInfo::LineTablesOnly => f.write_str("line-tables-only"),
+ }
+ }
}
#[derive(Deserialize, Serialize, Clone, Debug, Default, Eq, PartialEq)]
@@ -456,7 +546,7 @@ pub struct TomlProfile {
pub lto: Option<StringOrBool>,
pub codegen_backend: Option<InternedString>,
pub codegen_units: Option<u32>,
- pub debug: Option<U32OrBool>,
+ pub debug: Option<TomlDebugInfo>,
pub split_debuginfo: Option<String>,
pub debug_assertions: Option<bool>,
pub rpath: Option<bool>,
@@ -1332,6 +1422,29 @@ impl<'de> de::Deserialize<'de> for MaybeWorkspaceBtreeMap {
}
}
+type MaybeWorkspaceLints = MaybeWorkspace<TomlLints, TomlWorkspaceField>;
+
+impl<'de> de::Deserialize<'de> for MaybeWorkspaceLints {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ let value = serde_value::Value::deserialize(deserializer)?;
+
+ if let Ok(w) = TomlWorkspaceField::deserialize(
+ serde_value::ValueDeserializer::<D::Error>::new(value.clone()),
+ ) {
+ return if w.workspace() {
+ Ok(MaybeWorkspace::Workspace(w))
+ } else {
+ Err(de::Error::custom("`workspace` cannot be false"))
+ };
+ }
+ TomlLints::deserialize(serde_value::ValueDeserializer::<D::Error>::new(value))
+ .map(MaybeWorkspace::Defined)
+ }
+}
+
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct TomlWorkspaceField {
#[serde(deserialize_with = "bool_no_false")]
@@ -1418,6 +1531,7 @@ pub struct TomlWorkspace {
// Properties that can be inherited by members.
package: Option<InheritableFields>,
dependencies: Option<BTreeMap<String, TomlDependency>>,
+ lints: Option<toml::Value>,
// Note that this field must come last due to the way toml serialization
// works which requires tables to be emitted after all values.
@@ -1431,6 +1545,9 @@ pub struct InheritableFields {
// and we don't want it present when serializing
#[serde(skip)]
dependencies: Option<BTreeMap<String, TomlDependency>>,
+ #[serde(skip)]
+ lints: Option<TomlLints>,
+
version: Option<semver::Version>,
authors: Option<Vec<String>>,
description: Option<String>,
@@ -1461,6 +1578,10 @@ impl InheritableFields {
self.dependencies = deps;
}
+ pub fn update_lints(&mut self, lints: Option<TomlLints>) {
+ self.lints = lints;
+ }
+
pub fn update_ws_path(&mut self, ws_root: PathBuf) {
self.ws_root = ws_root;
}
@@ -1472,6 +1593,12 @@ impl InheritableFields {
)
}
+ pub fn lints(&self) -> CargoResult<TomlLints> {
+ self.lints
+ .clone()
+ .map_or(Err(anyhow!("`workspace.lints` was not defined")), |d| Ok(d))
+ }
+
pub fn get_dependency(&self, name: &str, package_root: &Path) -> CargoResult<TomlDependency> {
self.dependencies.clone().map_or(
Err(anyhow!("`workspace.dependencies` was not defined")),
@@ -1789,6 +1916,7 @@ impl TomlManifest {
workspace: None,
badges: self.badges.clone(),
cargo_features: self.cargo_features.clone(),
+ lints: self.lints.clone(),
});
fn map_deps(
@@ -1917,6 +2045,9 @@ impl TomlManifest {
let mut inheritable = toml_config.package.clone().unwrap_or_default();
inheritable.update_ws_path(package_root.to_path_buf());
inheritable.update_deps(toml_config.dependencies.clone());
+ let lints = parse_unstable_lints(toml_config.lints.clone(), config, &mut warnings)?;
+ let lints = verify_lints(lints)?;
+ inheritable.update_lints(lints);
if let Some(ws_deps) = &inheritable.dependencies {
for (name, dep) in ws_deps {
unused_dep_keys(
@@ -2180,6 +2311,14 @@ impl TomlManifest {
&inherit_cell,
)?;
+ let lints =
+ parse_unstable_lints::<MaybeWorkspaceLints>(me.lints.clone(), config, cx.warnings)?
+ .map(|mw| mw.resolve("lints", || inherit()?.lints()))
+ .transpose()?;
+ let lints = verify_lints(lints)?;
+ let default = TomlLints::default();
+ let rustflags = lints_to_rustflags(lints.as_ref().unwrap_or(&default));
+
let mut target: BTreeMap<String, TomlPlatform> = BTreeMap::new();
for (name, platform) in me.target.iter().flatten() {
cx.platform = {
@@ -2278,6 +2417,7 @@ impl TomlManifest {
deps,
me.features.as_ref().unwrap_or(&empty_features),
package.links.as_deref(),
+ rust_version.as_deref().map(InternedString::new),
)?;
let metadata = ManifestMetadata {
@@ -2344,6 +2484,11 @@ impl TomlManifest {
.transpose()?
.unwrap_or_default(),
links: package.links.clone(),
+ rust_version: package
+ .rust_version
+ .clone()
+ .map(|mw| mw.resolve("rust-version", || inherit()?.rust_version()))
+ .transpose()?,
};
package.description = metadata
.description
@@ -2471,6 +2616,8 @@ impl TomlManifest {
.badges
.as_ref()
.map(|_| MaybeWorkspace::Defined(metadata.badges.clone())),
+ lints: lints
+ .map(|lints| toml::Value::try_from(MaybeWorkspaceLints::Defined(lints)).unwrap()),
};
let mut manifest = Manifest::new(
summary,
@@ -2495,6 +2642,7 @@ impl TomlManifest {
Rc::new(resolved_toml),
package.metabuild.clone().map(|sov| sov.0),
resolve_behavior,
+ rustflags,
);
if package.license_file.is_some() && package.license.is_some() {
manifest.warnings_mut().add_warning(
@@ -2600,6 +2748,9 @@ impl TomlManifest {
let mut inheritable = toml_config.package.clone().unwrap_or_default();
inheritable.update_ws_path(root.to_path_buf());
inheritable.update_deps(toml_config.dependencies.clone());
+ let lints = parse_unstable_lints(toml_config.lints.clone(), config, &mut warnings)?;
+ let lints = verify_lints(lints)?;
+ inheritable.update_lints(lints);
let ws_root_config = WorkspaceRootConfig::new(
root,
&toml_config.members,
@@ -2744,6 +2895,107 @@ impl TomlManifest {
}
}
+fn parse_unstable_lints<T: Deserialize<'static>>(
+ lints: Option<toml::Value>,
+ config: &Config,
+ warnings: &mut Vec<String>,
+) -> CargoResult<Option<T>> {
+ let Some(lints) = lints else { return Ok(None); };
+
+ if !config.cli_unstable().lints {
+ warn_for_lint_feature(config, warnings);
+ return Ok(None);
+ }
+
+ lints.try_into().map(Some).map_err(|err| err.into())
+}
+
+fn warn_for_lint_feature(config: &Config, warnings: &mut Vec<String>) {
+ use std::fmt::Write as _;
+
+ let key_name = "lints";
+ let feature_name = "lints";
+
+ let mut message = String::new();
+
+ let _ = write!(
+ message,
+ "unused manifest key `{key_name}` (may be supported in a future version)"
+ );
+ if config.nightly_features_allowed {
+ let _ = write!(
+ message,
+ "
+
+consider passing `-Z{feature_name}` to enable this feature."
+ );
+ } else {
+ let _ = write!(
+ message,
+ "
+
+this Cargo does not support nightly features, but if you
+switch to nightly channel you can pass
+`-Z{feature_name}` to enable this feature.",
+ );
+ }
+ warnings.push(message);
+}
+
+fn verify_lints(lints: Option<TomlLints>) -> CargoResult<Option<TomlLints>> {
+ let Some(lints) = lints else { return Ok(None); };
+
+ for (tool, lints) in &lints {
+ let supported = ["rust", "clippy", "rustdoc"];
+ if !supported.contains(&tool.as_str()) {
+ let supported = supported.join(", ");
+ anyhow::bail!("unsupported `{tool}` in `[lints]`, must be one of {supported}")
+ }
+ for name in lints.keys() {
+ if let Some((prefix, suffix)) = name.split_once("::") {
+ if tool == prefix {
+ anyhow::bail!(
+ "`lints.{tool}.{name}` is not valid lint name; try `lints.{prefix}.{suffix}`"
+ )
+ } else if tool == "rust" && supported.contains(&prefix) {
+ anyhow::bail!(
+ "`lints.{tool}.{name}` is not valid lint name; try `lints.{prefix}.{suffix}`"
+ )
+ } else {
+ anyhow::bail!("`lints.{tool}.{name}` is not a valid lint name")
+ }
+ }
+ }
+ }
+
+ Ok(Some(lints))
+}
+
+fn lints_to_rustflags(lints: &TomlLints) -> Vec<String> {
+ let mut rustflags = lints
+ .iter()
+ .flat_map(|(tool, lints)| {
+ lints.iter().map(move |(name, config)| {
+ let flag = config.level().flag();
+ let option = if tool == "rust" {
+ format!("{flag}={name}")
+ } else {
+ format!("{flag}={tool}::{name}")
+ };
+ (
+ config.priority(),
+ // Since the most common group will be `all`, put it last so people are more
+ // likely to notice that they need to use `priority`.
+ std::cmp::Reverse(name),
+ option,
+ )
+ })
+ })
+ .collect::<Vec<_>>();
+ rustflags.sort();
+ rustflags.into_iter().map(|(_, _, option)| option).collect()
+}
+
fn unused_dep_keys(
dep_name: &str,
kind: &str,
@@ -2908,8 +3160,8 @@ impl<P: ResolveToPath + Clone> DetailedTomlDependency<P> {
if self.version.is_none() && self.path.is_none() && self.git.is_none() {
let msg = format!(
"dependency ({}) specified without \
- providing a local path, Git repository, or \
- version to use. This will be considered an \
+ providing a local path, Git repository, version, or \
+ workspace dependency to use. This will be considered an \
error in future versions",
name_in_toml
);
@@ -3301,3 +3553,58 @@ impl fmt::Debug for PathValue {
self.0.fmt(f)
}
}
+
+pub type TomlLints = BTreeMap<String, TomlToolLints>;
+
+pub type TomlToolLints = BTreeMap<String, TomlLint>;
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+#[serde(untagged)]
+pub enum TomlLint {
+ Level(TomlLintLevel),
+ Config(TomlLintConfig),
+}
+
+impl TomlLint {
+ fn level(&self) -> TomlLintLevel {
+ match self {
+ Self::Level(level) => *level,
+ Self::Config(config) => config.level,
+ }
+ }
+
+ fn priority(&self) -> i8 {
+ match self {
+ Self::Level(_) => 0,
+ Self::Config(config) => config.priority,
+ }
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+#[serde(rename_all = "kebab-case")]
+pub struct TomlLintConfig {
+ level: TomlLintLevel,
+ #[serde(default)]
+ priority: i8,
+}
+
+#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
+#[serde(rename_all = "kebab-case")]
+pub enum TomlLintLevel {
+ Forbid,
+ Deny,
+ Warn,
+ Allow,
+}
+
+impl TomlLintLevel {
+ fn flag(&self) -> &'static str {
+ match self {
+ Self::Forbid => "--forbid",
+ Self::Deny => "--deny",
+ Self::Warn => "--warn",
+ Self::Allow => "--allow",
+ }
+ }
+}
diff --git a/src/tools/cargo/src/cargo/util/toml_mut/dependency.rs b/src/tools/cargo/src/cargo/util/toml_mut/dependency.rs
index d8a2f2750..1b24833c1 100644
--- a/src/tools/cargo/src/cargo/util/toml_mut/dependency.rs
+++ b/src/tools/cargo/src/cargo/util/toml_mut/dependency.rs
@@ -225,62 +225,72 @@ impl Dependency {
(key.to_owned(), None)
};
- let source: Source =
- if let Some(git) = table.get("git") {
- let mut src = GitSource::new(
- git.as_str()
- .ok_or_else(|| invalid_type(key, "git", git.type_name(), "string"))?,
- );
- if let Some(value) = table.get("branch") {
- src = src.set_branch(value.as_str().ok_or_else(|| {
+ let source: Source = if let Some(git) = table.get("git") {
+ let mut src = GitSource::new(
+ git.as_str()
+ .ok_or_else(|| invalid_type(key, "git", git.type_name(), "string"))?,
+ );
+ if let Some(value) = table.get("branch") {
+ src =
+ src.set_branch(value.as_str().ok_or_else(|| {
invalid_type(key, "branch", value.type_name(), "string")
})?);
- }
- if let Some(value) = table.get("tag") {
- src = src.set_tag(value.as_str().ok_or_else(|| {
+ }
+ if let Some(value) = table.get("tag") {
+ src =
+ src.set_tag(value.as_str().ok_or_else(|| {
invalid_type(key, "tag", value.type_name(), "string")
})?);
- }
- if let Some(value) = table.get("rev") {
- src = src.set_rev(value.as_str().ok_or_else(|| {
+ }
+ if let Some(value) = table.get("rev") {
+ src =
+ src.set_rev(value.as_str().ok_or_else(|| {
invalid_type(key, "rev", value.type_name(), "string")
})?);
- }
- if let Some(value) = table.get("version") {
- src = src.set_version(value.as_str().ok_or_else(|| {
- invalid_type(key, "version", value.type_name(), "string")
- })?);
- }
- src.into()
- } else if let Some(path) = table.get("path") {
- let path = crate_root
+ }
+ if let Some(value) = table.get("version") {
+ src = src.set_version(value.as_str().ok_or_else(|| {
+ invalid_type(key, "version", value.type_name(), "string")
+ })?);
+ }
+ src.into()
+ } else if let Some(path) = table.get("path") {
+ let path =
+ crate_root
.join(path.as_str().ok_or_else(|| {
invalid_type(key, "path", path.type_name(), "string")
})?);
- let mut src = PathSource::new(path);
- if let Some(value) = table.get("version") {
- src = src.set_version(value.as_str().ok_or_else(|| {
- invalid_type(key, "version", value.type_name(), "string")
- })?);
- }
- src.into()
- } else if let Some(version) = table.get("version") {
- let src = RegistrySource::new(version.as_str().ok_or_else(|| {
+ let mut src = PathSource::new(path);
+ if let Some(value) = table.get("version") {
+ src = src.set_version(value.as_str().ok_or_else(|| {
+ invalid_type(key, "version", value.type_name(), "string")
+ })?);
+ }
+ src.into()
+ } else if let Some(version) = table.get("version") {
+ let src =
+ RegistrySource::new(version.as_str().ok_or_else(|| {
invalid_type(key, "version", version.type_name(), "string")
})?);
- src.into()
- } else if let Some(workspace) = table.get("workspace") {
- let workspace_bool = workspace.as_bool().ok_or_else(|| {
- invalid_type(key, "workspace", workspace.type_name(), "bool")
- })?;
- if !workspace_bool {
- anyhow::bail!("`{key}.workspace = false` is unsupported")
- }
- let src = WorkspaceSource::new();
- src.into()
- } else {
- anyhow::bail!("Unrecognized dependency source for `{key}`");
- };
+ src.into()
+ } else if let Some(workspace) = table.get("workspace") {
+ let workspace_bool = workspace
+ .as_bool()
+ .ok_or_else(|| invalid_type(key, "workspace", workspace.type_name(), "bool"))?;
+ if !workspace_bool {
+ anyhow::bail!("`{key}.workspace = false` is unsupported")
+ }
+ let src = WorkspaceSource::new();
+ src.into()
+ } else {
+ let mut msg = format!("unrecognized dependency source for `{key}`");
+ if table.is_empty() {
+ msg.push_str(
+ ", expected a local path, Git repository, version, or workspace dependency to be specified",
+ );
+ }
+ anyhow::bail!(msg);
+ };
let registry = if let Some(value) = table.get("registry") {
Some(
value
diff --git a/src/tools/cargo/src/doc/README.md b/src/tools/cargo/src/doc/README.md
index 79181b7f6..d67838868 100644
--- a/src/tools/cargo/src/doc/README.md
+++ b/src/tools/cargo/src/doc/README.md
@@ -50,17 +50,17 @@ directory) to three different formats:
3. Plain text (needed for embedded man pages on platforms without man such as
Windows), saved in [`src/doc/man/generated_txt/`](man/generated_txt).
-To rebuild the man pages, run the script `build-man.sh` in the `src/doc` directory.
-
-```console
-$ ./build-man.sh
-```
+To rebuild the man pages, run `cargo build-man` inside the workspace.
### SemVer chapter tests
There is a script to verify that the examples in the SemVer chapter work as
-intended. To run the tests, go into the `semver-check` directory and run
-`cargo run`.
+intended. To run the tests, run `cargo +stable run -p semver-check`.
+
+Note that these tests run on the most recent stable release because they
+validate the output of the compiler diagnostics. The output can change between
+releases, so we pin to a specific release to avoid frequent and unexpected
+breakage.
## Contributing
diff --git a/src/tools/cargo/src/doc/build-man.sh b/src/tools/cargo/src/doc/build-man.sh
deleted file mode 100755
index 7b1330b58..000000000
--- a/src/tools/cargo/src/doc/build-man.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-#
-# This script builds the Cargo man pages.
-#
-# The source for the man pages are located in src/doc/man/ in markdown format.
-# These also are handlebars templates, see crates/mdman/README.md for details.
-#
-# The generated man pages are placed in the src/etc/man/ directory. The pages
-# are also expanded into markdown (after being expanded by handlebars) and
-# saved in the src/doc/src/commands/ directory. These are included in the
-# Cargo book, which is converted to HTML by mdbook.
-
-set -e
-
-cd "$(dirname "${BASH_SOURCE[0]}")"
-
-OPTIONS="--url https://doc.rust-lang.org/cargo/commands/ \
- --man rustc:1=https://doc.rust-lang.org/rustc/index.html \
- --man rustdoc:1=https://doc.rust-lang.org/rustdoc/index.html"
-
-cargo run --manifest-path=../../crates/mdman/Cargo.toml -- \
- -t md -o src/commands man/cargo*.md \
- $OPTIONS
-
-cargo run --manifest-path=../../crates/mdman/Cargo.toml -- \
- -t txt -o man/generated_txt man/cargo*.md \
- $OPTIONS
-
-cargo run --manifest-path=../../crates/mdman/Cargo.toml -- \
- -t man -o ../etc/man man/cargo*.md \
- $OPTIONS
diff --git a/src/tools/cargo/src/doc/contrib/src/SUMMARY.md b/src/tools/cargo/src/doc/contrib/src/SUMMARY.md
index 643cc5ac7..053a9db35 100644
--- a/src/tools/cargo/src/doc/contrib/src/SUMMARY.md
+++ b/src/tools/cargo/src/doc/contrib/src/SUMMARY.md
@@ -2,6 +2,7 @@
- [Introduction](./index.md)
- [Issue Tracker](./issues.md)
+- [Cargo Team](./team.md)
- [Process](./process/index.md)
- [Working on Cargo](./process/working-on-cargo.md)
- [Release process](./process/release.md)
diff --git a/src/tools/cargo/src/doc/contrib/src/implementation/console.md b/src/tools/cargo/src/doc/contrib/src/implementation/console.md
index a73d232e0..99d31b951 100644
--- a/src/tools/cargo/src/doc/contrib/src/implementation/console.md
+++ b/src/tools/cargo/src/doc/contrib/src/implementation/console.md
@@ -19,7 +19,7 @@ the [`JobQueue`] as it processes each message.
[`Shell`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/shell.rs
[`Config`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/util/config/mod.rs
[`drop_print`]: https://github.com/rust-lang/cargo/blob/e4b65bdc80f2a293447f2f6a808fa7c84bf9a357/src/cargo/util/config/mod.rs#L1820-L1848
-[`JobQueue`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/job_queue.rs
+[`JobQueue`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/job_queue/mod.rs
## Errors
diff --git a/src/tools/cargo/src/doc/contrib/src/implementation/filesystem.md b/src/tools/cargo/src/doc/contrib/src/implementation/filesystem.md
index 0f70c5833..3c1b2dbd5 100644
--- a/src/tools/cargo/src/doc/contrib/src/implementation/filesystem.md
+++ b/src/tools/cargo/src/doc/contrib/src/implementation/filesystem.md
@@ -17,5 +17,5 @@ its best to handle them. Some examples of issues to deal with:
fractional part of the time stamp.
* Symlinks are not always supported, particularly on Windows.
-[`fingerprint`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/fingerprint.rs
+[`fingerprint`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/fingerprint/mod.rs
[`fs::canonicalize`]: https://doc.rust-lang.org/std/fs/fn.canonicalize.html
diff --git a/src/tools/cargo/src/doc/contrib/src/index.md b/src/tools/cargo/src/doc/contrib/src/index.md
index 5ab169ea7..848b0efaa 100644
--- a/src/tools/cargo/src/doc/contrib/src/index.md
+++ b/src/tools/cargo/src/doc/contrib/src/index.md
@@ -5,8 +5,8 @@ overview of how to contribute to Cargo, how to dive into the code, and how the
testing infrastructure works.
There are many ways to contribute, such as [helping other users], [filing
-issues], [improving the documentation], [fixing bugs], and working on [small]
-and [large features].
+issues], [improving the documentation], [triaging issues], [fixing bugs], and
+working on [small] and [large features].
If you have a general question about Cargo or its internals, feel free to ask
on [Zulip].
@@ -24,6 +24,7 @@ Please also read the [Rust Code of Conduct].
[rustup]: https://rust-lang.github.io/rustup/
[git]: https://git-scm.com/
[improving the documentation]: https://github.com/rust-lang/cargo/tree/master/src/doc
-[fixing bugs]: process/index.md#working-on-small-bugs
+[fixing bugs]: process/index.md#working-on-issues
[small]: process/index.md#working-on-small-features
[large features]: process/index.md#working-on-large-features
+[triaging issues]: issues.md#triaging-issues
diff --git a/src/tools/cargo/src/doc/contrib/src/issues.md b/src/tools/cargo/src/doc/contrib/src/issues.md
index 8fc69544c..b82492d27 100644
--- a/src/tools/cargo/src/doc/contrib/src/issues.md
+++ b/src/tools/cargo/src/doc/contrib/src/issues.md
@@ -57,53 +57,184 @@ necessary.
## Issue labels
[Issue labels] are very helpful to identify the types of issues and which
-category they are related to. The Cargo team typically manages assigning
-labels. The labels use a naming convention with short prefixes and colors to
-indicate the kind of label:
+category they are related to.
-* Yellow, **A**-prefixed labels state which **area** of the project an issue
- relates to.
+Anyone can apply most labels by posting comments with a form such as:
-* Light purple, **C**-prefixed labels represent the **category** of an issue.
- In particular, **[C-feature-request]** marks *proposals* for new features. If
- an issue is **C-feature-request**, but is not **[Feature accepted]** or
- **[I-nominated]**, then it was not thoroughly discussed, and might need some
- additional design or perhaps should be implemented as an external subcommand
- first. Ping @rust-lang/cargo if you want to send a PR for such issue.
+```text
+@rustbot label: +A-doctests, -A-dependency-resolution
+```
-* Dark purple, **Command**-prefixed labels mean the issue has to do with a
- specific cargo command.
+This example will add the [`A-doctests`] label and remove the
+[`A-dependency-resolution`] label.
-* Green, **E**-prefixed labels indicate the level of **experience** or
- **effort** necessary to fix the issue. **[E-mentor]** issues also
- have some instructions on how to get started. Generally, all of the
- **E**-prefixed labels are issues that are ready for someone to contribute
- to!
+[Issue labels]: https://github.com/rust-lang/cargo/labels
+[`A-doctests`]: https://github.com/rust-lang/cargo/labels/A-doctests
+[`A-dependency-resolution`]: https://github.com/rust-lang/cargo/labels/A-dependency-resolution
+
+The labels use a naming convention with short prefixes and colors to indicate
+the kind of label:
+
+<style>
+.label-color {
+ border-radius:0.5em;
+}
+table td:nth-child(2) {
+ white-space: nowrap;
+}
+
+</style>
+
+| Labels | Color | Description |
+|--------|-------|-------------|
+| [A-] | <span class="label-color" style="background-color:#fbca04;">&#x2003;</span>&nbsp;Yellow | The **area** of the project an issue relates to. |
+| [beta-] | <span class="label-color" style="background-color:#1e76d9;">&#x2003;</span>&nbsp;Dark Blue | Tracks changes which need to be [backported to beta][beta-backport] |
+| [C-] | <span class="label-color" style="background-color:#f5f1fd;">&#x2003;</span>&nbsp;Light Purple | The **category** of an issue. |
+| [Command-] | <span class="label-color" style="background-color:#5319e7;">&#x2003;</span>&nbsp;Dark Purple | The `cargo` command it is related to. |
+| [E-] | <span class="label-color" style="background-color:#02e10c;">&#x2003;</span>&nbsp;Green | The **experience** level necessary to fix an issue. |
+| [I-] | <span class="label-color" style="background-color:#fc2929;">&#x2003;</span>&nbsp;Red | The **importance** of the issue. |
+| [O-] | <span class="label-color" style="background-color:#7e7ec8;">&#x2003;</span>&nbsp;Purple Grey | The **operating system** or platform that the issue is specific to. |
+| [P-] | <span class="label-color" style="background-color:#eb6420;">&#x2003;</span>&nbsp;Orange | The issue **priority**. |
+| [regression-] | <span class="label-color" style="background-color:#e4008a;">&#x2003;</span>&nbsp;Pink | Tracks regressions from a stable release. |
+| [relnotes] | <span class="label-color" style="background-color:#fad8c7;">&#x2003;</span>&nbsp;Light Orange | Marks issues or PRs that should be highlighted in the [Rust release notes] of the next release. |
+| [S-] | Varies | Tracks the **status** of issues and pull requests (see [Issue status labels](#issue-status-labels)) |
+| [Z-] | <span class="label-color" style="background-color:#453574;">&#x2003;</span>&nbsp;Dark Blue | Unstable, [nightly features]. |
+
+
+[A-]: https://github.com/rust-lang/cargo/labels?q=A
+[beta-]: https://github.com/rust-lang/cargo/labels?q=beta
+[beta-backport]: https://forge.rust-lang.org/release/backporting.html#beta-backporting-in-rust-langcargo
+[C-]: https://github.com/rust-lang/cargo/labels?q=C
+[Command-]: https://github.com/rust-lang/cargo/labels?q=Command
+[E-]: https://github.com/rust-lang/cargo/labels?q=E
+[I-]: https://github.com/rust-lang/cargo/labels?q=I
+[nightly features]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html
+[O-]: https://github.com/rust-lang/cargo/labels?q=O
+[P-]: https://github.com/rust-lang/cargo/labels?q=P
+[regression-]: https://github.com/rust-lang/cargo/labels?q=regression
+[relnotes]: https://github.com/rust-lang/cargo/issues?q=label%3Arelnotes
+[Rust release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md
+[S-]: https://github.com/rust-lang/cargo/labels?q=S
+[Z-]: https://github.com/rust-lang/cargo/labels?q=nightly
-* Red, **I**-prefixed labels indicate the **importance** of the issue. The
- **[I-nominated]** label indicates that an issue has been nominated for
- prioritizing at the next triage meeting.
+### Issue status labels
-* Purple gray, **O**-prefixed labels are the **operating system** or platform
- that this issue is specific to.
+The `S-` prefixed *status* labels are the primary mechanism we use to track
+what is happening with an issue and what it is waiting on. The following is a
+list of the status labels and what they mean. This is listed roughly in the
+order that an issue might go through, though issues will often jump to
+different steps, or in rare cases have multiple statuses.
-* Orange, **P**-prefixed labels indicate a bug's **priority**.
+* **[S-triage]** --- New issues get this label automatically assigned to them
+ to indicate that nobody has yet looked at them, and they need someone to
+ assign other labels and decide what the next step is.
-* **S**-prefixed labels are "status" labels, typically used for PRs, but can
- also indicate an issue is **[S-blocked]**.
+* **[S-needs-info]** --- Needs more info, such as a reproduction or more
+ background for a feature request.
-* The light orange **[relnotes]** label marks issues that should be highlighted
- in the [Rust release notes] of the next release.
+ Anyone is welcome to help with providing additional info to help reproduce
+ or provide more detail on use cases and such. But usually this is a request
+ to the initial author.
-* Dark blue, **Z**-prefixed labels are for unstable, [nightly features].
+ When adding this label, there should also usually be a comment that goes
+ along with it stating the information requested.
+
+* **[S-needs-team-input]** --- Needs input from team on whether/how to
+ proceed.
+
+ Here it is essentially blocked waiting for a team member to move it to the
+ next stage.
+
+* **[S-needs-design]** --- Needs someone to work further on the design for the
+ feature or fix.
+
+ Anyone is welcome to help at this stage, but it should be clear that it is
+ not yet accepted. It is expected that people should contribute comments and
+ ideas to the issue which furthers the process of fleshing out what is
+ needed, or alternate ideas. This may also require reaching out to the wider
+ community via forums and such.
+
+* **[S-needs-rfc]** --- Needs an [RFC] before this can make more progress.
+
+ Anyone is welcome to help at this stage, but it should be clear that it is
+ not yet accepted. However, this should only be tagged for changes that are
+ somewhat likely to be accepted.
+
+* **[S-needs-mentor]** --- Needs a Cargo team member to commit to helping and
+ reviewing.
+
+ This is for something that is accepted, such as after an RFC or a team
+ discussion, or an obvious issue that just needs fixing, but no team member
+ is available to help or review.
+
+* **[S-accepted]** --- Issue or feature is accepted, and has a team member
+ available to help mentor or review.
+
+* **[S-waiting-on-feedback]** --- An implemented feature is waiting on
+ community feedback for bugs or design concerns.
+
+ This is typically used on a [tracking issue] after it has been implemented
+ to indicate what it is waiting on.
+
+
+[S-triage]: https://github.com/rust-lang/cargo/labels/S-triage
+[S-needs-info]: https://github.com/rust-lang/cargo/labels/S-needs-info
+[S-needs-team-input]: https://github.com/rust-lang/cargo/labels/S-needs-team-input
+[S-needs-design]: https://github.com/rust-lang/cargo/labels/S-needs-design
+[S-needs-rfc]: https://github.com/rust-lang/cargo/labels/S-needs-rfc
+[S-needs-mentor]: https://github.com/rust-lang/cargo/labels/S-needs-mentor
+[S-accepted]: https://github.com/rust-lang/cargo/labels/S-accepted
+[S-waiting-on-feedback]: https://github.com/rust-lang/cargo/labels/S-waiting-on-feedback
+[RFC]: https://github.com/rust-lang/rfcs/
+[tracking issue]: https://github.com/rust-lang/cargo/labels/C-tracking-issue
+
+## Triaging issues
+
+Triaging issues involves processing issues to assign appropriate labels, make
+sure the issue has sufficient information, and to decide the next steps.
+When new issues are filed, they should automatically get the [S-triage] label
+assuming the author uses one of the templates. This helps identify which
+issues have not yet been triaged.
+
+There are several things to consider when triaging an issue:
+
+* Is this a duplicate? Search the issue tracker (including closed issues) to
+ see if there is something similar or identical to what is reported. If it is
+ obviously a duplicate, write a comment that it is a duplicate of the other
+ issue, and close the issue. If it isn't obvious that it is a duplicate,
+ leave a comment asking the author if the other issue covers what they reported.
+
+* For a bug, check if the report contains enough information to reproduce it.
+ If you can't reproduce it, solicit more information from the author to
+ better understand the issue.
+ Change the label from [S-triage] to [S-needs-info] if this is the case.
+
+* Add labels that describe what the issue is related to.
+
+ * Add the appropriate [A-], [Command-], [O-], and [Z-] prefixed labels.
+ * If this is a regression from stable, add one of the [regression-]
+ prefixed labels (depending on if it is a regression in an already
+ released stable release, or it is in nightly).
-[Issue labels]: https://github.com/rust-lang/cargo/labels
-[E-easy]: https://github.com/rust-lang/cargo/labels/E-easy
-[E-mentor]: https://github.com/rust-lang/cargo/labels/E-mentor
-[I-nominated]: https://github.com/rust-lang/cargo/labels/I-nominated
-[C-feature-request]: https://github.com/rust-lang/cargo/labels/C-feature-request
-[Feature accepted]: https://github.com/rust-lang/cargo/labels/Feature%20accepted
-[S-blocked]: https://github.com/rust-lang/cargo/labels/S-blocked
-[Rust release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md
-[nightly features]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html
-[relnotes]: https://github.com/rust-lang/cargo/issues?q=label%3Arelnotes
+* Assuming the issue looks valid, remove the [S-triage] label and move it onto
+ a new status:
+
+ * [S-needs-rfc] --- This is a large feature request that will require a
+ public design process.
+ * [S-needs-design] --- The resolution of the issue or small feature request
+ will need more work to come up with the appropriate design.
+ * [S-needs-team-input] --- The next steps are not clear, and the Cargo team
+ needs to discuss whether or not to proceed and what needs to be done to
+ address the issue.
+ * [S-needs-mentor] --- This is something the Cargo team wants to address,
+ but does not currently have the capacity to help with reviewing.
+ * [S-accepted] --- This is something that clearly needs to be addressed, and
+ a Cargo team member has volunteered to help review.
+
+Anyone is welcome to help with the triaging process. You can help with
+reproducing issues, checking for duplicates, gathering more information from
+the reporter, assigning labels using [`@rustbot` comments](#issue-labels), and
+creating a test using [Cargo's testsuite] ([example][cargotest-example]).
+
+[Cargo's testsuite]: tests/writing.md
+[cargotest-example]: https://github.com/rust-lang/cargo/issues/11628#issuecomment-1411088951
diff --git a/src/tools/cargo/src/doc/contrib/src/process/index.md b/src/tools/cargo/src/doc/contrib/src/process/index.md
index 348c49ba9..63f07ca55 100644
--- a/src/tools/cargo/src/doc/contrib/src/process/index.md
+++ b/src/tools/cargo/src/doc/contrib/src/process/index.md
@@ -15,16 +15,12 @@ reviewed.**
[Working on Cargo]: working-on-cargo.md
-## Cargo team
+## Mentorship
-Cargo is managed by a [team] of volunteers. The Cargo Team reviews all
-changes, and sets the direction for the project.
+Some Cargo team members are available to directly mentor contributions to Cargo.
+See the [office hours] page for more information.
-The team meets on a weekly basis on a video chat. If you are interested in
-participating, feel free to contact us on [Zulip].
-
-If you would like more direct mentorship, you can join our
-[office hours](https://github.com/rust-lang/cargo/wiki/Office-Hours).
+[office hours]: https://github.com/rust-lang/cargo/wiki/Office-Hours
## Roadmap
@@ -38,44 +34,40 @@ The [RFC Project Board] is used for tracking [RFCs].
[RFC Project Board]: https://github.com/rust-lang/cargo/projects/2
[RFCs]: https://github.com/rust-lang/rfcs/
-## Working on small bugs
+## Working on issues
-Issues labeled with the [E-help-wanted], [E-easy], or [E-mentor] [labels] are
-typically issues that the Cargo team wants to see addressed, and are
-relatively easy to get started with. If you are interested in one of those,
-and it has not already been assigned to someone, leave a comment. See [Issue
+Issues labeled with the [S-accepted] [label] are typically issues that the
+Cargo team wants to see addressed. If you are interested in one of those, and
+it has not already been assigned to someone, leave a comment. See [Issue
assignment](#issue-assignment) below for assigning yourself.
-If there is a specific issue that you are interested in, but it doesn't have
-one of the `E-` labels, leave a comment on the issue. If a Cargo team member
-has the time to help out, they will respond to help with the next steps.
-
-[E-help-wanted]: https://github.com/rust-lang/cargo/labels/E-help-wanted
-[E-easy]: https://github.com/rust-lang/cargo/labels/E-easy
-[E-mentor]: https://github.com/rust-lang/cargo/labels/E-mentor
-[labels]: ../issues.md#issue-labels
-
-## Working on large bugs
+When possible, the Cargo team will try to also include [E-easy], [E-medium],
+or [E-hard] labels to try to give an estimate of the difficulty involved with
+the issue.
-Some issues may be difficult to fix. They may require significant code
-changes, or major design decisions. The [E-medium] and [E-hard] [labels] can
-be used to tag such issues. These will typically involve some discussion with
-the Cargo team on how to tackle it.
+If there is a specific issue that you are interested in, but it is not marked
+as [S-accepted], leave a comment on the issue. If a Cargo team member has the
+time to help out, they will respond to help with the next steps.
+[E-easy]: https://github.com/rust-lang/cargo/labels/E-easy
[E-medium]: https://github.com/rust-lang/cargo/labels/E-medium
[E-hard]: https://github.com/rust-lang/cargo/labels/E-hard
+[S-accepted]: https://github.com/rust-lang/cargo/labels/S-accepted
+[label]: ../issues.md#issue-labels
## Working on small features
Small feature requests are typically managed on the [issue
tracker][issue-feature-request]. Features that the Cargo team have approved
-will have the [Feature accepted] label or the [E-mentor] label. If there is a
-feature request that you are interested in, feel free to leave a comment
-expressing your interest. If a Cargo team member has the time to help out,
-they will respond to help with the next steps. Keep in mind that the Cargo
-team has limited time, and may not be able to help with every feature request.
-Most of them require some design work, which can be difficult. Check out the
-[design principles chapter] for some guidance.
+will have the [S-accepted] label.
+
+If there is a feature request that you are interested in, but it is not marked
+as [S-accepted], feel free to leave a comment expressing your interest. If a
+Cargo team member has the time to help out, they will respond to help with the
+next steps. Keep in mind that the Cargo team has limited time, and may not be
+able to help with every feature request. Most of them require some design
+work, which can be difficult. Check out the [design principles chapter] for
+some guidance.
## Working on large features
@@ -114,11 +106,11 @@ The Cargo project uses several bots:
## Issue assignment
-Normally, if you plan to work on an issue that has been marked with one of the
-`E-` tags or [Feature accepted], it is sufficient just to leave a comment that
-you are working on it. We also have a bot that allows you to formally "claim"
-an issue by entering the text `@rustbot claim` in a comment. See the
-[Assignment] docs on how this works.
+Normally, if you plan to work on an issue that has been marked with the
+[S-accepted] label, it is sufficient just to leave a comment that you are
+working on it. We also have a bot that allows you to formally claim an issue
+by entering the text `@rustbot claim` in a comment. See the [Assignment] docs
+on how this works.
[Assignment]: https://github.com/rust-lang/triagebot/wiki/Assignment
diff --git a/src/tools/cargo/src/doc/contrib/src/process/unstable.md b/src/tools/cargo/src/doc/contrib/src/process/unstable.md
index d59b9aa34..9b05efc2e 100644
--- a/src/tools/cargo/src/doc/contrib/src/process/unstable.md
+++ b/src/tools/cargo/src/doc/contrib/src/process/unstable.md
@@ -33,10 +33,30 @@ typically created when a PR is close to being merged, or soon after it is
merged. Use the [tracking issue template] when creating a tracking issue.
Larger features should also get a new label in the issue tracker so that when
-issues are filed, they can be easily tied together.
+issues are filed, they can be easily tied together. Typically this would be
+one of the `Z-` prefixed labels for nightly features.
+
+When opening a tracking issue, be sure to also add an `S-` status label to
+indicate what needs to happen for it to move forward:
+
+* [S-needs-mentor] --- The feature isn't yet implemented, and needs a Cargo
+ team member to commit to helping guide and review the implementation.
+* [S-accepted] --- The feature isn't yet implemented, and has a Cargo team
+ member willing to help review the implementation.
+* [S-waiting-on-feedback] --- After the feature has been implemented, this
+ label indicates that it is waiting on community feedback for bugs or design
+ concerns.
+
+Tracking issues may have multiple status labels if necessary, for example if
+something is only partially implemented, it may have both
+[S-waiting-on-feedback] (for what is implemented) and [S-needs-mentor] or
+[S-accepted] to finish the rest of the work.
[tracking issue]: https://github.com/rust-lang/cargo/labels/C-tracking-issue
[tracking issue template]: https://github.com/rust-lang/cargo/issues/new?labels=C-tracking-issue&template=tracking_issue.md
+[S-needs-mentor]: https://github.com/rust-lang/cargo/labels/S-needs-mentor
+[S-accepted]: https://github.com/rust-lang/cargo/labels/S-accepted
+[S-waiting-on-feedback]: https://github.com/rust-lang/cargo/labels/S-waiting-on-feedback
## Pre-Stabilization
diff --git a/src/tools/cargo/src/doc/contrib/src/team.md b/src/tools/cargo/src/doc/contrib/src/team.md
new file mode 100644
index 000000000..51b8eeddd
--- /dev/null
+++ b/src/tools/cargo/src/doc/contrib/src/team.md
@@ -0,0 +1,157 @@
+# Cargo Team
+
+## Mission
+
+The Cargo Team is a group of volunteers that support the Rust community in developing and maintaining Cargo, the Rust package manager and build tool.
+The team is responsible for deciding how Cargo and its related libraries operate and evolve.
+The team has a shared responsibility with the [crates.io team] for the design and usage of Cargo's index format and its registry API as it relates to the [crates.io] service.
+
+The team is expected to keep Cargo in an operational state, to support Rust's 6-week release cycle, and to uphold the [Design Principles] of Cargo.
+
+[crates.io team]: https://www.rust-lang.org/governance/teams/crates-io
+[crates.io]: https://crates.io/
+[Design Principles]: design.md
+
+## Team membership
+
+The Cargo Team consists of team members with one serving as a team leader.
+The team leader is responsible for coordinating the team and providing a contact point with other teams.
+The leader is selected by consensus of the existing members with no objections.
+
+Membership is maintained in the [Rust team database].
+
+[Rust team database]: https://github.com/rust-lang/team/blob/master/teams/cargo.toml
+
+### Membership expectations
+
+Team members are expected to participate in voting on RFCs and major change proposals
+
+Team members are expected to regularly participate in at least some of the following membership-related activities.
+Members are not expected to participate in all of these activities, but exhibit some interest and involvement in the project that covers some of these activities.
+
+- Attending meetings
+- Reviewing contributions (auto-assignment is managed in [triagebot.toml])
+- Triaging and responding to issues
+- Mentoring new contributors
+- Shepherding major changes and RFCs
+- Coordinating interaction with other Rust groups and outside interests
+- Managing and updating the policies of the Cargo Team itself
+- Keeping up with maintenance of the Cargo codebase, ensuring it stays functional and that infrastructure and team processes continue to run smoothly
+
+Breaks and vacations are welcome and encouraged.
+If a member is no longer participating after a few months, they may be asked to step down.
+
+Members are required to always:
+
+- Represent the Rust project in a way that upholds the [Rust code of conduct][coc] to a high standard.
+- Represent the Cargo Team in a way that upholds the expectations of this charter, and be friendly, welcoming, and constructive with contributors and users.
+
+Members are given privileges, such as:
+
+- Merge permissions (bors rights)
+- Issue and project management (GitHub permissions)
+- Voting and decision making (RFCs, major changes)
+- Access to private communications related to team management and security discussions
+
+[coc]: https://www.rust-lang.org/policies/code-of-conduct
+[triagebot.toml]: https://github.com/rust-lang/cargo/blob/master/triagebot.toml
+
+### Meetings
+
+The team meets on a weekly basis on a video chat.
+If you are interested in participating, feel free to contact us on [Zulip].
+
+### Becoming a member
+
+A contributor can become a member of the Cargo Team by requesting a review or being nominated by one of the existing members.
+They can be added by unanimous consent of the team.
+The team lead or another member of the team will also confirm with the moderation team that there are no concerns involving the proposed team member.
+
+Contributors who wish to join the team should exhibit an interest in carrying the design principles of Cargo and participate in some of the activities listed above in [Membership Expectations](#membership-expectations).
+
+Members may leave at any time, preferably by letting the team know ahead of time.
+
+## Decision process
+
+The team uses a consensus-driven process for making decisions ranging from new features and major changes to management of the team itself.
+The degree of process is correlated with the degree of change being proposed:
+
+- Bug fixes, refactorings, documentation updates, and other small changes are usually delegated to a single team member (who is not the author) to approve based on their judgement.
+ Team members may also solicit feedback from other members or the whole team for any change should they want to gather other perspectives from the team.
+
+ Some examples of what this might cover are:
+ - Bug fixes that do not introduce backwards-incompatible changes, and adhere to Cargo's expected behavior.
+ - Addition of new warnings, or other diagnostic changes.
+ - New or updated documentation.
+ - Localized refactorings (that is, those that do not have a significant, wide-ranging impact to the usage and maintenance of the codebase).
+ - Minor or planned changes to Cargo's console output.
+ - Beta backports that clearly address a regression, and are expected to be low-risk.
+ - Development of a previously approved unstable feature that matches the expected development of that feature.
+
+- Small features or changes, large refactorings, or major changes to Cargo's codebase or process require an approval by the team via consensus.
+ These decisions can be done via the FCP process of [rfcbot], or in an ad-hoc manner such as during a team meeting.
+ rfcbot FCP requests do not require waiting for the 10-day feedback window if there is a complete team consensus, as this process is mostly aimed at polling the team rather than publicly soliciting feedback.
+ Though, public feedback is welcome at any time.
+
+ Some examples of what this might cover are:
+ - Addition of a new, minor command-line argument, or an addition of an option to an existing one.
+ - Addition of new fields and values to JSON outputs.
+ - A bug fix or change that may technically involve a backwards-incompatible change.
+ See the [Backwards compatibility] section for some examples.
+ - Documentation changes that may substantially change the expected usage of Rust and Cargo.
+ For example, the [SemVer chapter] contains subjective prescriptions for how users should develop their code.
+ - A significant change in Cargo's console output.
+ - A significant change to Cargo's code structure, or how maintenance or usage of the Cargo codebase is handled.
+ - Beta backports that are risky or have any uncertainty about their necessity.
+ - [Stable backports].
+ These usually also require involvement with the Release team.
+ - A significant change to the management of the Cargo team itself or the processes it uses, such as significant updates to this document.
+ - Addition of new members to the Cargo team, or other actions involving the team membership.
+ These decisions are usually processed via private channels by the entirety of the team.
+ - A change that is a "one-way door".
+ That is, something that is difficult to reverse without breaking backwards compatibility.
+
+- Larger features should usually go through the [RFC process].
+ This usually involves first soliciting feedback from the Cargo team and the rest of the community, often via the [Rust Internals] discussion board, [Cargo's issue tracker], and the [Zulip] channel.
+ If there is positive feedback to the idea, the next step is to formally post an RFC on the RFC repo.
+ The community and the Cargo team will have an opportunity to provide feedback on the proposal.
+ After some period of time, the Cargo team may decide to either accept, postpone, or close a proposal based on the interest in the proposal and the team's availability.
+
+ Some examples of what this might cover are:
+ - Major changes or new features or options in `Cargo.toml` or the config files.
+ - Changes to the registry index or API.
+ - New or changed CLI options that are expected to have a significant impact on how Cargo is used.
+ - New `cargo` commands that are not trivial.
+ In some cases, the team may decide to adopt a pre-existing external command without an RFC if the command has already been broadly adopted.
+
+- Stabilization of [Unstable] features requires an approval via the FCP process of [rfcbot].
+ This provides a final opportunity to solicit feedback from the public, and for the Cargo team to agree via consensus.
+
+- The team may decide to experiment with larger features without starting the RFC process if it is an initiative that the team has consensus that it is something they want to pursue.
+ This is usually reserved for something that has an unclear path that the RFC process is not expected to provide feedback that would substantially move the process forward.
+ Such experiments are expected to be nightly-only (see the [Unstable] chapter), and involve efforts to shape the final result via exploration, testing, and public involvement.
+ Any such features *must* ultimately have an RFC approved before they can be stabilized.
+
+[rfcbot]: https://github.com/rust-lang/rfcbot-rs
+[RFC process]: https://github.com/rust-lang/rfcs/
+[Rust Internals]: https://internals.rust-lang.org/
+[Unstable]: process/unstable.md
+[Backwards compatibility]: design.md#backwards-compatibility
+[Stable backports]: process/release.md#stable-backports
+[SemVer chapter]: https://doc.rust-lang.org/cargo/reference/semver.html
+
+## Contacting the team
+
+The team may be contacted through several channels:
+
+- If you have a **security concern**, please refer to Rust's [security policy] for the correct contact method.
+- Issues and feature requests can be submitted to [Cargo's issue tracker].
+ Please see the [Issues chapter] for more detail.
+- The [`t-cargo` Zulip channel][Zulip] stream is the chat platform the Cargo Team uses to coordinate on.
+- The <cargo@rust-lang.org> email address can be used to contact the team.
+ However, using one of the other channels is strongly encouraged.
+
+[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo
+[security policy]: https://www.rust-lang.org/security.html
+[Cargo's issue tracker]: https://github.com/rust-lang/cargo/issues/
+[Issues chapter]: issues.md
diff --git a/src/tools/cargo/src/doc/man/cargo-add.md b/src/tools/cargo/src/doc/man/cargo-add.md
index c441a82b2..3c15fc9d5 100644
--- a/src/tools/cargo/src/doc/man/cargo-add.md
+++ b/src/tools/cargo/src/doc/man/cargo-add.md
@@ -123,6 +123,15 @@ crates, the features for a specific crate may be enabled with
which enables all specified features.
{{/option}}
+{{#option "`--ignore-rust-version`" }}
+Ignore `rust-version` specification in packages.
+
+This option is unstable and available only on the
+[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
+and requires the `-Z unstable-options` flag to enable.
+See <https://github.com/rust-lang/cargo/issues/5579> for more information.
+{{/option}}
+
{{/options}}
diff --git a/src/tools/cargo/src/doc/man/cargo-bench.md b/src/tools/cargo/src/doc/man/cargo-bench.md
index 80785891b..18771c3d2 100644
--- a/src/tools/cargo/src/doc/man/cargo-bench.md
+++ b/src/tools/cargo/src/doc/man/cargo-bench.md
@@ -86,11 +86,17 @@ following targets of the selected packages:
The default behavior can be changed by setting the `bench` flag for the target
in the manifest settings. Setting examples to `bench = true` will build and
-run the example as a benchmark. Setting targets to `bench = false` will stop
-them from being benchmarked by default. Target selection options that take a
-target by name ignore the `bench` flag and will always benchmark the given
+run the example as a benchmark, replacing the example's `main` function with
+the libtest harness.
+
+Setting targets to `bench = false` will stop them from being bencharmked by
+default. Target selection options that take a target by name (such as
+`--example foo`) ignore the `bench` flag and will always benchmark the given
target.
+See [Configuring a target](../reference/cargo-targets.html#configuring-a-target)
+for more information on per-target settings.
+
{{> options-targets-bin-auto-built }}
{{> options-targets }}
diff --git a/src/tools/cargo/src/doc/man/cargo-install.md b/src/tools/cargo/src/doc/man/cargo-install.md
index 31c3d6048..385ed27c2 100644
--- a/src/tools/cargo/src/doc/man/cargo-install.md
+++ b/src/tools/cargo/src/doc/man/cargo-install.md
@@ -173,7 +173,7 @@ Directory to install packages into.
{{> options-target-dir }}
{{#option "`--debug`" }}
-Build with the `dev` profile instead the `release` profile.
+Build with the `dev` profile instead of the `release` profile.
See also the `--profile` option for choosing a specific profile by name.
{{/option}}
diff --git a/src/tools/cargo/src/doc/man/cargo-metadata.md b/src/tools/cargo/src/doc/man/cargo-metadata.md
index 4f9032d56..0027a20b1 100644
--- a/src/tools/cargo/src/doc/man/cargo-metadata.md
+++ b/src/tools/cargo/src/doc/man/cargo-metadata.md
@@ -212,6 +212,12 @@ The output has the following format:
"workspace_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
],
+ /* Array of default members of the workspace.
+ Each entry is the Package ID for the package.
+ */
+ "workspace_default_members": [
+ "my-package 0.1.0 (path+file:///path/to/my-package)",
+ ],
// The resolved dependency graph for the entire workspace. The enabled
// features are based on the enabled features for the "current" package.
// Inactivated optional dependencies are not listed.
diff --git a/src/tools/cargo/src/doc/man/cargo-test.md b/src/tools/cargo/src/doc/man/cargo-test.md
index 3dce146e6..49792d6be 100644
--- a/src/tools/cargo/src/doc/man/cargo-test.md
+++ b/src/tools/cargo/src/doc/man/cargo-test.md
@@ -89,13 +89,20 @@ following targets of the selected packages:
The default behavior can be changed by setting the `test` flag for the target
in the manifest settings. Setting examples to `test = true` will build and run
-the example as a test. Setting targets to `test = false` will stop them from
-being tested by default. Target selection options that take a target by name
+the example as a test, replacing the example's `main` function with the
+libtest harness. If you don't want the `main` function replaced, also include
+`harness = false`, in which case the example will be built and executed as-is.
+
+Setting targets to `test = false` will stop them from being tested by default.
+Target selection options that take a target by name (such as `--example foo`)
ignore the `test` flag and will always test the given target.
Doc tests for libraries may be disabled by setting `doctest = false` for the
library in the manifest.
+See [Configuring a target](../reference/cargo-targets.html#configuring-a-target)
+for more information on per-target settings.
+
{{> options-targets-bin-auto-built }}
{{> options-targets }}
diff --git a/src/tools/cargo/src/doc/man/cargo-yank.md b/src/tools/cargo/src/doc/man/cargo-yank.md
index 8ad28ef24..946e98c85 100644
--- a/src/tools/cargo/src/doc/man/cargo-yank.md
+++ b/src/tools/cargo/src/doc/man/cargo-yank.md
@@ -15,9 +15,9 @@ The yank command removes a previously published crate's version from the
server's index. This command does not delete any data, and the crate will
still be available for download via the registry's download link.
-Note that existing crates locked to a yanked version will still be able to
-download the yanked version to use it. Cargo will, however, not allow any new
-crates to be locked to any yanked version.
+Cargo will not use a yanked version for any new project or checkout without a
+pre-existing lockfile, and will generate an error if there are no longer
+any compatible versions for your crate.
This command requires you to be authenticated with either the `--token` option
or using {{man "cargo-login" 1}}.
@@ -25,6 +25,56 @@ or using {{man "cargo-login" 1}}.
If the crate name is not specified, it will use the package name from the
current directory.
+### How yank works
+
+For example, the `foo` crate published version `1.5.0` and another crate `bar`
+declared a dependency on version `foo = "1.5"`. Now `foo` releases a new, but
+not semver compatible, version `2.0.0`, and finds a critical issue with `1.5.0`.
+If `1.5.0` is yanked, no new project or checkout without an existing lockfile
+will be able to use crate `bar` as it relies on `1.5`.
+
+In this case, the maintainers of `foo` should first publish a semver compatible
+version such as `1.5.1` prior to yanking `1.5.0` so that `bar` and all projects
+that depend on `bar` will continue to work.
+
+As another example, consider a crate `bar` with published versions `1.5.0`,
+`1.5.1`, `1.5.2`, `2.0.0` and `3.0.0`. The following table identifies the
+versions cargo could use in the absence of a lockfile for different SemVer
+requirements, following a given release being yanked:
+
+| Yanked Version / SemVer requirement | `bar = "1.5.0"` | `bar = "=1.5.0"` | `bar = "2.0.0"` |
+|-------------------------------------|-----------------------------------------|------------------|------------------|
+| `1.5.0` | Use either `1.5.1` or `1.5.2` | **Return Error** | Use `2.0.0` |
+| `1.5.1` | Use either `1.5.0` or `1.5.2` | Use `1.5.0` | Use `2.0.0` |
+| `2.0.0` | Use either `1.5.0`, `1.5.1` or `0.22.2` | Use `1.5.0` | **Return Error** |
+
+### When to yank
+
+Crates should only be yanked in exceptional circumstances, for example, an
+accidental publish, an unintentional SemVer breakages, or a significantly
+broken and unusable crate. In the case of security vulnerabilities, [RustSec]
+is typically a less disruptive mechanism to inform users and encourage them
+to upgrade, and avoids the possibility of significant downstream disruption
+irrespective of susceptibility to the vulnerability in question.
+
+A common workflow is to yank a crate having already published a semver
+compatible version, to reduce the probability of preventing dependent
+crates from compiling.
+
+When addressing copyright, licensing, or personal data issues with a published
+crate, simply yanking it may not suffice. In such cases, contact the maintainers
+of the registry you used. For crates.io, refer to their [policies] and contact
+them at <help@crates.io>.
+
+If credentials have been leaked, the recommended course of action is to revoke
+them immediately. Once a crate has been published, it is impossible to determine
+if the leaked credentials have been copied. Yanking the crate only prevents new
+users from downloading it, but cannot stop those who have already downloaded it
+from keeping or even spreading the leaked credentials.
+
+[RustSec]: https://rustsec.org/
+[policies]: https://crates.io/policies
+
## OPTIONS
### Yank Options
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-add.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-add.txt
index ac332a44e..6447499dc 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-add.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-add.txt
@@ -111,6 +111,15 @@ OPTIONS
be enabled with package-name/feature-name syntax. This flag may be
specified multiple times, which enables all specified features.
+ --ignore-rust-version
+ Ignore rust-version specification in packages.
+
+ This option is unstable and available only on the nightly channel
+ <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and
+ requires the -Z unstable-options flag to enable. See
+ <https://github.com/rust-lang/cargo/issues/5579> for more
+ information.
+
Display Options
-v, --verbose
Use verbose output. May be specified twice for “very verbose”
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt
index 1ca72d577..9108d6165 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt
@@ -120,10 +120,17 @@ OPTIONS
The default behavior can be changed by setting the bench flag for the
target in the manifest settings. Setting examples to bench = true will
- build and run the example as a benchmark. Setting targets to bench =
- false will stop them from being benchmarked by default. Target selection
- options that take a target by name ignore the bench flag and will always
- benchmark the given target.
+ build and run the example as a benchmark, replacing the example’s main
+ function with the libtest harness.
+
+ Setting targets to bench = false will stop them from being bencharmked
+ by default. Target selection options that take a target by name (such as
+ --example foo) ignore the bench flag and will always benchmark the given
+ target.
+
+ See Configuring a target
+ <https://doc.rust-lang.org/cargo/reference/cargo-targets.html#configuring-a-target>
+ for more information on per-target settings.
Binary targets are automatically built if there is an integration test
or benchmark being selected to benchmark. This allows an integration
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt
index a29cdcd46..7aefd3492 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt
@@ -207,8 +207,8 @@ OPTIONS
workspace of the local crate unless --target-dir is specified.
--debug
- Build with the dev profile instead the release profile. See also the
- --profile option for choosing a specific profile by name.
+ Build with the dev profile instead of the release profile. See also
+ the --profile option for choosing a specific profile by name.
--profile name
Install with the given profile. See the the reference
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt
index be8bed7c6..d9d48fd9a 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt
@@ -207,6 +207,12 @@ OUTPUT FORMAT
"workspace_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
],
+ /* Array of default members of the workspace.
+ Each entry is the Package ID for the package.
+ */
+ "workspace_default_members": [
+ "my-package 0.1.0 (path+file:///path/to/my-package)",
+ ],
// The resolved dependency graph for the entire workspace. The enabled
// features are based on the enabled features for the "current" package.
// Inactivated optional dependencies are not listed.
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt
index 3f4ed6072..9e26f8aae 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt
@@ -128,14 +128,23 @@ OPTIONS
The default behavior can be changed by setting the test flag for the
target in the manifest settings. Setting examples to test = true will
- build and run the example as a test. Setting targets to test = false
- will stop them from being tested by default. Target selection options
- that take a target by name ignore the test flag and will always test the
- given target.
+ build and run the example as a test, replacing the example’s main
+ function with the libtest harness. If you don’t want the main function
+ replaced, also include harness = false, in which case the example will
+ be built and executed as-is.
+
+ Setting targets to test = false will stop them from being tested by
+ default. Target selection options that take a target by name (such as
+ --example foo) ignore the test flag and will always test the given
+ target.
Doc tests for libraries may be disabled by setting doctest = false for
the library in the manifest.
+ See Configuring a target
+ <https://doc.rust-lang.org/cargo/reference/cargo-targets.html#configuring-a-target>
+ for more information on per-target settings.
+
Binary targets are automatically built if there is an integration test
or benchmark being selected to test. This allows an integration test to
execute the binary to exercise and test its behavior. The
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-yank.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-yank.txt
index 376d7373c..784e71a1a 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-yank.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-yank.txt
@@ -13,9 +13,9 @@ DESCRIPTION
crate will still be available for download via the registry’s download
link.
- Note that existing crates locked to a yanked version will still be able
- to download the yanked version to use it. Cargo will, however, not allow
- any new crates to be locked to any yanked version.
+ Cargo will not use a yanked version for any new project or checkout
+ without a pre-existing lockfile, and will generate an error if there are
+ no longer any compatible versions for your crate.
This command requires you to be authenticated with either the --token
option or using cargo-login(1).
@@ -23,6 +23,62 @@ DESCRIPTION
If the crate name is not specified, it will use the package name from
the current directory.
+ How yank works
+ For example, the foo crate published version 1.5.0 and another crate bar
+ declared a dependency on version foo = "1.5". Now foo releases a new,
+ but not semver compatible, version 2.0.0, and finds a critical issue
+ with 1.5.0. If 1.5.0 is yanked, no new project or checkout without an
+ existing lockfile will be able to use crate bar as it relies on 1.5.
+
+ In this case, the maintainers of foo should first publish a semver
+ compatible version such as 1.5.1 prior to yanking 1.5.0 so that bar and
+ all projects that depend on bar will continue to work.
+
+ As another example, consider a crate bar with published versions 1.5.0,
+ 1.5.1, 1.5.2, 2.0.0 and 3.0.0. The following table identifies the
+ versions cargo could use in the absence of a lockfile for different
+ SemVer requirements, following a given release being yanked:
+
+ +------------------------+----------------------+----------+----------+
+ | Yanked Version / | bar = "1.5.0" | bar = | bar = |
+ | SemVer requirement | | "=1.5.0" | "2.0.0" |
+ +------------------------+----------------------+----------+----------+
+ | 1.5.0 | Use either 1.5.1 or | Return | Use |
+ | | 1.5.2 | Error | 2.0.0 |
+ +------------------------+----------------------+----------+----------+
+ | 1.5.1 | Use either 1.5.0 or | Use | Use |
+ | | 1.5.2 | 1.5.0 | 2.0.0 |
+ +------------------------+----------------------+----------+----------+
+ | 2.0.0 | Use either 1.5.0, | Use | Return |
+ | | 1.5.1 or 0.22.2 | 1.5.0 | Error |
+ +------------------------+----------------------+----------+----------+
+
+ When to yank
+ Crates should only be yanked in exceptional circumstances, for example,
+ an accidental publish, an unintentional SemVer breakages, or a
+ significantly broken and unusable crate. In the case of security
+ vulnerabilities, RustSec <https://rustsec.org/> is typically a less
+ disruptive mechanism to inform users and encourage them to upgrade, and
+ avoids the possibility of significant downstream disruption irrespective
+ of susceptibility to the vulnerability in question.
+
+ A common workflow is to yank a crate having already published a semver
+ compatible version, to reduce the probability of preventing dependent
+ crates from compiling.
+
+ When addressing copyright, licensing, or personal data issues with a
+ published crate, simply yanking it may not suffice. In such cases,
+ contact the maintainers of the registry you used. For crates.io, refer
+ to their policies <https://crates.io/policies> and contact them at
+ <help@crates.io>.
+
+ If credentials have been leaked, the recommended course of action is to
+ revoke them immediately. Once a crate has been published, it is
+ impossible to determine if the leaked credentials have been copied.
+ Yanking the crate only prevents new users from downloading it, but
+ cannot stop those who have already downloaded it from keeping or even
+ spreading the leaked credentials.
+
OPTIONS
Yank Options
--vers version, --version version
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-add.md b/src/tools/cargo/src/doc/src/commands/cargo-add.md
index 89c1cc6f1..132c09326 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-add.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-add.md
@@ -129,6 +129,14 @@ crates, the features for a specific crate may be enabled with
which enables all specified features.</dd>
+<dt class="option-term" id="option-cargo-add---ignore-rust-version"><a class="option-anchor" href="#option-cargo-add---ignore-rust-version"></a><code>--ignore-rust-version</code></dt>
+<dd class="option-desc">Ignore <code>rust-version</code> specification in packages.</p>
+<p>This option is unstable and available only on the
+<a href="https://doc.rust-lang.org/book/appendix-07-nightly-rust.html">nightly channel</a>
+and requires the <code>-Z unstable-options</code> flag to enable.
+See <a href="https://github.com/rust-lang/cargo/issues/5579">https://github.com/rust-lang/cargo/issues/5579</a> for more information.</dd>
+
+
</dl>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-bench.md b/src/tools/cargo/src/doc/src/commands/cargo-bench.md
index e7e9b36fb..df0101be5 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-bench.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-bench.md
@@ -143,11 +143,17 @@ following targets of the selected packages:
The default behavior can be changed by setting the `bench` flag for the target
in the manifest settings. Setting examples to `bench = true` will build and
-run the example as a benchmark. Setting targets to `bench = false` will stop
-them from being benchmarked by default. Target selection options that take a
-target by name ignore the `bench` flag and will always benchmark the given
+run the example as a benchmark, replacing the example's `main` function with
+the libtest harness.
+
+Setting targets to `bench = false` will stop them from being bencharmked by
+default. Target selection options that take a target by name (such as
+`--example foo`) ignore the `bench` flag and will always benchmark the given
target.
+See [Configuring a target](../reference/cargo-targets.html#configuring-a-target)
+for more information on per-target settings.
+
Binary targets are automatically built if there is an integration test or
benchmark being selected to benchmark. This allows an integration
test to execute the binary to exercise and test its behavior.
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-install.md b/src/tools/cargo/src/doc/src/commands/cargo-install.md
index 99697c156..5d413010c 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-install.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-install.md
@@ -238,7 +238,7 @@ is specified.</dd>
<dt class="option-term" id="option-cargo-install---debug"><a class="option-anchor" href="#option-cargo-install---debug"></a><code>--debug</code></dt>
-<dd class="option-desc">Build with the <code>dev</code> profile instead the <code>release</code> profile.
+<dd class="option-desc">Build with the <code>dev</code> profile instead of the <code>release</code> profile.
See also the <code>--profile</code> option for choosing a specific profile by name.</dd>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-metadata.md b/src/tools/cargo/src/doc/src/commands/cargo-metadata.md
index ebde0ea10..e9aeac7df 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-metadata.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-metadata.md
@@ -212,6 +212,12 @@ The output has the following format:
"workspace_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
],
+ /* Array of default members of the workspace.
+ Each entry is the Package ID for the package.
+ */
+ "workspace_default_members": [
+ "my-package 0.1.0 (path+file:///path/to/my-package)",
+ ],
// The resolved dependency graph for the entire workspace. The enabled
// features are based on the enabled features for the "current" package.
// Inactivated optional dependencies are not listed.
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-test.md b/src/tools/cargo/src/doc/src/commands/cargo-test.md
index 2967d7381..24fcc70ff 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-test.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-test.md
@@ -146,13 +146,20 @@ following targets of the selected packages:
The default behavior can be changed by setting the `test` flag for the target
in the manifest settings. Setting examples to `test = true` will build and run
-the example as a test. Setting targets to `test = false` will stop them from
-being tested by default. Target selection options that take a target by name
+the example as a test, replacing the example's `main` function with the
+libtest harness. If you don't want the `main` function replaced, also include
+`harness = false`, in which case the example will be built and executed as-is.
+
+Setting targets to `test = false` will stop them from being tested by default.
+Target selection options that take a target by name (such as `--example foo`)
ignore the `test` flag and will always test the given target.
Doc tests for libraries may be disabled by setting `doctest = false` for the
library in the manifest.
+See [Configuring a target](../reference/cargo-targets.html#configuring-a-target)
+for more information on per-target settings.
+
Binary targets are automatically built if there is an integration test or
benchmark being selected to test. This allows an integration
test to execute the binary to exercise and test its behavior.
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-yank.md b/src/tools/cargo/src/doc/src/commands/cargo-yank.md
index 18565d2dc..7fac5bf47 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-yank.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-yank.md
@@ -15,9 +15,9 @@ The yank command removes a previously published crate's version from the
server's index. This command does not delete any data, and the crate will
still be available for download via the registry's download link.
-Note that existing crates locked to a yanked version will still be able to
-download the yanked version to use it. Cargo will, however, not allow any new
-crates to be locked to any yanked version.
+Cargo will not use a yanked version for any new project or checkout without a
+pre-existing lockfile, and will generate an error if there are no longer
+any compatible versions for your crate.
This command requires you to be authenticated with either the `--token` option
or using [cargo-login(1)](cargo-login.html).
@@ -25,6 +25,56 @@ or using [cargo-login(1)](cargo-login.html).
If the crate name is not specified, it will use the package name from the
current directory.
+### How yank works
+
+For example, the `foo` crate published version `1.5.0` and another crate `bar`
+declared a dependency on version `foo = "1.5"`. Now `foo` releases a new, but
+not semver compatible, version `2.0.0`, and finds a critical issue with `1.5.0`.
+If `1.5.0` is yanked, no new project or checkout without an existing lockfile
+will be able to use crate `bar` as it relies on `1.5`.
+
+In this case, the maintainers of `foo` should first publish a semver compatible
+version such as `1.5.1` prior to yanking `1.5.0` so that `bar` and all projects
+that depend on `bar` will continue to work.
+
+As another example, consider a crate `bar` with published versions `1.5.0`,
+`1.5.1`, `1.5.2`, `2.0.0` and `3.0.0`. The following table identifies the
+versions cargo could use in the absence of a lockfile for different SemVer
+requirements, following a given release being yanked:
+
+| Yanked Version / SemVer requirement | `bar = "1.5.0"` | `bar = "=1.5.0"` | `bar = "2.0.0"` |
+|-------------------------------------|-----------------------------------------|------------------|------------------|
+| `1.5.0` | Use either `1.5.1` or `1.5.2` | **Return Error** | Use `2.0.0` |
+| `1.5.1` | Use either `1.5.0` or `1.5.2` | Use `1.5.0` | Use `2.0.0` |
+| `2.0.0` | Use either `1.5.0`, `1.5.1` or `0.22.2` | Use `1.5.0` | **Return Error** |
+
+### When to yank
+
+Crates should only be yanked in exceptional circumstances, for example, an
+accidental publish, an unintentional SemVer breakages, or a significantly
+broken and unusable crate. In the case of security vulnerabilities, [RustSec]
+is typically a less disruptive mechanism to inform users and encourage them
+to upgrade, and avoids the possibility of significant downstream disruption
+irrespective of susceptibility to the vulnerability in question.
+
+A common workflow is to yank a crate having already published a semver
+compatible version, to reduce the probability of preventing dependent
+crates from compiling.
+
+When addressing copyright, licensing, or personal data issues with a published
+crate, simply yanking it may not suffice. In such cases, contact the maintainers
+of the registry you used. For crates.io, refer to their [policies] and contact
+them at <help@crates.io>.
+
+If credentials have been leaked, the recommended course of action is to revoke
+them immediately. Once a crate has been published, it is impossible to determine
+if the leaked credentials have been copied. Yanking the crate only prevents new
+users from downloading it, but cannot stop those who have already downloaded it
+from keeping or even spreading the leaked credentials.
+
+[RustSec]: https://rustsec.org/
+[policies]: https://crates.io/policies
+
## OPTIONS
### Yank Options
diff --git a/src/tools/cargo/src/doc/src/faq.md b/src/tools/cargo/src/doc/src/faq.md
index 8a8840b8f..abe90c000 100644
--- a/src/tools/cargo/src/doc/src/faq.md
+++ b/src/tools/cargo/src/doc/src/faq.md
@@ -98,9 +98,9 @@ Yes!
All commits to Cargo are required to pass the local test suite on Windows.
If you encounter an issue while running on Windows, we consider it a bug, so [please file an
-issue][3].
+issue][cargo-issues].
-[3]: https://github.com/rust-lang/cargo/issues
+[cargo-issues]: https://github.com/rust-lang/cargo/issues
### Why do binaries have `Cargo.lock` in version control, but not libraries?
diff --git a/src/tools/cargo/src/doc/src/reference/manifest.md b/src/tools/cargo/src/doc/src/reference/manifest.md
index 49d5b96c6..5a3d60ccc 100644
--- a/src/tools/cargo/src/doc/src/reference/manifest.md
+++ b/src/tools/cargo/src/doc/src/reference/manifest.md
@@ -203,7 +203,8 @@ description = "A short description of my package"
The `documentation` field specifies a URL to a website hosting the crate's
documentation. If no URL is specified in the manifest file, [crates.io] will
-automatically link your crate to the corresponding [docs.rs] page.
+automatically link your crate to the corresponding [docs.rs] page when the
+documentation has been built and is available (see [docs.rs queue]).
```toml
[package]
@@ -211,6 +212,8 @@ automatically link your crate to the corresponding [docs.rs] page.
documentation = "https://docs.rs/bitflags"
```
+[docs.rs queue]: https://docs.rs/releases/queue
+
#### The `readme` field
The `readme` field should be the path to a file in the package root (relative
diff --git a/src/tools/cargo/src/doc/src/reference/profiles.md b/src/tools/cargo/src/doc/src/reference/profiles.md
index 56c8538f8..124203d55 100644
--- a/src/tools/cargo/src/doc/src/reference/profiles.md
+++ b/src/tools/cargo/src/doc/src/reference/profiles.md
@@ -67,14 +67,20 @@ amount of debug information included in the compiled binary.
The valid options are:
-* `0` or `false`: no debug info at all
-* `1`: line tables only
-* `2` or `true`: full debug info
+* `0`, `false`, or `"none"`: no debug info at all, default for [`release`](#release)
+* `"line-directives-only"`: line info directives only. For the nvptx* targets this enables [profiling]. For other use cases, `line-tables-only` is the better, more compatible choice.
+* `"line-tables-only"`: line tables only. Generates the minimal amount of debug info for backtraces with filename/line number info, but not anything else, i.e. no variable or function parameter info.
+* `1` or `"limited"`: debug info without type or variable-level information. Generates more detailed module-level info than `line-tables-only`.
+* `2`, `true`, or `"full"`: full debug info, default for [`dev`](#dev)
+
+For more information on what each option does see `rustc`'s docs on [debuginfo].
You may wish to also configure the [`split-debuginfo`](#split-debuginfo) option
depending on your needs as well.
[`-C debuginfo` flag]: ../../rustc/codegen-options/index.html#debuginfo
+[debuginfo]: ../../rustc/codegen-options/index.html#debuginfo
+[profiling]: https://reviews.llvm.org/D46061
#### split-debuginfo
diff --git a/src/tools/cargo/src/doc/src/reference/publishing.md b/src/tools/cargo/src/doc/src/reference/publishing.md
index 98d572c34..564dfb34e 100644
--- a/src/tools/cargo/src/doc/src/reference/publishing.md
+++ b/src/tools/cargo/src/doc/src/reference/publishing.md
@@ -12,10 +12,10 @@ limit to the number of versions which can be published, however.
First things first, you’ll need an account on [crates.io] to acquire
an API token. To do so, [visit the home page][crates.io] and log in via a GitHub
-account (required for now). You will also need to verify your email address on the
-[Account Settings](https://crates.io/me) page. Once that is done create an API token,
-make sure you copy it. Once you leave the page you will not be able to see it
-again.
+account (required for now). You will also need to provide and verify your email
+address on the [Account Settings](https://crates.io/settings/profile) page. Once
+that is done [create an API token](https://crates.io/settings/tokens), make sure
+you copy it. Once you leave the page you will not be able to see it again.
Then run the [`cargo login`] command.
diff --git a/src/tools/cargo/src/doc/src/reference/registry-index.md b/src/tools/cargo/src/doc/src/reference/registry-index.md
index 38e3dd5fe..9e5be3e5b 100644
--- a/src/tools/cargo/src/doc/src/reference/registry-index.md
+++ b/src/tools/cargo/src/doc/src/reference/registry-index.md
@@ -199,6 +199,9 @@ explaining the format of the entry.
"features2": {
"serde": ["dep:serde", "chrono?/serde"]
}
+ // The minimal supported Rust version (optional)
+ // This must be a valid version requirement without an operator (e.g. no `=`)
+ "rust_version": "1.60"
}
```
@@ -221,6 +224,8 @@ The JSON objects should not be modified after they are added except for the
> * The publish API includes several other fields, such as `description` and `readme`, which don't appear in the index.
> These are intended to make it easier for a registry to obtain the metadata about the crate to display on a website without needing to extract and parse the `.crate` file.
> This additional information is typically added to a database on the registry server.
+> * Although `rust_version` is included here, [crates.io] will ignore this field
+> and instead read it from the `Cargo.toml` contained in the `.crate` file.
>
> For [`cargo metadata`], the differences are:
>
diff --git a/src/tools/cargo/src/doc/src/reference/registry-web-api.md b/src/tools/cargo/src/doc/src/reference/registry-web-api.md
index 147ababd5..8260028c0 100644
--- a/src/tools/cargo/src/doc/src/reference/registry-web-api.md
+++ b/src/tools/cargo/src/doc/src/reference/registry-web-api.md
@@ -161,7 +161,10 @@ considered as an exhaustive list of restrictions [crates.io] imposes.
},
// The `links` string value from the package's manifest, or null if not
// specified. This field is optional and defaults to null.
- "links": null
+ "links": null,
+ // The minimal supported Rust version (optional)
+ // This must be a valid version requirement without an operator (e.g. no `=`)
+ "rust_version": null
}
```
@@ -305,6 +308,8 @@ A successful response includes the JSON object:
{
// Indicates the remove succeeded, always true.
"ok": true
+ // A string to be displayed to the user. Currently ignored by cargo.
+ "msg": "owners successfully removed",
}
```
diff --git a/src/tools/cargo/src/doc/src/reference/semver.md b/src/tools/cargo/src/doc/src/reference/semver.md
index 22c42610f..5a53a6554 100644
--- a/src/tools/cargo/src/doc/src/reference/semver.md
+++ b/src/tools/cargo/src/doc/src/reference/semver.md
@@ -88,8 +88,10 @@ considered incompatible.
* [Possibly-breaking: introducing a new function type parameter](#fn-generic-new)
* [Minor: generalizing a function to use generics (supporting original type)](#fn-generalize-compatible)
* [Major: generalizing a function to use generics with type mismatch](#fn-generalize-mismatch)
+ * [Minor: making an `unsafe` function safe](#fn-unsafe-safe)
* Attributes
* [Major: switching from `no_std` support to requiring `std`](#attr-no-std-to-std)
+ * [Major: adding `non_exhaustive` to an existing enum, variant, or struct with no private fields](#attr-adding-non-exhaustive)
* Tooling and environment compatibility
* [Possibly-breaking: changing the minimum version of Rust required](#env-new-rust)
* [Possibly-breaking: changing the platform and environment requirements](#env-change-requirements)
@@ -870,7 +872,7 @@ fn main() {
It is safe to change a generic type to a more generic one. For example, the
following adds a generic parameter that defaults to the original type, which
is safe because all existing users will be using the same type for both
-fields, the the defaulted parameter does not need to be specified.
+fields, the defaulted parameter does not need to be specified.
```rust,ignore
// MINOR CHANGE
@@ -1079,6 +1081,47 @@ fn main() {
}
```
+<a id="fn-unsafe-safe"></a>
+### Minor: making an `unsafe` function safe
+
+A previously `unsafe` function can be made safe without breaking code.
+
+Note however that it may cause the [`unused_unsafe`][unused_unsafe] lint to
+trigger as in the example below, which will cause local crates that have
+specified `#![deny(warnings)]` to stop compiling. Per [introducing new
+lints](#new-lints), it is allowed for updates to introduce new warnings.
+
+Going the other way (making a safe function `unsafe`) is a breaking change.
+
+```rust,ignore
+// MINOR CHANGE
+
+///////////////////////////////////////////////////////////
+// Before
+pub unsafe fn foo() {}
+
+///////////////////////////////////////////////////////////
+// After
+pub fn foo() {}
+
+///////////////////////////////////////////////////////////
+// Example use of the library that will trigger a lint.
+use updated_crate::foo;
+
+unsafe fn bar(f: unsafe fn()) {
+ f()
+}
+
+fn main() {
+ unsafe { foo() }; // The `unused_unsafe` lint will trigger here
+ unsafe { bar(foo) };
+}
+```
+
+Making a previously `unsafe` associated function or method on structs / enums
+safe is also a minor change, while the same is not true for associated
+function on traits (see [any change to trait item signatures](#trait-item-signature)).
+
<a id="attr-no-std-to-std"></a>
### Major: switching from `no_std` support to requiring `std`
@@ -1115,6 +1158,89 @@ Mitigation strategies:
optionally enables `std` support, and when the feature is off, the library
can be used in a `no_std` environment.
+<a id="attr-adding-non-exhaustive"></a>
+### Major: adding `non_exhaustive` to an existing enum, variant, or struct with no private fields
+
+Making items [`#[non_exhaustive]`][non_exhaustive] changes how they may
+be used outside the crate where they are defined:
+
+- Non-exhaustive structs and enum variants cannot be constructed
+ using [struct literal] syntax, including [functional update syntax].
+- Pattern matching on non-exhaustive structs requires `..` and
+ matching on enums does not count towards exhaustiveness.
+- Casting enum variants to their discriminant with `as` is not allowed.
+
+Structs with private fields cannot be constructed using [struct literal] syntax
+regardless of whether [`#[non_exhaustive]`][non_exhaustive] is used.
+Adding [`#[non_exhaustive]`][non_exhaustive] to such a struct is not
+a breaking change.
+
+```rust,ignore
+// MAJOR CHANGE
+
+///////////////////////////////////////////////////////////
+// Before
+pub struct Foo {
+ pub bar: usize,
+}
+
+pub enum Bar {
+ X,
+ Y(usize),
+ Z { a: usize },
+}
+
+pub enum Quux {
+ Var,
+}
+
+///////////////////////////////////////////////////////////
+// After
+#[non_exhaustive]
+pub struct Foo {
+ pub bar: usize,
+}
+
+pub enum Bar {
+ #[non_exhaustive]
+ X,
+
+ #[non_exhaustive]
+ Y(usize),
+
+ #[non_exhaustive]
+ Z { a: usize },
+}
+
+#[non_exhaustive]
+pub enum Quux {
+ Var,
+}
+
+///////////////////////////////////////////////////////////
+// Example usage that will break.
+use updated_crate::{Bar, Foo, Quux};
+
+fn main() {
+ let foo = Foo { bar: 0 }; // Error: cannot create non-exhaustive struct using struct expression
+
+ let bar_x = Bar::X; // Error: unit variant `X` is private
+ let bar_y = Bar::Y(0); // Error: tuple variant `Y` is private
+ let bar_z = Bar::Z { a: 0 }; // Error: cannot create non-exhaustive variant using struct expression
+
+ let q = Quux::Var;
+ match q {
+ Quux::Var => 0,
+ // Error: non-exhaustive patterns: `_` not covered
+ };
+}
+```
+
+Mitigation strategies:
+* Mark structs, enums, and enum variants as
+ [`#[non_exhaustive]`][non_exhaustive] when first introducing them,
+ rather than adding [`#[non_exhaustive]`][non_exhaustive] later on.
+
## Tooling and environment compatibility
<a id="env-new-rust"></a>
@@ -1125,7 +1251,8 @@ projects that are using older versions of Rust. This also includes using new
features in a new release of Cargo, and requiring the use of a nightly-only
feature in a crate that previously worked on stable.
-Some projects choose to allow this in a minor release for various reasons. It
+It is generally recommended to treat this as a minor change, rather than as
+a major change, for [various reasons][msrv-is-minor]. It
is usually relatively easy to update to a newer version of Rust. Rust also has
a rapid 6-week release cycle, and some projects will provide compatibility
within a window of releases (such as the current stable release plus N
@@ -1393,6 +1520,7 @@ document what your commitments are.
[Default]: ../../std/default/trait.Default.html
[deprecated]: ../../reference/attributes/diagnostics.html#the-deprecated-attribute
[disambiguation syntax]: ../../reference/expressions/call-expr.html#disambiguating-function-calls
+[functional update syntax]: ../../reference/expressions/struct-expr.html#functional-update-syntax
[inherent implementations]: ../../reference/items/implementations.html#inherent-implementations
[items]: ../../reference/items.html
[non_exhaustive]: ../../reference/attributes/type_system.html#the-non_exhaustive-attribute
@@ -1402,3 +1530,5 @@ document what your commitments are.
[SemVer]: https://semver.org/
[struct literal]: ../../reference/expressions/struct-expr.html
[wildcard patterns]: ../../reference/patterns.html#wildcard-pattern
+[unused_unsafe]: ../../rustc/lints/listing/warn-by-default.html#unused-unsafe
+[msrv-is-minor]: https://github.com/rust-lang/api-guidelines/discussions/231
diff --git a/src/tools/cargo/src/doc/src/reference/unstable.md b/src/tools/cargo/src/doc/src/reference/unstable.md
index accd45d8e..7484db9b5 100644
--- a/src/tools/cargo/src/doc/src/reference/unstable.md
+++ b/src/tools/cargo/src/doc/src/reference/unstable.md
@@ -69,6 +69,7 @@ Each new feature described below should explain how to use it.
* [minimal-versions](#minimal-versions) --- Forces the resolver to use the lowest compatible version instead of the highest.
* [direct-minimal-versions](#direct-minimal-versions) — Forces the resolver to use the lowest compatible version instead of the highest.
* [public-dependency](#public-dependency) --- Allows dependencies to be classified as either public or private.
+ * [msrv-policy](#msrv-policy) --- MSRV-aware resolver and version selection
* Output behavior
* [out-dir](#out-dir) --- Adds a directory where artifacts are copied to.
* [Different binary name](#different-binary-name) --- Assign a name to the built binary that is separate from the crate name.
@@ -92,6 +93,7 @@ Each new feature described below should explain how to use it.
* [codegen-backend](#codegen-backend) --- Select the codegen backend used by rustc.
* [per-package-target](#per-package-target) --- Sets the `--target` to use for each individual package.
* [artifact dependencies](#artifact-dependencies) --- Allow build artifacts to be included into other build artifacts and build them for different targets.
+ * [`[lints]`](#lints) --- Configure lint levels for various linter tools.
* Information and metadata
* [Build-plan](#build-plan) --- Emits JSON information on which commands will be run.
* [unit-graph](#unit-graph) --- Emits JSON for Cargo's internal graph structure.
@@ -300,6 +302,14 @@ my_dep = { version = "1.2.3", public = true }
private_dep = "2.0.0" # Will be 'private' by default
```
+### msrv-policy
+- [#9930](https://github.com/rust-lang/cargo/issues/9930) (MSRV-aware resolver)
+- [#10653](https://github.com/rust-lang/cargo/issues/10653) (MSRV-aware cargo-add)
+- [#10903](https://github.com/rust-lang/cargo/issues/10903) (MSRV-aware cargo-install)
+
+The `msrv-policy` feature enables experiments in MSRV-aware policy for cargo in
+preparation for an upcoming RFC.
+
### build-std
* Tracking Repository: <https://github.com/rust-lang/wg-cargo-std-aware>
@@ -772,12 +782,120 @@ the command line) target.
* Tracking Issue: [#9096](https://github.com/rust-lang/cargo/pull/9096)
* Original Pull Request: [#9992](https://github.com/rust-lang/cargo/pull/9992)
-Allow Cargo packages to depend on `bin`, `cdylib`, and `staticlib` crates,
+Artifact dependencies allow Cargo packages to depend on `bin`, `cdylib`, and `staticlib` crates,
and use the artifacts built by those crates at compile time.
Run `cargo` with `-Z bindeps` to enable this functionality.
-**Example:** use _cdylib_ artifact in build script
+#### artifact-dependencies: Dependency declarations
+
+Artifact-dependencies adds the following keys to a dependency declaration in `Cargo.toml`:
+
+- `artifact` --- This specifies the [Cargo Target](cargo-targets.md) to build.
+ Normally without this field, Cargo will only build the `[lib]` target from a dependency.
+ This field allows specifying which target will be built, and made available as a binary at build time:
+
+ * `"bin"` --- Compiled executable binaries, corresponding to all of the `[[bin]]` sections in the dependency's manifest.
+ * `"bin:<bin-name>"` --- Compiled executable binary, corresponding to a specific binary target specified by the given `<bin-name>`.
+ * `"cdylib"` --- A C-compatible dynamic library, corresponding to a `[lib]` section with `crate-type = ["cdylib"]` in the dependency's manifest.
+ * `"staticlib"` --- A C-compatible static library, corresponding to a `[lib]` section with `crate-type = ["staticlib"]` in the dependency's manifest.
+
+ The `artifact` value can be a string, or it can be an array of strings to specify multiple targets.
+
+ Example:
+
+ ```toml
+ [dependencies]
+ bar = { version = "1.0", artifact = "staticlib" }
+ zoo = { version = "1.0", artifact = ["bin:cat", "bin:dog"]}
+ ```
+
+- `lib` --- This is a Boolean value which indicates whether or not to also build the dependency's library as a normal Rust `lib` dependency.
+ This field can only be specified when `artifact` is specified.
+
+ The default for this field is `false` when `artifact` is specified.
+ If this is set to `true`, then the dependency's `[lib]` target will also be built for the platform target the declaring package is being built for.
+ This allows the package to use the dependency from Rust code like a normal dependency in addition to an artifact dependency.
+
+ Example:
+
+ ```toml
+ [dependencies]
+ bar = { version = "1.0", artifact = "bin", lib = true }
+ ```
+
+- `target` --- The platform target to build the dependency for.
+ This field can only be specified when `artifact` is specified.
+
+ The default if this is not specified depends on the dependency kind.
+ For build dependencies, it will be built for the host target.
+ For all other dependencies, it will be built for the same targets the declaring package is built for.
+
+ For a build dependency, this can also take the special value of `"target"` which means to build the dependency for the same targets that the package is being built for.
+
+ ```toml
+ [build-dependencies]
+ bar = { version = "1.0", artifact = "cdylib", target = "wasm32-unknown-unknown"}
+ same-target = { version = "1.0", artifact = "bin", target = "target" }
+ ```
+
+#### artifact-dependencies: Environment variables
+
+After building an artifact dependency, Cargo provides the following environment variables that you can use to access the artifact:
+
+- `CARGO_<ARTIFACT-TYPE>_DIR_<DEP>` --- This is the directory containing all the artifacts from the dependency.
+
+ `<ARTIFACT-TYPE>` is the `artifact` specified for the dependency (uppercased as in `CDYLIB`, `STATICLIB`, or `BIN`) and `<DEP>` is the name of the dependency.
+ As with other Cargo environment variables, dependency names are converted to uppercase, with dashes replaced by underscores.
+
+ If your manifest renames the dependency, `<DEP>` corresponds to the name you specify, not the original package name.
+
+- `CARGO_<ARTIFACT-TYPE>_FILE_<DEP>_<NAME>` --- This is the full path to the artifact.
+
+ `<ARTIFACT-TYPE>` is the `artifact` specified for the dependency (uppercased as above), `<DEP>` is the name of the dependency (transformed as above), and `<NAME>` is the name of the artifact from the dependency.
+
+ Note that `<NAME>` is not modified in any way from the `name` specified in the crate supplying the artifact, or the crate name if not specified; for instance, it may be in lowercase, or contain dashes.
+
+ For convenience, if the artifact name matches the original package name, cargo additionally supplies a copy of this variable with the `_<NAME>` suffix omitted.
+ For instance, if the `cmake` crate supplies a binary named `cmake`, Cargo supplies both `CARGO_BIN_FILE_CMAKE` and `CARGO_BIN_FILE_CMAKE_cmake`.
+
+For each kind of dependency, these variables are supplied to the same part of the build process that has access to that kind of dependency:
+
+- For build-dependencies, these variables are supplied to the `build.rs` script, and can be accessed using [`std::env::var_os`](https://doc.rust-lang.org/std/env/fn.var_os.html).
+ (As with any OS file path, these may or may not be valid UTF-8.)
+- For normal dependencies, these variables are supplied during the compilation of the crate, and can be accessed using the [`env!`] macro.
+- For dev-dependencies, these variables are supplied during the compilation of examples, tests, and benchmarks, and can be accessed using the [`env!`] macro.
+
+[`env!`]: https://doc.rust-lang.org/std/macro.env.html
+
+#### artifact-dependencies: Examples
+
+##### Example: use a binary executable from a build script
+
+In the `Cargo.toml` file, you can specify a dependency on a binary to make available for a build script:
+
+```toml
+[build-dependencies]
+some-build-tool = { version = "1.0", artifact = "bin" }
+```
+
+Then inside the build script, the binary can be executed at build time:
+
+```rust
+fn main() {
+ let build_tool = std::env::var_os("CARGO_BIN_FILE_SOME_BUILD_TOOL").unwrap();
+ let status = std::process::Command::new(build_tool)
+ .arg("do-stuff")
+ .status()
+ .unwrap();
+ if !status.success() {
+ eprintln!("failed!");
+ std::process::exit(1);
+ }
+}
+```
+
+##### Example: use _cdylib_ artifact in build script
The `Cargo.toml` in the consuming package, building the `bar` library as `cdylib`
for a specific build target…
@@ -791,11 +909,11 @@ bar = { artifact = "cdylib", version = "1.0", target = "wasm32-unknown-unknown"
```rust
fn main() {
- wasm::run_file(std::env::var("CARGO_CDYLIB_FILE_BAR").unwrap());
+ wasm::run_file(std::env::var("CARGO_CDYLIB_FILE_BAR").unwrap());
}
```
-**Example:** use _binary_ artifact and its library in a binary
+##### Example: use _binary_ artifact and its library in a binary
The `Cargo.toml` in the consuming package, building the `bar` binary for inclusion
as artifact while making it available as library as well…
@@ -809,8 +927,8 @@ bar = { artifact = "bin", version = "1.0", lib = true }
```rust
fn main() {
- bar::init();
- command::run(env!("CARGO_BIN_FILE_BAR"));
+ bar::init();
+ command::run(env!("CARGO_BIN_FILE_BAR"));
}
```
@@ -1251,7 +1369,7 @@ codegen-backend = "cranelift"
* Tracking Issue: [#11813](https://github.com/rust-lang/cargo/issues/11813)
-With the 'gitoxide' unstable feature, all or the the specified git operations will be performed by
+With the 'gitoxide' unstable feature, all or the specified git operations will be performed by
the `gitoxide` crate instead of `git2`.
While `-Zgitoxide` enables all currently implemented features, one can individually select git operations
@@ -1260,10 +1378,114 @@ to run with `gitoxide` with the `-Zgitoxide=operation[,operationN]` syntax.
Valid operations are the following:
* `fetch` - All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index.
-* `shallow-index` *(planned)* - perform a shallow clone of the index.
-* `shallow-deps` *(planned)* - perform a shallow clone of git dependencies.
+* `shallow-index` - perform a shallow clone of the index.
+* `shallow-deps` - perform a shallow clone of git dependencies.
* `checkout` *(planned)* - checkout the worktree, with support for filters and submodules.
+**Details on shallow clones**
+
+* To enable shallow clones, add `-Zgitoxide=fetch,shallow_deps` for fetching git dependencies or `-Zgitoxide=fetch,shallow_index` for fetching registry index.
+* Shallow-cloned and shallow-checked-out git repositories reside at their own `-shallow` suffixed directories, i.e,
+ - `~/.cargo/registry/index/*-shallow`
+ - `~/.cargo/git/db/*-shallow`
+ - `~/.cargo/git/checkouts/*-shallow`
+* When the unstable feature is on, fetching/cloning a git repository is always a shallow fetch. This roughly equals to `git fetch --depth 1` everywhere.
+* Even with the presence of `Cargo.lock` or specifying a commit `{ rev = "…" }`, gitoxide is still smart enough to shallow fetch without unshallowing the existing repository.
+
+### `[lints]`
+
+* Tracking Issue: [#12115](https://github.com/rust-lang/cargo/issues/12115)
+
+A new `lints` table would be added to configure lints:
+```toml
+[lints.rust]
+unsafe = "forbid"
+```
+and `cargo` would pass these along as flags to `rustc`, `clippy`, or other lint tools when `-Zlints` is used.
+
+This would work with
+[RFC 2906 `workspace-deduplicate`](https://rust-lang.github.io/rfcs/2906-cargo-workspace-deduplicate.html):
+```toml
+[lints]
+workspace = true
+
+[workspace.lints.rust]
+unsafe = "forbid"
+```
+
+#### Documentation Updates
+
+##### The `lints` section
+
+*as a new ["Manifest Format" entry](./manifest.html#the-manifest-format)*
+
+Override the default level of lints from different tools by assigning them to a new level in a
+table, for example:
+```toml
+[lints.rust]
+unsafe = "forbid"
+```
+
+This is short-hand for:
+```toml
+[lints.rust]
+unsafe = { level = "forbid", priority = 0 }
+```
+
+`level` corresponds to the lint levels in `rustc`:
+- `forbid`
+- `deny`
+- `warn`
+- `allow`
+
+`priority` is a signed integer that controls which lints or lint groups override other lint groups:
+- lower (particularly negative) numbers have lower priority, being overridden
+ by higher numbers, and show up first on the command-line to tools like
+ `rustc`
+
+To know which table under `[lints]` a particular lint belongs under, it is the part before `::` in the lint
+name. If there isn't a `::`, then the tool is `rust`. For example a warning
+about `unsafe` would be `lints.rust.unsafe` but a lint about
+`clippy::enum_glob_use` would be `lints.clippy.enum_glob_use`.
+
+For example:
+```toml
+[lints.rust]
+unsafe = "forbid"
+
+[lints.clippy]
+enum_glob_use = "deny"
+```
+
+##### The `lints` table
+
+*as a new [`[workspace]` entry](./workspaces.html#the-workspace-section)*
+
+The `workspace.lints` table is where you define lint configuration to be inherited by members of a workspace.
+
+Specifying a workspace lint configuration is similar to package lints.
+
+Example:
+
+```toml
+# [PROJECT_DIR]/Cargo.toml
+[workspace]
+members = ["crates/*"]
+
+[workspace.lints.rust]
+unsafe = "forbid"
+```
+
+```toml
+# [PROJECT_DIR]/crates/bar/Cargo.toml
+[package]
+name = "bar"
+version = "0.1.0"
+
+[lints]
+workspace = true
+```
+
## Stabilized and removed features
### Compile progress
diff --git a/src/tools/cargo/src/etc/man/cargo-add.1 b/src/tools/cargo/src/etc/man/cargo-add.1
index 086a561fd..f69e6d0db 100644
--- a/src/tools/cargo/src/etc/man/cargo-add.1
+++ b/src/tools/cargo/src/etc/man/cargo-add.1
@@ -140,6 +140,16 @@ crates, the features for a specific crate may be enabled with
\fBpackage\-name/feature\-name\fR syntax. This flag may be specified multiple times,
which enables all specified features.
.RE
+.sp
+\fB\-\-ignore\-rust\-version\fR
+.RS 4
+Ignore \fBrust\-version\fR specification in packages.
+.sp
+This option is unstable and available only on the
+\fInightly channel\fR <https://doc.rust\-lang.org/book/appendix\-07\-nightly\-rust.html>
+and requires the \fB\-Z unstable\-options\fR flag to enable.
+See <https://github.com/rust\-lang/cargo/issues/5579> for more information.
+.RE
.SS "Display Options"
.sp
\fB\-v\fR,
diff --git a/src/tools/cargo/src/etc/man/cargo-bench.1 b/src/tools/cargo/src/etc/man/cargo-bench.1
index b95902c4e..44ff593fd 100644
--- a/src/tools/cargo/src/etc/man/cargo-bench.1
+++ b/src/tools/cargo/src/etc/man/cargo-bench.1
@@ -145,11 +145,17 @@ available)
.sp
The default behavior can be changed by setting the \fBbench\fR flag for the target
in the manifest settings. Setting examples to \fBbench = true\fR will build and
-run the example as a benchmark. Setting targets to \fBbench = false\fR will stop
-them from being benchmarked by default. Target selection options that take a
-target by name ignore the \fBbench\fR flag and will always benchmark the given
+run the example as a benchmark, replacing the example\[cq]s \fBmain\fR function with
+the libtest harness.
+.sp
+Setting targets to \fBbench = false\fR will stop them from being bencharmked by
+default. Target selection options that take a target by name (such as
+\fB\-\-example foo\fR) ignore the \fBbench\fR flag and will always benchmark the given
target.
.sp
+See \fIConfiguring a target\fR <https://doc.rust\-lang.org/cargo/reference/cargo\-targets.html#configuring\-a\-target>
+for more information on per\-target settings.
+.sp
Binary targets are automatically built if there is an integration test or
benchmark being selected to benchmark. This allows an integration
test to execute the binary to exercise and test its behavior.
diff --git a/src/tools/cargo/src/etc/man/cargo-install.1 b/src/tools/cargo/src/etc/man/cargo-install.1
index d0e5c5181..a9eb6266b 100644
--- a/src/tools/cargo/src/etc/man/cargo-install.1
+++ b/src/tools/cargo/src/etc/man/cargo-install.1
@@ -263,7 +263,7 @@ is specified.
.sp
\fB\-\-debug\fR
.RS 4
-Build with the \fBdev\fR profile instead the \fBrelease\fR profile.
+Build with the \fBdev\fR profile instead of the \fBrelease\fR profile.
See also the \fB\-\-profile\fR option for choosing a specific profile by name.
.RE
.sp
diff --git a/src/tools/cargo/src/etc/man/cargo-metadata.1 b/src/tools/cargo/src/etc/man/cargo-metadata.1
index 8549290cd..f2ebb63c7 100644
--- a/src/tools/cargo/src/etc/man/cargo-metadata.1
+++ b/src/tools/cargo/src/etc/man/cargo-metadata.1
@@ -209,6 +209,12 @@ The output has the following format:
"workspace_members": [
"my\-package 0.1.0 (path+file:///path/to/my\-package)",
],
+ /* Array of default members of the workspace.
+ Each entry is the Package ID for the package.
+ */
+ "workspace_default_members": [
+ "my\-package 0.1.0 (path+file:///path/to/my\-package)",
+ ],
// The resolved dependency graph for the entire workspace. The enabled
// features are based on the enabled features for the "current" package.
// Inactivated optional dependencies are not listed.
diff --git a/src/tools/cargo/src/etc/man/cargo-test.1 b/src/tools/cargo/src/etc/man/cargo-test.1
index 85260b067..1ee2f7672 100644
--- a/src/tools/cargo/src/etc/man/cargo-test.1
+++ b/src/tools/cargo/src/etc/man/cargo-test.1
@@ -149,13 +149,20 @@ available)
.sp
The default behavior can be changed by setting the \fBtest\fR flag for the target
in the manifest settings. Setting examples to \fBtest = true\fR will build and run
-the example as a test. Setting targets to \fBtest = false\fR will stop them from
-being tested by default. Target selection options that take a target by name
+the example as a test, replacing the example\[cq]s \fBmain\fR function with the
+libtest harness. If you don\[cq]t want the \fBmain\fR function replaced, also include
+\fBharness = false\fR, in which case the example will be built and executed as\-is.
+.sp
+Setting targets to \fBtest = false\fR will stop them from being tested by default.
+Target selection options that take a target by name (such as \fB\-\-example foo\fR)
ignore the \fBtest\fR flag and will always test the given target.
.sp
Doc tests for libraries may be disabled by setting \fBdoctest = false\fR for the
library in the manifest.
.sp
+See \fIConfiguring a target\fR <https://doc.rust\-lang.org/cargo/reference/cargo\-targets.html#configuring\-a\-target>
+for more information on per\-target settings.
+.sp
Binary targets are automatically built if there is an integration test or
benchmark being selected to test. This allows an integration
test to execute the binary to exercise and test its behavior.
diff --git a/src/tools/cargo/src/etc/man/cargo-yank.1 b/src/tools/cargo/src/etc/man/cargo-yank.1
index 423c7bc99..107c59e49 100644
--- a/src/tools/cargo/src/etc/man/cargo-yank.1
+++ b/src/tools/cargo/src/etc/man/cargo-yank.1
@@ -14,15 +14,94 @@ The yank command removes a previously published crate\[cq]s version from the
server\[cq]s index. This command does not delete any data, and the crate will
still be available for download via the registry\[cq]s download link.
.sp
-Note that existing crates locked to a yanked version will still be able to
-download the yanked version to use it. Cargo will, however, not allow any new
-crates to be locked to any yanked version.
+Cargo will not use a yanked version for any new project or checkout without a
+pre\-existing lockfile, and will generate an error if there are no longer
+any compatible versions for your crate.
.sp
This command requires you to be authenticated with either the \fB\-\-token\fR option
or using \fBcargo\-login\fR(1).
.sp
If the crate name is not specified, it will use the package name from the
current directory.
+.SS "How yank works"
+For example, the \fBfoo\fR crate published version \fB1.5.0\fR and another crate \fBbar\fR
+declared a dependency on version \fBfoo = "1.5"\fR\&. Now \fBfoo\fR releases a new, but
+not semver compatible, version \fB2.0.0\fR, and finds a critical issue with \fB1.5.0\fR\&.
+If \fB1.5.0\fR is yanked, no new project or checkout without an existing lockfile
+will be able to use crate \fBbar\fR as it relies on \fB1.5\fR\&.
+.sp
+In this case, the maintainers of \fBfoo\fR should first publish a semver compatible
+version such as \fB1.5.1\fR prior to yanking \fB1.5.0\fR so that \fBbar\fR and all projects
+that depend on \fBbar\fR will continue to work.
+.sp
+As another example, consider a crate \fBbar\fR with published versions \fB1.5.0\fR,
+\fB1.5.1\fR, \fB1.5.2\fR, \fB2.0.0\fR and \fB3.0.0\fR\&. The following table identifies the
+versions cargo could use in the absence of a lockfile for different SemVer
+requirements, following a given release being yanked:
+
+.TS
+allbox tab(:);
+lt lt lt lt.
+T{
+Yanked Version / SemVer requirement
+T}:T{
+\fBbar = "1.5.0"\fR
+T}:T{
+\fBbar = "=1.5.0"\fR
+T}:T{
+\fBbar = "2.0.0"\fR
+T}
+T{
+\fB1.5.0\fR
+T}:T{
+Use either \fB1.5.1\fR or \fB1.5.2\fR
+T}:T{
+\fBReturn Error\fR
+T}:T{
+Use \fB2.0.0\fR
+T}
+T{
+\fB1.5.1\fR
+T}:T{
+Use either \fB1.5.0\fR or \fB1.5.2\fR
+T}:T{
+Use \fB1.5.0\fR
+T}:T{
+Use \fB2.0.0\fR
+T}
+T{
+\fB2.0.0\fR
+T}:T{
+Use either \fB1.5.0\fR, \fB1.5.1\fR or \fB0.22.2\fR
+T}:T{
+Use \fB1.5.0\fR
+T}:T{
+\fBReturn Error\fR
+T}
+.TE
+.sp
+.SS "When to yank"
+Crates should only be yanked in exceptional circumstances, for example, an
+accidental publish, an unintentional SemVer breakages, or a significantly
+broken and unusable crate. In the case of security vulnerabilities, \fIRustSec\fR <https://rustsec.org/>
+is typically a less disruptive mechanism to inform users and encourage them
+to upgrade, and avoids the possibility of significant downstream disruption
+irrespective of susceptibility to the vulnerability in question.
+.sp
+A common workflow is to yank a crate having already published a semver
+compatible version, to reduce the probability of preventing dependent
+crates from compiling.
+.sp
+When addressing copyright, licensing, or personal data issues with a published
+crate, simply yanking it may not suffice. In such cases, contact the maintainers
+of the registry you used. For crates.io, refer to their \fIpolicies\fR <https://crates.io/policies> and contact
+them at <help@crates.io>\&.
+.sp
+If credentials have been leaked, the recommended course of action is to revoke
+them immediately. Once a crate has been published, it is impossible to determine
+if the leaked credentials have been copied. Yanking the crate only prevents new
+users from downloading it, but cannot stop those who have already downloaded it
+from keeping or even spreading the leaked credentials.
.SH "OPTIONS"
.SS "Yank Options"
.sp
diff --git a/src/tools/cargo/tests/testsuite/alt_registry.rs b/src/tools/cargo/tests/testsuite/alt_registry.rs
index 97da909b8..ac60ca92f 100644
--- a/src/tools/cargo/tests/testsuite/alt_registry.rs
+++ b/src/tools/cargo/tests/testsuite/alt_registry.rs
@@ -366,6 +366,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"repository": null,
"homepage": null,
"documentation": null,
+ "rust_version": null,
"vers": "0.0.1"
}"#,
"foo-0.0.1.crate",
@@ -515,6 +516,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"repository": null,
"homepage": null,
"documentation": null,
+ "rust_version": null,
"vers": "0.0.1"
}"#,
"foo-0.0.1.crate",
@@ -607,6 +609,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"repository": null,
"homepage": null,
"documentation": null,
+ "rust_version": null,
"vers": "0.0.1"
}"#,
"foo-0.0.1.crate",
@@ -899,6 +902,9 @@ fn alt_reg_metadata() {
"workspace_members": [
"foo 0.0.1 (path+file:[..]/foo)"
],
+ "workspace_default_members": [
+ "foo 0.0.1 (path+file:[..]/foo)"
+ ],
"resolve": null,
"target_directory": "[..]/foo/target",
"version": 1,
@@ -1099,6 +1105,9 @@ fn alt_reg_metadata() {
"workspace_members": [
"foo 0.0.1 (path+file:[..]/foo)"
],
+ "workspace_default_members": [
+ "foo 0.0.1 (path+file:[..]/foo)"
+ ],
"resolve": "{...}",
"target_directory": "[..]/foo/target",
"version": 1,
@@ -1262,6 +1271,9 @@ fn unknown_registry() {
"workspace_members": [
"foo 0.0.1 (path+file://[..]/foo)"
],
+ "workspace_default_members": [
+ "foo 0.0.1 (path+file://[..]/foo)"
+ ],
"resolve": "{...}",
"target_directory": "[..]/foo/target",
"version": 1,
diff --git a/src/tools/cargo/tests/testsuite/artifact_dep.rs b/src/tools/cargo/tests/testsuite/artifact_dep.rs
index ec6bb7103..08e413bf5 100644
--- a/src/tools/cargo/tests/testsuite/artifact_dep.rs
+++ b/src/tools/cargo/tests/testsuite/artifact_dep.rs
@@ -1956,6 +1956,7 @@ You may press ctrl-c [..]
"readme": null,
"readme_file": null,
"repository": "foo",
+ "rust_version": null,
"vers": "0.1.0"
}
"#,
diff --git a/src/tools/cargo/tests/testsuite/bad_config.rs b/src/tools/cargo/tests/testsuite/bad_config.rs
index ca51b101e..4434ea90d 100644
--- a/src/tools/cargo/tests/testsuite/bad_config.rs
+++ b/src/tools/cargo/tests/testsuite/bad_config.rs
@@ -780,8 +780,8 @@ fn empty_dependencies() {
p.cargo("check")
.with_stderr_contains(
"\
-warning: dependency (bar) specified without providing a local path, Git repository, or version \
-to use. This will be considered an error in future versions
+warning: dependency (bar) specified without providing a local path, Git repository, version, \
+or workspace dependency to use. This will be considered an error in future versions
",
)
.run();
@@ -1317,10 +1317,42 @@ fn bad_debuginfo() {
.with_status(101)
.with_stderr(
"\
+error: failed to parse manifest [..]
+
+Caused by:
+ invalid value: string \"a\", expected a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"
+ in `profile.dev.debug`
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn bad_debuginfo2() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [profile.dev]
+ debug = 3.6
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
error: failed to parse manifest at `[..]`
Caused by:
- expected a boolean or an integer
+ invalid type: floating point `3.6`, expected a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"
in `profile.dev.debug`
",
)
diff --git a/src/tools/cargo/tests/testsuite/build.rs b/src/tools/cargo/tests/testsuite/build.rs
index 8a1b6ca86..7b555a71b 100644
--- a/src/tools/cargo/tests/testsuite/build.rs
+++ b/src/tools/cargo/tests/testsuite/build.rs
@@ -3885,7 +3885,7 @@ fn compiler_json_error_format() {
},
"profile": {
"debug_assertions": true,
- "debuginfo": null,
+ "debuginfo": 0,
"opt_level": "0",
"overflow_checks": true,
"test": false
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/in/Cargo.toml
new file mode 100644
index 000000000..cac16bb94
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/in/Cargo.toml
@@ -0,0 +1,8 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+your-face = { }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/in/src/lib.rs
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/in/src/lib.rs
@@ -0,0 +1 @@
+
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/mod.rs
new file mode 100644
index 000000000..f6c507188
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/mod.rs
@@ -0,0 +1,25 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line("your-face --features eyes")
+ .current_dir(cwd)
+ .assert()
+ .code(101)
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/out/Cargo.toml
new file mode 100644
index 000000000..cac16bb94
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/out/Cargo.toml
@@ -0,0 +1,8 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+your-face = { }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/stderr.log
new file mode 100644
index 000000000..3acd7b944
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/stderr.log
@@ -0,0 +1 @@
+error: unrecognized dependency source for `your-face`, expected a local path, Git repository, version, or workspace dependency to be specified
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/empty_dep_table/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
index ca58474d2..cd7e94e09 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
@@ -15,6 +15,7 @@ mod dev;
mod dev_build_conflict;
mod dev_prefer_existing_version;
mod dry_run;
+mod empty_dep_table;
mod features;
mod features_empty;
mod features_multiple_occurrences;
@@ -101,6 +102,10 @@ mod quiet;
mod registry;
mod rename;
mod require_weak;
+mod rust_version_ignore;
+mod rust_version_incompatible;
+mod rust_version_latest;
+mod rust_version_older;
mod sorted_table_with_dotted_item;
mod target;
mod target_cfg;
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/in/Cargo.toml
new file mode 100644
index 000000000..b24cd9deb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/in/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.68"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
new file mode 100644
index 000000000..9aa11eaac
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
@@ -0,0 +1,36 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.0")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.2.1")
+ .rust_version("1.72")
+ .publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("-Zmsrv-policy")
+ .arg("add")
+ .arg("--ignore-rust-version")
+ .arg_line("rust-version-user")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/out/Cargo.toml
new file mode 100644
index 000000000..62164a344
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/out/Cargo.toml
@@ -0,0 +1,9 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.68"
+
+[dependencies]
+rust-version-user = "0.2.1"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/out/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/out/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
new file mode 100644
index 000000000..430abe31b
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding rust-version-user v0.2.1 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/in/Cargo.toml
new file mode 100644
index 000000000..ef6fce441
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/in/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.56"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs
new file mode 100644
index 000000000..6baad0e05
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs
@@ -0,0 +1,38 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.0")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.1")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.2.1")
+ .rust_version("1.72")
+ .publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("-Zmsrv-policy")
+ .arg("add")
+ .arg_line("rust-version-user")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .assert()
+ .failure()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/out/Cargo.toml
new file mode 100644
index 000000000..ef6fce441
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/out/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.56"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/out/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/out/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/stderr.log
new file mode 100644
index 000000000..babed5b23
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/stderr.log
@@ -0,0 +1,4 @@
+ Updating `dummy-registry` index
+error: could not find version of crate `rust-version-user` that satisfies this package's rust-version of 1.56
+help: use `--ignore-rust-version` to override this behavior
+note: the lowest rust-version available for `rust-version-user` is 1.66, used in version 0.1.1
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_incompatible/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/in/Cargo.toml
new file mode 100644
index 000000000..d9358a5de
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/in/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.72"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/mod.rs
new file mode 100644
index 000000000..60e38960f
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/mod.rs
@@ -0,0 +1,35 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.0")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.2.1")
+ .rust_version("1.72")
+ .publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("-Zmsrv-policy")
+ .arg("add")
+ .arg_line("rust-version-user")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/out/Cargo.toml
new file mode 100644
index 000000000..f824b41c3
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/out/Cargo.toml
@@ -0,0 +1,9 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.72"
+
+[dependencies]
+rust-version-user = "0.2.1"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/out/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/out/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/stderr.log
new file mode 100644
index 000000000..430abe31b
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding rust-version-user v0.2.1 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_latest/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/in/Cargo.toml
new file mode 100644
index 000000000..6fd6f1232
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/in/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.70"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/mod.rs
new file mode 100644
index 000000000..60e38960f
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/mod.rs
@@ -0,0 +1,35 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.0")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.2.1")
+ .rust_version("1.72")
+ .publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("-Zmsrv-policy")
+ .arg("add")
+ .arg_line("rust-version-user")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/out/Cargo.toml
new file mode 100644
index 000000000..14737e328
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/out/Cargo.toml
@@ -0,0 +1,9 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.70"
+
+[dependencies]
+rust-version-user = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/out/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/out/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/stderr.log
new file mode 100644
index 000000000..4c5988d0b
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/stderr.log
@@ -0,0 +1,3 @@
+ Updating `dummy-registry` index
+warning: ignoring `rust-version-user@0.2.1` (which has a rust-version of 1.72) to satisfy this package's rust-version of 1.70 (use `--ignore-rust-version` to override)
+ Adding rust-version-user v0.1.0 to dependencies.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_older/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_env_config.rs b/src/tools/cargo/tests/testsuite/cargo_env_config.rs
index d80c38d0e..dbb89664d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_env_config.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_env_config.rs
@@ -1,5 +1,6 @@
//! Tests for `[env]` config.
+use cargo_test_support::basic_manifest;
use cargo_test_support::{basic_bin_manifest, project};
#[cargo_test]
@@ -58,29 +59,31 @@ fn env_invalid() {
}
#[cargo_test]
-fn env_no_cargo_home() {
+fn env_no_disallowed() {
+ // Checks for keys that are not allowed in the [env] table.
let p = project()
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file(
- "src/main.rs",
- r#"
- fn main() {
- }
- "#,
- )
- .file(
- ".cargo/config",
- r#"
- [env]
- CARGO_HOME = "/"
- "#,
- )
+ .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
+ .file("src/lib.rs", "")
.build();
- p.cargo("check")
- .with_status(101)
- .with_stderr_contains("[..]setting the `CARGO_HOME` environment variable is not supported in the `[env]` configuration table")
- .run();
+ for disallowed in &["CARGO_HOME", "RUSTUP_HOME", "RUSTUP_TOOLCHAIN"] {
+ p.change_file(
+ ".cargo/config",
+ &format!(
+ r#"
+ [env]
+ {disallowed} = "foo"
+ "#
+ ),
+ );
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(&format!(
+ "[ERROR] setting the `{disallowed}` environment variable \
+ is not supported in the `[env]` configuration table"
+ ))
+ .run();
+ }
}
#[cargo_test]
@@ -179,3 +182,60 @@ fn env_no_override() {
.with_stdout_contains("CARGO_PKG_NAME:unchanged")
.run();
}
+
+#[cargo_test]
+fn env_applied_to_target_info_discovery_rustc() {
+ let wrapper = project()
+ .at("wrapper")
+ .file("Cargo.toml", &basic_manifest("wrapper", "1.0.0"))
+ .file(
+ "src/main.rs",
+ r#"
+ fn main() {
+ let mut args = std::env::args().skip(1);
+ let env_test = std::env::var("ENV_TEST").unwrap();
+ eprintln!("WRAPPER ENV_TEST:{env_test}");
+ let status = std::process::Command::new(&args.next().unwrap())
+ .args(args).status().unwrap();
+ std::process::exit(status.code().unwrap_or(1));
+ }
+ "#,
+ )
+ .build();
+ wrapper.cargo("build").run();
+ let wrapper = &wrapper.bin("wrapper");
+
+ let p = project()
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file(
+ "src/main.rs",
+ r#"
+ fn main() {
+ eprintln!( "MAIN ENV_TEST:{}", std::env!("ENV_TEST") );
+ }
+ "#,
+ )
+ .file(
+ ".cargo/config",
+ r#"
+ [env]
+ ENV_TEST = "from-config"
+ "#,
+ )
+ .build();
+
+ p.cargo("run")
+ .env("RUSTC_WORKSPACE_WRAPPER", wrapper)
+ .with_stderr_contains("WRAPPER ENV_TEST:from-config")
+ .with_stderr_contains("MAIN ENV_TEST:from-config")
+ .run();
+
+ // Ensure wrapper also maintains the same overridden priority for envs.
+ p.cargo("clean").run();
+ p.cargo("run")
+ .env("ENV_TEST", "from-env")
+ .env("RUSTC_WORKSPACE_WRAPPER", wrapper)
+ .with_stderr_contains("WRAPPER ENV_TEST:from-env")
+ .with_stderr_contains("MAIN ENV_TEST:from-env")
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/Cargo.toml
new file mode 100644
index 000000000..b7a2e9036
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/Cargo.toml
@@ -0,0 +1,21 @@
+[workspace]
+members = [
+ "crates/*",
+]
+
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
+version = "1.2.3"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/README.md b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/README.md
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/README.md
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table.in/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/in b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/in
new file mode 120000
index 000000000..aba551efe
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/in
@@ -0,0 +1 @@
+../inherit_workspace_package_table.in \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs
new file mode 100644
index 000000000..9b9642468
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs
@@ -0,0 +1,22 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("new")
+ .args(["crates/foo"])
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/Cargo.toml
new file mode 100644
index 000000000..b7a2e9036
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/Cargo.toml
@@ -0,0 +1,21 @@
+[workspace]
+members = [
+ "crates/*",
+]
+
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
+version = "1.2.3"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml
new file mode 100644
index 000000000..137ed1c87
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "foo"
+authors.workspace = true
+description.workspace = true
+edition.workspace = true
+homepage.workspace = true
+keywords.workspace = true
+readme.workspace = true
+rust-version.workspace = true
+categories.workspace = true
+documentation.workspace = true
+exclude.workspace = true
+include.workspace = true
+license.workspace = true
+publish.workspace = true
+repository.workspace = true
+version.workspace = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/src/main.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/src/main.rs
new file mode 100644
index 000000000..e7a11a969
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/out/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/stderr.log b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/stderr.log
new file mode 100644
index 000000000..90150cdf5
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/stderr.log
@@ -0,0 +1 @@
+ Created binary (application) `crates/foo` package
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/in b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/in
new file mode 120000
index 000000000..aba551efe
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/in
@@ -0,0 +1 @@
+../inherit_workspace_package_table.in \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs
new file mode 100644
index 000000000..c3ac2d375
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs
@@ -0,0 +1,22 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("new")
+ .args(["crates/foo", "--edition", "2021"])
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/Cargo.toml
new file mode 100644
index 000000000..b7a2e9036
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/Cargo.toml
@@ -0,0 +1,21 @@
+[workspace]
+members = [
+ "crates/*",
+]
+
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
+version = "1.2.3"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml
new file mode 100644
index 000000000..abb427d43
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "foo"
+edition = "2021"
+authors.workspace = true
+description.workspace = true
+homepage.workspace = true
+keywords.workspace = true
+readme.workspace = true
+rust-version.workspace = true
+categories.workspace = true
+documentation.workspace = true
+exclude.workspace = true
+include.workspace = true
+license.workspace = true
+publish.workspace = true
+repository.workspace = true
+version.workspace = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/src/main.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/src/main.rs
new file mode 100644
index 000000000..e7a11a969
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stderr.log b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stderr.log
new file mode 100644
index 000000000..90150cdf5
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stderr.log
@@ -0,0 +1 @@
+ Created binary (application) `crates/foo` package
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/in b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/in
new file mode 120000
index 000000000..aba551efe
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/in
@@ -0,0 +1 @@
+../inherit_workspace_package_table.in \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs
new file mode 100644
index 000000000..16ec66ea2
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs
@@ -0,0 +1,22 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("new")
+ .args(["crates/foo", "--registry", "foo"])
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/Cargo.toml
new file mode 100644
index 000000000..b7a2e9036
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/Cargo.toml
@@ -0,0 +1,21 @@
+[workspace]
+members = [
+ "crates/*",
+]
+
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
+version = "1.2.3"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml
new file mode 100644
index 000000000..642a64e46
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "foo"
+publish = ["foo"]
+authors.workspace = true
+description.workspace = true
+edition.workspace = true
+homepage.workspace = true
+keywords.workspace = true
+readme.workspace = true
+rust-version.workspace = true
+categories.workspace = true
+documentation.workspace = true
+exclude.workspace = true
+include.workspace = true
+license.workspace = true
+repository.workspace = true
+version.workspace = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/src/main.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/src/main.rs
new file mode 100644
index 000000000..e7a11a969
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stderr.log b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stderr.log
new file mode 100644
index 000000000..90150cdf5
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stderr.log
@@ -0,0 +1 @@
+ Created binary (application) `crates/foo` package
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/Cargo.toml
new file mode 100644
index 000000000..112fef55c
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/Cargo.toml
@@ -0,0 +1,20 @@
+[workspace]
+members = [
+ "crates/*",
+]
+
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/README.md b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/README.md
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/README.md
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs
new file mode 100644
index 000000000..9b9642468
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs
@@ -0,0 +1,22 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("new")
+ .args(["crates/foo"])
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/Cargo.toml
new file mode 100644
index 000000000..112fef55c
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/Cargo.toml
@@ -0,0 +1,20 @@
+[workspace]
+members = [
+ "crates/*",
+]
+
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml
new file mode 100644
index 000000000..4fcf77121
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "foo"
+version = "0.1.0"
+authors.workspace = true
+description.workspace = true
+edition.workspace = true
+homepage.workspace = true
+keywords.workspace = true
+readme.workspace = true
+rust-version.workspace = true
+categories.workspace = true
+documentation.workspace = true
+exclude.workspace = true
+include.workspace = true
+license.workspace = true
+publish.workspace = true
+repository.workspace = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/src/main.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/src/main.rs
new file mode 100644
index 000000000..e7a11a969
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stderr.log b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stderr.log
new file mode 100644
index 000000000..90150cdf5
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stderr.log
@@ -0,0 +1 @@
+ Created binary (application) `crates/foo` package
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/mod.rs
new file mode 100644
index 000000000..762a70b34
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/mod.rs
@@ -0,0 +1,5 @@
+mod inherit_workspace_package_table;
+mod inherit_workspace_package_table_with_edition;
+mod inherit_workspace_package_table_with_registry;
+mod inherit_workspace_package_table_without_version;
+mod not_inherit_workspace_package_table_if_not_memebers;
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/Cargo.toml
new file mode 100644
index 000000000..2d204581c
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/Cargo.toml
@@ -0,0 +1,15 @@
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/README.md b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/README.md
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/README.md
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/mod.rs
new file mode 100644
index 000000000..cdddf0e64
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/mod.rs
@@ -0,0 +1,22 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("new")
+ .args(["foo"])
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/Cargo.toml
new file mode 100644
index 000000000..2d204581c
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/Cargo.toml
@@ -0,0 +1,15 @@
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/Cargo.toml
new file mode 100644
index 000000000..4fcf77121
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "foo"
+version = "0.1.0"
+authors.workspace = true
+description.workspace = true
+edition.workspace = true
+homepage.workspace = true
+keywords.workspace = true
+readme.workspace = true
+rust-version.workspace = true
+categories.workspace = true
+documentation.workspace = true
+exclude.workspace = true
+include.workspace = true
+license.workspace = true
+publish.workspace = true
+repository.workspace = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/src/main.rs b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/src/main.rs
new file mode 100644
index 000000000..e7a11a969
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stderr.log b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stderr.log
new file mode 100644
index 000000000..03b1ff6db
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stderr.log
@@ -0,0 +1,9 @@
+warning: compiling this new package may not work due to invalid workspace configuration
+
+current package believes it's in a workspace when it's not:
+current: [ROOT]/case/foo/Cargo.toml
+workspace: [ROOT]/case/Cargo.toml
+
+this may be fixable by adding `foo` to the `workspace.members` array of the manifest located at: [ROOT]/case/Cargo.toml
+Alternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.
+ Created binary (application) `foo` package
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/check.rs b/src/tools/cargo/tests/testsuite/check.rs
index bbcf750fb..7bc9a38a3 100644
--- a/src/tools/cargo/tests/testsuite/check.rs
+++ b/src/tools/cargo/tests/testsuite/check.rs
@@ -6,8 +6,8 @@ use crate::messages::raw_rustc_output;
use cargo_test_support::install::exe;
use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::registry::Package;
-use cargo_test_support::tools;
use cargo_test_support::{basic_bin_manifest, basic_manifest, git, project};
+use cargo_test_support::{tools, wrapped_clippy_driver};
#[cargo_test]
fn check_success() {
@@ -1416,25 +1416,6 @@ fn check_fixable_mixed() {
#[cargo_test]
fn check_fixable_warning_for_clippy() {
- // A wrapper around `rustc` instead of calling `clippy`
- let clippy_driver = project()
- .at(cargo_test_support::paths::global_root().join("clippy-driver"))
- .file("Cargo.toml", &basic_manifest("clippy-driver", "0.0.1"))
- .file(
- "src/main.rs",
- r#"
- fn main() {
- let mut args = std::env::args_os();
- let _me = args.next().unwrap();
- let rustc = args.next().unwrap();
- let status = std::process::Command::new(rustc).args(args).status().unwrap();
- std::process::exit(status.code().unwrap_or(1));
- }
- "#,
- )
- .build();
- clippy_driver.cargo("build").run();
-
let foo = project()
.file(
"Cargo.toml",
@@ -1452,10 +1433,7 @@ fn check_fixable_warning_for_clippy() {
foo.cargo("check")
// We can't use `clippy` so we use a `rustc` workspace wrapper instead
- .env(
- "RUSTC_WORKSPACE_WRAPPER",
- clippy_driver.bin("clippy-driver"),
- )
+ .env("RUSTC_WORKSPACE_WRAPPER", wrapped_clippy_driver())
.with_stderr_contains("[..] (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion)")
.run();
}
diff --git a/src/tools/cargo/tests/testsuite/config.rs b/src/tools/cargo/tests/testsuite/config.rs
index 92e1f4264..b0f9d167b 100644
--- a/src/tools/cargo/tests/testsuite/config.rs
+++ b/src/tools/cargo/tests/testsuite/config.rs
@@ -3,7 +3,7 @@
use cargo::core::{PackageIdSpec, Shell};
use cargo::util::config::{self, Config, Definition, SslVersionConfig, StringList};
use cargo::util::interning::InternedString;
-use cargo::util::toml::{self as cargo_toml, VecStringOrBool as VSOB};
+use cargo::util::toml::{self as cargo_toml, TomlDebugInfo, VecStringOrBool as VSOB};
use cargo::CargoResult;
use cargo_test_support::compare;
use cargo_test_support::{panic_error, paths, project, symlink_supported, t};
@@ -401,7 +401,7 @@ lto = false
opt_level: Some(cargo_toml::TomlOptLevel("s".to_string())),
lto: Some(cargo_toml::StringOrBool::Bool(true)),
codegen_units: Some(5),
- debug: Some(cargo_toml::U32OrBool::Bool(true)),
+ debug: Some(cargo_toml::TomlDebugInfo::Full),
debug_assertions: Some(true),
rpath: Some(true),
panic: Some("abort".to_string()),
@@ -444,7 +444,7 @@ fn profile_env_var_prefix() {
.build();
let p: cargo_toml::TomlProfile = config.get("profile.dev").unwrap();
assert_eq!(p.debug_assertions, None);
- assert_eq!(p.debug, Some(cargo_toml::U32OrBool::U32(1)));
+ assert_eq!(p.debug, Some(cargo_toml::TomlDebugInfo::Limited));
let config = ConfigBuilder::new()
.env("CARGO_PROFILE_DEV_DEBUG_ASSERTIONS", "false")
@@ -452,7 +452,7 @@ fn profile_env_var_prefix() {
.build();
let p: cargo_toml::TomlProfile = config.get("profile.dev").unwrap();
assert_eq!(p.debug_assertions, Some(false));
- assert_eq!(p.debug, Some(cargo_toml::U32OrBool::U32(1)));
+ assert_eq!(p.debug, Some(cargo_toml::TomlDebugInfo::Limited));
}
#[cargo_test]
@@ -1511,7 +1511,7 @@ fn all_profile_options() {
lto: Some(cargo_toml::StringOrBool::String("thin".to_string())),
codegen_backend: Some(InternedString::new("example")),
codegen_units: Some(123),
- debug: Some(cargo_toml::U32OrBool::U32(1)),
+ debug: Some(cargo_toml::TomlDebugInfo::Limited),
split_debuginfo: Some("packed".to_string()),
debug_assertions: Some(true),
rpath: Some(true),
@@ -1594,3 +1594,60 @@ known-hosts = [
Definition::Environment("CARGO_NET_SSH_KNOWN_HOSTS".to_string())
);
}
+
+#[cargo_test]
+fn debuginfo_parsing() {
+ let config = ConfigBuilder::new().build();
+ let p: cargo_toml::TomlProfile = config.get("profile.dev").unwrap();
+ assert_eq!(p.debug, None);
+
+ let env_test_cases = [
+ (TomlDebugInfo::None, ["false", "0", "none"].as_slice()),
+ (TomlDebugInfo::LineDirectivesOnly, &["line-directives-only"]),
+ (TomlDebugInfo::LineTablesOnly, &["line-tables-only"]),
+ (TomlDebugInfo::Limited, &["1", "limited"]),
+ (TomlDebugInfo::Full, &["true", "2", "full"]),
+ ];
+ for (expected, config_strs) in env_test_cases {
+ for &val in config_strs {
+ let config = ConfigBuilder::new()
+ .env("CARGO_PROFILE_DEV_DEBUG", val)
+ .build();
+ let debug: TomlDebugInfo = config.get("profile.dev.debug").unwrap();
+ assert_eq!(debug, expected, "failed to parse {val}");
+ }
+ }
+
+ let toml_test_cases = [
+ (TomlDebugInfo::None, ["false", "0", "\"none\""].as_slice()),
+ (
+ TomlDebugInfo::LineDirectivesOnly,
+ &["\"line-directives-only\""],
+ ),
+ (TomlDebugInfo::LineTablesOnly, &["\"line-tables-only\""]),
+ (TomlDebugInfo::Limited, &["1", "\"limited\""]),
+ (TomlDebugInfo::Full, &["true", "2", "\"full\""]),
+ ];
+ for (expected, config_strs) in toml_test_cases {
+ for &val in config_strs {
+ let config = ConfigBuilder::new()
+ .config_arg(format!("profile.dev.debug={val}"))
+ .build();
+ let debug: TomlDebugInfo = config.get("profile.dev.debug").unwrap();
+ assert_eq!(debug, expected, "failed to parse {val}");
+ }
+ }
+
+ let toml_err_cases = ["\"\"", "\"unrecognized\"", "3"];
+ for err_val in toml_err_cases {
+ let config = ConfigBuilder::new()
+ .config_arg(format!("profile.dev.debug={err_val}"))
+ .build();
+ let err = config
+ .get::<TomlDebugInfo>("profile.dev.debug")
+ .unwrap_err();
+ assert!(err
+ .to_string()
+ .ends_with("could not load config key `profile.dev.debug`"));
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/features_namespaced.rs b/src/tools/cargo/tests/testsuite/features_namespaced.rs
index 8ec2fc2e3..f24186c15 100644
--- a/src/tools/cargo/tests/testsuite/features_namespaced.rs
+++ b/src/tools/cargo/tests/testsuite/features_namespaced.rs
@@ -609,6 +609,7 @@ fn json_exposed() {
}
],
"workspace_members": "{...}",
+ "workspace_default_members": "{...}",
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
@@ -942,6 +943,7 @@ You may press ctrl-c [..]
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.1.0"
}
"#,
@@ -1057,6 +1059,7 @@ You may press ctrl-c [..]
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.1.0"
}
"#,
@@ -1213,3 +1216,81 @@ Caused by:
)
.run();
}
+
+#[cargo_test]
+fn dep_feature_when_hidden() {
+ // Checks for behavior with dep:bar and bar/feat syntax when there is no
+ // `bar` feature.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar", optional = true }
+
+ [features]
+ f1 = ["dep:bar"]
+ f2 = ["bar/bar_feat"]
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "bar/Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+
+ [features]
+ bar_feat = []
+ "#,
+ )
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ p.cargo("tree -f")
+ .arg("{p} features={f}")
+ .with_stdout(
+ "\
+foo v0.1.0 ([ROOT]/foo) features=",
+ )
+ .with_stderr("")
+ .run();
+
+ p.cargo("tree -F f1 -f")
+ .arg("{p} features={f}")
+ .with_stdout(
+ "\
+foo v0.1.0 ([ROOT]/foo) features=f1
+└── bar v0.1.0 ([ROOT]/foo/bar) features=
+",
+ )
+ .with_stderr("")
+ .run();
+
+ p.cargo("tree -F f2 -f")
+ .arg("{p} features={f}")
+ .with_stdout(
+ "\
+foo v0.1.0 ([ROOT]/foo) features=f2
+└── bar v0.1.0 ([ROOT]/foo/bar) features=bar_feat
+",
+ )
+ .with_stderr("")
+ .run();
+
+ p.cargo("tree --all-features -f")
+ .arg("{p} features={f}")
+ .with_stdout(
+ "\
+foo v0.1.0 ([ROOT]/foo) features=f1,f2
+└── bar v0.1.0 ([ROOT]/foo/bar) features=bar_feat
+",
+ )
+ .with_stderr("")
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/fix.rs b/src/tools/cargo/tests/testsuite/fix.rs
index 54a021c03..33de721cd 100644
--- a/src/tools/cargo/tests/testsuite/fix.rs
+++ b/src/tools/cargo/tests/testsuite/fix.rs
@@ -5,8 +5,8 @@ use cargo_test_support::compare::assert_match_exact;
use cargo_test_support::git::{self, init};
use cargo_test_support::paths::{self, CargoPathExt};
use cargo_test_support::registry::{Dependency, Package};
-use cargo_test_support::tools;
-use cargo_test_support::{basic_manifest, is_nightly, project};
+use cargo_test_support::{basic_manifest, is_nightly, project, Project};
+use cargo_test_support::{tools, wrapped_clippy_driver};
#[cargo_test]
fn do_not_fix_broken_builds() {
@@ -53,8 +53,7 @@ fn fix_broken_if_requested() {
.run();
}
-#[cargo_test]
-fn broken_fixes_backed_out() {
+fn rustc_shim_for_cargo_fix() -> Project {
// This works as follows:
// - Create a `rustc` shim (the "foo" project) which will pretend that the
// verification step fails.
@@ -109,7 +108,6 @@ fn broken_fixes_backed_out() {
fs::File::create(&first).unwrap();
}
}
-
let status = Command::new("rustc")
.args(env::args().skip(1))
.status()
@@ -142,11 +140,60 @@ fn broken_fixes_backed_out() {
// Build our rustc shim
p.cargo("build").cwd("foo").run();
- // Attempt to fix code, but our shim will always fail the second compile
+ p
+}
+
+#[cargo_test]
+fn broken_fixes_backed_out() {
+ let p = rustc_shim_for_cargo_fix();
+ // Attempt to fix code, but our shim will always fail the second compile.
+ p.cargo("fix --allow-no-vcs --lib")
+ .cwd("bar")
+ .env("__CARGO_FIX_YOLO", "1")
+ .env("RUSTC", p.root().join("foo/target/debug/foo"))
+ .with_stderr_contains(
+ "warning: failed to automatically apply fixes suggested by rustc \
+ to crate `bar`\n\
+ \n\
+ after fixes were automatically applied the compiler reported \
+ errors within these files:\n\
+ \n \
+ * src/lib.rs\n\
+ \n\
+ This likely indicates a bug in either rustc or cargo itself,\n\
+ and we would appreciate a bug report! You're likely to see \n\
+ a number of compiler warnings after this message which cargo\n\
+ attempted to fix but failed. If you could open an issue at\n\
+ https://github.com/rust-lang/rust/issues\n\
+ quoting the full output of this command we'd be very appreciative!\n\
+ Note that you may be able to make some more progress in the near-term\n\
+ fixing code with the `--broken-code` flag\n\
+ \n\
+ The following errors were reported:\n\
+ error: expected one of `!` or `::`, found `rust`\n\
+ ",
+ )
+ .with_stderr_contains("Original diagnostics will follow.")
+ .with_stderr_contains("[WARNING] variable does not need to be mutable")
+ .with_stderr_does_not_contain("[..][FIXED][..]")
+ .run();
+
+ // Make sure the fix which should have been applied was backed out
+ assert!(p.read_file("bar/src/lib.rs").contains("let mut x = 3;"));
+}
+
+#[cargo_test]
+fn broken_clippy_fixes_backed_out() {
+ let p = rustc_shim_for_cargo_fix();
+ // Attempt to fix code, but our shim will always fail the second compile.
+ // Also, we use `clippy` as a workspace wrapper to make sure that we properly
+ // generate the report bug text.
p.cargo("fix --allow-no-vcs --lib")
.cwd("bar")
.env("__CARGO_FIX_YOLO", "1")
.env("RUSTC", p.root().join("foo/target/debug/foo"))
+ // We can't use `clippy` so we use a `rustc` workspace wrapper instead
+ .env("RUSTC_WORKSPACE_WRAPPER", wrapped_clippy_driver())
.with_stderr_contains(
"warning: failed to automatically apply fixes suggested by rustc \
to crate `bar`\n\
@@ -160,7 +207,7 @@ fn broken_fixes_backed_out() {
and we would appreciate a bug report! You're likely to see \n\
a number of compiler warnings after this message which cargo\n\
attempted to fix but failed. If you could open an issue at\n\
- [..]\n\
+ https://github.com/rust-lang/rust-clippy/issues\n\
quoting the full output of this command we'd be very appreciative!\n\
Note that you may be able to make some more progress in the near-term\n\
fixing code with the `--broken-code` flag\n\
diff --git a/src/tools/cargo/tests/testsuite/git.rs b/src/tools/cargo/tests/testsuite/git.rs
index b170c204f..7c717e967 100644
--- a/src/tools/cargo/tests/testsuite/git.rs
+++ b/src/tools/cargo/tests/testsuite/git.rs
@@ -548,90 +548,6 @@ Caused by:
}
#[cargo_test]
-fn two_revs_same_deps() {
- let bar = git::new("meta-dep", |project| {
- project
- .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- });
-
- let repo = git2::Repository::open(&bar.root()).unwrap();
- let rev1 = repo.revparse_single("HEAD").unwrap().id();
-
- // Commit the changes and make sure we trigger a recompile
- bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
- git::add(&repo);
- let rev2 = git::commit(&repo);
-
- let foo = project()
- .file(
- "Cargo.toml",
- &format!(
- r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- git = '{}'
- rev = "{}"
-
- [dependencies.baz]
- path = "../baz"
- "#,
- bar.url(),
- rev1
- ),
- )
- .file(
- "src/main.rs",
- r#"
- extern crate bar;
- extern crate baz;
-
- fn main() {
- assert_eq!(bar::bar(), 1);
- assert_eq!(baz::baz(), 2);
- }
- "#,
- )
- .build();
-
- let _baz = project()
- .at("baz")
- .file(
- "Cargo.toml",
- &format!(
- r#"
- [package]
- name = "baz"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- git = '{}'
- rev = "{}"
- "#,
- bar.url(),
- rev2
- ),
- )
- .file(
- "src/lib.rs",
- r#"
- extern crate bar;
- pub fn baz() -> i32 { bar::bar() }
- "#,
- )
- .build();
-
- foo.cargo("build -v").run();
- assert!(foo.bin("foo").is_file());
- foo.process(&foo.bin("foo")).run();
-}
-
-#[cargo_test]
fn recompilation() {
let git_project = git::new("bar", |project| {
project
@@ -2795,7 +2711,7 @@ fn use_the_cli() {
[UPDATING] git repository `[..]`
[RUNNING] `git fetch [..]`
From [..]
- * [new ref] -> origin/HEAD
+ * [new ref] [..] -> origin/HEAD[..]
[CHECKING] dep1 [..]
[RUNNING] `rustc [..]`
[CHECKING] foo [..]
@@ -3421,6 +3337,9 @@ fn metadata_master_consistency() {
"workspace_members": [
"foo 0.1.0 [..]"
],
+ "workspace_default_members": [
+ "foo 0.1.0 [..]"
+ ],
"resolve": {
"nodes": [
{
diff --git a/src/tools/cargo/tests/testsuite/git_shallow.rs b/src/tools/cargo/tests/testsuite/git_shallow.rs
new file mode 100644
index 000000000..8045880cf
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/git_shallow.rs
@@ -0,0 +1,831 @@
+use crate::git_gc::find_index;
+use cargo_test_support::registry::Package;
+use cargo_test_support::{basic_manifest, git, paths, project};
+
+enum RepoMode {
+ Shallow,
+ Complete,
+}
+
+#[cargo_test]
+fn gitoxide_clones_shallow_two_revs_same_deps() {
+ perform_two_revs_same_deps(true)
+}
+
+fn perform_two_revs_same_deps(shallow: bool) {
+ let bar = git::new("meta-dep", |project| {
+ project
+ .file("Cargo.toml", &basic_manifest("bar", "0.0.0"))
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ });
+
+ let repo = git2::Repository::open(&bar.root()).unwrap();
+ let rev1 = repo.revparse_single("HEAD").unwrap().id();
+
+ // Commit the changes and make sure we trigger a recompile
+ bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }");
+ git::add(&repo);
+ let rev2 = git::commit(&repo);
+
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ git = '{}'
+ rev = "{}"
+
+ [dependencies.baz]
+ path = "../baz"
+ "#,
+ bar.url(),
+ rev1
+ ),
+ )
+ .file(
+ "src/main.rs",
+ r#"
+ extern crate bar;
+ extern crate baz;
+
+ fn main() {
+ assert_eq!(bar::bar(), 1);
+ assert_eq!(baz::baz(), 2);
+ }
+ "#,
+ )
+ .build();
+
+ let _baz = project()
+ .at("baz")
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "baz"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ git = '{}'
+ rev = "{}"
+ "#,
+ bar.url(),
+ rev2
+ ),
+ )
+ .file(
+ "src/lib.rs",
+ r#"
+ extern crate bar;
+ pub fn baz() -> i32 { bar::bar() }
+ "#,
+ )
+ .build();
+
+ let args = if shallow {
+ "build -v -Zgitoxide=fetch,shallow-deps"
+ } else {
+ "build -v"
+ };
+ foo.cargo(args)
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+ assert!(foo.bin("foo").is_file());
+ foo.process(&foo.bin("foo")).run();
+}
+
+#[cargo_test]
+fn two_revs_same_deps() {
+ perform_two_revs_same_deps(false)
+}
+
+#[cargo_test]
+fn gitoxide_clones_registry_with_shallow_protocol_and_follow_up_with_git2_fetch(
+) -> anyhow::Result<()> {
+ Package::new("bar", "1.0.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("fetch")
+ .arg("-Zgitoxide=fetch,shallow-index")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let shallow_repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;
+ assert_eq!(
+ shallow_repo
+ .rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "shallow clones always start at depth of 1 to minimize download size"
+ );
+ assert!(shallow_repo.is_shallow());
+
+ Package::new("bar", "1.1.0").publish();
+ p.cargo("update")
+ .env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0")
+ .run();
+
+ let repo = gix::open_opts(
+ find_remote_index(RepoMode::Complete),
+ gix::open::Options::isolated(),
+ )?;
+ assert_eq!(
+ repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 3,
+ "an entirely new repo was cloned which is never shallow"
+ );
+ assert!(!repo.is_shallow());
+ Ok(())
+}
+
+#[cargo_test]
+fn gitoxide_clones_git_dependency_with_shallow_protocol_and_git2_is_used_for_followup_fetches(
+) -> anyhow::Result<()> {
+ // Example where an old lockfile with an explicit branch="master" in Cargo.toml.
+ Package::new("bar", "1.0.0").publish();
+ let (bar, bar_repo) = git::new_repo("bar", |p| {
+ p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+
+ bar.change_file("src/lib.rs", "// change");
+ git::add(&bar_repo);
+ git::commit(&bar_repo);
+
+ {
+ let mut walk = bar_repo.revwalk()?;
+ walk.push_head()?;
+ assert_eq!(
+ walk.count(),
+ 2,
+ "original repo has initial commit and change commit"
+ );
+ }
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = {{ version = "1.0", git = "{}", branch = "master" }}
+ "#,
+ bar.url()
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch,shallow-deps")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let db_clone = gix::open_opts(
+ find_bar_db(RepoMode::Shallow),
+ gix::open::Options::isolated(),
+ )?;
+ assert!(db_clone.is_shallow());
+ assert_eq!(
+ db_clone
+ .rev_parse_single("origin/master")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "db clones are shallow and have a shortened history"
+ );
+
+ let dep_checkout = gix::open_opts(
+ find_lexicographically_first_bar_checkout(),
+ gix::open::Options::isolated(),
+ )?;
+ assert!(dep_checkout.is_shallow());
+ assert_eq!(
+ dep_checkout.head_id()?.ancestors().all()?.count(),
+ 1,
+ "db checkouts are hard-linked clones with the shallow file copied separately."
+ );
+
+ bar.change_file("src/lib.rs", "// another change");
+ git::add(&bar_repo);
+ git::commit(&bar_repo);
+ {
+ let mut walk = bar_repo.revwalk()?;
+ walk.push_head()?;
+ assert_eq!(
+ walk.count(),
+ 3,
+ "original repo has initial commit and change commit, and another change"
+ );
+ }
+
+ p.cargo("update")
+ .env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0")
+ .run();
+
+ let db_clone = gix::open_opts(
+ find_bar_db(RepoMode::Complete),
+ gix::open::Options::isolated(),
+ )?;
+ assert_eq!(
+ db_clone
+ .rev_parse_single("origin/master")?
+ .ancestors()
+ .all()?
+ .count(),
+ 3,
+ "the db clone was re-initialized and has all commits"
+ );
+ assert!(
+ !db_clone.is_shallow(),
+ "shallow-ness was removed as git2 does not support it"
+ );
+ assert_eq!(
+ dep_checkout.head_id()?.ancestors().all()?.count(),
+ 1,
+ "the original dep checkout didn't change - there is a new one for each update we get locally"
+ );
+
+ let max_history_depth = glob::glob(
+ paths::home()
+ .join(".cargo/git/checkouts/bar-*/*/.git")
+ .to_str()
+ .unwrap(),
+ )?
+ .map(|path| -> anyhow::Result<usize> {
+ let dep_checkout = gix::open_opts(path?, gix::open::Options::isolated())?;
+ let depth = dep_checkout.head_id()?.ancestors().all()?.count();
+ assert_eq!(dep_checkout.is_shallow(), depth == 1, "the first checkout is done with gitoxide and shallow, the second one is git2 non-shallow");
+ Ok(depth)
+ })
+ .map(Result::unwrap)
+ .max()
+ .expect("two checkout repos");
+
+ assert_eq!(
+ max_history_depth, 3,
+ "the new checkout sees all commits of the non-shallow DB repository"
+ );
+
+ Ok(())
+}
+
+#[cargo_test]
+fn gitoxide_shallow_clone_followed_by_non_shallow_update() -> anyhow::Result<()> {
+ Package::new("bar", "1.0.0").publish();
+ let (bar, bar_repo) = git::new_repo("bar", |p| {
+ p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+
+ bar.change_file("src/lib.rs", "// change");
+ git::add(&bar_repo);
+ git::commit(&bar_repo);
+
+ {
+ let mut walk = bar_repo.revwalk()?;
+ walk.push_head()?;
+ assert_eq!(
+ walk.count(),
+ 2,
+ "original repo has initial commit and change commit"
+ );
+ }
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = {{ version = "1.0", git = "{}", branch = "master" }}
+ "#,
+ bar.url()
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch,shallow-deps")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let shallow_db_clone = gix::open_opts(
+ find_bar_db(RepoMode::Shallow),
+ gix::open::Options::isolated(),
+ )?;
+ assert!(shallow_db_clone.is_shallow());
+ assert_eq!(
+ shallow_db_clone
+ .rev_parse_single("origin/master")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "db clones are shallow and have a shortened history"
+ );
+
+ let dep_checkout = gix::open_opts(
+ find_lexicographically_first_bar_checkout(),
+ gix::open::Options::isolated(),
+ )?;
+ assert!(dep_checkout.is_shallow());
+ assert_eq!(
+ dep_checkout.head_id()?.ancestors().all()?.count(),
+ 1,
+ "db checkouts are hard-linked clones with the shallow file copied separately."
+ );
+
+ bar.change_file("src/lib.rs", "// another change");
+ git::add(&bar_repo);
+ git::commit(&bar_repo);
+ {
+ let mut walk = bar_repo.revwalk()?;
+ walk.push_head()?;
+ assert_eq!(
+ walk.count(),
+ 3,
+ "original repo has initial commit and change commit, and another change"
+ );
+ }
+
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch") // shallow-deps is omitted intentionally
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let db_clone = gix::open_opts(
+ find_bar_db(RepoMode::Complete),
+ gix::open::Options::isolated(),
+ )?;
+ assert_eq!(
+ db_clone
+ .rev_parse_single("origin/master")?
+ .ancestors()
+ .all()?
+ .count(),
+ 3,
+ "we created an entirely new non-shallow clone"
+ );
+ assert!(!db_clone.is_shallow());
+ assert_eq!(
+ dep_checkout.head_id()?.ancestors().all()?.count(),
+ 1,
+ "the original dep checkout didn't change - there is a new one for each update we get locally"
+ );
+
+ let max_history_depth = glob::glob(
+ paths::home()
+ .join(".cargo/git/checkouts/bar-*/*/.git")
+ .to_str()
+ .unwrap(),
+ )?
+ .map(|path| -> anyhow::Result<usize> {
+ let path = path?;
+ let dep_checkout = gix::open_opts(&path, gix::open::Options::isolated())?;
+ assert_eq!(
+ dep_checkout.is_shallow(),
+ path.to_string_lossy().contains("-shallow"),
+ "checkouts of shallow db repos are shallow as well"
+ );
+ let depth = dep_checkout.head_id()?.ancestors().all()?.count();
+ Ok(depth)
+ })
+ .map(Result::unwrap)
+ .max()
+ .expect("two checkout repos");
+
+ assert_eq!(
+ max_history_depth, 3,
+ "we see the previous shallow checkout as well as new new unshallow one"
+ );
+
+ Ok(())
+}
+
+#[cargo_test]
+fn gitoxide_clones_registry_with_shallow_protocol_and_follow_up_fetch_maintains_shallowness(
+) -> anyhow::Result<()> {
+ Package::new("bar", "1.0.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("fetch")
+ .arg("-Zgitoxide=fetch,shallow-index")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;
+ assert_eq!(
+ repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "shallow clones always start at depth of 1 to minimize download size"
+ );
+ assert!(repo.is_shallow());
+
+ Package::new("bar", "1.1.0").publish();
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch,shallow-index") // NOTE: the flag needs to be consistent or else a different index is created
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ assert_eq!(
+ repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits"
+ );
+ assert!(repo.is_shallow());
+
+ Package::new("bar", "1.2.0").publish();
+ Package::new("bar", "1.3.0").publish();
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch,shallow-index")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ assert_eq!(
+ repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "shallow boundaries are moved with each fetch to maintain only a single commit of history"
+ );
+ assert!(repo.is_shallow());
+
+ Ok(())
+}
+
+/// If there is shallow *and* non-shallow clones, non-shallow will naturally be returned due to sort order.
+#[cargo_test]
+fn gitoxide_clones_registry_without_shallow_protocol_and_follow_up_fetch_uses_shallowness(
+) -> anyhow::Result<()> {
+ Package::new("bar", "1.0.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("fetch")
+ .arg("-Zgitoxide=fetch")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;
+ assert_eq!(
+ repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 2,
+ "initial commit and the first crate"
+ );
+ assert!(!repo.is_shallow());
+
+ Package::new("bar", "1.1.0").publish();
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch,shallow-index")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let shallow_repo = gix::open_opts(
+ find_remote_index(RepoMode::Shallow),
+ gix::open::Options::isolated(),
+ )?;
+ assert_eq!(
+ shallow_repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "the follow up clones an entirely new index which is now shallow and which is in its own location"
+ );
+ assert!(shallow_repo.is_shallow());
+
+ Package::new("bar", "1.2.0").publish();
+ Package::new("bar", "1.3.0").publish();
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch,shallow-index")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ assert_eq!(
+ shallow_repo
+ .rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits"
+ );
+ assert!(shallow_repo.is_shallow());
+
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ assert_eq!(
+ repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 5,
+ "we can separately fetch the non-shallow index as well and it sees all commits"
+ );
+
+ Ok(())
+}
+
+#[cargo_test]
+fn gitoxide_git_dependencies_switch_from_branch_to_rev() -> anyhow::Result<()> {
+ // db exists from previous build, then dependency changes to refer to revision that isn't
+ // available in the shallow clone.
+
+ let (bar, bar_repo) = git::new_repo("bar", |p| {
+ p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+
+ // this commit would not be available in a shallow clone.
+ let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap();
+
+ bar.change_file("src/lib.rs", "// change");
+ git::add(&bar_repo);
+ git::commit(&bar_repo);
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = {{ git = "{}", branch = "master" }}
+ "#,
+ bar.url(),
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .arg("-Zgitoxide=fetch,shallow-deps")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let db_clone = gix::open_opts(
+ find_bar_db(RepoMode::Shallow),
+ gix::open::Options::isolated(),
+ )?;
+ assert!(db_clone.is_shallow());
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = {{ git = "{}", rev = "{}" }}
+ "#,
+ bar.url(),
+ first_commit_pre_change
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .arg("-Zgitoxide=fetch,shallow-deps")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ assert!(
+ db_clone.is_shallow(),
+ "we maintain shallowness and never unshallow"
+ );
+
+ Ok(())
+}
+
+#[cargo_test]
+fn shallow_deps_work_with_revisions_and_branches_mixed_on_same_dependency() -> anyhow::Result<()> {
+ let (bar, bar_repo) = git::new_repo("bar", |p| {
+ p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
+ .file("src/lib.rs", "")
+ });
+
+ // this commit would not be available in a shallow clone.
+ let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap();
+
+ bar.change_file("src/lib.rs", "// change");
+ git::add(&bar_repo);
+ git::commit(&bar_repo);
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar-renamed = {{ package = "bar", git = "{}", rev = "{}" }}
+ bar = {{ git = "{}", branch = "master" }}
+ "#,
+ bar.url(),
+ first_commit_pre_change,
+ bar.url(),
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .arg("-Zgitoxide=fetch,shallow-deps")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let db_paths = glob::glob(paths::home().join(".cargo/git/db/bar-*").to_str().unwrap())?
+ .map(Result::unwrap)
+ .collect::<Vec<_>>();
+ assert_eq!(
+ db_paths.len(),
+ 1,
+ "only one db checkout source is used per dependency"
+ );
+ let db_clone = gix::open_opts(&db_paths[0], gix::open::Options::isolated())?;
+ assert!(
+ db_clone.is_shallow(),
+ "the repo is shallow while having all data it needs"
+ );
+
+ Ok(())
+}
+
+#[cargo_test]
+fn gitoxide_clones_registry_with_shallow_protocol_and_aborts_and_updates_again(
+) -> anyhow::Result<()> {
+ Package::new("bar", "1.0.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ p.cargo("fetch")
+ .arg("-Zgitoxide=fetch,shallow-index")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;
+ assert_eq!(
+ repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "shallow clones always start at depth of 1 to minimize download size"
+ );
+ assert!(repo.is_shallow());
+ let shallow_lock = repo.shallow_file().with_extension("lock");
+ // adding a lock file and deleting the original simulates a left-over clone that was aborted, leaving a lock file
+ // in place without ever having moved it to the right location.
+ std::fs::write(&shallow_lock, &[])?;
+ std::fs::remove_file(repo.shallow_file())?;
+
+ Package::new("bar", "1.1.0").publish();
+ p.cargo("update")
+ .arg("-Zgitoxide=fetch,shallow-index")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"])
+ .run();
+
+ assert!(!shallow_lock.is_file(), "the repository was re-initialized");
+ assert!(repo.is_shallow());
+ assert_eq!(
+ repo.rev_parse_single("origin/HEAD")?
+ .ancestors()
+ .all()?
+ .count(),
+ 1,
+ "it's a fresh shallow clone - otherwise it would have 2 commits if the previous shallow clone would still be present"
+ );
+
+ Ok(())
+}
+
+fn find_lexicographically_first_bar_checkout() -> std::path::PathBuf {
+ glob::glob(
+ paths::home()
+ .join(".cargo/git/checkouts/bar-*/*/.git")
+ .to_str()
+ .unwrap(),
+ )
+ .unwrap()
+ .next()
+ .unwrap()
+ .unwrap()
+ .to_owned()
+}
+
+fn find_remote_index(mode: RepoMode) -> std::path::PathBuf {
+ glob::glob(
+ paths::home()
+ .join(".cargo/registry/index/*")
+ .to_str()
+ .unwrap(),
+ )
+ .unwrap()
+ .map(Result::unwrap)
+ .filter(|p| p.to_string_lossy().ends_with("-shallow") == matches!(mode, RepoMode::Shallow))
+ .next()
+ .unwrap()
+}
+
+/// Find a checkout directory for bar, `shallow` or not.
+fn find_bar_db(mode: RepoMode) -> std::path::PathBuf {
+ glob::glob(paths::home().join(".cargo/git/db/bar-*").to_str().unwrap())
+ .unwrap()
+ .map(Result::unwrap)
+ .filter(|p| p.to_string_lossy().ends_with("-shallow") == matches!(mode, RepoMode::Shallow))
+ .next()
+ .unwrap()
+ .to_owned()
+}
diff --git a/src/tools/cargo/tests/testsuite/https.rs b/src/tools/cargo/tests/testsuite/https.rs
index 501eeae05..c7aec9111 100644
--- a/src/tools/cargo/tests/testsuite/https.rs
+++ b/src/tools/cargo/tests/testsuite/https.rs
@@ -30,7 +30,7 @@ fn self_signed_should_fail() {
.build();
// I think the text here depends on the curl backend.
let err_msg = if cfg!(target_os = "macos") {
- "unexpected return value from ssl handshake -9806; class=Ssl (16)"
+ "untrusted connection error; class=Ssl (16); code=Certificate (-17)"
} else if cfg!(unix) {
"the SSL certificate is invalid; class=Ssl (16); code=Certificate (-17)"
} else if cfg!(windows) {
diff --git a/src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs b/src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs
index 92c96b985..cc261a47f 100644
--- a/src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs
+++ b/src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs
@@ -201,6 +201,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"readme": null,
"readme_file": null,
"repository": "https://github.com/example/example",
+ "rust_version": "1.60",
"vers": "1.2.3"
}
"#,
@@ -376,6 +377,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.2.0"
}
"#,
@@ -503,6 +505,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.2.0"
}
"#,
@@ -734,6 +737,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"readme": "README.md",
"readme_file": "../README.md",
"repository": "https://github.com/example/example",
+ "rust_version": "1.60",
"vers": "1.2.3"
}
"#,
@@ -917,6 +921,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.2.0"
}
"#,
@@ -1269,7 +1274,9 @@ fn error_workspace_dependency_looked_for_workspace_itself() {
.with_stderr(
"\
[WARNING] [CWD]/Cargo.toml: unused manifest key: workspace.dependencies.dep.workspace
-[WARNING] [CWD]/Cargo.toml: dependency (dep) specified without providing a local path, Git repository, or version to use. This will be considered an error in future versions
+[WARNING] [CWD]/Cargo.toml: dependency (dep) specified without providing a local path, Git repository, version, \
+or workspace dependency to use. \
+This will be considered an error in future versions
[UPDATING] `dummy-registry` index
[ERROR] no matching package named `dep` found
location searched: registry `crates-io`
@@ -1589,7 +1596,9 @@ fn cannot_inherit_in_patch() {
.with_stderr(
"\
[WARNING] [CWD]/Cargo.toml: unused manifest key: patch.crates-io.bar.workspace
-[WARNING] [CWD]/Cargo.toml: dependency (bar) specified without providing a local path, Git repository, or version to use. This will be considered an error in future versions
+[WARNING] [CWD]/Cargo.toml: dependency (bar) specified without providing a local path, Git repository, version, \
+or workspace dependency to use. \
+This will be considered an error in future versions
[UPDATING] `dummy-registry` index
[ERROR] failed to resolve patches for `https://github.com/rust-lang/crates.io-index`
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/Cargo.toml b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/Cargo.toml
new file mode 100644
index 000000000..b7a2e9036
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/Cargo.toml
@@ -0,0 +1,21 @@
+[workspace]
+members = [
+ "crates/*",
+]
+
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
+version = "1.2.3"
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/README.md b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/README.md
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/README.md
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/crates/foo/src/main.rs b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/crates/foo/src/main.rs
new file mode 100644
index 000000000..43f0dac5e
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/crates/foo/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Check that our file is not overwritten")
+}
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/src/lib.rs b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/mod.rs b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/mod.rs
new file mode 100644
index 000000000..4e1dda845
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/mod.rs
@@ -0,0 +1,22 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("init")
+ .args(["crates/foo"])
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/Cargo.toml b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/Cargo.toml
new file mode 100644
index 000000000..b7a2e9036
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/Cargo.toml
@@ -0,0 +1,21 @@
+[workspace]
+members = [
+ "crates/*",
+]
+
+[workspace.package]
+authors = ["Rustaceans"]
+description = "foo"
+edition = "2018"
+homepage = "foo"
+keywords = ["foo", "bar"]
+readme = "README.md"
+rust-version = "1.67.0"
+categories = ["algorithms"]
+documentation = "foo"
+exclude = ["foo"]
+include = ["foo"]
+license = "MIT OR Apache-2.0"
+publish = false
+repository = "foo"
+version = "1.2.3"
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml
new file mode 100644
index 000000000..137ed1c87
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "foo"
+authors.workspace = true
+description.workspace = true
+edition.workspace = true
+homepage.workspace = true
+keywords.workspace = true
+readme.workspace = true
+rust-version.workspace = true
+categories.workspace = true
+documentation.workspace = true
+exclude.workspace = true
+include.workspace = true
+license.workspace = true
+publish.workspace = true
+repository.workspace = true
+version.workspace = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/src/main.rs b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/src/main.rs
new file mode 100644
index 000000000..43f0dac5e
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Check that our file is not overwritten")
+}
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/src/lib.rs b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/src/lib.rs
new file mode 100644
index 000000000..7d12d9af8
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stderr.log b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stderr.log
new file mode 100644
index 000000000..3847e4e4a
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stderr.log
@@ -0,0 +1 @@
+ Created binary (application) package
diff --git a/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stdout.log b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/init/mod.rs b/src/tools/cargo/tests/testsuite/init/mod.rs
index 99df9d39d..7853a1a0b 100644
--- a/src/tools/cargo/tests/testsuite/init/mod.rs
+++ b/src/tools/cargo/tests/testsuite/init/mod.rs
@@ -21,6 +21,7 @@ mod git_ignore_exists_no_conflicting_entries;
mod ignores_failure_to_format_source;
mod inferred_bin_with_git;
mod inferred_lib_with_git;
+mod inherit_workspace_package_table;
mod invalid_dir_name;
mod lib_already_exists_nosrc;
mod lib_already_exists_src;
diff --git a/src/tools/cargo/tests/testsuite/install.rs b/src/tools/cargo/tests/testsuite/install.rs
index dd9844f17..9b881dfdc 100644
--- a/src/tools/cargo/tests/testsuite/install.rs
+++ b/src/tools/cargo/tests/testsuite/install.rs
@@ -1416,6 +1416,46 @@ fn path_install_workspace_root_despite_default_members() {
}
#[cargo_test]
+fn git_install_workspace_root_despite_default_members() {
+ let p = git::repo(&paths::root().join("foo"))
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "ws-root"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["ws-member"]
+ default-members = ["ws-member"]
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .file(
+ "ws-member/Cargo.toml",
+ r#"
+ [package]
+ name = "ws-member"
+ version = "0.1.0"
+ authors = []
+ "#,
+ )
+ .file("ws-member/src/main.rs", "fn main() {}")
+ .build();
+
+ cargo_process("install --git")
+ .arg(p.url().to_string())
+ .arg("ws-root")
+ .with_stderr_contains(
+ "[INSTALLED] package `ws-root v0.1.0 ([..])` (executable `ws-root[EXE]`)",
+ )
+ // Particularly avoid "Installed package `ws-root v0.1.0 ([..]])` (executable `ws-member`)":
+ .with_stderr_does_not_contain("ws-member")
+ .run();
+}
+
+#[cargo_test]
fn dev_dependencies_no_check() {
Package::new("foo", "1.0.0").publish();
let p = project()
@@ -2287,3 +2327,84 @@ fn sparse_install() {
"#,
);
}
+
+#[cargo_test]
+fn self_referential() {
+ // Some packages build-dep on prior versions of themselves.
+ Package::new("foo", "0.0.1")
+ .file("src/lib.rs", "fn hello() {}")
+ .file("src/main.rs", "fn main() {}")
+ .file("build.rs", "fn main() {}")
+ .publish();
+ Package::new("foo", "0.0.2")
+ .file("src/lib.rs", "fn hello() {}")
+ .file("src/main.rs", "fn main() {}")
+ .file("build.rs", "fn main() {}")
+ .build_dep("foo", "0.0.1")
+ .publish();
+
+ cargo_process("install foo")
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] foo v0.0.2 (registry [..])
+[INSTALLING] foo v0.0.2
+[DOWNLOADING] crates ...
+[DOWNLOADED] foo v0.0.1 (registry [..])
+[COMPILING] foo v0.0.1
+[COMPILING] foo v0.0.2
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
+[INSTALLED] package `foo v0.0.2` (executable `foo[EXE]`)
+[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ )
+ .run();
+ assert_has_installed_exe(cargo_home(), "foo");
+}
+
+#[cargo_test]
+fn ambiguous_registry_vs_local_package() {
+ // Correctly install 'foo' from a local package, even if that package also
+ // depends on a registry dependency named 'foo'.
+ Package::new("foo", "0.0.1")
+ .file("src/lib.rs", "fn hello() {}")
+ .publish();
+
+ let p = project()
+ .file("src/main.rs", "fn main() {}")
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ edition = "2021"
+
+ [dependencies]
+ foo = "0.0.1"
+ "#,
+ )
+ .build();
+
+ cargo_process("install --path")
+ .arg(p.root())
+ .with_stderr(
+ "\
+[INSTALLING] foo v0.1.0 ([..])
+[UPDATING] `[..]` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] foo v0.0.1 (registry [..])
+[COMPILING] foo v0.0.1
+[COMPILING] foo v0.1.0 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] [CWD]/home/.cargo/bin/foo[EXE]
+[INSTALLED] package `foo v0.1.0 ([..])` (executable `foo[EXE]`)
+[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ )
+ .run();
+ assert_has_installed_exe(cargo_home(), "foo");
+}
diff --git a/src/tools/cargo/tests/testsuite/lints.rs b/src/tools/cargo/tests/testsuite/lints.rs
new file mode 100644
index 000000000..fb31da30a
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/lints.rs
@@ -0,0 +1,639 @@
+//! Tests for `[lints]`
+
+use cargo_test_support::project;
+use cargo_test_support::registry::Package;
+
+#[cargo_test]
+fn package_requires_option() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lints.rust]
+ unsafe_code = "forbid"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check")
+ .with_stderr(
+ "\
+warning: unused manifest key `lints` (may be supported in a future version)
+
+this Cargo does not support nightly features, but if you
+switch to nightly channel you can pass
+`-Zlints` to enable this feature.
+[CHECKING] [..]
+[FINISHED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn workspace_requires_option() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [workspace.lints.rust]
+ unsafe_code = "forbid"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check")
+ .with_stderr(
+ "\
+warning: [CWD]/Cargo.toml: unused manifest key `lints` (may be supported in a future version)
+
+this Cargo does not support nightly features, but if you
+switch to nightly channel you can pass
+`-Zlints` to enable this feature.
+[CHECKING] [..]
+[FINISHED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn dependency_warning_ignored() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar.path = "../bar"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ let _bar = project()
+ .at("bar")
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lints.rust]
+ unsafe_code = "forbid"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check")
+ .with_stderr(
+ "\
+[CHECKING] [..]
+[CHECKING] [..]
+[FINISHED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn malformed_on_stable() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ lints = 20
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check")
+ .with_stderr(
+ "\
+warning: unused manifest key `lints` (may be supported in a future version)
+
+this Cargo does not support nightly features, but if you
+switch to nightly channel you can pass
+`-Zlints` to enable this feature.
+[CHECKING] [..]
+[FINISHED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn malformed_on_nightly() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ lints = 20
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr(
+ "\
+error: failed to parse manifest[..]
+
+Caused by:
+ invalid type: integer `20`, expected a map
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn fail_on_invalid_tool() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [workspace.lints.super-awesome-linter]
+ unsafe_code = "forbid"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr(
+ "\
+[..]
+
+Caused by:
+ unsupported `super-awesome-linter` in `[lints]`, must be one of rust, clippy, rustdoc
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn fail_on_tool_injection() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [workspace.lints.rust]
+ "clippy::cyclomatic_complexity" = "warn"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr(
+ "\
+[..]
+
+Caused by:
+ `lints.rust.clippy::cyclomatic_complexity` is not valid lint name; try `lints.clippy.cyclomatic_complexity`
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn fail_on_redundant_tool() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [workspace.lints.rust]
+ "rust::unsafe_code" = "forbid"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr(
+ "\
+[..]
+
+Caused by:
+ `lints.rust.rust::unsafe_code` is not valid lint name; try `lints.rust.unsafe_code`
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn fail_on_conflicting_tool() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [workspace.lints.rust]
+ "super-awesome-tool::unsafe_code" = "forbid"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr(
+ "\
+[..]
+
+Caused by:
+ `lints.rust.super-awesome-tool::unsafe_code` is not a valid lint name
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn package_lint_deny() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lints.rust]
+ "unsafe_code" = "deny"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+pub fn foo(num: i32) -> u32 {
+ unsafe { std::mem::transmute(num) }
+}
+",
+ )
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr_contains(
+ "\
+error: usage of an `unsafe` block
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn workspace_lint_deny() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lints]
+ workspace = true
+
+ [workspace.lints.rust]
+ "unsafe_code" = "deny"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+pub fn foo(num: i32) -> u32 {
+ unsafe { std::mem::transmute(num) }
+}
+",
+ )
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr_contains(
+ "\
+error: usage of an `unsafe` block
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn attribute_has_precedence() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lints.rust]
+ "unsafe_code" = "deny"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+#![allow(unsafe_code)]
+
+pub fn foo(num: i32) -> u32 {
+ unsafe { std::mem::transmute(num) }
+}
+",
+ )
+ .build();
+
+ foo.cargo("check -Zlints")
+ .arg("-v") // Show order of rustflags on failure
+ .masquerade_as_nightly_cargo(&["lints"])
+ .run();
+}
+
+#[cargo_test]
+fn rustflags_has_precedence() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lints.rust]
+ "unsafe_code" = "deny"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+pub fn foo(num: i32) -> u32 {
+ unsafe { std::mem::transmute(num) }
+}
+",
+ )
+ .build();
+
+ foo.cargo("check -Zlints")
+ .arg("-v") // Show order of rustflags on failure
+ .env("RUSTFLAGS", "-Aunsafe_code")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .run();
+}
+
+#[cargo_test]
+fn profile_rustflags_has_precedence() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ cargo-features = ["profile-rustflags"]
+
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lints.rust]
+ "unsafe_code" = "deny"
+
+ [profile.dev]
+ rustflags = ["-A", "unsafe_code"]
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+pub fn foo(num: i32) -> u32 {
+ unsafe { std::mem::transmute(num) }
+}
+",
+ )
+ .build();
+
+ foo.cargo("check -Zlints")
+ .arg("-v") // Show order of rustflags on failure
+ .masquerade_as_nightly_cargo(&["lints", "profile-rustflags"])
+ .run();
+}
+
+#[cargo_test]
+fn build_rustflags_has_precedence() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lints.rust]
+ "unsafe_code" = "deny"
+ "#,
+ )
+ .file(
+ ".cargo/config.toml",
+ r#"
+ [build]
+ rustflags = ["-A", "unsafe_code"]
+"#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+pub fn foo(num: i32) -> u32 {
+ unsafe { std::mem::transmute(num) }
+}
+",
+ )
+ .build();
+
+ foo.cargo("check -Zlints")
+ .arg("-v") // Show order of rustflags on failure
+ .masquerade_as_nightly_cargo(&["lints"])
+ .run();
+}
+
+#[cargo_test]
+fn without_priority() {
+ Package::new("reg-dep", "1.0.0").publish();
+
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ edition = "2018"
+ authors = []
+
+ [dependencies]
+ reg-dep = "1.0.0"
+
+ [lints.rust]
+ "rust-2018-idioms" = "deny"
+ "unused-extern-crates" = "allow"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+extern crate reg_dep;
+
+pub fn foo() -> u32 {
+ 2
+}
+",
+ )
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr_contains(
+ "\
+error: unused extern crate
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn with_priority() {
+ Package::new("reg-dep", "1.0.0").publish();
+
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ edition = "2018"
+ authors = []
+
+ [dependencies]
+ reg-dep = "1.0.0"
+
+ [lints.rust]
+ "rust-2018-idioms" = { level = "deny", priority = -1 }
+ "unused-extern-crates" = "allow"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+extern crate reg_dep;
+
+pub fn foo() -> u32 {
+ 2
+}
+",
+ )
+ .build();
+
+ foo.cargo("check -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .run();
+}
+
+#[cargo_test]
+fn rustdoc_lint() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lints.rustdoc]
+ broken_intra_doc_links = "deny"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+/// [`bar`] doesn't exist
+pub fn foo() -> u32 {
+}
+",
+ )
+ .build();
+
+ foo.cargo("doc -Zlints")
+ .masquerade_as_nightly_cargo(&["lints"])
+ .with_status(101)
+ .with_stderr_contains(
+ "\
+error: unresolved link to `bar`
+",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/main.rs b/src/tools/cargo/tests/testsuite/main.rs
index a1e293acd..170a22667 100644
--- a/src/tools/cargo/tests/testsuite/main.rs
+++ b/src/tools/cargo/tests/testsuite/main.rs
@@ -24,6 +24,7 @@ mod cargo_command;
mod cargo_config;
mod cargo_env_config;
mod cargo_features;
+mod cargo_new;
mod cargo_remove;
mod cargo_targets;
mod cfg;
@@ -59,6 +60,7 @@ mod generate_lockfile;
mod git;
mod git_auth;
mod git_gc;
+mod git_shallow;
mod glob_targets;
mod help;
mod https;
@@ -67,6 +69,7 @@ mod init;
mod install;
mod install_upgrade;
mod jobserver;
+mod lints;
mod list_availables;
mod local_registry;
mod locate_project;
@@ -119,6 +122,7 @@ mod rustdoc;
mod rustdoc_extern_html;
mod rustdocflags;
mod rustflags;
+mod rustup;
mod search;
mod shell_quoting;
mod source_replacement;
diff --git a/src/tools/cargo/tests/testsuite/metadata.rs b/src/tools/cargo/tests/testsuite/metadata.rs
index 547916e7a..ac2cec396 100644
--- a/src/tools/cargo/tests/testsuite/metadata.rs
+++ b/src/tools/cargo/tests/testsuite/metadata.rs
@@ -65,6 +65,7 @@ fn cargo_metadata_simple() {
}
],
"workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
+ "workspace_default_members": ["foo 0.5.0 (path+file:[..]foo)"],
"resolve": {
"nodes": [
{
@@ -164,6 +165,7 @@ crate-type = ["lib", "staticlib"]
}
],
"workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
+ "workspace_default_members": ["foo 0.5.0 (path+file:[..]foo)"],
"resolve": {
"nodes": [
{
@@ -257,6 +259,7 @@ optional_feat = []
}
],
"workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
+ "workspace_default_members": ["foo 0.5.0 (path+file:[..]foo)"],
"resolve": {
"nodes": [
{
@@ -587,6 +590,9 @@ fn cargo_metadata_with_deps_and_version() {
"workspace_members": [
"foo 0.5.0 (path+file:[..]foo)"
],
+ "workspace_default_members": [
+ "foo 0.5.0 (path+file:[..]foo)"
+ ],
"workspace_root": "[..]/foo",
"metadata": null
}"#,
@@ -668,6 +674,9 @@ name = "ex"
"workspace_members": [
"foo 0.1.0 (path+file:[..]foo)"
],
+ "workspace_default_members": [
+ "foo 0.1.0 (path+file:[..]foo)"
+ ],
"resolve": {
"root": "foo 0.1.0 (path+file://[..]foo)",
"nodes": [
@@ -763,6 +772,9 @@ crate-type = ["rlib", "dylib"]
"workspace_members": [
"foo 0.1.0 (path+file:[..]foo)"
],
+ "workspace_default_members": [
+ "foo 0.1.0 (path+file:[..]foo)"
+ ],
"resolve": {
"root": "foo 0.1.0 (path+file://[..]foo)",
"nodes": [
@@ -892,6 +904,7 @@ fn workspace_metadata() {
}
],
"workspace_members": ["bar 0.5.0 (path+file:[..]bar)", "baz 0.5.0 (path+file:[..]baz)"],
+ "workspace_default_members": ["bar 0.5.0 (path+file:[..]bar)", "baz 0.5.0 (path+file:[..]baz)"],
"resolve": {
"nodes": [
{
@@ -1123,6 +1136,11 @@ fn workspace_metadata_with_dependencies_no_deps() {
"artifact 0.5.0 (path+file:[..]/foo/artifact)",
"baz 0.5.0 (path+file:[..]baz)"
],
+ "workspace_default_members": [
+ "bar 0.5.0 (path+file:[..]bar)",
+ "artifact 0.5.0 (path+file:[..]/foo/artifact)",
+ "baz 0.5.0 (path+file:[..]baz)"
+ ],
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
@@ -1755,6 +1773,12 @@ fn workspace_metadata_with_dependencies_and_resolve() {
"bin-only-artifact 0.5.0 (path+file://[..]/foo/bin-only-artifact)",
"non-artifact 0.5.0 (path+file://[..]/foo/non-artifact)"
],
+ "workspace_default_members": [
+ "bar 0.5.0 (path+file://[..]/foo/bar)",
+ "artifact 0.5.0 (path+file://[..]/foo/artifact)",
+ "bin-only-artifact 0.5.0 (path+file://[..]/foo/bin-only-artifact)",
+ "non-artifact 0.5.0 (path+file://[..]/foo/non-artifact)"
+ ],
"workspace_root": "[..]/foo"
}
"#,
@@ -1953,6 +1977,7 @@ const MANIFEST_OUTPUT: &str = r#"
"documentation": null
}],
"workspace_members": [ "foo 0.5.0 (path+file:[..]foo)" ],
+ "workspace_default_members": [ "foo 0.5.0 (path+file:[..]foo)" ],
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
@@ -2147,6 +2172,7 @@ fn package_metadata() {
}
],
"workspace_members": ["foo[..]"],
+ "workspace_default_members": ["foo[..]"],
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
@@ -2222,6 +2248,7 @@ fn package_publish() {
}
],
"workspace_members": ["foo[..]"],
+ "workspace_default_members": ["foo[..]"],
"resolve": null,
"target_directory": "[..]foo/target",
"version": 1,
@@ -2317,6 +2344,9 @@ fn cargo_metadata_path_to_cargo_toml_project() {
"workspace_members": [
"bar 0.5.0 (path+file:[..])"
],
+ "workspace_default_members": [
+ "bar 0.5.0 (path+file:[..])"
+ ],
"workspace_root": "[..]",
"metadata": null
}
@@ -2405,6 +2435,9 @@ fn package_edition_2018() {
"workspace_members": [
"foo 0.1.0 (path+file:[..])"
],
+ "workspace_default_members": [
+ "foo 0.1.0 (path+file:[..])"
+ ],
"workspace_root": "[..]",
"metadata": null
}
@@ -2553,6 +2586,9 @@ fn target_edition_2018() {
"workspace_members": [
"foo 0.1.0 (path+file:[..])"
],
+ "workspace_default_members": [
+ "foo 0.1.0 (path+file:[..])"
+ ],
"workspace_root": "[..]",
"metadata": null
}
@@ -2789,6 +2825,9 @@ fn rename_dependency() {
"workspace_members": [
"foo 0.0.1[..]"
],
+ "workspace_default_members": [
+ "foo 0.0.1[..]"
+ ],
"workspace_root": "[..]",
"metadata": null
}"#,
@@ -2889,6 +2928,9 @@ fn metadata_links() {
"workspace_members": [
"foo 0.5.0 [..]"
],
+ "workspace_default_members": [
+ "foo 0.5.0 [..]"
+ ],
"workspace_root": "[..]/foo",
"metadata": null
}
@@ -2979,6 +3021,9 @@ fn deps_with_bin_only() {
"workspace_members": [
"foo 0.1.0 ([..])"
],
+ "workspace_default_members": [
+ "foo 0.1.0 ([..])"
+ ],
"resolve": {
"nodes": [
{
@@ -3358,6 +3403,9 @@ fn filter_platform() {
"workspace_members": [
"foo 0.1.0 (path+file:[..]foo)"
],
+ "workspace_default_members": [
+ "foo 0.1.0 (path+file:[..]foo)"
+ ],
"resolve": {
"nodes": [
{
@@ -3477,6 +3525,7 @@ fn filter_platform() {
$NORMAL_DEP
],
"workspace_members": "{...}",
+ "workspace_default_members": "{...}",
"resolve": {
"nodes": [
{
@@ -3558,6 +3607,7 @@ fn filter_platform() {
$NORMAL_DEP
],
"workspace_members": "{...}",
+ "workspace_default_members": "{...}",
"resolve": {
"nodes": [
{
@@ -3642,6 +3692,7 @@ fn filter_platform() {
$NORMAL_DEP
],
"workspace_members": "{...}",
+ "workspace_default_members": "{...}",
"resolve": {
"nodes": [
{
@@ -3756,6 +3807,7 @@ fn dep_kinds() {
{
"packages": "{...}",
"workspace_members": "{...}",
+ "workspace_default_members": "{...}",
"target_directory": "{...}",
"version": 1,
"workspace_root": "{...}",
@@ -3871,6 +3923,7 @@ fn dep_kinds_workspace() {
{
"packages": "{...}",
"workspace_members": "{...}",
+ "workspace_default_members": "{...}",
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_root": "[..]/foo",
@@ -4184,6 +4237,11 @@ fn workspace_metadata_with_dependencies_no_deps_artifact() {
"artifact 0.5.0 (path+file://[..]/foo/artifact)",
"baz 0.5.0 (path+file://[..]/foo/baz)"
],
+ "workspace_default_members": [
+ "bar 0.5.0 (path+file://[..]/foo/bar)",
+ "artifact 0.5.0 (path+file://[..]/foo/artifact)",
+ "baz 0.5.0 (path+file://[..]/foo/baz)"
+ ],
"workspace_root": "[..]/foo"
}
"#,
diff --git a/src/tools/cargo/tests/testsuite/mock-std/library/sysroot/Cargo.toml b/src/tools/cargo/tests/testsuite/mock-std/library/sysroot/Cargo.toml
new file mode 100644
index 000000000..615c894db
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/mock-std/library/sysroot/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "sysroot"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+proc_macro = { path = "../proc_macro" }
+std = { path = "../std" }
+test = { path = "../test" }
+
+[features]
+panic-unwind = []
+backtrace = []
+feature1 = ["std/feature1"]
+default = []
diff --git a/src/tools/cargo/tests/testsuite/mock-std/library/sysroot/src/lib.rs b/src/tools/cargo/tests/testsuite/mock-std/library/sysroot/src/lib.rs
new file mode 100644
index 000000000..7215576fc
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/mock-std/library/sysroot/src/lib.rs
@@ -0,0 +1 @@
+// Intentionally left blank.
diff --git a/src/tools/cargo/tests/testsuite/mock-std/library/test/Cargo.toml b/src/tools/cargo/tests/testsuite/mock-std/library/test/Cargo.toml
index 299db7bfd..b9f51eda7 100644
--- a/src/tools/cargo/tests/testsuite/mock-std/library/test/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/mock-std/library/test/Cargo.toml
@@ -5,14 +5,7 @@ authors = ["Alex Crichton <alex@alexcrichton.com>"]
edition = "2018"
[dependencies]
-proc_macro = { path = "../proc_macro" }
std = { path = "../std" }
panic_unwind = { path = "../panic_unwind" }
compiler_builtins = { path = "../compiler_builtins" }
registry-dep-using-std = { version = "*", features = ['mockbuild'] }
-
-[features]
-panic-unwind = []
-backtrace = []
-feature1 = ["std/feature1"]
-default = []
diff --git a/src/tools/cargo/tests/testsuite/offline.rs b/src/tools/cargo/tests/testsuite/offline.rs
index fe54fc59d..5f164dbeb 100644
--- a/src/tools/cargo/tests/testsuite/offline.rs
+++ b/src/tools/cargo/tests/testsuite/offline.rs
@@ -3,6 +3,7 @@
use cargo_test_support::{
basic_manifest, git, main_file, path2url, project,
registry::{Package, RegistryBuilder},
+ Execs,
};
use std::fs;
@@ -377,6 +378,15 @@ fn update_offline_not_cached_git() {
#[cargo_test]
fn cargo_compile_offline_with_cached_git_dep() {
+ compile_offline_with_cached_git_dep(false)
+}
+
+#[cargo_test]
+fn gitoxide_cargo_compile_offline_with_cached_git_dep_shallow_dep() {
+ compile_offline_with_cached_git_dep(true)
+}
+
+fn compile_offline_with_cached_git_dep(shallow: bool) {
let git_project = git::new("dep1", |project| {
project
.file("Cargo.toml", &basic_manifest("dep1", "0.5.0"))
@@ -420,7 +430,17 @@ fn cargo_compile_offline_with_cached_git_dep() {
)
.file("src/main.rs", "fn main(){}")
.build();
- prj.cargo("build").run();
+ let maybe_use_shallow = |mut cargo: Execs| -> Execs {
+ if shallow {
+ cargo
+ .arg("-Zgitoxide=fetch,shallow-deps")
+ .masquerade_as_nightly_cargo(&[
+ "unstable features must be available for -Z gitoxide",
+ ]);
+ }
+ cargo
+ };
+ maybe_use_shallow(prj.cargo("build")).run();
prj.change_file(
"Cargo.toml",
@@ -438,7 +458,7 @@ fn cargo_compile_offline_with_cached_git_dep() {
rev2
),
);
- prj.cargo("build").run();
+ maybe_use_shallow(prj.cargo("build")).run();
let p = project()
.file(
@@ -463,15 +483,15 @@ fn cargo_compile_offline_with_cached_git_dep() {
let git_root = git_project.root();
- p.cargo("build --offline")
- .with_stderr(format!(
- "\
+ let mut cargo = p.cargo("build --offline");
+ cargo.with_stderr(format!(
+ "\
[COMPILING] dep1 v0.5.0 ({}#[..])
[COMPILING] foo v0.5.0 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
- path2url(git_root),
- ))
- .run();
+ path2url(git_root),
+ ));
+ maybe_use_shallow(cargo).run();
assert!(p.bin("foo").is_file());
@@ -496,7 +516,7 @@ fn cargo_compile_offline_with_cached_git_dep() {
),
);
- p.cargo("build --offline").run();
+ maybe_use_shallow(p.cargo("build --offline")).run();
p.process(&p.bin("foo"))
.with_stdout("hello from cached git repo rev1\n")
.run();
diff --git a/src/tools/cargo/tests/testsuite/package.rs b/src/tools/cargo/tests/testsuite/package.rs
index 14bac6618..3b4328242 100644
--- a/src/tools/cargo/tests/testsuite/package.rs
+++ b/src/tools/cargo/tests/testsuite/package.rs
@@ -1775,6 +1775,142 @@ fn exclude_dot_files_and_directories_by_default() {
}
#[cargo_test]
+fn empty_readme_path() {
+ // Warn but don't fail if `readme` is empty.
+ // Issue #11522.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ readme = ""
+ license = "MIT"
+ description = "foo"
+ homepage = "foo"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("package --no-verify")
+ .with_stderr(
+ "\
+[WARNING] readme `` does not appear to exist (relative to `[..]/foo`).
+Please update the readme setting in the manifest at `[..]/foo/Cargo.toml`
+This may become a hard error in the future.
+[PACKAGING] foo v1.0.0 ([..]/foo)
+[PACKAGED] [..] files, [..] ([..] compressed)
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn invalid_readme_path() {
+ // Warn but don't fail if `readme` path is invalid.
+ // Issue #11522.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ readme = "DOES-NOT-EXIST"
+ license = "MIT"
+ description = "foo"
+ homepage = "foo"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("package --no-verify")
+ .with_stderr(
+ "\
+[WARNING] readme `DOES-NOT-EXIST` does not appear to exist (relative to `[..]/foo`).
+Please update the readme setting in the manifest at `[..]/foo/Cargo.toml`
+This may become a hard error in the future.
+[PACKAGING] foo v1.0.0 ([..]/foo)
+[PACKAGED] [..] files, [..] ([..] compressed)
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn readme_or_license_file_is_dir() {
+ // Test warning when `readme` or `license-file` is a directory, not a file.
+ // Issue #11522.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ readme = "./src"
+ license-file = "./src"
+ description = "foo"
+ homepage = "foo"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("package --no-verify")
+ .with_stderr(
+ "\
+[WARNING] license-file `./src` does not appear to exist (relative to `[..]/foo`).
+Please update the license-file setting in the manifest at `[..]/foo/Cargo.toml`
+This may become a hard error in the future.
+[WARNING] readme `./src` does not appear to exist (relative to `[..]/foo`).
+Please update the readme setting in the manifest at `[..]/foo/Cargo.toml`
+This may become a hard error in the future.
+[PACKAGING] foo v1.0.0 ([..]/foo)
+[PACKAGED] [..] files, [..] ([..] compressed)
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn empty_license_file_path() {
+ // Warn but don't fail if license-file is empty.
+ // Issue #11522.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ license-file = ""
+ description = "foo"
+ homepage = "foo"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("package --no-verify")
+ .with_stderr(
+ "\
+[WARNING] manifest has no license or license-file.
+See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
+[WARNING] license-file `` does not appear to exist (relative to `[..]/foo`).
+Please update the license-file setting in the manifest at `[..]/foo/Cargo.toml`
+This may become a hard error in the future.
+[PACKAGING] foo v1.0.0 ([..]/foo)
+[PACKAGED] [..] files, [..] ([..] compressed)
+",
+ )
+ .run();
+}
+
+#[cargo_test]
fn invalid_license_file_path() {
// Test warning when license-file points to a non-existent file.
let p = project()
@@ -2400,6 +2536,91 @@ See [..]
}
#[cargo_test]
+fn workspace_noconflict_readme() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["bar"]
+ "#,
+ )
+ .file("README.md", "workspace readme")
+ .file(
+ "bar/Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ repository = "https://github.com/bar/bar"
+ authors = []
+ license = "MIT"
+ description = "bar"
+ readme = "../README.md"
+ workspace = ".."
+ "#,
+ )
+ .file("bar/src/main.rs", "fn main() {}")
+ .file("bar/example/README.md", "# example readmdBar")
+ .build();
+
+ p.cargo("package")
+ .with_stderr(
+ "\
+[PACKAGING] bar v0.0.1 ([CWD]/bar)
+[VERIFYING] bar v0.0.1 ([CWD]/bar)
+[COMPILING] bar v0.0.1 ([CWD]/[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[PACKAGED] [..] files, [..] ([..] compressed)
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn workspace_conflict_readme() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["bar"]
+ "#,
+ )
+ .file("README.md", "workspace readme")
+ .file(
+ "bar/Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ repository = "https://github.com/bar/bar"
+ authors = []
+ license = "MIT"
+ description = "bar"
+ readme = "../README.md"
+ workspace = ".."
+ "#,
+ )
+ .file("bar/src/main.rs", "fn main() {}")
+ .file("bar/README.md", "# workspace member: Bar")
+ .build();
+
+ p.cargo("package")
+ .with_stderr(
+ "\
+warning: readme `../README.md` appears to be a path outside of the package, but there is already a file named `README.md` in the root of the package. The archived crate will contain the copy in the root of the package. Update the readme to point to the path relative to the root of the package to remove this warning.
+[PACKAGING] bar v0.0.1 ([CWD]/bar)
+[VERIFYING] bar v0.0.1 ([CWD]/bar)
+[COMPILING] bar v0.0.1 ([CWD]/[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[PACKAGED] [..] files, [..] ([..] compressed)
+",
+ )
+ .run();
+}
+
+#[cargo_test]
fn workspace_overrides_resolver() {
let p = project()
.file(
diff --git a/src/tools/cargo/tests/testsuite/patch.rs b/src/tools/cargo/tests/testsuite/patch.rs
index 681c02416..f2f077d7d 100644
--- a/src/tools/cargo/tests/testsuite/patch.rs
+++ b/src/tools/cargo/tests/testsuite/patch.rs
@@ -2466,7 +2466,11 @@ fn can_update_with_alt_reg() {
}
#[cargo_test]
-fn old_git_patch() {
+fn gitoxide_clones_shallow_old_git_patch() {
+ perform_old_git_patch(true)
+}
+
+fn perform_old_git_patch(shallow: bool) {
// Example where an old lockfile with an explicit branch="master" in Cargo.toml.
Package::new("bar", "1.0.0").publish();
let (bar, bar_repo) = git::new_repo("bar", |p| {
@@ -2524,7 +2528,13 @@ dependencies = [
git::commit(&bar_repo);
// This *should* keep the old lock.
- p.cargo("tree")
+ let mut cargo = p.cargo("tree");
+ if shallow {
+ cargo
+ .arg("-Zgitoxide=fetch,shallow-deps")
+ .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]);
+ }
+ cargo
// .env("CARGO_LOG", "trace")
.with_stderr(
"\
@@ -2542,6 +2552,11 @@ foo v0.1.0 [..]
.run();
}
+#[cargo_test]
+fn old_git_patch() {
+ perform_old_git_patch(false)
+}
+
// From https://github.com/rust-lang/cargo/issues/7463
#[cargo_test]
fn patch_eq_conflict_panic() {
diff --git a/src/tools/cargo/tests/testsuite/profile_config.rs b/src/tools/cargo/tests/testsuite/profile_config.rs
index c59ed7a97..cf9807964 100644
--- a/src/tools/cargo/tests/testsuite/profile_config.rs
+++ b/src/tools/cargo/tests/testsuite/profile_config.rs
@@ -1,5 +1,6 @@
//! Tests for profiles defined in config files.
+use cargo::util::toml::TomlDebugInfo;
use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::registry::Package;
use cargo_test_support::{basic_lib_manifest, paths, project};
@@ -436,7 +437,7 @@ fn named_config_profile() {
assert_eq!(p.name, "foo");
assert_eq!(p.codegen_units, Some(2)); // "foo" from config
assert_eq!(p.opt_level, "1"); // "middle" from manifest
- assert_eq!(p.debuginfo.to_option(), Some(1)); // "bar" from config
+ assert_eq!(p.debuginfo.to_option(), Some(TomlDebugInfo::Limited)); // "bar" from config
assert_eq!(p.debug_assertions, true); // "dev" built-in (ignore build-override)
assert_eq!(p.overflow_checks, true); // "dev" built-in (ignore package override)
@@ -445,7 +446,7 @@ fn named_config_profile() {
assert_eq!(bo.name, "foo");
assert_eq!(bo.codegen_units, Some(6)); // "foo" build override from config
assert_eq!(bo.opt_level, "0"); // default to zero
- assert_eq!(bo.debuginfo.to_option(), Some(1)); // SAME as normal
+ assert_eq!(bo.debuginfo.to_option(), Some(TomlDebugInfo::Limited)); // SAME as normal
assert_eq!(bo.debug_assertions, false); // "foo" build override from manifest
assert_eq!(bo.overflow_checks, true); // SAME as normal
@@ -454,7 +455,7 @@ fn named_config_profile() {
assert_eq!(po.name, "foo");
assert_eq!(po.codegen_units, Some(7)); // "foo" package override from config
assert_eq!(po.opt_level, "1"); // SAME as normal
- assert_eq!(po.debuginfo.to_option(), Some(1)); // SAME as normal
+ assert_eq!(po.debuginfo.to_option(), Some(TomlDebugInfo::Limited)); // SAME as normal
assert_eq!(po.debug_assertions, true); // SAME as normal
assert_eq!(po.overflow_checks, false); // "middle" package override from manifest
}
diff --git a/src/tools/cargo/tests/testsuite/profile_targets.rs b/src/tools/cargo/tests/testsuite/profile_targets.rs
index b3235972c..0449e8ab3 100644
--- a/src/tools/cargo/tests/testsuite/profile_targets.rs
+++ b/src/tools/cargo/tests/testsuite/profile_targets.rs
@@ -83,16 +83,16 @@ fn profile_selection_build() {
// - bdep `panic` is not set because it thinks `build.rs` is a plugin.
// - build_script_build is built without panic because it thinks `build.rs` is a plugin.
// - We make sure that the build dependencies bar, bdep, and build.rs
- // are built without debuginfo.
+ // are built with debuginfo=0.
p.cargo("build -vv")
.with_stderr_unordered("\
[COMPILING] bar [..]
[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]
-[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]
+[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 -C debuginfo=0[..]
[COMPILING] bdep [..]
-[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]
+[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 -C debuginfo=0[..]
[COMPILING] foo [..]
-[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]
+[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 -C debuginfo=0[..]
[RUNNING] `[..]/target/debug/build/foo-[..]/build-script-build`
[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0
[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]
@@ -100,9 +100,6 @@ fn profile_selection_build() {
[FINISHED] dev [unoptimized + debuginfo] [..]
"
)
- .with_stderr_line_without(&["[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]-C codegen-units=5 [..]"], &["-C debuginfo"])
- .with_stderr_line_without(&["[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]-C codegen-units=5 [..]"], &["-C debuginfo"])
- .with_stderr_line_without(&["[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]-C codegen-units=5 [..]"], &["-C debuginfo"])
.run();
p.cargo("build -vv")
.with_stderr_unordered(
@@ -158,7 +155,7 @@ fn profile_selection_build_all_targets() {
// - Benchmark dependencies are compiled in `dev` mode, which may be
// surprising. See issue rust-lang/cargo#4929.
// - We make sure that the build dependencies bar, bdep, and build.rs
- // are built without debuginfo.
+ // are built with debuginfo=0.
//
// - Dependency profiles:
// Pkg Target Profile Reason
@@ -184,11 +181,11 @@ fn profile_selection_build_all_targets() {
[COMPILING] bar [..]
[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]
[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]
-[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]
+[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 -C debuginfo=0[..]
[COMPILING] bdep [..]
-[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]
+[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 -C debuginfo=0[..]
[COMPILING] foo [..]
-[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]
+[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 -C debuginfo=0[..]
[RUNNING] `[..]/target/debug/build/foo-[..]/build-script-build`
[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0
[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]`
@@ -202,9 +199,6 @@ fn profile_selection_build_all_targets() {
[FINISHED] dev [unoptimized + debuginfo] [..]
"
)
- .with_stderr_line_without(&["[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]-C codegen-units=5 [..]"], &["-C debuginfo"])
- .with_stderr_line_without(&["[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]-C codegen-units=5 [..]"], &["-C debuginfo"])
- .with_stderr_line_without(&["[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]-C codegen-units=5 [..]"], &["-C debuginfo"])
.run();
p.cargo("build -vv")
.with_stderr_unordered(
diff --git a/src/tools/cargo/tests/testsuite/publish.rs b/src/tools/cargo/tests/testsuite/publish.rs
index 00a79fe73..45b7c7da5 100644
--- a/src/tools/cargo/tests/testsuite/publish.rs
+++ b/src/tools/cargo/tests/testsuite/publish.rs
@@ -25,6 +25,7 @@ const CLEAN_FOO_JSON: &str = r#"
"readme": null,
"readme_file": null,
"repository": "foo",
+ "rust_version": null,
"vers": "0.0.1"
}
"#;
@@ -49,6 +50,7 @@ fn validate_upload_foo() {
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.0.1"
}
"#,
@@ -77,6 +79,7 @@ fn validate_upload_li() {
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": "1.69",
"vers": "0.0.1"
}
"#,
@@ -1270,6 +1273,7 @@ You may press ctrl-c [..]
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.0.1"
}
"#,
@@ -1469,6 +1473,7 @@ You may press ctrl-c [..]
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.1.0"
}
"#,
@@ -1581,6 +1586,7 @@ You may press ctrl-c [..]
"readme": null,
"readme_file": null,
"repository": "foo",
+ "rust_version": null,
"vers": "0.1.0"
}
"#,
@@ -1756,6 +1762,9 @@ fn publish_with_missing_readme() {
.with_stderr(&format!(
"\
[UPDATING] [..]
+[WARNING] readme `foo.md` does not appear to exist (relative to `[..]/foo`).
+Please update the readme setting in the manifest at `[..]/foo/Cargo.toml`
+This may become a hard error in the future.
[PACKAGING] foo v0.1.0 [..]
[PACKAGED] [..] files, [..] ([..] compressed)
[UPLOADING] foo v0.1.0 [..]
@@ -2046,6 +2055,7 @@ fn in_package_workspace() {
[package]
name = "li"
version = "0.0.1"
+ rust-version = "1.69"
description = "li"
license = "MIT"
"#,
@@ -2148,6 +2158,7 @@ fn in_package_workspace_with_members_with_features_old() {
[package]
name = "li"
version = "0.0.1"
+ rust-version = "1.69"
description = "li"
license = "MIT"
"#,
@@ -2243,6 +2254,7 @@ fn in_virtual_workspace_with_p() {
[package]
name = "li"
version = "0.0.1"
+ rust-version = "1.69"
description = "li"
license = "MIT"
"#,
diff --git a/src/tools/cargo/tests/testsuite/registry.rs b/src/tools/cargo/tests/testsuite/registry.rs
index 05ec9b158..bd5e42b45 100644
--- a/src/tools/cargo/tests/testsuite/registry.rs
+++ b/src/tools/cargo/tests/testsuite/registry.rs
@@ -2546,7 +2546,7 @@ fn package_lock_inside_package_is_overwritten() {
.join("bar-0.0.1")
.join(".cargo-ok");
- assert_eq!(ok.metadata().unwrap().len(), 2);
+ assert_eq!(ok.metadata().unwrap().len(), 7);
}
#[cargo_test]
@@ -2586,7 +2586,7 @@ fn package_lock_as_a_symlink_inside_package_is_overwritten() {
let librs = pkg_root.join("src/lib.rs");
// Is correctly overwritten and doesn't affect the file linked to
- assert_eq!(ok.metadata().unwrap().len(), 2);
+ assert_eq!(ok.metadata().unwrap().len(), 7);
assert_eq!(fs::read_to_string(librs).unwrap(), "pub fn f() {}");
}
@@ -3135,7 +3135,7 @@ fn corrupted_ok_overwritten() {
fs::write(&ok, "").unwrap();
assert_eq!(fs::read_to_string(&ok).unwrap(), "");
p.cargo("fetch").with_stderr("").run();
- assert_eq!(fs::read_to_string(&ok).unwrap(), "ok");
+ assert_eq!(fs::read_to_string(&ok).unwrap(), r#"{"v":1}"#);
}
#[cargo_test]
@@ -3166,7 +3166,7 @@ fn not_found_permutations() {
authors = []
[dependencies]
- a-b-c = "1.0"
+ a-b_c = "1.0"
"#,
)
.file("src/lib.rs", "")
@@ -3177,7 +3177,7 @@ fn not_found_permutations() {
.with_stderr(
"\
[UPDATING] `dummy-registry` index
-error: no matching package named `a-b-c` found
+error: no matching package named `a-b_c` found
location searched: registry `crates-io`
required by package `foo v0.0.1 ([ROOT]/foo)`
",
@@ -3190,7 +3190,6 @@ required by package `foo v0.0.1 ([ROOT]/foo)`
&[
"/index/a-/b-/a-b-c",
"/index/a-/b_/a-b_c",
- "/index/a_/b-/a_b-c",
"/index/a_/b_/a_b_c"
]
);
@@ -3404,3 +3403,129 @@ Caused by:
Please slow down
").run();
}
+
+#[cfg(unix)]
+#[cargo_test]
+fn set_mask_during_unpacking() {
+ use std::os::unix::fs::MetadataExt;
+
+ Package::new("bar", "1.0.0")
+ .file_with_mode("example.sh", 0o777, "#!/bin/sh")
+ .file_with_mode("src/lib.rs", 0o666, "")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("fetch")
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
+",
+ )
+ .run();
+ let src_file_path = |path: &str| {
+ glob::glob(
+ paths::home()
+ .join(".cargo/registry/src/*/bar-1.0.0/")
+ .join(path)
+ .to_str()
+ .unwrap(),
+ )
+ .unwrap()
+ .next()
+ .unwrap()
+ .unwrap()
+ };
+
+ let umask = cargo::util::get_umask();
+ let metadata = fs::metadata(src_file_path("src/lib.rs")).unwrap();
+ assert_eq!(metadata.mode() & 0o777, 0o666 & !umask);
+ let metadata = fs::metadata(src_file_path("example.sh")).unwrap();
+ assert_eq!(metadata.mode() & 0o777, 0o777 & !umask);
+}
+
+#[cargo_test]
+fn unpack_again_when_cargo_ok_is_unrecognized() {
+ Package::new("bar", "1.0.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("fetch")
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
+",
+ )
+ .run();
+
+ let src_file_path = |path: &str| {
+ glob::glob(
+ paths::home()
+ .join(".cargo/registry/src/*/bar-1.0.0/")
+ .join(path)
+ .to_str()
+ .unwrap(),
+ )
+ .unwrap()
+ .next()
+ .unwrap()
+ .unwrap()
+ };
+
+ // Change permissions to simulate the old behavior not respecting umask.
+ let lib_rs = src_file_path("src/lib.rs");
+ let cargo_ok = src_file_path(".cargo-ok");
+ let mut perms = fs::metadata(&lib_rs).unwrap().permissions();
+ assert!(!perms.readonly());
+ perms.set_readonly(true);
+ fs::set_permissions(&lib_rs, perms).unwrap();
+ let ok = fs::read_to_string(&cargo_ok).unwrap();
+ assert_eq!(&ok, r#"{"v":1}"#);
+
+ p.cargo("fetch").with_stderr("").run();
+
+ // Without changing `.cargo-ok`, a unpack won't be triggered.
+ let perms = fs::metadata(&lib_rs).unwrap().permissions();
+ assert!(perms.readonly());
+
+ // Write "ok" to simulate the old behavior and trigger the unpack again.
+ fs::write(&cargo_ok, "ok").unwrap();
+
+ p.cargo("fetch").with_stderr("").run();
+
+ // Permission has been restored and `.cargo-ok` is in the new format.
+ let perms = fs::metadata(lib_rs).unwrap().permissions();
+ assert!(!perms.readonly());
+ let ok = fs::read_to_string(&cargo_ok).unwrap();
+ assert_eq!(&ok, r#"{"v":1}"#);
+}
diff --git a/src/tools/cargo/tests/testsuite/registry_auth.rs b/src/tools/cargo/tests/testsuite/registry_auth.rs
index 7779e285a..97cdf6748 100644
--- a/src/tools/cargo/tests/testsuite/registry_auth.rs
+++ b/src/tools/cargo/tests/testsuite/registry_auth.rs
@@ -1,6 +1,7 @@
//! Tests for registry authentication.
-use cargo_test_support::registry::{Package, RegistryBuilder};
+use cargo_test_support::compare::match_contains;
+use cargo_test_support::registry::{Package, RegistryBuilder, Token};
use cargo_test_support::{project, Execs, Project};
fn cargo(p: &Project, s: &str) -> Execs {
@@ -517,3 +518,73 @@ Caused by:
)
.run();
}
+
+#[cargo_test]
+fn token_not_logged() {
+ // Checks that the token isn't displayed in debug output (for both HTTP
+ // index and registry API). Note that this doesn't fully verify the
+ // correct behavior since we don't have an HTTP2 server, and curl behaves
+ // significantly differently when using HTTP2.
+ let crates_io = RegistryBuilder::new()
+ .http_api()
+ .http_index()
+ .auth_required()
+ .token(Token::Plaintext("a-unique_token".to_string()))
+ .build();
+ Package::new("bar", "1.0.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+ let output = cargo(&p, "publish")
+ .replace_crates_io(crates_io.index_url())
+ .env("CARGO_HTTP_DEBUG", "true")
+ .env("CARGO_LOG", "trace")
+ .exec_with_output()
+ .unwrap();
+ let log = String::from_utf8(output.stderr).unwrap();
+ let lines = "\
+[UPDATING] crates.io index
+[PACKAGING] foo v0.1.0 [..]
+[VERIFYING] foo v0.1.0 [..]
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v1.0.0
+[COMPILING] bar v1.0.0
+[COMPILING] foo v0.1.0 [..]
+[FINISHED] [..]
+[PACKAGED] 3 files[..]
+[UPLOADING] foo v0.1.0[..]
+[UPLOADED] foo v0.1.0 to registry `crates-io`
+note: Waiting [..]
+";
+ for line in lines.lines() {
+ match_contains(line, &log, None).unwrap();
+ }
+ let authorizations: Vec<_> = log
+ .lines()
+ .filter(|line| {
+ line.contains("http-debug:") && line.to_lowercase().contains("authorization")
+ })
+ .collect();
+ assert!(authorizations.iter().all(|line| line.contains("REDACTED")));
+ // Total authorizations:
+ // 1. Initial config.json
+ // 2. config.json again for verification
+ // 3. /index/3/b/bar
+ // 4. /dl/bar/1.0.0/download
+ // 5. /api/v1/crates/new
+ // 6. config.json for the "wait for publish"
+ // 7. /index/3/f/foo for the "wait for publish"
+ assert_eq!(authorizations.len(), 7);
+ assert!(!log.contains("a-unique_token"));
+}
diff --git a/src/tools/cargo/tests/testsuite/rustup.rs b/src/tools/cargo/tests/testsuite/rustup.rs
new file mode 100644
index 000000000..aa93f546c
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/rustup.rs
@@ -0,0 +1,262 @@
+//! Tests for Cargo's behavior under Rustup.
+
+use cargo_test_support::paths::{home, root, CargoPathExt};
+use cargo_test_support::{cargo_process, process, project};
+use std::env;
+use std::env::consts::EXE_EXTENSION;
+use std::ffi::OsString;
+use std::fs;
+use std::path::{Path, PathBuf};
+
+/// Helper to generate an executable.
+fn make_exe(dest: &Path, name: &str, contents: &str, env: &[(&str, PathBuf)]) -> PathBuf {
+ let rs_name = format!("{name}.rs");
+ fs::write(
+ root().join(&rs_name),
+ &format!("fn main() {{ {contents} }}"),
+ )
+ .unwrap();
+ let mut pb = process("rustc");
+ env.iter().for_each(|(key, value)| {
+ pb.env(key, value);
+ });
+ pb.arg("--edition=2021")
+ .arg(root().join(&rs_name))
+ .exec()
+ .unwrap();
+ let exe = Path::new(name).with_extension(EXE_EXTENSION);
+ let output = dest.join(&exe);
+ fs::rename(root().join(&exe), &output).unwrap();
+ output
+}
+
+fn prepend_path(path: &Path) -> OsString {
+ let mut paths = vec![path.to_path_buf()];
+ paths.extend(env::split_paths(&env::var_os("PATH").unwrap_or_default()));
+ env::join_paths(paths).unwrap()
+}
+
+struct RustupEnvironment {
+ /// Path for ~/.cargo/bin
+ cargo_bin: PathBuf,
+ /// Path for ~/.rustup
+ rustup_home: PathBuf,
+ /// Path to the cargo executable in the toolchain directory
+ /// (~/.rustup/toolchain/test-toolchain/bin/cargo.exe).
+ cargo_toolchain_exe: PathBuf,
+}
+
+/// Creates an executable which prints a message and then runs the *real* rustc.
+fn real_rustc_wrapper(bin_dir: &Path, message: &str) -> PathBuf {
+ let real_rustc = cargo_util::paths::resolve_executable("rustc".as_ref()).unwrap();
+ // The toolchain rustc needs to call the real rustc. In order to do that,
+ // it needs to restore or clear the RUSTUP environment variables so that
+ // if rustup is installed, it will call the correct rustc.
+ let rustup_toolchain_setup = match std::env::var_os("RUSTUP_TOOLCHAIN") {
+ Some(t) => format!(
+ ".env(\"RUSTUP_TOOLCHAIN\", \"{}\")",
+ t.into_string().unwrap()
+ ),
+ None => format!(".env_remove(\"RUSTUP_TOOLCHAIN\")"),
+ };
+ let mut env = vec![("CARGO_RUSTUP_TEST_real_rustc", real_rustc)];
+ let rustup_home_setup = match std::env::var_os("RUSTUP_HOME") {
+ Some(h) => {
+ env.push(("CARGO_RUSTUP_TEST_RUSTUP_HOME", h.into()));
+ format!(".env(\"RUSTUP_HOME\", env!(\"CARGO_RUSTUP_TEST_RUSTUP_HOME\"))")
+ }
+ None => format!(".env_remove(\"RUSTUP_HOME\")"),
+ };
+ make_exe(
+ bin_dir,
+ "rustc",
+ &format!(
+ r#"
+ eprintln!("{message}");
+ let r = std::process::Command::new(env!("CARGO_RUSTUP_TEST_real_rustc"))
+ .args(std::env::args_os().skip(1))
+ {rustup_toolchain_setup}
+ {rustup_home_setup}
+ .status();
+ std::process::exit(r.unwrap().code().unwrap_or(2));
+ "#
+ ),
+ &env,
+ )
+}
+
+/// Creates a simulation of a rustup environment with `~/.cargo/bin` and
+/// `~/.rustup` directories populated with some executables that simulate
+/// rustup.
+fn simulated_rustup_environment() -> RustupEnvironment {
+ // Set up ~/.rustup/toolchains/test-toolchain/bin with a custom rustc and cargo.
+ let rustup_home = home().join(".rustup");
+ let toolchain_bin = rustup_home
+ .join("toolchains")
+ .join("test-toolchain")
+ .join("bin");
+ toolchain_bin.mkdir_p();
+ let rustc_toolchain_exe = real_rustc_wrapper(&toolchain_bin, "real rustc running");
+ let cargo_toolchain_exe = make_exe(
+ &toolchain_bin,
+ "cargo",
+ r#"panic!("cargo toolchain should not be called");"#,
+ &[],
+ );
+
+ // Set up ~/.cargo/bin with a typical set of rustup proxies.
+ let cargo_bin = home().join(".cargo").join("bin");
+ cargo_bin.mkdir_p();
+
+ let rustc_proxy = make_exe(
+ &cargo_bin,
+ "rustc",
+ &format!(
+ r#"
+ match std::env::args().next().unwrap().as_ref() {{
+ "rustc" => {{}}
+ arg => panic!("proxy only supports rustc, got {{arg:?}}"),
+ }}
+ eprintln!("rustc proxy running");
+ let r = std::process::Command::new(env!("CARGO_RUSTUP_TEST_rustc_toolchain_exe"))
+ .args(std::env::args_os().skip(1))
+ .status();
+ std::process::exit(r.unwrap().code().unwrap_or(2));
+ "#
+ ),
+ &[("CARGO_RUSTUP_TEST_rustc_toolchain_exe", rustc_toolchain_exe)],
+ );
+ fs::hard_link(
+ &rustc_proxy,
+ cargo_bin.join("cargo").with_extension(EXE_EXTENSION),
+ )
+ .unwrap();
+ fs::hard_link(
+ &rustc_proxy,
+ cargo_bin.join("rustup").with_extension(EXE_EXTENSION),
+ )
+ .unwrap();
+
+ RustupEnvironment {
+ cargo_bin,
+ rustup_home,
+ cargo_toolchain_exe,
+ }
+}
+
+#[cargo_test]
+fn typical_rustup() {
+ // Test behavior under a typical rustup setup with a normal toolchain.
+ let RustupEnvironment {
+ cargo_bin,
+ rustup_home,
+ cargo_toolchain_exe,
+ } = simulated_rustup_environment();
+
+ // Set up a project and run a normal cargo build.
+ let p = project().file("src/lib.rs", "").build();
+ // The path is modified so that cargo will call `rustc` from
+ // `~/.cargo/bin/rustc to use our custom rustup proxies.
+ let path = prepend_path(&cargo_bin);
+ p.cargo("check")
+ .env("RUSTUP_TOOLCHAIN", "test-toolchain")
+ .env("RUSTUP_HOME", &rustup_home)
+ .env("PATH", &path)
+ .with_stderr(
+ "\
+[CHECKING] foo v0.0.1 [..]
+real rustc running
+[FINISHED] [..]
+",
+ )
+ .run();
+
+ // Do a similar test, but with a toolchain link that does not have cargo
+ // (which normally would do a fallback to nightly/beta/stable).
+ cargo_toolchain_exe.rm_rf();
+ p.build_dir().rm_rf();
+
+ p.cargo("check")
+ .env("RUSTUP_TOOLCHAIN", "test-toolchain")
+ .env("RUSTUP_HOME", &rustup_home)
+ .env("PATH", &path)
+ .with_stderr(
+ "\
+[CHECKING] foo v0.0.1 [..]
+real rustc running
+[FINISHED] [..]
+",
+ )
+ .run();
+}
+
+// This doesn't work on Windows because Cargo forces the PATH to contain the
+// sysroot_libdir, which is actually `bin`, preventing the test from
+// overriding the bin directory.
+#[cargo_test(ignore_windows = "PATH can't be overridden on Windows")]
+fn custom_calls_other_cargo() {
+ // Test behavior when a custom subcommand tries to manipulate PATH to use
+ // a different toolchain.
+ let RustupEnvironment {
+ cargo_bin,
+ rustup_home,
+ cargo_toolchain_exe: _,
+ } = simulated_rustup_environment();
+
+ // Create a directory with a custom toolchain (outside of the rustup universe).
+ let custom_bin = root().join("custom-bin");
+ custom_bin.mkdir_p();
+ // `cargo` points to the real cargo.
+ let cargo_exe = cargo_test_support::cargo_exe();
+ fs::hard_link(&cargo_exe, custom_bin.join(cargo_exe.file_name().unwrap())).unwrap();
+ // `rustc` executes the real rustc.
+ real_rustc_wrapper(&custom_bin, "custom toolchain rustc running");
+
+ // A project that cargo-custom will try to build.
+ let p = project().file("src/lib.rs", "").build();
+
+ // Create a custom cargo subcommand.
+ // This will modify PATH to a custom toolchain and call cargo from that.
+ make_exe(
+ &cargo_bin,
+ "cargo-custom",
+ r#"
+ use std::env;
+ use std::process::Command;
+
+ eprintln!("custom command running");
+
+ let mut paths = vec![std::path::PathBuf::from(env!("CARGO_RUSTUP_TEST_custom_bin"))];
+ paths.extend(env::split_paths(&env::var_os("PATH").unwrap_or_default()));
+ let path = env::join_paths(paths).unwrap();
+
+ let status = Command::new("cargo")
+ .arg("check")
+ .current_dir(env!("CARGO_RUSTUP_TEST_project_dir"))
+ .env("PATH", path)
+ .status()
+ .unwrap();
+ assert!(status.success());
+ "#,
+ &[
+ ("CARGO_RUSTUP_TEST_custom_bin", custom_bin),
+ ("CARGO_RUSTUP_TEST_project_dir", p.root()),
+ ],
+ );
+
+ cargo_process("custom")
+ // Set these to simulate what would happen when running under rustup.
+ // We want to make sure that cargo-custom does not try to use the
+ // rustup proxies.
+ .env("RUSTUP_TOOLCHAIN", "test-toolchain")
+ .env("RUSTUP_HOME", &rustup_home)
+ .with_stderr(
+ "\
+custom command running
+[CHECKING] foo [..]
+custom toolchain rustc running
+[FINISHED] [..]
+",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/tree.rs b/src/tools/cargo/tests/testsuite/tree.rs
index c3c1ca6d3..e2e74c4f9 100644
--- a/src/tools/cargo/tests/testsuite/tree.rs
+++ b/src/tools/cargo/tests/testsuite/tree.rs
@@ -1086,6 +1086,59 @@ fn duplicates_with_target() {
}
#[cargo_test]
+fn duplicates_with_proc_macro() {
+ Package::new("dupe-dep", "1.0.0").publish();
+ Package::new("dupe-dep", "2.0.0").publish();
+ Package::new("proc", "1.0.0")
+ .proc_macro(true)
+ .dep("dupe-dep", "1.0")
+ .publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ proc = "1.0"
+ dupe-dep = "2.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("tree")
+ .with_stdout(
+ "\
+foo v0.1.0 ([..]/foo)
+├── dupe-dep v2.0.0
+└── proc v1.0.0 (proc-macro)
+ └── dupe-dep v1.0.0
+",
+ )
+ .run();
+
+ p.cargo("tree --duplicates")
+ .with_stdout(
+ "\
+dupe-dep v1.0.0
+└── proc v1.0.0 (proc-macro)
+ └── foo v0.1.0 ([..]/foo)
+
+dupe-dep v2.0.0
+└── foo v0.1.0 ([..]/foo)
+",
+ )
+ .run();
+
+ p.cargo("tree --duplicates --edges no-proc-macro")
+ .with_stdout("")
+ .run();
+}
+
+#[cargo_test]
fn charset() {
let p = make_simple_proj();
p.cargo("tree --charset ascii")
@@ -1540,8 +1593,6 @@ somedep v1.0.0
"\
somedep v1.0.0
└── foo v0.1.0 ([..]/foo)
-
-somedep v1.0.0
",
)
.run();
diff --git a/src/tools/cargo/tests/testsuite/update.rs b/src/tools/cargo/tests/testsuite/update.rs
index 057c8fca4..1d3ee05b7 100644
--- a/src/tools/cargo/tests/testsuite/update.rs
+++ b/src/tools/cargo/tests/testsuite/update.rs
@@ -633,6 +633,9 @@ fn update_precise_first_run() {
"workspace_members": [
"bar 0.0.1 (path+file://[..]/foo)"
],
+ "workspace_default_members": [
+ "bar 0.0.1 (path+file://[..]/foo)"
+ ],
"workspace_root": "[..]/foo",
"metadata": null
}"#,
diff --git a/src/tools/cargo/tests/testsuite/vendor.rs b/src/tools/cargo/tests/testsuite/vendor.rs
index 21a1c097c..2b8b090c2 100644
--- a/src/tools/cargo/tests/testsuite/vendor.rs
+++ b/src/tools/cargo/tests/testsuite/vendor.rs
@@ -1051,10 +1051,11 @@ fn vendor_preserves_permissions() {
p.cargo("vendor --respect-source-config").run();
+ let umask = cargo::util::get_umask();
let metadata = fs::metadata(p.root().join("vendor/bar/src/lib.rs")).unwrap();
- assert_eq!(metadata.mode() & 0o777, 0o644);
+ assert_eq!(metadata.mode() & 0o777, 0o644 & !umask);
let metadata = fs::metadata(p.root().join("vendor/bar/example.sh")).unwrap();
- assert_eq!(metadata.mode() & 0o777, 0o755);
+ assert_eq!(metadata.mode() & 0o777, 0o755 & !umask);
}
#[cargo_test]
diff --git a/src/tools/cargo/tests/testsuite/weak_dep_features.rs b/src/tools/cargo/tests/testsuite/weak_dep_features.rs
index ee91114df..6f7c03547 100644
--- a/src/tools/cargo/tests/testsuite/weak_dep_features.rs
+++ b/src/tools/cargo/tests/testsuite/weak_dep_features.rs
@@ -601,6 +601,7 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
"readme": null,
"readme_file": null,
"repository": null,
+ "rust_version": null,
"vers": "0.1.0"
}
"#,
diff --git a/src/tools/cargo/triagebot.toml b/src/tools/cargo/triagebot.toml
index 192859537..00a98e008 100644
--- a/src/tools/cargo/triagebot.toml
+++ b/src/tools/cargo/triagebot.toml
@@ -9,7 +9,6 @@ allow-unauthenticated = [
"S-*",
"Z-*",
"beta-nominated",
- "needs-mcve",
"regression-*",
"relnotes",
]
@@ -104,7 +103,10 @@ trigger_files = ["src/cargo/sources/directory.rs"]
trigger_files = ["src/doc/"]
[autolabel."A-environment-variables"]
-trigger_files = ["crates/home/"]
+trigger_files = [
+ "crates/home/",
+ "src/cargo/util/config/environment.rs",
+]
[autolabel."A-errors"]
trigger_files = ["src/cargo/util/diagnostic_server.rs"]
@@ -121,6 +123,19 @@ trigger_files = ["src/cargo/core/compiler/future_incompat.rs"]
[autolabel."A-git"]
trigger_files = ["src/cargo/sources/git/"]
+[autolabel."A-infrastructure"]
+trigger_files = [
+ ".cargo/",
+ ".github/",
+ "build.rs",
+ "ci/",
+ "clippy.toml",
+ "crates/xtask-",
+ "deny.toml",
+ "publish.py",
+ "triagebot.toml",
+]
+
[autolabel."A-interacts-with-crates.io"]
trigger_files = ["crates/crates-io/", "src/cargo/ops/registry.rs"]
@@ -150,7 +165,7 @@ trigger_files = [
]
[autolabel."A-networking"]
-trigger_files = ["src/cargo/util/network.rs"]
+trigger_files = ["src/cargo/util/network/"]
[autolabel."A-overrides"]
trigger_files = ["src/cargo/sources/replaced.rs"]
@@ -165,13 +180,13 @@ trigger_files = ["src/cargo/core/compiler/fingerprint/"]
trigger_files = ["src/cargo/sources/registry/", "src/cargo/core/registry.rs"]
[autolabel."A-registry-authentication"]
-trigger_files = ["src/cargo/util/auth.rs", "crates/credential/"]
+trigger_files = ["src/cargo/util/auth.rs", "credential/"]
[autolabel."A-semver"]
trigger_files = [
+ "crates/semver-check",
"src/cargo/util/semver_ext.rs",
"src/cargo/util/to_semver.rs",
- "src/doc/semver-check/",
]
[autolabel."A-source-replacement"]
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index b99213011..a9d42159c 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -39,7 +39,7 @@ jobs:
github_token: "${{ secrets.github_token }}"
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
- name: Install toolchain
run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 93198aabd..30a156c92 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -27,7 +27,7 @@ jobs:
github_token: "${{ secrets.github_token }}"
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
with:
ref: ${{ github.ref }}
@@ -83,7 +83,7 @@ jobs:
github_token: "${{ secrets.github_token }}"
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
- name: Install toolchain
run: rustup show active-toolchain
@@ -149,7 +149,7 @@ jobs:
github_token: "${{ secrets.github_token }}"
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
- name: Install toolchain
run: rustup show active-toolchain
@@ -173,7 +173,7 @@ jobs:
github_token: "${{ secrets.github_token }}"
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
- name: Install toolchain
run: rustup show active-toolchain
@@ -233,7 +233,7 @@ jobs:
github_token: "${{ secrets.github_token }}"
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
- name: Install toolchain
run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 14f20212a..514706d64 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -25,7 +25,7 @@ jobs:
steps:
# Setup
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
# Run
- name: Build
diff --git a/src/tools/clippy/.github/workflows/deploy.yml b/src/tools/clippy/.github/workflows/deploy.yml
index 71d71d103..f42928c2c 100644
--- a/src/tools/clippy/.github/workflows/deploy.yml
+++ b/src/tools/clippy/.github/workflows/deploy.yml
@@ -21,10 +21,10 @@ jobs:
steps:
# Setup
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
with:
ref: ${{ env.TARGET_BRANCH }}
path: 'out'
diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml
index 116058b7c..7d25b6a2b 100644
--- a/src/tools/clippy/.github/workflows/remark.yml
+++ b/src/tools/clippy/.github/workflows/remark.yml
@@ -16,10 +16,10 @@ jobs:
steps:
# Setup
- name: Checkout
- uses: actions/checkout@v3.0.2
+ uses: actions/checkout@v3
- name: Setup Node.js
- uses: actions/setup-node@v1.4.4
+ uses: actions/setup-node@v3
with:
node-version: '14.x'
@@ -36,6 +36,12 @@ jobs:
- name: Check *.md files
run: git ls-files -z '*.md' | xargs -0 -n 1 -I {} ./node_modules/.bin/remark {} -u lint -f > /dev/null
+ - name: Linkcheck book
+ run: |
+ rustup toolchain install nightly --component rust-docs
+ curl https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh -o linkcheck.sh
+ sh linkcheck.sh clippy --path ./book
+
- name: Build mdbook
run: mdbook build book
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 559b560dd..79f2a4711 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,126 @@ document.
## Unreleased / Beta / In Rust Nightly
-[7f27e2e7...master](https://github.com/rust-lang/rust-clippy/compare/7f27e2e7...master)
+[149392b0...master](https://github.com/rust-lang/rust-clippy/compare/149392b0...master)
+
+## Rust 1.69
+
+Current stable, released 2023-04-20
+
+[7f27e2e7...149392b0](https://github.com/rust-lang/rust-clippy/compare/7f27e2e7...149392b0)
+
+### New Lints
+
+* [`no_mangle_with_rust_abi`]
+ [#10369](https://github.com/rust-lang/rust-clippy/pull/10369)
+* [`significant_drop_tightening`]
+ [#10163](https://github.com/rust-lang/rust-clippy/pull/10163)
+* [`suspicious_command_arg_space`]
+ [#10317](https://github.com/rust-lang/rust-clippy/pull/10317)
+* [`let_underscore_untyped`]
+ [#10356](https://github.com/rust-lang/rust-clippy/pull/10356)
+* [`question_mark_used`]
+ [#10342](https://github.com/rust-lang/rust-clippy/pull/10342)
+* [`extra_unused_type_parameters`]
+ [#10028](https://github.com/rust-lang/rust-clippy/pull/10028)
+* [`impl_trait_in_params`]
+ [10197](https://github.com/rust-lang/rust-clippy/pull/10197)
+* [`transmute_int_to_non_zero`]
+ [#10360](https://github.com/rust-lang/rust-clippy/pull/10360)
+* [`multiple_unsafe_ops_per_block`]
+ [#10206](https://github.com/rust-lang/rust-clippy/pull/10206)
+
+### Moves and Deprecations
+
+* Moved [`uninlined_format_args`] to `pedantic` (Now allow-by-default)
+ [#10265](https://github.com/rust-lang/rust-clippy/pull/10265)
+* Moved [`unchecked_duration_subtraction`] to `pedantic` (Now allow-by-default)
+ [#10194](https://github.com/rust-lang/rust-clippy/pull/10194)
+
+### Enhancements
+
+* [`arithmetic_side_effects`]: No longer lints if safe constant values are used.
+ [#10310](https://github.com/rust-lang/rust-clippy/pull/10310)
+* [`needless_lifetimes`]: Now works in local macros
+ [#10257](https://github.com/rust-lang/rust-clippy/pull/10257)
+* [`unused_io_amount`]: Now detects usages of `is_ok` and `is_err`
+ [#10225](https://github.com/rust-lang/rust-clippy/pull/10225)
+* [`missing_docs_in_private_items`]: Added new configuration `missing-docs-in-crate-items` to lint
+ on items visible within the current crate. For example, `pub(crate)` items.
+ [#10303](https://github.com/rust-lang/rust-clippy/pull/10303)
+* [`almost_swapped`]: Now detects almost swaps using `let` statements
+ [#10177](https://github.com/rust-lang/rust-clippy/pull/10177)
+* [`wildcard_enum_match_arm`]: Now lints missing private variants, for local enums
+ [#10250](https://github.com/rust-lang/rust-clippy/pull/10250)
+
+### False Positive Fixes
+
+* [`explicit_auto_deref`]: Now considers projections when determining if auto deref is applicable
+ [#10386](https://github.com/rust-lang/rust-clippy/pull/10386)
+* [`manual_let_else`]: Now considers side effects of branches before linting
+ [#10336](https://github.com/rust-lang/rust-clippy/pull/10336)
+* [`uninlined_format_args`]: No longer lints for arguments with generic parameters
+ [#10343](https://github.com/rust-lang/rust-clippy/pull/10343)
+* [`needless_lifetimes`]: No longer lints signatures in macros if the lifetime is a metavariable
+ [#10380](https://github.com/rust-lang/rust-clippy/pull/10380)
+* [`len_without_is_empty`]: No longer lints if `len` as a non-default signature
+ [#10255](https://github.com/rust-lang/rust-clippy/pull/10255)
+* [`unusual_byte_groupings`]: Relaxed the required restrictions for specific sizes to reduce false
+ positives
+ [#10353](https://github.com/rust-lang/rust-clippy/pull/10353)
+* [`manual_let_else`]: No longer lints `if-else` blocks if they can divergent
+ [#10332](https://github.com/rust-lang/rust-clippy/pull/10332)
+* [`expect_used`], [`unwrap_used`], [`dbg_macro`], [`print_stdout`], [`print_stderr`]: No longer lint
+ in test functions if `allow-expect-in-tests` is set
+ [#10391](https://github.com/rust-lang/rust-clippy/pull/10391)
+* [`unnecessary_safety_comment`]: No longer lints code inside macros
+ [#10106](https://github.com/rust-lang/rust-clippy/pull/10106)
+* [`never_loop`]: No longer lints statements following break statements for outer blocks.
+ [#10311](https://github.com/rust-lang/rust-clippy/pull/10311)
+
+### Suggestion Fixes/Improvements
+
+* [`box_default`]: The suggestion now includes the type for trait objects when needed
+ [#10382](https://github.com/rust-lang/rust-clippy/pull/10382)
+* [`cast_possible_truncation`]: Now suggests using `try_from` or allowing the lint
+ [#10038](https://github.com/rust-lang/rust-clippy/pull/10038)
+* [`invalid_regex`]: Regex errors for non-literals or regular strings containing escape sequences will
+ now show the complete error
+ [#10231](https://github.com/rust-lang/rust-clippy/pull/10231)
+* [`transmutes_expressible_as_ptr_casts`]: The suggestion now works if the base type is borrowed
+ [#10193](https://github.com/rust-lang/rust-clippy/pull/10193)
+* [`needless_return`]: Now removes all semicolons on the same line
+ [#10187](https://github.com/rust-lang/rust-clippy/pull/10187)
+* [`suspicious_to_owned`]: The suggestion now shows all options clearly
+ [#10295](https://github.com/rust-lang/rust-clippy/pull/10295)
+* [`bytes_nth`]: Now suggests the correct replacement based on the context
+ [#10361](https://github.com/rust-lang/rust-clippy/pull/10361)
+* [`bool_assert_comparison`]: The suggestion is now machine applicable
+ [#10218](https://github.com/rust-lang/rust-clippy/pull/10218)
+* [`cast_possible_truncation`]: Corrected the lint name in the help message
+ [#10330](https://github.com/rust-lang/rust-clippy/pull/10330)
+* [`needless_return`]: The suggestion now works on if sequences
+ [#10345](https://github.com/rust-lang/rust-clippy/pull/10345)
+* [`needless_lifetimes`]: The suggestion is now machine applicable
+ [#10222](https://github.com/rust-lang/rust-clippy/pull/10222)
+* [`map_entry`]: The suggestion no longer expands macros
+ [#10346](https://github.com/rust-lang/rust-clippy/pull/10346)
+
+### ICE Fixes
+
+* [`needless_pass_by_value`]: Fixed an ICE caused by how late bounds were handled
+ [#10328](https://github.com/rust-lang/rust-clippy/pull/10328)
+* [`needless_borrow`]: No longer panics on ambiguous projections
+ [#10403](https://github.com/rust-lang/rust-clippy/pull/10403)
+
+### Documentation Improvements
+
+* All configurations are now documented in the Clippy Book
+ [#10199](https://github.com/rust-lang/rust-clippy/pull/10199)
## Rust 1.68
-Current stable, released 2023-03-09
+Released 2023-03-09
[d822110d...7f27e2e7](https://github.com/rust-lang/rust-clippy/compare/d822110d...7f27e2e7)
@@ -4467,6 +4582,7 @@ Released 2018-09-13
[`debug_assert_with_mut_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#debug_assert_with_mut_call
[`decimal_literal_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation
[`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const
+[`default_constructed_unit_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_constructed_unit_structs
[`default_instead_of_iter_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_instead_of_iter_empty
[`default_numeric_fallback`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_numeric_fallback
[`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access
@@ -4504,6 +4620,7 @@ Released 2018-09-13
[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
[`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
[`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
+[`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments
[`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
[`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop
[`empty_structs_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_structs_with_brackets
@@ -4615,6 +4732,7 @@ Released 2018-09-13
[`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters
[`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
+[`items_after_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_test_module
[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect
[`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count
[`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map
@@ -4668,6 +4786,7 @@ Released 2018-09-13
[`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
[`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
+[`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back
[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
[`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
[`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
@@ -4681,6 +4800,7 @@ Released 2018-09-13
[`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
[`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
+[`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_while_let_some
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
[`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_collect_result_unit
@@ -4748,6 +4868,7 @@ Released 2018-09-13
[`needless_arbitrary_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_arbitrary_self_type
[`needless_bitwise_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bitwise_bool
[`needless_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool
+[`needless_bool_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool_assign
[`needless_borrow`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
[`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
[`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect
@@ -4778,6 +4899,7 @@ Released 2018-09-13
[`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
[`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
+[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
@@ -4859,6 +4981,7 @@ Released 2018-09-13
[`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
[`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
+[`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns
[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
[`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
[`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index c35dfcbd8..3c72bb62e 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy"
-version = "0.1.70"
+version = "0.1.71"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
@@ -22,13 +22,12 @@ path = "src/driver.rs"
[dependencies]
clippy_lints = { path = "clippy_lints" }
-semver = "1.0"
rustc_tools_util = "0.3.0"
tempfile = { version = "3.2", optional = true }
termize = "0.1"
[dev-dependencies]
-compiletest_rs = { version = "0.9", features = ["tmp"] }
+compiletest_rs = { version = "0.10", features = ["tmp"] }
tester = "0.9"
regex = "1.5"
toml = "0.5"
@@ -49,7 +48,7 @@ if_chain = "1.0"
itertools = "0.10.1"
quote = "1.0"
serde = { version = "1.0.125", features = ["derive"] }
-syn = { version = "1.0", features = ["full"] }
+syn = { version = "2.0", features = ["full"] }
futures = "0.3"
parking_lot = "0.12"
tokio = { version = "1", features = ["io-util"] }
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 85798e0e8..d712d3e67 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -91,7 +91,8 @@ cargo clippy
#### Automatically applying Clippy suggestions
-Clippy can automatically apply some lint suggestions, just like the compiler.
+Clippy can automatically apply some lint suggestions, just like the compiler. Note that `--fix` implies
+`--all-targets`, so it can fix as much code as it can.
```terminal
cargo clippy --fix
@@ -277,7 +278,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
<!-- REUSE-IgnoreStart -->
-Copyright 2014-2022 The Rust Project Developers
+Copyright 2014-2023 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/SUMMARY.md b/src/tools/clippy/book/src/SUMMARY.md
index cbd73376d..22fbdce75 100644
--- a/src/tools/clippy/book/src/SUMMARY.md
+++ b/src/tools/clippy/book/src/SUMMARY.md
@@ -13,7 +13,9 @@
- [Development](development/README.md)
- [Basics](development/basics.md)
- [Adding Lints](development/adding_lints.md)
+ - [Lint Passes](development/lint_passes.md)
- [Type Checking](development/type_checking.md)
+ - [Macro Expansions](development/macro_expansions.md)
- [Common Tools](development/common_tools_writing_lints.md)
- [Infrastructure](development/infrastructure/README.md)
- [Syncing changes between Clippy and rust-lang/rust](development/infrastructure/sync.md)
diff --git a/src/tools/clippy/book/src/development/README.md b/src/tools/clippy/book/src/development/README.md
index 616e6d182..8f09f66f5 100644
--- a/src/tools/clippy/book/src/development/README.md
+++ b/src/tools/clippy/book/src/development/README.md
@@ -13,6 +13,24 @@ If this is your first time contributing to Clippy, you should first read the
[Basics docs](basics.md). This will explain the basics on how to get the source
code and how to compile and test the code.
+## Additional Readings for Beginners
+
+If a dear reader of this documentation has never taken a class on compilers
+and interpreters, it might be confusing as to why AST level deals with only
+the language's syntax. And some readers might not even understand what lexing,
+parsing, and AST mean.
+
+This documentation serves by no means as a crash course on compilers or language design.
+And for details specifically related to Rust, the [Rustc Development Guide][rustc_dev_guide]
+is a far better choice to peruse.
+
+The [Syntax and AST][ast] chapter and the [High-Level IR][hir] chapter are
+great introduction to the concepts mentioned in this chapter.
+
+Some readers might also find the [introductory chapter][map_of_territory] of
+Robert Nystrom's _Crafting Interpreters_ a helpful overview of compiled and
+interpreted languages before jumping back to the Rustc guide.
+
## Writing code
If you have done the basic setup, it's time to start hacking.
@@ -37,6 +55,10 @@ book](../lints.md).
> - Triage procedure
> - Bors and Homu
+[ast]: https://rustc-dev-guide.rust-lang.org/syntax-intro.html
+[hir]: https://rustc-dev-guide.rust-lang.org/hir.html
+[rustc_dev_guide]: https://rustc-dev-guide.rust-lang.org/
+[map_of_territory]: https://craftinginterpreters.com/a-map-of-the-territory.html
[clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md
[rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees
[rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index 9dacaaaae..ccae8d374 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -164,7 +164,7 @@ The process of generating the `.stderr` file is the same, and prepending the
## Rustfix tests
If the lint you are working on is making use of structured suggestions, the test
-file should include a `// run-rustfix` comment at the top. This will
+file should include a `//@run-rustfix` comment at the top. This will
additionally run [rustfix] for that test. Rustfix will apply the suggestions
from the lint to the code of the test file and compare that to the contents of a
`.fixed` file.
diff --git a/src/tools/clippy/book/src/development/lint_passes.md b/src/tools/clippy/book/src/development/lint_passes.md
new file mode 100644
index 000000000..621fc2097
--- /dev/null
+++ b/src/tools/clippy/book/src/development/lint_passes.md
@@ -0,0 +1,114 @@
+# Lint passes
+
+Before working on the logic of a new lint, there is an important decision
+that every Clippy developer must make: to use
+[`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass].
+
+In short, the `LateLintPass` has access to type and symbol information while the
+`EarlyLintPass` doesn't. If you don't need access to type information, use the
+`EarlyLintPass`.
+
+Let us expand on these two traits more below.
+
+## `EarlyLintPass`
+
+If you examine the documentation on [`EarlyLintPass`][early_lint_pass] closely,
+you'll see that every method defined for this trait utilizes a
+[`EarlyContext`][early_context]. In `EarlyContext`'s documentation, it states:
+
+> Context for lint checking of the AST, after expansion, before lowering to HIR.
+
+Voilà. `EarlyLintPass` works only on the Abstract Syntax Tree (AST) level.
+And AST is generated during the [lexing and parsing][lexing_and_parsing] phase
+of code compilation. Therefore, it doesn't know what a symbol means or information about types, and it should
+be our trait choice for a new lint if the lint only deals with syntax-related issues.
+
+While linting speed has not been a concern for Clippy,
+the `EarlyLintPass` is faster, and it should be your choice
+if you know for sure a lint does not need type information.
+
+As a reminder, run the following command to generate boilerplate for lints
+that use `EarlyLintPass`:
+
+```sh
+$ cargo dev new_lint --name=<your_new_lint> --pass=early --category=<your_category_choice>
+```
+
+### Example for `EarlyLintPass`
+
+Take a look at the following code:
+
+```rust
+let x = OurUndefinedType;
+x.non_existing_method();
+```
+
+From the AST perspective, both lines are "grammatically" correct.
+The assignment uses a `let` and ends with a semicolon. The invocation
+of a method looks fine, too. As programmers, we might raise a few
+questions already, but the parser is okay with it. This is what we
+mean when we say `EarlyLintPass` deals with only syntax on the AST level.
+
+Alternatively, think of the `foo_functions` lint we mentioned in
+define new lints <!-- FIXME: add link --> chapter.
+
+We want the `foo_functions` lint to detect functions with `foo` as their name.
+Writing a lint that only checks for the name of a function means that we only
+work with the AST and don't have to access the type system at all (the type system is where
+`LateLintPass` comes into the picture).
+
+## `LateLintPass`
+
+In contrast to `EarlyLintPass`, `LateLintPass` contains type information.
+
+If you examine the documentation on [`LateLintPass`][late_lint_pass] closely,
+you see that every method defined in this trait utilizes a
+[`LateContext`][late_context].
+
+In `LateContext`'s documentation we will find methods that
+deal with type-checking, which do not exist in `EarlyContext`, such as:
+
+- [`maybe_typeck_results`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#method.maybe_typeck_results)
+- [`typeck_results`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#method.typeck_results)
+
+### Example for `LateLintPass`
+
+Let us take a look with the following example:
+
+```rust
+let x = OurUndefinedType;
+x.non_existing_method();
+```
+
+These two lines of code are syntactically correct code from the perspective
+of the AST. We have an assignment and invoke a method on the variable that
+is of a type. Grammatically, everything is in order for the parser.
+
+However, going down a level and looking at the type information,
+the compiler will notice that both `OurUndefinedType` and `non_existing_method()`
+**are undefined**.
+
+As Clippy developers, to access such type information, we must implement
+`LateLintPass` on our lint.
+When you browse through Clippy's lints, you will notice that almost every lint
+is implemented in a `LateLintPass`, specifically because we often need to check
+not only for syntactic issues but also type information.
+
+Another limitation of the `EarlyLintPass` is that the nodes are only identified
+by their position in the AST. This means that you can't just get an `id` and
+request a certain node. For most lints that is fine, but we have some lints
+that require the inspection of other nodes, which is easier at the HIR level.
+In these cases, `LateLintPass` is the better choice.
+
+As a reminder, run the following command to generate boilerplate for lints
+that use `LateLintPass`:
+
+```sh
+$ cargo dev new_lint --name=<your_new_lint> --pass=late --category=<your_category_choice>
+```
+
+[early_context]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.EarlyContext.html
+[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html
+[late_context]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html
+[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
+[lexing_and_parsing]: https://rustc-dev-guide.rust-lang.org/overview.html#lexing-and-parsing
diff --git a/src/tools/clippy/book/src/development/macro_expansions.md b/src/tools/clippy/book/src/development/macro_expansions.md
new file mode 100644
index 000000000..c5eb00027
--- /dev/null
+++ b/src/tools/clippy/book/src/development/macro_expansions.md
@@ -0,0 +1,158 @@
+# Dealing with macros and expansions
+
+Sometimes we might encounter Rust macro expansions while working with Clippy.
+While macro expansions are not as dramatic and profound as the expansion
+of our universe, they can certainly bring chaos to the orderly world
+of code and logic.
+
+The general rule of thumb is that we should ignore code with macro
+expansions when working with Clippy because the code can be dynamic
+in ways that are difficult or impossible for us to foresee.
+
+## False Positives
+
+What exactly do we mean by _dynamic in ways that are difficult to foresee_?
+
+Macros are [expanded][expansion] in the `EarlyLintPass` level,
+so the Abstract Syntax Tree (AST) is generated in place of macros.
+This means the code which we work with in Clippy is already expanded.
+
+If we wrote a new lint, there is a possibility that the lint is
+triggered in macro-generated code. Since this expanded macro code
+is not written by the macro's user but really by the macro's author,
+the user cannot and should not be responsible for fixing the issue
+that triggers the lint.
+
+Besides, a [Span] in a macro can be changed by the macro author.
+Therefore, any lint check related to lines or columns should be
+avoided since they might be changed at any time and become unreliable
+or incorrect information.
+
+Because of these unforeseeable or unstable behaviors, macro expansion
+should often not be regarded as a part of the stable API.
+This is also why most lints check if they are inside a macro or not
+before emitting suggestions to the end user to avoid false positives.
+
+## How to Work with Macros
+
+Several functions are available for working with macros.
+
+### The `Span.from_expansion` method
+
+We could utilize a `span`'s [`from_expansion`] method, which
+detects if the `span` is from a macro expansion / desugaring.
+This is a very common first step in a lint:
+
+```rust
+if expr.span.from_expansion() {
+ // We most likely want to ignore it.
+ return;
+}
+```
+
+### `Span.ctxt` method
+
+The `span`'s context, given by the method [`ctxt`] and returning [SpanContext],
+represents if the span is from a macro expansion and, if it is, which
+macro call expanded this span.
+
+Sometimes, it is useful to check if the context of two spans are equal.
+For instance, suppose we have the following line of code that would
+expand into `1 + 0`:
+
+```rust
+// The following code expands to `1 + 0` for both `EarlyLintPass` and `LateLintPass`
+1 + mac!()
+```
+
+Assuming that we'd collect the `1` expression as a variable `left` and the
+`0`/`mac!()` expression as a variable `right`, we can simply compare their
+contexts. If the context is different, then we most likely are dealing with a
+macro expansion and should just ignore it:
+
+```rust
+if left.span.ctxt() != right.span.ctxt() {
+ // The code author most likely cannot modify this expression
+ return;
+}
+```
+
+> **Note**: Code that is not from expansion is in the "root" context.
+> So any spans whose `from_expansion` returns `false` can be assumed
+> to have the same context. Because of this, using `span.from_expansion()`
+> is often sufficient.
+
+Going a bit deeper, in a simple expression such as `a == b`,
+`a` and `b` have the same context.
+However, in a `macro_rules!` with `a == $b`, `$b` is expanded to
+an expression that contains a different context from `a`.
+
+Take a look at the following macro `m`:
+
+```rust
+macro_rules! m {
+ ($a:expr, $b:expr) => {
+ if $a.is_some() {
+ $b;
+ }
+ }
+}
+
+let x: Option<u32> = Some(42);
+m!(x, x.unwrap());
+```
+
+If the `m!(x, x.unwrapp());` line is expanded, we would get two expanded
+expressions:
+
+- `x.is_some()` (from the `$a.is_some()` line in the `m` macro)
+- `x.unwrap()` (corresponding to `$b` in the `m` macro)
+
+Suppose `x.is_some()` expression's span is associated with the `x_is_some_span` variable
+and `x.unwrap()` expression's span is associated with `x_unwrap_span` variable,
+we could assume that these two spans do not share the same context:
+
+```rust
+// x.is_some() is from inside the macro
+// x.unwrap() is from outside the macro
+assert_ne!(x_is_some_span.ctxt(), x_unwrap_span.ctxt());
+```
+
+### The `in_external_macro` function
+
+`rustc_middle::lint` provides a function ([`in_external_macro`]) that can
+detect if the given span is from a macro defined in a foreign crate.
+
+Therefore, if we really want a new lint to work with macro-generated code,
+this is the next line of defense to avoid macros not defined inside
+the current crate since it is unfair to the user if Clippy lints code
+which the user cannot change.
+
+For example, assume we have the following code that is being examined
+by Clippy:
+
+```rust
+#[macro_use]
+extern crate a_foreign_crate_with_macros;
+
+// `foo` macro is defined in `a_foreign_crate_with_macros`
+foo!("bar");
+```
+
+Also assume that we get the corresponding variable `foo_span` for the
+`foo` macro call, we could decide not to lint if `in_external_macro`
+results in `true` (note that `cx` can be `EarlyContext` or `LateContext`):
+
+```rust
+if in_external_macro(cx.sess(), foo_span) {
+ // We should ignore macro from a foreign crate.
+ return;
+}
+```
+
+[`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_middle/lint/fn.in_external_macro.html
+[Span]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html
+[SpanContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html
diff --git a/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md b/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
index 36d722609..285488cec 100644
--- a/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
+++ b/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
@@ -139,7 +139,7 @@ whether the pattern matched.
## Pattern syntax
-The following examples demonstate the pattern syntax:
+The following examples demonstrate the pattern syntax:
#### Any (`_`)
diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md
index 5ce434b99..d7c2775b8 100644
--- a/src/tools/clippy/book/src/development/type_checking.md
+++ b/src/tools/clippy/book/src/development/type_checking.md
@@ -51,7 +51,7 @@ impl LateLintPass<'_> for MyStructLint {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
// Get type of `expr`
let ty = cx.typeck_results().expr_ty(expr);
-
+
// Check if the `Ty` of this expression is of character type
if ty.is_char() {
println!("Our expression is a char!");
@@ -70,18 +70,18 @@ pub fn is_char(self) -> bool {
}
```
-Indeed, we just discovered `Ty`'s [`kind` method][kind], which provides us
+Indeed, we just discovered `Ty`'s [`kind()` method][kind], which provides us
with [`TyKind`][TyKind] of a `Ty`.
## `TyKind`
`TyKind` defines the kinds of types in Rust's type system.
Peeking into [`TyKind` documentation][TyKind], we will see that it is an
-enum of 27 variants, including items such as `Bool`, `Int`, `Ref`, etc.
+enum of over 25 variants, including items such as `Bool`, `Int`, `Ref`, etc.
### `kind` Usage
-The `TyKind` of `Ty` can be returned by calling [`Ty.kind` method][kind].
+The `TyKind` of `Ty` can be returned by calling [`Ty.kind()` method][kind].
We often use this method to perform pattern matching in Clippy.
For instance, if we want to check for a `struct`, we could examine if the
@@ -107,15 +107,21 @@ impl LateLintPass<'_> for MyStructLint {
We've been talking about [`ty::Ty`][middle_ty] this whole time without addressing [`hir::Ty`][hir_ty], but the latter
is also important to understand.
-`hir::Ty` would represent *what* an user wrote, while `ty::Ty` would understand the meaning of it (because it has more
-information).
+`hir::Ty` would represent *what* the user wrote, while `ty::Ty` is how the compiler sees the type and has more
+information. Example:
-**Example: `fn foo(x: u32) -> u32 { x }`**
+```rust
+fn foo(x: u32) -> u32 { x }
+```
Here the HIR sees the types without "thinking" about them, it knows that the function takes an `u32` and returns
-an `u32`. But at the `ty::Ty` level the compiler understands that they're the same type, in-depth lifetimes, etc...
+an `u32`. As far as `hir::Ty` is concerned those might be different types. But at the `ty::Ty` level the compiler
+understands that they're the same type, in-depth lifetimes, etc...
+
+To get from a `hir::Ty` to a `ty::Ty`, you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function outside of bodies or
+outside of bodies the [`TypeckResults::node_type()`][node_type] method.
-you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function to convert from a `hir::Ty` to a `ty::Ty`
+> **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs.
## Useful Links
@@ -127,17 +133,18 @@ in this chapter:
- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
- [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
-[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt
+[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Adt
[AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html
[expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty
+[node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type
[is_char]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.is_char
[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1831-1834
[kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind
[LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html
[LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
-[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty
+[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/typeck_results/struct.TypeckResults.html#method.pat_ty
[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
-[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
+[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html
[TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html
[middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html
[hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 78e1a55cf..5646c9b15 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -13,6 +13,8 @@ Please use that command to update the file and do not edit it by hand.
| [msrv](#msrv) | `None` |
| [cognitive-complexity-threshold](#cognitive-complexity-threshold) | `25` |
| [disallowed-names](#disallowed-names) | `["foo", "baz", "quux"]` |
+| [semicolon-inside-block-ignore-singleline](#semicolon-inside-block-ignore-singleline) | `false` |
+| [semicolon-outside-block-ignore-multiline](#semicolon-outside-block-ignore-multiline) | `false` |
| [doc-valid-idents](#doc-valid-idents) | `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` |
| [too-many-arguments-threshold](#too-many-arguments-threshold) | `7` |
| [type-complexity-threshold](#type-complexity-threshold) | `250` |
@@ -55,6 +57,7 @@ Please use that command to update the file and do not edit it by hand.
| [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` |
| [missing-docs-in-crate-items](#missing-docs-in-crate-items) | `false` |
| [future-size-threshold](#future-size-threshold) | `16384` |
+| [unnecessary-box-size](#unnecessary-box-size) | `128` |
### arithmetic-side-effects-allowed
Suppress checking of the passed type names in all types of operations.
@@ -202,6 +205,22 @@ default configuration of Clippy. By default, any configuration will replace the
* [disallowed_names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names)
+### semicolon-inside-block-ignore-singleline
+Whether to lint only if it's multiline.
+
+**Default Value:** `false` (`bool`)
+
+* [semicolon_inside_block](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block)
+
+
+### semicolon-outside-block-ignore-multiline
+Whether to lint only if it's singleline.
+
+**Default Value:** `false` (`bool`)
+
+* [semicolon_outside_block](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block)
+
+
### doc-valid-idents
The list of words this lint should not consider as identifiers needing ticks. The value
`".."` can be used as part of the list to indicate, that the configured values should be appended to the
@@ -561,4 +580,12 @@ The maximum byte size a `Future` can have, before it triggers the `clippy::large
* [large_futures](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures)
+### unnecessary-box-size
+The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
+
+**Default Value:** `128` (`u64`)
+
+* [unnecessary_box_returns](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
+
+
diff --git a/src/tools/clippy/book/src/usage.md b/src/tools/clippy/book/src/usage.md
index 32084a919..36448e4cc 100644
--- a/src/tools/clippy/book/src/usage.md
+++ b/src/tools/clippy/book/src/usage.md
@@ -111,7 +111,8 @@ fn main() {
### Automatically applying Clippy suggestions
-Clippy can automatically apply some lint suggestions, just like the compiler.
+Clippy can automatically apply some lint suggestions, just like the compiler. Note that `--fix` implies
+`--all-targets`, so it can fix as much code as it can.
```terminal
cargo clippy --fix
diff --git a/src/tools/clippy/clippy_dev/src/dogfood.rs b/src/tools/clippy/clippy_dev/src/dogfood.rs
index b69e9f649..a0d57f5ab 100644
--- a/src/tools/clippy/clippy_dev/src/dogfood.rs
+++ b/src/tools/clippy/clippy_dev/src/dogfood.rs
@@ -1,4 +1,4 @@
-use crate::clippy_project_root;
+use crate::{clippy_project_root, exit_if_err};
use std::process::Command;
/// # Panics
@@ -10,7 +10,7 @@ pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool) {
cmd.current_dir(clippy_project_root())
.args(["test", "--test", "dogfood"])
.args(["--features", "internal"])
- .args(["--", "dogfood_clippy"]);
+ .args(["--", "dogfood_clippy", "--nocapture"]);
let mut dogfood_args = Vec::new();
if fix {
@@ -27,7 +27,5 @@ pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool) {
cmd.env("__CLIPPY_DOGFOOD_ARGS", dogfood_args.join(" "));
- let output = cmd.output().expect("failed to run command");
-
- println!("{}", String::from_utf8_lossy(&output.stdout));
+ exit_if_err(cmd.status());
}
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 3a8b070d7..56a269288 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -10,7 +10,9 @@
extern crate rustc_driver;
extern crate rustc_lexer;
+use std::io;
use std::path::PathBuf;
+use std::process::{self, ExitStatus};
pub mod bless;
pub mod dogfood;
@@ -58,3 +60,14 @@ pub fn clippy_project_root() -> PathBuf {
}
panic!("error: Can't determine root of project. Please run inside a Clippy working dir.");
}
+
+pub fn exit_if_err(status: io::Result<ExitStatus>) {
+ match status.expect("failed to run command").code() {
+ Some(0) => {},
+ Some(n) => process::exit(n),
+ None => {
+ eprintln!("Killed by signal");
+ process::exit(1);
+ },
+ }
+}
diff --git a/src/tools/clippy/clippy_dev/src/lint.rs b/src/tools/clippy/clippy_dev/src/lint.rs
index aafd0f71a..a19be1bca 100644
--- a/src/tools/clippy/clippy_dev/src/lint.rs
+++ b/src/tools/clippy/clippy_dev/src/lint.rs
@@ -1,17 +1,6 @@
-use crate::cargo_clippy_path;
-use std::process::{self, Command, ExitStatus};
-use std::{fs, io};
-
-fn exit_if_err(status: io::Result<ExitStatus>) {
- match status.expect("failed to run command").code() {
- Some(0) => {},
- Some(n) => process::exit(n),
- None => {
- eprintln!("Killed by signal");
- process::exit(1);
- },
- }
-}
+use crate::{cargo_clippy_path, exit_if_err};
+use std::fs;
+use std::process::{self, Command};
pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) {
let is_file = match fs::metadata(path) {
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 95222a9ac..7213c9dfe 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -36,60 +36,6 @@ pub enum UpdateMode {
pub fn update(update_mode: UpdateMode) {
let (lints, deprecated_lints, renamed_lints) = gather_all();
generate_lint_files(update_mode, &lints, &deprecated_lints, &renamed_lints);
- remove_old_files(update_mode);
-}
-
-/// Remove files no longer needed after <https://github.com/rust-lang/rust-clippy/pull/9541>
-/// that may be reintroduced unintentionally
-///
-/// FIXME: This is a temporary measure that should be removed when there are no more PRs that
-/// include the stray files
-fn remove_old_files(update_mode: UpdateMode) {
- let mut failed = false;
- let mut remove_file = |path: &Path| match update_mode {
- UpdateMode::Check => {
- if path.exists() {
- failed = true;
- println!("unexpected file: {}", path.display());
- }
- },
- UpdateMode::Change => {
- if fs::remove_file(path).is_ok() {
- println!("removed file: {}", path.display());
- }
- },
- };
-
- let files = [
- "clippy_lints/src/lib.register_all.rs",
- "clippy_lints/src/lib.register_cargo.rs",
- "clippy_lints/src/lib.register_complexity.rs",
- "clippy_lints/src/lib.register_correctness.rs",
- "clippy_lints/src/lib.register_internal.rs",
- "clippy_lints/src/lib.register_lints.rs",
- "clippy_lints/src/lib.register_nursery.rs",
- "clippy_lints/src/lib.register_pedantic.rs",
- "clippy_lints/src/lib.register_perf.rs",
- "clippy_lints/src/lib.register_restriction.rs",
- "clippy_lints/src/lib.register_style.rs",
- "clippy_lints/src/lib.register_suspicious.rs",
- "src/docs.rs",
- ];
-
- for file in files {
- remove_file(Path::new(file));
- }
-
- if let Ok(docs_dir) = fs::read_dir("src/docs") {
- for doc_file in docs_dir {
- let path = doc_file.unwrap().path();
- remove_file(&path);
- }
- }
-
- if failed {
- exit_with_failure();
- }
}
fn generate_lint_files(
@@ -741,7 +687,7 @@ fn gen_deprecated_lints_test(lints: &[DeprecatedLint]) -> String {
fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String {
let mut seen_lints = HashSet::new();
let mut res: String = GENERATED_FILE_COMMENT.into();
- res.push_str("// run-rustfix\n\n");
+ res.push_str("//@run-rustfix\n\n");
for lint in lints {
if seen_lints.insert(&lint.new_name) {
writeln!(res, "#![allow({})]", lint.new_name).unwrap();
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 18e8bf772..98e69c7fd 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy_lints"
-version = "0.1.70"
+version = "0.1.71"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
@@ -17,7 +17,7 @@ if_chain = "1.0"
itertools = "0.10.1"
pulldown-cmark = { version = "0.9", default-features = false }
quine-mc_cluskey = "0.2"
-regex-syntax = "0.6"
+regex-syntax = "0.7"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", optional = true }
tempfile = { version = "3.2", optional = true }
diff --git a/src/tools/clippy/clippy_lints/src/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/allow_attributes.rs
index 15d46e954..add73d0ae 100644
--- a/src/tools/clippy/clippy_lints/src/allow_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/allow_attributes.rs
@@ -2,11 +2,12 @@ use ast::AttrStyle;
use clippy_utils::diagnostics::span_lint_and_sugg;
use rustc_ast as ast;
use rustc_errors::Applicability;
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! {
- /// Detects uses of the `#[allow]` attribute and suggests replacing it with
+ /// Checks for usage of the `#[allow]` attribute and suggests replacing it with
/// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
///
/// The expect attribute is still unstable and requires the `lint_reasons`
@@ -51,6 +52,7 @@ impl LateLintPass<'_> for AllowAttribute {
// Separate each crate's features.
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
if_chain! {
+ if !in_external_macro(cx.sess(), attr.span);
if cx.tcx.features().lint_reasons;
if let AttrStyle::Outer = attr.style;
if let Some(ident) = attr.ident();
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index a36df55d0..a8dc0cb3b 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
_ => return,
};
let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else { return };
- let Some((Constant::Bool(val), _)) = constant(cx, cx.typeck_results(), condition) else { return };
+ let Some(Constant::Bool(val)) = constant(cx, cx.typeck_results(), condition) else { return };
if val {
span_lint_and_help(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 751c26267..897495ba1 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -178,6 +178,52 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
+ /// Checks for empty lines after documenation comments.
+ ///
+ /// ### Why is this bad?
+ /// The documentation comment was most likely meant to be an inner attribute or regular comment.
+ /// If it was intended to be a documentation comment, then the empty line should be removed to
+ /// be more idiomatic.
+ ///
+ /// ### Known problems
+ /// Only detects empty lines immediately following the documentation. If the doc comment is followed
+ /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr`
+ /// in combination with this lint to detect both cases.
+ ///
+ /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
+ ///
+ /// ### Example
+ /// ```rust
+ /// /// Some doc comment with a blank line after it.
+ ///
+ /// fn not_quite_good_code() { }
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust
+ /// /// Good (no blank line)
+ /// fn this_is_fine() { }
+ /// ```
+ ///
+ /// ```rust
+ /// // Good (convert to a regular comment)
+ ///
+ /// fn this_is_fine_too() { }
+ /// ```
+ ///
+ /// ```rust
+ /// //! Good (convert to a comment on an inner attribute)
+ ///
+ /// fn this_is_fine_as_well() { }
+ /// ```
+ #[clippy::version = "1.70.0"]
+ pub EMPTY_LINE_AFTER_DOC_COMMENTS,
+ nursery,
+ "empty line after documentation comments"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
/// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
///
/// ### Why is this bad?
@@ -292,6 +338,30 @@ declare_clippy_lint! {
"ensures that all `allow` and `expect` attributes have a reason"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for `any` and `all` combinators in `cfg` with only one condition.
+ ///
+ /// ### Why is this bad?
+ /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
+ ///
+ /// ### Example
+ /// ```rust
+ /// #[cfg(any(unix))]
+ /// pub struct Bar;
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust
+ /// #[cfg(unix)]
+ /// pub struct Bar;
+ /// ```
+ #[clippy::version = "1.71.0"]
+ pub NON_MINIMAL_CFG,
+ style,
+ "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
+}
+
declare_lint_pass!(Attributes => [
ALLOW_ATTRIBUTES_WITHOUT_REASON,
INLINE_ALWAYS,
@@ -604,6 +674,8 @@ impl_lint_pass!(EarlyAttributes => [
DEPRECATED_CFG_ATTR,
MISMATCHED_TARGET_OS,
EMPTY_LINE_AFTER_OUTER_ATTR,
+ EMPTY_LINE_AFTER_DOC_COMMENTS,
+ NON_MINIMAL_CFG,
]);
impl EarlyLintPass for EarlyAttributes {
@@ -614,15 +686,22 @@ impl EarlyLintPass for EarlyAttributes {
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
check_deprecated_cfg_attr(cx, attr, &self.msrv);
check_mismatched_target_os(cx, attr);
+ check_minimal_cfg_condition(cx, attr);
}
extract_msrv_attr!(EarlyContext);
}
+/// Check for empty lines after outer attributes.
+///
+/// Attributes and documenation comments are both considered outer attributes
+/// by the AST. However, the average user likely considers them to be different.
+/// Checking for empty lines after each of these attributes is split into two different
+/// lints but can share the same logic.
fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
let mut iter = item.attrs.iter().peekable();
while let Some(attr) = iter.next() {
- if matches!(attr.kind, AttrKind::Normal(..))
+ if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..)))
&& attr.style == AttrStyle::Outer
&& is_present_in_source(cx, attr.span)
{
@@ -639,13 +718,20 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
let lines = without_block_comments(lines);
if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
- span_lint(
- cx,
- EMPTY_LINE_AFTER_OUTER_ATTR,
- begin_of_attr_to_item,
- "found an empty line after an outer attribute. \
- Perhaps you forgot to add a `!` to make it an inner attribute?",
- );
+ let (lint_msg, lint_type) = match attr.kind {
+ AttrKind::DocComment(..) => (
+ "found an empty line after a doc comment. \
+ Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?",
+ EMPTY_LINE_AFTER_DOC_COMMENTS,
+ ),
+ AttrKind::Normal(..) => (
+ "found an empty line after an outer attribute. \
+ Perhaps you forgot to add a `!` to make it an inner attribute?",
+ EMPTY_LINE_AFTER_OUTER_ATTR,
+ ),
+ };
+
+ span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg);
}
}
}
@@ -690,6 +776,48 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
}
}
+fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
+ for item in items.iter() {
+ if let NestedMetaItem::MetaItem(meta) = item {
+ if !meta.has_name(sym::any) && !meta.has_name(sym::all) {
+ continue;
+ }
+ if let MetaItemKind::List(list) = &meta.kind {
+ check_nested_cfg(cx, list);
+ if list.len() == 1 {
+ span_lint_and_then(
+ cx,
+ NON_MINIMAL_CFG,
+ meta.span,
+ "unneeded sub `cfg` when there is only one condition",
+ |diag| {
+ if let Some(snippet) = snippet_opt(cx, list[0].span()) {
+ diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
+ }
+ },
+ );
+ } else if list.is_empty() && meta.has_name(sym::all) {
+ span_lint_and_then(
+ cx,
+ NON_MINIMAL_CFG,
+ meta.span,
+ "unneeded sub `cfg` when there is no condition",
+ |_| {},
+ );
+ }
+ }
+ }
+ }
+}
+
+fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
+ if attr.has_name(sym::cfg) &&
+ let Some(items) = attr.meta_item_list()
+ {
+ check_nested_cfg(cx, &items);
+ }
+}
+
fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
fn find_os(name: &str) -> Option<&'static str> {
UNIX_SYSTEMS
diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
index 1d9096ea6..8c3ad24ee 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -41,7 +41,7 @@ fn extract_bool_lit(e: &Expr<'_>) -> Option<bool> {
}) = e.kind
&& !e.span.from_expansion()
{
- Some(b)
+ Some(*b)
} else {
None
}
diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
index c4520d003..814108ed8 100644
--- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
@@ -1,5 +1,6 @@
use crate::reference::DEREF_ADDROF;
use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_from_proc_macro;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::implements_trait;
use clippy_utils::{get_parent_expr, is_lint_allowed};
@@ -47,8 +48,8 @@ declare_clippy_lint! {
declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
-impl LateLintPass<'_> for BorrowDerefRef {
- fn check_expr(&mut self, cx: &LateContext<'_>, e: &rustc_hir::Expr<'_>) {
+impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
if_chain! {
if !e.span.from_expansion();
if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind;
@@ -58,6 +59,7 @@ impl LateLintPass<'_> for BorrowDerefRef {
if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) );
let ref_ty = cx.typeck_results().expr_ty(deref_target);
if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind();
+ if !is_from_proc_macro(cx, e);
then{
if let Some(parent_expr) = get_parent_expr(cx, e){
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index dfa949d1a..e42c3fe24 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -8,7 +8,9 @@ use rustc_hir::{
Block, Expr, ExprKind, Local, Node, QPath, TyKind,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
+use rustc_middle::ty::IsSuggestable;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
@@ -49,7 +51,6 @@ impl LateLintPass<'_> for BoxDefault {
&& path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
&& is_default_equivalent(cx, arg)
{
- let arg_ty = cx.typeck_results().expr_ty(arg);
span_lint_and_sugg(
cx,
BOX_DEFAULT,
@@ -58,8 +59,10 @@ impl LateLintPass<'_> for BoxDefault {
"try",
if is_plain_default(arg_path) || given_type(cx, expr) {
"Box::default()".into()
- } else {
+ } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
+ } else {
+ return
},
Applicability::MachineApplicable
);
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
index 322dc41b3..da756129d 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
@@ -21,8 +21,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
match constant(cx, cx.typeck_results(), e) {
- Some((Constant::F64(n), _)) => n.is_nan(),
- Some((Constant::F32(n), _)) => n.is_nan(),
+ Some(Constant::F64(n)) => n.is_nan(),
+ Some(Constant::F32(n)) => n.is_nan(),
_ => false,
}
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index 95c2ecbf7..84b99ad5c 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -15,7 +15,7 @@ use rustc_target::abi::IntegerType;
use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
- if let Some((Constant::Int(c), _)) = constant(cx, cx.typeck_results(), expr) {
+ if let Some(Constant::Int(c)) = constant(cx, cx.typeck_results(), expr) {
Some(c)
} else {
None
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index a20a97d4e..a83dfd94d 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -29,7 +29,7 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
// Don't lint for positive constants.
let const_val = constant(cx, cx.typeck_results(), cast_op);
if_chain! {
- if let Some((Constant::Int(n), _)) = const_val;
+ if let Some(Constant::Int(n)) = const_val;
if let ty::Int(ity) = *cast_from.kind();
if sext(cx.tcx, n, ity) >= 0;
then {
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index 362f70d12..cfeb75eed 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -506,7 +506,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for uses of the `abs()` method that cast the result to unsigned.
+ /// Checks for usage of the `abs()` method that cast the result to unsigned.
///
/// ### Why is this bad?
/// The `unsigned_abs()` method avoids panic when called on the MIN value.
@@ -625,20 +625,20 @@ declare_clippy_lint! {
///
/// ### Example
/// ```rust
- /// let string = String::with_capacity(1);
- /// let ptr = string.as_ptr() as *mut u8;
+ /// let mut vec = Vec::<u8>::with_capacity(1);
+ /// let ptr = vec.as_ptr() as *mut u8;
/// unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR
/// ```
/// Use instead:
/// ```rust
- /// let mut string = String::with_capacity(1);
- /// let ptr = string.as_mut_ptr();
+ /// let mut vec = Vec::<u8>::with_capacity(1);
+ /// let ptr = vec.as_mut_ptr();
/// unsafe { ptr.write(4) };
/// ```
#[clippy::version = "1.66.0"]
pub AS_PTR_CAST_MUT,
nursery,
- "casting the result of the `&self`-taking `as_ptr` to a mutabe pointer"
+ "casting the result of the `&self`-taking `as_ptr` to a mutable pointer"
}
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index 7e2331807..804ae8411 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -141,9 +141,9 @@ fn lint_unnecessary_cast(
fn get_numeric_literal<'e>(expr: &'e Expr<'e>) -> Option<&'e Lit> {
match expr.kind {
- ExprKind::Lit(ref lit) => Some(lit),
+ ExprKind::Lit(lit) => Some(lit),
ExprKind::Unary(UnOp::Neg, e) => {
- if let ExprKind::Lit(ref lit) = e.kind {
+ if let ExprKind::Lit(lit) = e.kind {
Some(lit)
} else {
None
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 970f50049..1c321f46e 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -591,7 +591,7 @@ fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>], ignored_ty_ids: &De
conds,
|e| hash_expr(cx, e),
|lhs, rhs| {
- // Ignore eq_expr side effects iff one of the expressin kind is a method call
+ // Ignore eq_expr side effects iff one of the expression kind is a method call
// and the caller is not a mutable, including inner mutable type.
if let ExprKind::MethodCall(_, caller, _, _) = lhs.kind {
if method_caller_is_mutable(cx, caller, ignored_ty_ids) {
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index b2fe0386f..7436e9ce8 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -9,7 +9,7 @@ use rustc_span::{symbol::sym, Span};
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `crate` as opposed to `$crate` in a macro definition.
+ /// Checks for usage of `crate` as opposed to `$crate` in a macro definition.
///
/// ### Why is this bad?
/// `crate` refers to the macro call's crate, whereas `$crate` refers to the macro definition's
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index 799e71e84..ea17e7a60 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -3,10 +3,10 @@ use clippy_utils::macros::root_macro_call_first_node;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_in_cfg_test, is_in_test_function};
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_hir::{Expr, ExprKind, Node};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::sym;
+use rustc_span::{sym, BytePos, Pos, Span};
declare_clippy_lint! {
/// ### What it does
@@ -31,6 +31,31 @@ declare_clippy_lint! {
"`dbg!` macro is intended as a debugging tool"
}
+/// Gets the span of the statement up to the next semicolon, if and only if the next
+/// non-whitespace character actually is a semicolon.
+/// E.g.
+/// ```rust,ignore
+///
+/// dbg!();
+/// ^^^^^^^ this span is returned
+///
+/// foo!(dbg!());
+/// no span is returned
+/// ```
+fn span_including_semi(cx: &LateContext<'_>, span: Span) -> Option<Span> {
+ let sm = cx.sess().source_map();
+ let sf = sm.lookup_source_file(span.hi());
+ let src = sf.src.as_ref()?.get(span.hi().to_usize()..)?;
+ let first_non_whitespace = src.find(|c: char| !c.is_whitespace())?;
+
+ if src.as_bytes()[first_non_whitespace] == b';' {
+ let hi = span.hi() + BytePos::from_usize(first_non_whitespace + 1);
+ Some(span.with_hi(hi))
+ } else {
+ None
+ }
+}
+
#[derive(Copy, Clone)]
pub struct DbgMacro {
allow_dbg_in_tests: bool,
@@ -55,13 +80,25 @@ impl LateLintPass<'_> for DbgMacro {
return;
}
let mut applicability = Applicability::MachineApplicable;
- let suggestion = match expr.peel_drop_temps().kind {
+
+ let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
// dbg!()
- ExprKind::Block(_, _) => String::new(),
- // dbg!(1)
- ExprKind::Match(val, ..) => {
- snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string()
+ ExprKind::Block(..) => {
+ // If the `dbg!` macro is a "free" statement and not contained within other expressions,
+ // remove the whole statement.
+ if let Some(Node::Stmt(stmt)) = cx.tcx.hir().find_parent(expr.hir_id)
+ && let Some(span) = span_including_semi(cx, stmt.span.source_callsite())
+ {
+ (span, String::new())
+ } else {
+ (macro_call.span, String::from("()"))
+ }
},
+ // dbg!(1)
+ ExprKind::Match(val, ..) => (
+ macro_call.span,
+ snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string(),
+ ),
// dbg!(2, 3)
ExprKind::Tup(
[
@@ -82,7 +119,7 @@ impl LateLintPass<'_> for DbgMacro {
"..",
&mut applicability,
);
- format!("({snippet})")
+ (macro_call.span, format!("({snippet})"))
},
_ => return,
};
@@ -90,7 +127,7 @@ impl LateLintPass<'_> for DbgMacro {
span_lint_and_sugg(
cx,
DBG_MACRO,
- macro_call.span,
+ sugg_span,
"the `dbg!` macro is intended as a debugging tool",
"remove the invocation before committing it to a version control system",
suggestion,
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index f24dab627..423eee477 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -48,9 +48,11 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
crate::attrs::DEPRECATED_CFG_ATTR_INFO,
crate::attrs::DEPRECATED_SEMVER_INFO,
+ crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
crate::attrs::INLINE_ALWAYS_INFO,
crate::attrs::MISMATCHED_TARGET_OS_INFO,
+ crate::attrs::NON_MINIMAL_CFG_INFO,
crate::attrs::USELESS_ATTRIBUTE_INFO,
crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,
@@ -105,6 +107,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::dbg_macro::DBG_MACRO_INFO,
crate::default::DEFAULT_TRAIT_ACCESS_INFO,
crate::default::FIELD_REASSIGN_WITH_DEFAULT_INFO,
+ crate::default_constructed_unit_structs::DEFAULT_CONSTRUCTED_UNIT_STRUCTS_INFO,
crate::default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY_INFO,
crate::default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK_INFO,
crate::default_union_representation::DEFAULT_UNION_REPRESENTATION_INFO,
@@ -131,12 +134,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::doc::NEEDLESS_DOCTEST_MAIN_INFO,
crate::doc::UNNECESSARY_SAFETY_DOC_INFO,
crate::double_parens::DOUBLE_PARENS_INFO,
- crate::drop_forget_ref::DROP_COPY_INFO,
crate::drop_forget_ref::DROP_NON_DROP_INFO,
- crate::drop_forget_ref::DROP_REF_INFO,
- crate::drop_forget_ref::FORGET_COPY_INFO,
crate::drop_forget_ref::FORGET_NON_DROP_INFO,
- crate::drop_forget_ref::FORGET_REF_INFO,
crate::drop_forget_ref::UNDROPPED_MANUALLY_DROPS_INFO,
crate::duplicate_mod::DUPLICATE_MOD_INFO,
crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO,
@@ -215,6 +214,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
crate::invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED_INFO,
crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO,
+ crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO,
crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO,
crate::large_enum_variant::LARGE_ENUM_VARIANT_INFO,
@@ -248,6 +248,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::loops::MANUAL_FIND_INFO,
crate::loops::MANUAL_FLATTEN_INFO,
crate::loops::MANUAL_MEMCPY_INFO,
+ crate::loops::MANUAL_WHILE_LET_SOME_INFO,
crate::loops::MISSING_SPIN_LOOP_INFO,
crate::loops::MUT_RANGE_BOUND_INFO,
crate::loops::NEEDLESS_RANGE_LOOP_INFO,
@@ -312,7 +313,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::methods::CHARS_NEXT_CMP_INFO,
crate::methods::CLEAR_WITH_DRAIN_INFO,
crate::methods::CLONED_INSTEAD_OF_COPIED_INFO,
- crate::methods::CLONE_DOUBLE_REF_INFO,
crate::methods::CLONE_ON_COPY_INFO,
crate::methods::CLONE_ON_REF_PTR_INFO,
crate::methods::COLLAPSIBLE_STR_REPLACE_INFO,
@@ -349,6 +349,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::methods::ITER_WITH_DRAIN_INFO,
crate::methods::MANUAL_FILTER_MAP_INFO,
crate::methods::MANUAL_FIND_MAP_INFO,
+ crate::methods::MANUAL_NEXT_BACK_INFO,
crate::methods::MANUAL_OK_OR_INFO,
crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO,
crate::methods::MANUAL_SPLIT_ONCE_INFO,
@@ -445,6 +446,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE_INFO,
crate::needless_bool::BOOL_COMPARISON_INFO,
crate::needless_bool::NEEDLESS_BOOL_INFO,
+ crate::needless_bool::NEEDLESS_BOOL_ASSIGN_INFO,
crate::needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE_INFO,
crate::needless_continue::NEEDLESS_CONTINUE_INFO,
crate::needless_for_each::NEEDLESS_FOR_EACH_INFO,
@@ -486,7 +488,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::operators::FLOAT_EQUALITY_WITHOUT_ABS_INFO,
crate::operators::IDENTITY_OP_INFO,
crate::operators::INEFFECTIVE_BIT_MASK_INFO,
- crate::operators::INTEGER_ARITHMETIC_INFO,
crate::operators::INTEGER_DIVISION_INFO,
crate::operators::MISREFACTORED_ASSIGN_OP_INFO,
crate::operators::MODULO_ARITHMETIC_INFO,
@@ -536,6 +537,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::redundant_slicing::REDUNDANT_SLICING_INFO,
crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO,
crate::ref_option_ref::REF_OPTION_REF_INFO,
+ crate::ref_patterns::REF_PATTERNS_INFO,
crate::reference::DEREF_ADDROF_INFO,
crate::regex::INVALID_REGEX_INFO,
crate::regex::TRIVIAL_REGEX_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
new file mode 100644
index 000000000..fb037bbcb
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
@@ -0,0 +1,84 @@
+use clippy_utils::{diagnostics::span_lint_and_sugg, is_ty_alias, match_def_path, paths};
+use hir::{def::Res, ExprKind};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Check for construction on unit struct using `default`.
+ ///
+ /// ### Why is this bad?
+ /// This adds code complexity and an unnecessary function call.
+ ///
+ /// ### Example
+ /// ```rust
+ /// # use std::marker::PhantomData;
+ /// #[derive(Default)]
+ /// struct S<T> {
+ /// _marker: PhantomData<T>
+ /// }
+ ///
+ /// let _: S<i32> = S {
+ /// _marker: PhantomData::default()
+ /// };
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # use std::marker::PhantomData;
+ /// struct S<T> {
+ /// _marker: PhantomData<T>
+ /// }
+ ///
+ /// let _: S<i32> = S {
+ /// _marker: PhantomData
+ /// };
+ /// ```
+ #[clippy::version = "1.71.0"]
+ pub DEFAULT_CONSTRUCTED_UNIT_STRUCTS,
+ complexity,
+ "unit structs can be contructed without calling `default`"
+}
+declare_lint_pass!(DefaultConstructedUnitStructs => [DEFAULT_CONSTRUCTED_UNIT_STRUCTS]);
+
+fn is_alias(ty: hir::Ty<'_>) -> bool {
+ if let hir::TyKind::Path(ref qpath) = ty.kind {
+ is_ty_alias(qpath)
+ } else {
+ false
+ }
+}
+
+impl LateLintPass<'_> for DefaultConstructedUnitStructs {
+ fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+ if_chain!(
+ // make sure we have a call to `Default::default`
+ if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind;
+ if let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind;
+ // make sure this isn't a type alias:
+ // `<Foo as Bar>::Assoc` cannot be used as a constructor
+ if !is_alias(*base);
+ if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
+ if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
+ // make sure we have a struct with no fields (unit struct)
+ if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind();
+ if def.is_struct();
+ if let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant();
+ if !var.is_field_list_non_exhaustive();
+ if !expr.span.from_expansion() && !qpath.span().from_expansion();
+ then {
+ span_lint_and_sugg(
+ cx,
+ DEFAULT_CONSTRUCTED_UNIT_STRUCTS,
+ expr.span.with_lo(qpath.qself_span().hi()),
+ "use of `default` to create a unit struct",
+ "remove this call to `default`",
+ String::new(),
+ Applicability::MachineApplicable,
+ )
+ }
+ );
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index dec357ab7..03b5a2d6d 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
None,
&format!(
"consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
- cx.tcx.def_path_str(item.owner_id.to_def_id())
+ cx.tcx.def_path_str(item.owner_id)
),
);
}
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 7f3f26bed..b27ffe73f 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1424,6 +1424,7 @@ fn ty_auto_deref_stability<'tcx>(
continue;
},
ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
+ ty::Alias(ty::Inherent, _) => unreachable!("inherent projection should have been normalized away above"),
ty::Alias(ty::Projection, _) if ty.has_non_region_param() => {
TyPosition::new_deref_stable_for_result(precedence, ty)
},
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index f425dd5fb..8f5d319cd 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -517,7 +517,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain(
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
- trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]),
+ trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]),
constness: BoundConstness::NotConst,
polarity: ImplPolarity::Positive,
}))))
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index 11e1bcdf1..9c60edb17 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -9,102 +9,6 @@ use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
- /// Checks for calls to `std::mem::drop` with a reference
- /// instead of an owned value.
- ///
- /// ### Why is this bad?
- /// Calling `drop` on a reference will only drop the
- /// reference itself, which is a no-op. It will not call the `drop` method (from
- /// the `Drop` trait implementation) on the underlying referenced value, which
- /// is likely what was intended.
- ///
- /// ### Example
- /// ```ignore
- /// let mut lock_guard = mutex.lock();
- /// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex
- /// // still locked
- /// operation_that_requires_mutex_to_be_unlocked();
- /// ```
- #[clippy::version = "pre 1.29.0"]
- pub DROP_REF,
- correctness,
- "calls to `std::mem::drop` with a reference instead of an owned value"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for calls to `std::mem::forget` with a reference
- /// instead of an owned value.
- ///
- /// ### Why is this bad?
- /// Calling `forget` on a reference will only forget the
- /// reference itself, which is a no-op. It will not forget the underlying
- /// referenced
- /// value, which is likely what was intended.
- ///
- /// ### Example
- /// ```rust
- /// let x = Box::new(1);
- /// std::mem::forget(&x) // Should have been forget(x), x will still be dropped
- /// ```
- #[clippy::version = "pre 1.29.0"]
- pub FORGET_REF,
- correctness,
- "calls to `std::mem::forget` with a reference instead of an owned value"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for calls to `std::mem::drop` with a value
- /// that derives the Copy trait
- ///
- /// ### Why is this bad?
- /// Calling `std::mem::drop` [does nothing for types that
- /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
- /// value will be copied and moved into the function on invocation.
- ///
- /// ### Example
- /// ```rust
- /// let x: i32 = 42; // i32 implements Copy
- /// std::mem::drop(x) // A copy of x is passed to the function, leaving the
- /// // original unaffected
- /// ```
- #[clippy::version = "pre 1.29.0"]
- pub DROP_COPY,
- correctness,
- "calls to `std::mem::drop` with a value that implements Copy"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for calls to `std::mem::forget` with a value that
- /// derives the Copy trait
- ///
- /// ### Why is this bad?
- /// Calling `std::mem::forget` [does nothing for types that
- /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the
- /// value will be copied and moved into the function on invocation.
- ///
- /// An alternative, but also valid, explanation is that Copy types do not
- /// implement
- /// the Drop trait, which means they have no destructors. Without a destructor,
- /// there
- /// is nothing for `std::mem::forget` to ignore.
- ///
- /// ### Example
- /// ```rust
- /// let x: i32 = 42; // i32 implements Copy
- /// std::mem::forget(x) // A copy of x is passed to the function, leaving the
- /// // original unaffected
- /// ```
- #[clippy::version = "pre 1.29.0"]
- pub FORGET_COPY,
- correctness,
- "calls to `std::mem::forget` with a value that implements Copy"
-}
-
-declare_clippy_lint! {
- /// ### What it does
/// Checks for calls to `std::mem::drop` with a value that does not implement `Drop`.
///
/// ### Why is this bad?
@@ -172,24 +76,12 @@ declare_clippy_lint! {
"use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value"
}
-const DROP_REF_SUMMARY: &str = "calls to `std::mem::drop` with a reference instead of an owned value. \
- Dropping a reference does nothing";
-const FORGET_REF_SUMMARY: &str = "calls to `std::mem::forget` with a reference instead of an owned value. \
- Forgetting a reference does nothing";
-const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that implements `Copy`. \
- Dropping a copy leaves the original intact";
-const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements `Copy`. \
- Forgetting a copy leaves the original intact";
const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \
Dropping such a type only extends its contained lifetimes";
const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \
Forgetting such a type is the same as dropping it";
declare_lint_pass!(DropForgetRef => [
- DROP_REF,
- FORGET_REF,
- DROP_COPY,
- FORGET_COPY,
DROP_NON_DROP,
FORGET_NON_DROP,
UNDROPPED_MANUALLY_DROPS
@@ -206,10 +98,11 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
let is_copy = is_copy(cx, arg_ty);
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
let (lint, msg) = match fn_name {
- sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => (DROP_REF, DROP_REF_SUMMARY),
- sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
- sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
- sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
+ // early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types
+ sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return,
+ sym::mem_forget if arg_ty.is_ref() => return,
+ sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return,
+ sym::mem_forget if is_copy => return,
sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => {
span_lint_and_help(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 48a54f602..ee5a875ad 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -19,7 +19,7 @@ use rustc_span::{Span, SyntaxContext, DUMMY_SP};
declare_clippy_lint! {
/// ### What it does
- /// Checks for uses of `contains_key` + `insert` on `HashMap`
+ /// Checks for usage of `contains_key` + `insert` on `HashMap`
/// or `BTreeMap`.
///
/// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index 4c69dacf3..faac63404 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -1,6 +1,6 @@
//! lint on enum variants that are prefixed or suffixed by the same characters
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
use clippy_utils::source::is_present_in_source;
use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start};
use rustc_hir::{EnumDef, Item, ItemKind, Variant};
@@ -135,9 +135,10 @@ fn check_enum_start(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>
&& name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
&& name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
{
- span_lint(
+ span_lint_hir(
cx,
ENUM_VARIANT_NAMES,
+ variant.hir_id,
variant.span,
"variant name starts with the enum's name",
);
@@ -149,9 +150,10 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>)
let item_name_chars = item_name.chars().count();
if count_match_end(item_name, name).char_count == item_name_chars {
- span_lint(
+ span_lint_hir(
cx,
ENUM_VARIANT_NAMES,
+ variant.hir_id,
variant.span,
"variant name ends with the enum's name",
);
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index d6ab4c25e..a51a8ee09 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -92,11 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
if trait_item.id.owner_id.def_id == fn_def_id {
// be sure we have `self` parameter in this function
if trait_item.kind == (AssocItemKind::Fn { has_self: true }) {
- trait_self_ty = Some(
- TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id())
- .self_ty()
- .skip_binder(),
- );
+ trait_self_ty =
+ Some(TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id()).self_ty());
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index 6fee7fb30..93bf50fd5 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
let ty = cx.typeck_results().expr_ty(expr);
if_chain! {
if let ty::Float(fty) = *ty.kind();
- if let hir::ExprKind::Lit(ref lit) = expr.kind;
+ if let hir::ExprKind::Lit(lit) = expr.kind;
if let LitKind::Float(sym, lit_float_ty) = lit.node;
then {
let sym_str = sym.as_str();
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index f95b628e6..3c55a563a 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -2,9 +2,10 @@ use clippy_utils::consts::{
constant, constant_simple, Constant,
Constant::{Int, F32, F64},
};
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher;
-use clippy_utils::{eq_expr_value, get_parent_expr, in_constant, numeric_literal, peel_blocks, sugg};
+use clippy_utils::{
+ diagnostics::span_lint_and_sugg, eq_expr_value, get_parent_expr, higher, in_constant, is_no_std_crate,
+ numeric_literal, peel_blocks, sugg,
+};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
@@ -113,7 +114,7 @@ declare_lint_pass!(FloatingPointArithmetic => [
// Returns the specialized log method for a given base if base is constant
// and is one of 2, 10 and e
fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>) -> Option<&'static str> {
- if let Some((value, _)) = constant(cx, cx.typeck_results(), base) {
+ if let Some(value) = constant(cx, cx.typeck_results(), base) {
if F32(2.0) == value || F64(2.0) == value {
return Some("log2");
} else if F32(10.0) == value || F64(10.0) == value {
@@ -192,8 +193,8 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
constant(cx, cx.typeck_results(), lhs),
constant(cx, cx.typeck_results(), rhs),
) {
- (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
- (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
+ (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs,
+ (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs,
_ => return,
};
@@ -236,7 +237,7 @@ fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
// Check receiver
- if let Some((value, _)) = constant(cx, cx.typeck_results(), receiver) {
+ if let Some(value) = constant(cx, cx.typeck_results(), receiver) {
if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
Some("exp")
} else if F32(2.0) == value || F64(2.0) == value {
@@ -257,7 +258,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
}
// Check argument
- if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+ if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
(
SUBOPTIMAL_FLOPS,
@@ -297,7 +298,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
}
fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
- if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+ if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
if value == Int(2) {
if let Some(parent) = get_parent_expr(cx, expr) {
if let Some(grandparent) = get_parent_expr(cx, parent) {
@@ -383,8 +384,8 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
_
) = &add_rhs.kind;
if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
- if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), largs_1);
- if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), rargs_1);
+ if let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1);
+ if let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1);
if Int(2) == lvalue && Int(2) == rvalue;
then {
return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, "..").maybe_par(), Sugg::hir(cx, rargs_0, "..")));
@@ -415,7 +416,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
if_chain! {
if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind;
if cx.typeck_results().expr_ty(lhs).is_floating_point();
- if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs);
+ if let Some(value) = constant(cx, cx.typeck_results(), rhs);
if F32(1.0) == value || F64(1.0) == value;
if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind;
if cx.typeck_results().expr_ty(self_arg).is_floating_point();
@@ -668,8 +669,8 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
mul_lhs,
mul_rhs,
) = &div_lhs.kind;
- if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), div_rhs);
- if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), mul_rhs);
+ if let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs);
+ if let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs);
then {
// TODO: also check for constant values near PI/180 or 180/PI
if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) &&
@@ -677,7 +678,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
{
let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_par());
if_chain! {
- if let ExprKind::Lit(ref literal) = mul_lhs.kind;
+ if let ExprKind::Lit(literal) = mul_lhs.kind;
if let ast::LitKind::Float(ref value, float_type) = literal.node;
if float_type == ast::LitFloatType::Unsuffixed;
then {
@@ -703,7 +704,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
{
let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_par());
if_chain! {
- if let ExprKind::Lit(ref literal) = mul_lhs.kind;
+ if let ExprKind::Lit(literal) = mul_lhs.kind;
if let ast::LitKind::Float(ref value, float_type) = literal.node;
if float_type == ast::LitFloatType::Unsuffixed;
then {
@@ -730,7 +731,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- // All of these operations are currently not const.
+ // All of these operations are currently not const and are in std.
if in_constant(cx, expr.hir_id) {
return;
}
@@ -738,7 +739,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind {
let recv_ty = cx.typeck_results().expr_ty(receiver);
- if recv_ty.is_floating_point() {
+ if recv_ty.is_floating_point() && !is_no_std_crate(cx) {
match path.ident.name.as_str() {
"ln" => check_ln1p(cx, expr, receiver),
"log" => check_log_base(cx, expr, receiver, args),
@@ -749,10 +750,12 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
}
}
} else {
- check_expm1(cx, expr);
- check_mul_add(cx, expr);
- check_custom_abs(cx, expr);
- check_log_division(cx, expr);
+ if !is_no_std_crate(cx) {
+ check_expm1(cx, expr);
+ check_mul_add(cx, expr);
+ check_custom_abs(cx, expr);
+ check_log_division(cx, expr);
+ }
check_radians(cx, expr);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
index d8f4a5fe2..521045a9f 100644
--- a/src/tools/clippy/clippy_lints/src/fn_null_check.rs
+++ b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
@@ -89,11 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
// Catching:
// (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
- _ if matches!(
- constant(cx, cx.typeck_results(), to_check),
- Some((Constant::RawPtr(0), _))
- ) =>
- {
+ _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => {
lint_expr(cx, expr);
},
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index e3ddbfb59..3ddee1842 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -51,7 +51,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `println`, `print`, `eprintln` or `eprint` in an
+ /// Checks for usage of `println`, `print`, `eprintln` or `eprint` in an
/// implementation of a formatting trait.
///
/// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs
index a866a6898..4762b3543 100644
--- a/src/tools/clippy/clippy_lints/src/formatting.rs
+++ b/src/tools/clippy/clippy_lints/src/formatting.rs
@@ -10,7 +10,7 @@ use rustc_span::source_map::Span;
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of the non-existent `=*`, `=!` and `=-`
+ /// Checks for usage of the non-existent `=*`, `=!` and `=-`
/// operators.
///
/// ### Why is this bad?
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 bd66ace45..10ce2a0f0 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
);
}
- let message = format!("replace the `Into` implentation with `From<{}>`", middle_trait_ref.self_ty());
+ let message = format!("replace the `Into` implementation with `From<{}>`", middle_trait_ref.self_ty());
if let Some(suggestions) = convert_to_from(cx, into_trait_seg, target_ty, self_ty, impl_item_ref) {
diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
} else {
diff --git a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
index e5945939e..b244b9133 100644
--- a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
@@ -40,7 +40,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
};
// Body must be &(mut) <self_data>.name
- // self_data is not neccessarilly self, to also lint sub-getters, etc…
+ // self_data is not necessarily self, to also lint sub-getters, etc…
let block_expr = if_chain! {
if let ExprKind::Block(block,_) = body.value.kind;
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 7c5e44bb7..ee10334c6 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -252,6 +252,11 @@ declare_clippy_lint! {
/// A `Result` is at least as large as the `Err`-variant. While we
/// expect that variant to be seldomly used, the compiler needs to reserve
/// and move that much memory every single time.
+ /// Furthermore, errors are often simply passed up the call-stack, making
+ /// use of the `?`-operator and its type-conversion mechanics. If the
+ /// `Err`-variant further up the call-stack stores the `Err`-variant in
+ /// question (as library code often does), it itself needs to be at least
+ /// as large, propagating the problem.
///
/// ### Known problems
/// The size determined by Clippy is platform-dependent.
@@ -330,7 +335,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Lints when `impl Trait` is being used in a function's paremeters.
+ /// Lints when `impl Trait` is being used in a function's parameters.
/// ### Why is this bad?
/// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor.
///
@@ -348,7 +353,7 @@ declare_clippy_lint! {
/// // [...]
/// }
/// ```
- #[clippy::version = "1.68.0"]
+ #[clippy::version = "1.69.0"]
pub IMPL_TRAIT_IN_PARAMS,
restriction,
"`impl Trait` is used in the function's parameters"
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index ed0bd58c7..d1314795f 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind};
+use rustc_middle::ty::{self, AliasTy, Clause, PredicateKind};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
@@ -66,8 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() {
let preds = cx.tcx.explicit_item_bounds(def_id);
let mut is_future = false;
- for &(p, _span) in preds {
- let p = EarlyBinder(p).subst(cx.tcx, substs);
+ for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) {
if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
is_future = true;
@@ -97,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
if let PredicateKind::Clause(Clause::Trait(trait_pred)) =
obligation.predicate.kind().skip_binder()
{
- db.note(&format!(
+ db.note(format!(
"`{}` doesn't implement `{}`",
trait_pred.self_ty(),
trait_pred.trait_ref.print_only_trait_path(),
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
index 57e6caa87..ee7973b82 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
if expr1.span.ctxt() == ctxt;
if clippy_utils::SpanlessEq::new(cx).eq_expr(l, target);
if BinOpKind::Add == op1.node;
- if let ExprKind::Lit(ref lit) = value.kind;
+ if let ExprKind::Lit(lit) = value.kind;
if let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node;
if block.expr.is_none();
then {
@@ -101,10 +101,10 @@ fn get_int_max(ty: Ty<'_>) -> Option<u128> {
fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> {
if let ExprKind::Binary(op, l, r) = expr.kind {
let tr = cx.typeck_results();
- if let Some((Constant::Int(c), _)) = constant(cx, tr, r) {
+ if let Some(Constant::Int(c)) = constant(cx, tr, r) {
return Some((c, op.node, l));
};
- if let Some((Constant::Int(c), _)) = constant(cx, tr, l) {
+ if let Some(Constant::Int(c)) = constant(cx, tr, l) {
return Some((c, invert_op(op.node)?, r));
}
}
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 0c7aea6da..1e99b6faa 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
// Get the variable name
let var_name = ares_path.segments[0].ident.name.as_str();
match cond_num_val.kind {
- ExprKind::Lit(ref cond_lit) => {
+ ExprKind::Lit(cond_lit) => {
// Check if the constant is zero
if let LitKind::Int(0, _) = cond_lit.node {
if cx.typeck_results().expr_ty(cond_left).is_signed() {
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index bdeddf44d..7a269e98f 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -254,7 +254,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
let parent_id = map.parent_id(expr.hir_id);
if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id);
if let hir::ExprKind::Index(_, index_expr) = parent_expr.kind;
- if let Some((Constant::Int(index_value), _)) = constant(cx, cx.typeck_results(), index_expr);
+ if let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr);
if let Ok(index_value) = index_value.try_into();
if index_value < max_suggested_slice;
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index c384172fb..22c14d9b0 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -170,7 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
return;
}
// Index is a constant uint.
- if let Some(..) = constant(cx, cx.typeck_results(), index) {
+ if constant(cx, cx.typeck_results(), index).is_some() {
// Let rustc's `const_err` lint handle constant `usize` indexing on arrays.
return;
}
@@ -191,18 +191,14 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
/// Returns a tuple of options with the start and end (exclusive) values of
/// the range. If the start or end is not constant, None is returned.
fn to_const_range(cx: &LateContext<'_>, range: higher::Range<'_>, array_size: u128) -> (Option<u128>, Option<u128>) {
- let s = range
- .start
- .map(|expr| constant(cx, cx.typeck_results(), expr).map(|(c, _)| c));
+ let s = range.start.map(|expr| constant(cx, cx.typeck_results(), expr));
let start = match s {
Some(Some(Constant::Int(x))) => Some(x),
Some(_) => None,
None => Some(0),
};
- let e = range
- .end
- .map(|expr| constant(cx, cx.typeck_results(), expr).map(|(c, _)| c));
+ let e = range.end.map(|expr| constant(cx, cx.typeck_results(), expr));
let end = match e {
Some(Some(Constant::Int(x))) => {
if range.limits == RangeLimits::Closed {
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
new file mode 100644
index 000000000..40378ee82
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
@@ -0,0 +1,85 @@
+use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, is_in_cfg_test};
+use rustc_hir::{HirId, ItemId, ItemKind, Mod};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{sym, Span};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Triggers if an item is declared after the testing module marked with `#[cfg(test)]`.
+ /// ### Why is this bad?
+ /// Having items declared after the testing module is confusing and may lead to bad test coverage.
+ /// ### Example
+ /// ```rust
+ /// #[cfg(test)]
+ /// mod tests {
+ /// // [...]
+ /// }
+ ///
+ /// fn my_function() {
+ /// // [...]
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// fn my_function() {
+ /// // [...]
+ /// }
+ ///
+ /// #[cfg(test)]
+ /// mod tests {
+ /// // [...]
+ /// }
+ /// ```
+ #[clippy::version = "1.70.0"]
+ pub ITEMS_AFTER_TEST_MODULE,
+ style,
+ "An item was found after the testing module `tests`"
+}
+
+declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]);
+
+impl LateLintPass<'_> for ItemsAfterTestModule {
+ fn check_mod(&mut self, cx: &LateContext<'_>, _: &Mod<'_>, _: HirId) {
+ let mut was_test_mod_visited = false;
+ let mut test_mod_span: Option<Span> = None;
+
+ let hir = cx.tcx.hir();
+ let items = hir.items().collect::<Vec<ItemId>>();
+
+ for (i, itid) in items.iter().enumerate() {
+ let item = hir.item(*itid);
+
+ if_chain! {
+ if was_test_mod_visited;
+ if i == (items.len() - 3 /* Weird magic number (HIR-translation behaviour) */);
+ if cx.sess().source_map().lookup_char_pos(item.span.lo()).file.name_hash
+ == cx.sess().source_map().lookup_char_pos(test_mod_span.unwrap().lo()).file.name_hash; // Will never fail
+ if !matches!(item.kind, ItemKind::Mod(_));
+ if !is_in_cfg_test(cx.tcx, itid.hir_id()); // The item isn't in the testing module itself
+ if !in_external_macro(cx.sess(), item.span);
+ if !is_from_proc_macro(cx, item);
+
+ then {
+ span_lint_and_help(cx, ITEMS_AFTER_TEST_MODULE, test_mod_span.unwrap().with_hi(item.span.hi()), "items were found after the testing module", None, "move the items to before the testing module was defined");
+ }};
+
+ if let ItemKind::Mod(module) = item.kind && item.span.hi() == module.spans.inner_span.hi() {
+ // Check that it works the same way, the only I way I've found for #10713
+ for attr in cx.tcx.get_attrs(item.owner_id.to_def_id(), sym::cfg) {
+ if_chain! {
+ if attr.has_name(sym::cfg);
+ if let Some(mitems) = attr.meta_item_list();
+ if let [mitem] = &*mitems;
+ if mitem.has_name(sym::test);
+ then {
+ was_test_mod_visited = true;
+ test_mod_span = Some(item.span);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs
index 1b0544813..0ca31033b 100644
--- a/src/tools/clippy/clippy_lints/src/large_futures.rs
+++ b/src/tools/clippy/clippy_lints/src/large_futures.rs
@@ -11,7 +11,7 @@ declare_clippy_lint! {
/// It checks for the size of a `Future` created by `async fn` or `async {}`.
///
/// ### Why is this bad?
- /// Due to the current [unideal implemention](https://github.com/rust-lang/rust/issues/69826) of `Generator`,
+ /// Due to the current [unideal implementation](https://github.com/rust-lang/rust/issues/69826) of `Generator`,
/// large size of a `Future` may cause stack overflows.
///
/// ### Example
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 0805b4b19..17bd89efa 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -168,25 +168,27 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
}
if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind {
+ // expr.span might contains parenthesis, see issue #10529
+ let actual_span = left.span.with_hi(right.span.hi());
match cmp {
BinOpKind::Eq => {
- check_cmp(cx, expr.span, left, right, "", 0); // len == 0
- check_cmp(cx, expr.span, right, left, "", 0); // 0 == len
+ check_cmp(cx, actual_span, left, right, "", 0); // len == 0
+ check_cmp(cx, actual_span, right, left, "", 0); // 0 == len
},
BinOpKind::Ne => {
- check_cmp(cx, expr.span, left, right, "!", 0); // len != 0
- check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len
+ check_cmp(cx, actual_span, left, right, "!", 0); // len != 0
+ check_cmp(cx, actual_span, right, left, "!", 0); // 0 != len
},
BinOpKind::Gt => {
- check_cmp(cx, expr.span, left, right, "!", 0); // len > 0
- check_cmp(cx, expr.span, right, left, "", 1); // 1 > len
+ check_cmp(cx, actual_span, left, right, "!", 0); // len > 0
+ check_cmp(cx, actual_span, right, left, "", 1); // 1 > len
},
BinOpKind::Lt => {
- check_cmp(cx, expr.span, left, right, "", 1); // len < 1
- check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len
+ check_cmp(cx, actual_span, left, right, "", 1); // len < 1
+ check_cmp(cx, actual_span, right, left, "!", 0); // 0 < len
},
- BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len >= 1
- BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 <= len
+ BinOpKind::Ge => check_cmp(cx, actual_span, left, right, "!", 1), // len >= 1
+ BinOpKind::Le => check_cmp(cx, actual_span, right, left, "!", 1), // 1 <= len
_ => (),
}
}
@@ -530,7 +532,7 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex
}
fn is_empty_string(expr: &Expr<'_>) -> bool {
- if let ExprKind::Lit(ref lit) = expr.kind {
+ if let ExprKind::Lit(lit) = expr.kind {
if let LitKind::Str(lit, _) = lit.node {
let lit = lit.as_str();
return lit.is_empty();
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 51b5de27d..e66141809 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,11 +1,14 @@
use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_from_proc_macro;
use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
use clippy_utils::{is_must_use_func_call, paths};
use rustc_hir::{Local, PatKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::IsSuggestable;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{BytePos, Span};
declare_clippy_lint! {
/// ### What it does
@@ -137,7 +140,7 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
];
impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
- fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
+ fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) {
if !in_external_macro(cx.tcx.sess, local.span)
&& let PatKind::Wild = local.pat.kind
&& let Some(init) = local.init
@@ -189,13 +192,31 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
if local.pat.default_binding_modes && local.ty.is_none() {
// When `default_binding_modes` is true, the `let` keyword is present.
- span_lint_and_help(
+
+ // Ignore unnameable types
+ if let Some(init) = local.init
+ && !cx.typeck_results().expr_ty(init).is_suggestable(cx.tcx, true)
+ {
+ return;
+ }
+
+ // Ignore if it is from a procedural macro...
+ if is_from_proc_macro(cx, init) {
+ return;
+ }
+
+ span_lint_and_help(
cx,
LET_UNDERSCORE_UNTYPED,
local.span,
"non-binding `let` without a type annotation",
- None,
- "consider adding a type annotation or removing the `let` keyword",
+ Some(
+ Span::new(local.pat.span.hi(),
+ local.pat.span.hi() + BytePos(1),
+ local.pat.span.ctxt(),
+ local.pat.span.parent()
+ )),
+ "consider adding a type annotation",
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
index c01e3882d..a677fcc41 100644
--- a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
@@ -1,4 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet;
use rustc_hir::{Local, TyKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
@@ -25,14 +26,21 @@ declare_clippy_lint! {
declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]);
impl LateLintPass<'_> for UnderscoreTyped {
- fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
+ fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
if_chain! {
if !in_external_macro(cx.tcx.sess, local.span);
if let Some(ty) = local.ty; // Ensure that it has a type defined
if let TyKind::Infer = &ty.kind; // that type is '_'
if local.span.ctxt() == ty.span.ctxt();
then {
- span_lint_and_help(cx,
+ // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized,
+ // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty`
+ if snippet(cx, ty.span, "_").trim() != "_" {
+ return;
+ }
+
+ span_lint_and_help(
+ cx,
LET_WITH_TYPE_UNDERSCORE,
local.span,
"variable declared with type underscore",
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index b0ec14855..b442a4ac5 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -94,6 +94,7 @@ mod crate_in_macro_def;
mod create_dir;
mod dbg_macro;
mod default;
+mod default_constructed_unit_structs;
mod default_instead_of_iter_empty;
mod default_numeric_fallback;
mod default_union_representation;
@@ -158,6 +159,7 @@ mod int_plus_one;
mod invalid_upcast_comparisons;
mod invalid_utf8_in_unchecked;
mod items_after_statements;
+mod items_after_test_module;
mod iter_not_returning_iterator;
mod large_const_arrays;
mod large_enum_variant;
@@ -264,6 +266,7 @@ mod redundant_pub_crate;
mod redundant_slicing;
mod redundant_static_lifetimes;
mod ref_option_ref;
+mod ref_patterns;
mod reference;
mod regex;
mod return_self_not_must_use;
@@ -329,8 +332,11 @@ mod zero_div_zero;
mod zero_sized_map_values;
// end lints modules, do not remove this comment, it’s used in `update_lints`
-use crate::utils::conf::{format_error, TryConf};
pub use crate::utils::conf::{lookup_conf_file, Conf};
+use crate::utils::{
+ conf::{format_error, metadata::get_configuration_metadata, TryConf},
+ FindAll,
+};
/// Register all pre expansion lints
///
@@ -352,7 +358,7 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
pub fn read_conf(sess: &Session, path: &io::Result<(Option<PathBuf>, Vec<String>)>) -> Conf {
if let Ok((_, warnings)) = path {
for warning in warnings {
- sess.warn(warning);
+ sess.warn(warning.clone());
}
}
let file_name = match path {
@@ -469,7 +475,22 @@ pub(crate) struct LintInfo {
pub fn explain(name: &str) {
let target = format!("clippy::{}", name.to_ascii_uppercase());
match declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
- Some(info) => print!("{}", info.explanation),
+ Some(info) => {
+ println!("{}", info.explanation);
+ // Check if the lint has configuration
+ let mdconf = get_configuration_metadata();
+ if let Some(config_vec_positions) = mdconf
+ .iter()
+ .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
+ {
+ // If it has, print it
+ println!("### Configuration for {}:\n", info.lint.name_lower());
+ for position in config_vec_positions {
+ let conf = &mdconf[position];
+ println!(" - {}: {} (default: {})", conf.name, conf.doc, conf.default);
+ }
+ }
+ },
None => println!("unknown lint: {name}"),
}
}
@@ -932,7 +953,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
- store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock));
+ let semicolon_inside_block_ignore_singleline = conf.semicolon_inside_block_ignore_singleline;
+ let semicolon_outside_block_ignore_multiline = conf.semicolon_outside_block_ignore_multiline;
+ store.register_late_pass(move |_| {
+ Box::new(semicolon_block::SemicolonBlock::new(
+ semicolon_inside_block_ignore_singleline,
+ semicolon_outside_block_ignore_multiline,
+ ))
+ });
store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
@@ -950,15 +978,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
+ let unnecessary_box_size = conf.unnecessary_box_size;
store.register_late_pass(move |_| {
Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new(
avoid_breaking_exported_api,
+ unnecessary_box_size,
))
});
store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk));
store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule));
store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
+ store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule));
+ store.register_early_pass(|| Box::new(ref_patterns::RefPatterns));
+ store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs));
// add lints here, do not remove this comment, it's used in `new_lint`
}
diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
index b0f927647..09b2032e2 100644
--- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -10,7 +10,7 @@ use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
- /// Detect uses of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)`
+ /// Checks for usage of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)`
/// when `lines` has type `std::io::Lines`.
///
/// ### Why is this bad?
@@ -25,7 +25,7 @@ declare_clippy_lint! {
///
/// ### Known problems
/// This lint suggests replacing `filter_map()` or `flat_map()` applied to a `Lines`
- /// instance in all cases. There two cases where the suggestion might not be
+ /// instance in all cases. There are two cases where the suggestion might not be
/// appropriate or necessary:
///
/// - If the `Lines` instance can never produce any error, or if an error is produced
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index c87fc4f90..d4c3f76b8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -15,7 +15,7 @@ use rustc_span::symbol::sym;
use std::fmt::Display;
use std::iter::Iterator;
-/// Checks for for loops that sequentially copy items from one slice-like
+/// Checks for `for` loops that sequentially copy items from one slice-like
/// object to another.
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
new file mode 100644
index 000000000..cb9c84be4
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
@@ -0,0 +1,110 @@
+use clippy_utils::{
+ diagnostics::{multispan_sugg_with_applicability, span_lint_and_then},
+ match_def_path, paths,
+ source::snippet,
+ SpanlessEq,
+};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp};
+use rustc_lint::LateContext;
+use rustc_span::Span;
+use std::borrow::Cow;
+
+use super::MANUAL_WHILE_LET_SOME;
+
+/// The kind of statement that the `pop()` call appeared in.
+///
+/// Depending on whether the value was assigned to a variable or not changes what pattern
+/// we use for the suggestion.
+#[derive(Copy, Clone)]
+enum PopStmt<'hir> {
+ /// `x.pop().unwrap()` was and assigned to a variable.
+ /// The pattern of this local variable will be used and the local statement
+ /// is deleted in the suggestion.
+ Local(&'hir Pat<'hir>),
+ /// `x.pop().unwrap()` appeared in an arbitrary expression and was not assigned to a variable.
+ /// The suggestion will use some placeholder identifier and the `x.pop().unwrap()` expression
+ /// is replaced with that identifier.
+ Anonymous,
+}
+
+fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>, loop_span: Span, receiver_span: Span) {
+ span_lint_and_then(
+ cx,
+ MANUAL_WHILE_LET_SOME,
+ pop_span,
+ "you seem to be trying to pop elements from a `Vec` in a loop",
+ |diag| {
+ let (pat, pop_replacement) = match pop_stmt_kind {
+ PopStmt::Local(pat) => (snippet(cx, pat.span, ".."), String::new()),
+ PopStmt::Anonymous => (Cow::Borrowed("element"), "element".into()),
+ };
+
+ let loop_replacement = format!("while let Some({}) = {}.pop()", pat, snippet(cx, receiver_span, ".."));
+ multispan_sugg_with_applicability(
+ diag,
+ "consider using a `while..let` loop",
+ Applicability::MachineApplicable,
+ [(loop_span, loop_replacement), (pop_span, pop_replacement)],
+ );
+ },
+ );
+}
+
+fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool {
+ if let ExprKind::MethodCall(..) = expr.kind
+ && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+ {
+ match_def_path(cx, id, method)
+ } else {
+ false
+ }
+}
+
+fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool {
+ if (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT))
+ && let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind
+ && match_method_call(cx, unwrap_recv, &paths::VEC_POP)
+ && let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind
+ {
+ // make sure they're the same `Vec`
+ SpanlessEq::new(cx).eq_expr(pop_recv, is_empty_recv)
+ } else {
+ false
+ }
+}
+
+fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) {
+ if let StmtKind::Local(local) = stmt.kind
+ && let Some(init) = local.init
+ && is_vec_pop_unwrap(cx, init, is_empty_recv)
+ {
+ report_lint(cx, stmt.span, PopStmt::Local(local.pat), loop_span, is_empty_recv.span);
+ }
+}
+
+fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) {
+ if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind {
+ if let ExprKind::MethodCall(.., args, _) | ExprKind::Call(_, args) = expr.kind {
+ let offending_arg = args
+ .iter()
+ .find_map(|arg| is_vec_pop_unwrap(cx, arg, is_empty_recv).then_some(arg.span));
+
+ if let Some(offending_arg) = offending_arg {
+ report_lint(cx, offending_arg, PopStmt::Anonymous, loop_span, is_empty_recv.span);
+ }
+ }
+ }
+}
+
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) {
+ if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind
+ && let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind
+ && match_method_call(cx, cond, &paths::VEC_IS_EMPTY)
+ && let ExprKind::Block(body, _) = body.kind
+ && let Some(stmt) = body.stmts.first()
+ {
+ check_local(cx, stmt, is_empty_recv, loop_span);
+ check_call_arguments(cx, stmt, is_empty_recv, loop_span);
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 610a0233e..f83ad388a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -7,6 +7,7 @@ mod iter_next_loop;
mod manual_find;
mod manual_flatten;
mod manual_memcpy;
+mod manual_while_let_some;
mod missing_spin_loop;
mod mut_range_bound;
mod needless_range_loop;
@@ -575,6 +576,36 @@ declare_clippy_lint! {
"manual implementation of `Iterator::find`"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Looks for loops that check for emptiness of a `Vec` in the condition and pop an element
+ /// in the body as a separate operation.
+ ///
+ /// ### Why is this bad?
+ /// Such loops can be written in a more idiomatic way by using a while-let loop and directly
+ /// pattern matching on the return value of `Vec::pop()`.
+ ///
+ /// ### Example
+ /// ```rust
+ /// let mut numbers = vec![1, 2, 3, 4, 5];
+ /// while !numbers.is_empty() {
+ /// let number = numbers.pop().unwrap();
+ /// // use `number`
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// let mut numbers = vec![1, 2, 3, 4, 5];
+ /// while let Some(number) = numbers.pop() {
+ /// // use `number`
+ /// }
+ /// ```
+ #[clippy::version = "1.70.0"]
+ pub MANUAL_WHILE_LET_SOME,
+ style,
+ "checking for emptiness of a `Vec` in the loop condition and popping an element in the body"
+}
+
declare_lint_pass!(Loops => [
MANUAL_MEMCPY,
MANUAL_FLATTEN,
@@ -594,6 +625,7 @@ declare_lint_pass!(Loops => [
SINGLE_ELEMENT_LOOP,
MISSING_SPIN_LOOP,
MANUAL_FIND,
+ MANUAL_WHILE_LET_SOME
]);
impl<'tcx> LateLintPass<'tcx> for Loops {
@@ -640,9 +672,10 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
while_let_on_iterator::check(cx, expr);
- if let Some(higher::While { condition, body }) = higher::While::hir(expr) {
+ if let Some(higher::While { condition, body, span }) = higher::While::hir(expr) {
while_immutable_condition::check(cx, condition, body);
missing_spin_loop::check(cx, condition, body);
+ manual_while_let_some::check(cx, condition, body, span);
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index 5c317c2a5..cb4465675 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -208,7 +208,7 @@ fn is_end_eq_array_len<'tcx>(
indexed_ty: Ty<'tcx>,
) -> bool {
if_chain! {
- if let ExprKind::Lit(ref lit) = end.kind;
+ if let ExprKind::Lit(lit) = end.kind;
if let ast::LitKind::Int(end_int, _) = lit.node;
if let ty::Array(_, arr_len_const) = indexed_ty.kind();
if let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env);
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 f0a1b1dfe..5f1fdf00b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -226,7 +226,8 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
| InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
})
.fold(NeverLoopResult::Otherwise, combine_seq),
- ExprKind::Yield(_, _)
+ ExprKind::OffsetOf(_, _)
+ | ExprKind::Yield(_, _)
| ExprKind::Closure { .. }
| ExprKind::Path(_)
| ExprKind::ConstBlock(_)
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index ce5d657bc..45ea5aab4 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
};
let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});");
- // we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block
+ // we show to the user the suggestion without the comments, but when applying the fix, include the comments in the block
span_lint_and_then(
cx,
MANUAL_ASSERT,
diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs
index bc815dc4a..4629b22d1 100644
--- a/src/tools/clippy/clippy_lints/src/manual_bits.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs
@@ -13,7 +13,7 @@ use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
- /// Checks for uses of `std::mem::size_of::<T>() * 8` when
+ /// Checks for usage of `std::mem::size_of::<T>() * 8` when
/// `T::BITS` is available.
///
/// ### Why is this bad?
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 98e698c6c..3f8b42ffe 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -38,7 +38,6 @@ declare_clippy_lint! {
/// Could be written:
///
/// ```rust
- /// # #![feature(let_else)]
/// # fn main () {
/// # let w = Some(0);
/// let Some(v) = w else { return };
@@ -69,29 +68,23 @@ impl_lint_pass!(ManualLetElse => [MANUAL_LET_ELSE]);
impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
- let if_let_or_match = if_chain! {
- if self.msrv.meets(msrvs::LET_ELSE);
- if !in_external_macro(cx.sess(), stmt.span);
- if let StmtKind::Local(local) = stmt.kind;
- if let Some(init) = local.init;
- if local.els.is_none();
- if local.ty.is_none();
- if init.span.ctxt() == stmt.span.ctxt();
- if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init);
- then {
- if_let_or_match
- } else {
- return;
- }
- };
+ if !self.msrv.meets(msrvs::LET_ELSE) || in_external_macro(cx.sess(), stmt.span) {
+ return;
+ }
+ if let StmtKind::Local(local) = stmt.kind &&
+ let Some(init) = local.init &&
+ local.els.is_none() &&
+ local.ty.is_none() &&
+ init.span.ctxt() == stmt.span.ctxt() &&
+ let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) {
match if_let_or_match {
IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! {
if expr_is_simple_identity(let_pat, if_then);
if let Some(if_else) = if_else;
if expr_diverges(cx, if_else);
then {
- emit_manual_let_else(cx, stmt.span, if_let_expr, let_pat, if_else);
+ emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else);
}
},
IfLetOrMatch::Match(match_expr, arms, source) => {
@@ -101,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
if source != MatchSource::Normal {
return;
}
- // Any other number than two arms doesn't (neccessarily)
+ // Any other number than two arms doesn't (necessarily)
// have a trivial mapping to let else.
if arms.len() != 2 {
return;
@@ -128,15 +121,23 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
return;
}
- emit_manual_let_else(cx, stmt.span, match_expr, pat_arm.pat, diverging_arm.body);
+ emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body);
},
}
+ };
}
extract_msrv_attr!(LateContext);
}
-fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat: &Pat<'_>, else_body: &Expr<'_>) {
+fn emit_manual_let_else(
+ cx: &LateContext<'_>,
+ span: Span,
+ expr: &Expr<'_>,
+ local: &Pat<'_>,
+ pat: &Pat<'_>,
+ else_body: &Expr<'_>,
+) {
span_lint_and_then(
cx,
MANUAL_LET_ELSE,
@@ -145,12 +146,11 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
|diag| {
// This is far from perfect, for example there needs to be:
// * mut additions for the bindings
- // * renamings of the bindings
+ // * renamings of the bindings for `PatKind::Or`
// * unused binding collision detection with existing ones
// * putting patterns with at the top level | inside ()
// for this to be machine applicable.
let mut app = Applicability::HasPlaceholders;
- let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app);
let (sn_else, _) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app);
@@ -159,10 +159,21 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
} else {
format!("{{ {sn_else} }}")
};
- let sn_bl = if matches!(pat.kind, PatKind::Or(..)) {
- format!("({sn_pat})")
- } else {
- sn_pat.into_owned()
+ let sn_bl = match pat.kind {
+ PatKind::Or(..) => {
+ let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+ format!("({sn_pat})")
+ },
+ // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
+ PatKind::TupleStruct(ref w, args, ..) if args.len() == 1 => {
+ let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default();
+ let (sn_inner, _) = snippet_with_context(cx, local.span, span.ctxt(), "", &mut app);
+ format!("{sn_wrapper}({sn_inner})")
+ },
+ _ => {
+ let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+ sn_pat.into_owned()
+ },
};
let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
diag.span_suggestion(span, "consider writing", sugg, app);
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index 72cdb9c17..5259066eb 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -46,7 +46,7 @@ declare_clippy_lint! {
#[clippy::version = "1.64.0"]
pub MANUAL_RETAIN,
perf,
- "`retain()` is simpler and the same functionalitys"
+ "`retain()` is simpler and the same functionalities"
}
pub struct ManualRetain {
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 92ee79453..703a6b258 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
@@ -1,5 +1,7 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::{expr_or_init, in_constant};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_context;
+use clippy_utils::{expr_or_init, in_constant, std_or_core};
+use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
@@ -38,19 +40,27 @@ declare_lint_pass!(ManualSliceSizeCalculation => [MANUAL_SLICE_SIZE_CALCULATION]
impl<'tcx> LateLintPass<'tcx> for ManualSliceSizeCalculation {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
- // Does not apply inside const because size_of_value is not cost in stable.
+ // Does not apply inside const because size_of_val is not cost in stable.
if !in_constant(cx, expr.hir_id)
&& let ExprKind::Binary(ref op, left, right) = expr.kind
&& BinOpKind::Mul == op.node
- && let Some(_receiver) = simplify(cx, left, right)
+ && !expr.span.from_expansion()
+ && let Some(receiver) = simplify(cx, left, right)
{
- span_lint_and_help(
+ let ctxt = expr.span.ctxt();
+ let mut app = Applicability::MachineApplicable;
+ let val_name = snippet_with_context(cx, receiver.span, ctxt, "slice", &mut app).0;
+ let Some(sugg) = std_or_core(cx) else { return };
+
+ span_lint_and_sugg(
cx,
MANUAL_SLICE_SIZE_CALCULATION,
expr.span,
"manual slice size calculation",
- None,
- "consider using std::mem::size_of_value instead");
+ "try",
+ format!("{sugg}::mem::size_of_val({val_name})"),
+ app,
+ );
}
}
}
@@ -71,9 +81,9 @@ fn simplify_half<'tcx>(
expr1: &'tcx Expr<'tcx>,
expr2: &'tcx Expr<'tcx>,
) -> Option<&'tcx Expr<'tcx>> {
- if
+ if !expr1.span.from_expansion()
// expr1 is `[T1].len()`?
- let ExprKind::MethodCall(method_path, receiver, _, _) = expr1.kind
+ && let ExprKind::MethodCall(method_path, receiver, _, _) = expr1.kind
&& method_path.ident.name == sym::len
&& let receiver_ty = cx.typeck_results().expr_ty(receiver)
&& let ty::Slice(ty1) = receiver_ty.peel_refs().kind()
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index c795c1d9a..93d977a5c 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -144,7 +144,7 @@ fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx E
// Returns the length of the `expr` if it's a constant string or char.
fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
- let (value, _) = constant(cx, cx.typeck_results(), expr)?;
+ let value = constant(cx, cx.typeck_results(), expr)?;
match value {
Constant::Str(value) => Some(value.len() as u128),
Constant::Char(value) => Some(value.len_utf8() as u128),
@@ -159,7 +159,7 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t
..
}) = expr.kind
{
- constant_length(cx, pattern).map_or(false, |length| length == n)
+ constant_length(cx, pattern).map_or(false, |length| length == *n)
} else {
len_arg(cx, expr).map_or(false, |arg| eq_expr_value(cx, pattern, arg))
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
index df1e585f1..69105ff0d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
@@ -22,7 +22,7 @@ pub(crate) fn check(cx: &LateContext<'_>, scrutinee: &Expr<'_>, arms: &[Arm<'_>]
if arms.len() == 2 {
// no guards
let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
- if let ExprKind::Lit(ref lit) = arm_bool.kind {
+ if let ExprKind::Lit(lit) = arm_bool.kind {
match lit.node {
LitKind::Bool(true) => Some((arms[0].body, arms[1].body)),
LitKind::Bool(false) => Some((arms[1].body, arms[0].body)),
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 107fad323..0064619ef 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -1,10 +1,12 @@
+use super::REDUNDANT_PATTERN_MATCHING;
use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_lint_allowed;
use clippy_utils::is_wild;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::span_contains_comment;
use rustc_ast::{Attribute, LitKind};
use rustc_errors::Applicability;
-use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat};
+use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat, PatKind, QPath};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::ty;
use rustc_span::source_map::Spanned;
@@ -99,6 +101,14 @@ where
}
}
+ for arm in iter_without_last.clone() {
+ if let Some(pat) = arm.1 {
+ if !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) && is_some(pat.kind) {
+ return false;
+ }
+ }
+ }
+
// The suggestion may be incorrect, because some arms can have `cfg` attributes
// evaluated into `false` and so such arms will be stripped before.
let mut applicability = Applicability::MaybeIncorrect;
@@ -162,7 +172,7 @@ fn find_bool_lit(ex: &ExprKind<'_>) -> Option<bool> {
node: LitKind::Bool(b), ..
}) = exp.kind
{
- Some(b)
+ Some(*b)
} else {
None
}
@@ -170,3 +180,13 @@ fn find_bool_lit(ex: &ExprKind<'_>) -> Option<bool> {
_ => None,
}
}
+
+fn is_some(path_kind: PatKind<'_>) -> bool {
+ match path_kind {
+ PatKind::TupleStruct(QPath::Resolved(_, path), [first, ..], _) if is_wild(first) => {
+ let name = path.segments[0].ident;
+ name.name == rustc_span::sym::Some
+ },
+ _ => false,
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index 158e6caa4..ae8262ace 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -282,7 +282,7 @@ impl<'a> NormalizedPat<'a> {
// TODO: Handle negative integers. They're currently treated as a wild match.
ExprKind::Lit(lit) => match lit.node {
LitKind::Str(sym, _) => Self::LitStr(sym),
- LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes),
+ LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
LitKind::Byte(val) => Self::LitInt(val.into()),
LitKind::Char(val) => Self::LitInt(val.into()),
LitKind::Int(val, _) => Self::LitInt(val),
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 97ecca450..55ec9d447 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -25,9 +25,9 @@ mod wild_in_or_pats;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet_opt, walk_span_to_context};
-use clippy_utils::{higher, in_constant, is_span_match};
+use clippy_utils::{higher, in_constant, is_span_match, tokenize_with_text};
use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::TokenKind;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -843,7 +843,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `Err(x)?`.
+ /// Checks for usage of `Err(x)?`.
///
/// ### Why is this bad?
/// The `?` operator is designed to allow calls that
@@ -878,7 +878,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `match` which could be implemented using `map`
+ /// Checks for usage of `match` which could be implemented using `map`
///
/// ### Why is this bad?
/// Using the `map` method is clearer and more concise.
@@ -902,7 +902,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `match` which could be implemented using `filter`
+ /// Checks for usage of `match` which could be implemented using `filter`
///
/// ### Why is this bad?
/// Using the `filter` method is clearer and more concise.
@@ -1147,12 +1147,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
// Assume true. This would require either an invalid span, or one which crosses file boundaries.
return true;
};
- let mut pos = 0usize;
- let mut iter = tokenize(&snip).map(|t| {
- let start = pos;
- pos += t.len as usize;
- (t.kind, start..pos)
- });
+ let mut iter = tokenize_with_text(&snip);
// Search for the token sequence [`#`, `[`, `cfg`]
while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) {
@@ -1163,7 +1158,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
)
});
if matches!(iter.next(), Some((TokenKind::OpenBracket, _)))
- && matches!(iter.next(), Some((TokenKind::Ident, range)) if &snip[range.clone()] == "cfg")
+ && matches!(iter.next(), Some((TokenKind::Ident, "cfg")))
{
return true;
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index ae69ca8a3..abf2525a6 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -34,7 +34,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
if let Arm { pat, guard: None, .. } = *arm {
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
let lhs_const = match lhs {
- Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
+ Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
None => {
let min_val_const = ty.numeric_min_val(cx.tcx)?;
let min_constant = mir::ConstantKind::from_value(
@@ -45,7 +45,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
},
};
let rhs_const = match rhs {
- Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
+ Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
None => {
let max_val_const = ty.numeric_max_val(cx.tcx)?;
let max_constant = mir::ConstantKind::from_value(
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index 7b609ff3d..e81e09da4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -63,8 +63,11 @@ fn find_sugg_for_if_let<'tcx>(
// Determine which function should be used, and the type contained by the corresponding
// variant.
let (good_method, inner_ty) = match check_pat.kind {
- PatKind::TupleStruct(ref qpath, [sub_pat], _) => {
- if let PatKind::Wild = sub_pat.kind {
+ PatKind::TupleStruct(ref qpath, args, rest) => {
+ let is_wildcard = matches!(args.first().map(|p| &p.kind), Some(PatKind::Wild));
+ let is_rest = matches!((args, rest.as_opt_usize()), ([], Some(_)));
+
+ if is_wildcard || is_rest {
let res = cx.typeck_results().qpath_res(qpath, check_pat.hir_id);
let Some(id) = res.opt_def_id().map(|ctor_id| cx.tcx.parent(ctor_id)) else { return };
let lang_items = cx.tcx.lang_items();
@@ -186,73 +189,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
if arms.len() == 2 {
let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind);
- let found_good_method = match node_pair {
- (
- PatKind::TupleStruct(ref path_left, patterns_left, _),
- PatKind::TupleStruct(ref path_right, patterns_right, _),
- ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
- if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
- find_good_method_for_match(
- cx,
- arms,
- path_left,
- path_right,
- Item::Lang(ResultOk),
- Item::Lang(ResultErr),
- "is_ok()",
- "is_err()",
- )
- .or_else(|| {
- find_good_method_for_match(
- cx,
- arms,
- path_left,
- path_right,
- Item::Diag(sym::IpAddr, sym!(V4)),
- Item::Diag(sym::IpAddr, sym!(V6)),
- "is_ipv4()",
- "is_ipv6()",
- )
- })
- } else {
- None
- }
- },
- (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
- | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
- if patterns.len() == 1 =>
- {
- if let PatKind::Wild = patterns[0].kind {
- find_good_method_for_match(
- cx,
- arms,
- path_left,
- path_right,
- Item::Lang(OptionSome),
- Item::Lang(OptionNone),
- "is_some()",
- "is_none()",
- )
- .or_else(|| {
- find_good_method_for_match(
- cx,
- arms,
- path_left,
- path_right,
- Item::Lang(PollReady),
- Item::Lang(PollPending),
- "is_ready()",
- "is_pending()",
- )
- })
- } else {
- None
- }
- },
- _ => None,
- };
-
- if let Some(good_method) = found_good_method {
+ if let Some(good_method) = found_good_method(cx, arms, node_pair) {
let span = expr.span.to(op.span);
let result_expr = match &op.kind {
ExprKind::AddrOf(_, _, borrowed) => borrowed,
@@ -276,6 +213,127 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
}
}
+fn found_good_method<'a>(
+ cx: &LateContext<'_>,
+ arms: &[Arm<'_>],
+ node: (&PatKind<'_>, &PatKind<'_>),
+) -> Option<&'a str> {
+ match node {
+ (
+ PatKind::TupleStruct(ref path_left, patterns_left, _),
+ PatKind::TupleStruct(ref path_right, patterns_right, _),
+ ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
+ if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
+ find_good_method_for_match(
+ cx,
+ arms,
+ path_left,
+ path_right,
+ Item::Lang(ResultOk),
+ Item::Lang(ResultErr),
+ "is_ok()",
+ "is_err()",
+ )
+ .or_else(|| {
+ find_good_method_for_match(
+ cx,
+ arms,
+ path_left,
+ path_right,
+ Item::Diag(sym::IpAddr, sym!(V4)),
+ Item::Diag(sym::IpAddr, sym!(V6)),
+ "is_ipv4()",
+ "is_ipv6()",
+ )
+ })
+ } else {
+ None
+ }
+ },
+ (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
+ | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
+ if patterns.len() == 1 =>
+ {
+ if let PatKind::Wild = patterns[0].kind {
+ find_good_method_for_match(
+ cx,
+ arms,
+ path_left,
+ path_right,
+ Item::Lang(OptionSome),
+ Item::Lang(OptionNone),
+ "is_some()",
+ "is_none()",
+ )
+ .or_else(|| {
+ find_good_method_for_match(
+ cx,
+ arms,
+ path_left,
+ path_right,
+ Item::Lang(PollReady),
+ Item::Lang(PollPending),
+ "is_ready()",
+ "is_pending()",
+ )
+ })
+ } else {
+ None
+ }
+ },
+ (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Wild) if patterns.len() == 1 => {
+ if let PatKind::Wild = patterns[0].kind {
+ get_good_method(cx, arms, path_left)
+ } else {
+ None
+ }
+ },
+ (PatKind::Path(ref path_left), PatKind::Wild) => get_good_method(cx, arms, path_left),
+ _ => None,
+ }
+}
+
+fn get_ident(path: &QPath<'_>) -> Option<rustc_span::symbol::Ident> {
+ match path {
+ QPath::Resolved(_, path) => {
+ let name = path.segments[0].ident;
+ Some(name)
+ },
+ _ => None,
+ }
+}
+
+fn get_good_method<'a>(cx: &LateContext<'_>, arms: &[Arm<'_>], path_left: &QPath<'_>) -> Option<&'a str> {
+ if let Some(name) = get_ident(path_left) {
+ return match name.as_str() {
+ "Ok" => {
+ find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultOk), "is_ok()", "is_err()")
+ },
+ "Err" => {
+ find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultErr), "is_err()", "is_ok()")
+ },
+ "Some" => find_good_method_for_matches_macro(
+ cx,
+ arms,
+ path_left,
+ Item::Lang(OptionSome),
+ "is_some()",
+ "is_none()",
+ ),
+ "None" => find_good_method_for_matches_macro(
+ cx,
+ arms,
+ path_left,
+ Item::Lang(OptionNone),
+ "is_none()",
+ "is_some()",
+ ),
+ _ => None,
+ };
+ }
+ None
+}
+
#[derive(Clone, Copy)]
enum Item {
Lang(LangItem),
@@ -286,10 +344,11 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
let Some(id) = cx.typeck_results().qpath_res(path, pat.hir_id).opt_def_id() else { return false };
match expected_item {
- Item::Lang(expected_lang_item) => {
- let expected_id = cx.tcx.lang_items().require(expected_lang_item).unwrap();
- cx.tcx.parent(id) == expected_id
- },
+ Item::Lang(expected_lang_item) => cx
+ .tcx
+ .lang_items()
+ .get(expected_lang_item)
+ .map_or(false, |expected_id| cx.tcx.parent(id) == expected_id),
Item::Diag(expected_ty, expected_variant) => {
let ty = cx.typeck_results().pat_ty(pat);
@@ -334,7 +393,33 @@ fn find_good_method_for_match<'a>(
};
match body_node_pair {
- (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) {
+ (ExprKind::Lit(lit_left), ExprKind::Lit(lit_right)) => match (&lit_left.node, &lit_right.node) {
+ (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left),
+ (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right),
+ _ => None,
+ },
+ _ => None,
+ }
+}
+
+fn find_good_method_for_matches_macro<'a>(
+ cx: &LateContext<'_>,
+ arms: &[Arm<'_>],
+ path_left: &QPath<'_>,
+ expected_item_left: Item,
+ should_be_left: &'a str,
+ should_be_right: &'a str,
+) -> Option<&'a str> {
+ let first_pat = arms[0].pat;
+
+ let body_node_pair = if is_pat_variant(cx, first_pat, path_left, expected_item_left) {
+ (&arms[0].body.kind, &arms[1].body.kind)
+ } else {
+ return None;
+ };
+
+ match body_node_pair {
+ (ExprKind::Lit(lit_left), ExprKind::Lit(lit_right)) => match (&lit_left.node, &lit_right.node) {
(LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left),
(LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right),
_ => None,
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 04225beeb..794527539 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -342,6 +342,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
ExprKind::DropTemps(_) |
ExprKind::Err(_) |
ExprKind::InlineAsm(_) |
+ ExprKind::OffsetOf(_, _) |
ExprKind::Let(_) |
ExprKind::Lit(_) |
ExprKind::Loop(_, _, _, _) |
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
index 27a05337a..8984b2cf8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
@@ -18,7 +18,7 @@ pub(super) fn check(
) -> bool {
if_chain! {
if let Some(args) = method_chain_args(info.chain, chain_methods);
- if let hir::ExprKind::Lit(ref lit) = info.other.kind;
+ if let hir::ExprKind::Lit(lit) = info.other.kind;
if let ast::LitKind::Char(c) = lit.node;
then {
let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index 3795c0ec2..65fd50dff 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -1,7 +1,6 @@
-use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_node;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::sugg;
use clippy_utils::ty::is_copy;
use rustc_errors::Applicability;
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
@@ -9,7 +8,6 @@ use rustc_lint::LateContext;
use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths};
use rustc_span::symbol::{sym, Symbol};
-use super::CLONE_DOUBLE_REF;
use super::CLONE_ON_COPY;
/// Checks for the `CLONE_ON_COPY` lint.
@@ -42,41 +40,7 @@ pub(super) fn check(
let ty = cx.typeck_results().expr_ty(expr);
if let ty::Ref(_, inner, _) = arg_ty.kind() {
- if let ty::Ref(_, innermost, _) = inner.kind() {
- span_lint_and_then(
- cx,
- CLONE_DOUBLE_REF,
- expr.span,
- &with_forced_trimmed_paths!(format!(
- "using `clone` on a double-reference; \
- this will copy the reference of type `{ty}` instead of cloning the inner type"
- )),
- |diag| {
- if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
- let mut ty = innermost;
- let mut n = 0;
- while let ty::Ref(_, inner, _) = ty.kind() {
- ty = inner;
- n += 1;
- }
- let refs = "&".repeat(n + 1);
- let derefs = "*".repeat(n);
- let explicit = with_forced_trimmed_paths!(format!("<{refs}{ty}>::clone({snip})"));
- diag.span_suggestion(
- expr.span,
- "try dereferencing it",
- with_forced_trimmed_paths!(format!("{refs}({derefs}{}).clone()", snip.deref())),
- Applicability::MaybeIncorrect,
- );
- diag.span_suggestion(
- expr.span,
- "or try being explicit if you are sure, that you want to clone a reference",
- explicit,
- Applicability::MaybeIncorrect,
- );
- }
- },
- );
+ if let ty::Ref(..) = inner.kind() {
return; // don't report clone_on_copy
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
index 83c1bf203..e2029da80 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal
if let hir::ExprKind::Index(caller_var, index_expr) = &caller_expr.kind;
if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen })
= higher::Range::hir(index_expr);
- if let hir::ExprKind::Lit(ref start_lit) = &start_expr.kind;
+ if let hir::ExprKind::Lit(start_lit) = &start_expr.kind;
if let ast::LitKind::Int(start_idx, _) = start_lit.node;
then {
let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
index c830958d5..d1609eebf 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
@@ -13,7 +13,7 @@ use super::ITER_NTH_ZERO;
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
if_chain! {
if is_trait_method(cx, expr, sym::Iterator);
- if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg);
+ if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg);
then {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
index 64c09214a..b631cd00c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -9,7 +9,7 @@ use super::ITERATOR_STEP_BY_ZERO;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
if is_trait_method(cx, expr, sym::Iterator) {
- if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg) {
+ if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) {
span_lint(
cx,
ITERATOR_STEP_BY_ZERO,
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
new file mode 100644
index 000000000..5f3fec538
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_trait_method;
+use clippy_utils::ty::implements_trait;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_span::symbol::sym;
+
+pub(super) fn check<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx Expr<'_>,
+ rev_call: &'tcx Expr<'_>,
+ rev_recv: &'tcx Expr<'_>,
+) {
+ let rev_recv_ty = cx.typeck_results().expr_ty(rev_recv);
+
+ // check that the receiver of `rev` implements `DoubleEndedIterator` and
+ // that `rev` and `next` come from `Iterator`
+ if cx
+ .tcx
+ .get_diagnostic_item(sym::DoubleEndedIterator)
+ .map_or(false, |double_ended_iterator| {
+ implements_trait(cx, rev_recv_ty, double_ended_iterator, &[])
+ })
+ && is_trait_method(cx, rev_call, sym::Iterator)
+ && is_trait_method(cx, expr, sym::Iterator)
+ {
+ span_lint_and_sugg(
+ cx,
+ super::MANUAL_NEXT_BACK,
+ expr.span.with_lo(rev_recv.span.hi()),
+ "manual backwards iteration",
+ "use",
+ String::from(".next_back()"),
+ 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 64bf55ba2..9a594d964 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -45,6 +45,7 @@ mod iter_overeager_cloned;
mod iter_skip_next;
mod iter_with_drain;
mod iterator_step_by_zero;
+mod manual_next_back;
mod manual_ok_or;
mod manual_saturating_arithmetic;
mod manual_str_repeat;
@@ -121,7 +122,7 @@ use rustc_span::{sym, Span};
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `cloned()` on an `Iterator` or `Option` where
+ /// Checks for usage of `cloned()` on an `Iterator` or `Option` where
/// `copied()` could be used instead.
///
/// ### Why is this bad?
@@ -201,7 +202,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `Iterator::flat_map()` where `filter_map()` could be
+ /// Checks for usage of `Iterator::flat_map()` where `filter_map()` could be
/// used instead.
///
/// ### Why is this bad?
@@ -441,7 +442,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and
+ /// Checks for usage of `_.unwrap_or_else(Default::default)` on `Option` and
/// `Result` values.
///
/// ### Why is this bad?
@@ -986,29 +987,6 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usage of `.clone()` on an `&&T`.
- ///
- /// ### Why is this bad?
- /// Cloning an `&&T` copies the inner `&T`, instead of
- /// cloning the underlying `T`.
- ///
- /// ### Example
- /// ```rust
- /// fn main() {
- /// let x = vec![1];
- /// let y = &&x;
- /// let z = y.clone();
- /// println!("{:p} {:p}", *y, z); // prints out the same pointer
- /// }
- /// ```
- #[clippy::version = "pre 1.29.0"]
- pub CLONE_DOUBLE_REF,
- correctness,
- "using `clone` on `&&T`"
-}
-
-declare_clippy_lint! {
- /// ### What it does
/// Checks for usage of `.to_string()` on an `&&T` where
/// `T` implements `ToString` directly (like `&&str` or `&&String`).
///
@@ -1194,7 +1172,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `.iter().nth()` (and the related
+ /// Checks for usage of `.iter().nth()` (and the related
/// `.iter_mut().nth()`) on standard library types with *O*(1) element access.
///
/// ### Why is this bad?
@@ -1221,7 +1199,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `.skip(x).next()` on iterators.
+ /// Checks for usage of `.skip(x).next()` on iterators.
///
/// ### Why is this bad?
/// `.nth(x)` is cleaner
@@ -1246,7 +1224,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `.drain(..)` on `Vec` and `VecDeque` for iteration.
+ /// Checks for usage of `.drain(..)` on `Vec` and `VecDeque` for iteration.
///
/// ### Why is this bad?
/// `.into_iter()` is simpler with better performance.
@@ -1271,7 +1249,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for using `x.get(x.len() - 1)` instead of
+ /// Checks for usage of `x.get(x.len() - 1)` instead of
/// `x.last()`.
///
/// ### Why is this bad?
@@ -1304,7 +1282,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `.get().unwrap()` (or
+ /// Checks for usage of `.get().unwrap()` (or
/// `.get_mut().unwrap`) on a standard library type which implements `Index`
///
/// ### Why is this bad?
@@ -1475,7 +1453,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for using `fold` when a more succinct alternative exists.
+ /// Checks for usage of `fold` when a more succinct alternative exists.
/// Specifically, this checks for `fold`s which could be replaced by `any`, `all`,
/// `sum` or `product`.
///
@@ -2161,7 +2139,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `str::splitn(2, _)`
+ /// Checks for usage of `str::splitn(2, _)`
///
/// ### Why is this bad?
/// `split_once` is both clearer in intent and slightly more efficient.
@@ -2197,7 +2175,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same.
+ /// Checks for usage of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same.
/// ### Why is this bad?
/// The function `split` is simpler and there is no performance difference in these cases, considering
/// that both functions return a lazy iterator.
@@ -2251,7 +2229,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `.collect::<Vec<String>>().join("")` on iterators.
+ /// Checks for usage of `.collect::<Vec<String>>().join("")` on iterators.
///
/// ### Why is this bad?
/// `.collect::<String>()` is more concise and might be more performant
@@ -2377,7 +2355,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `.then_some(..).unwrap_or(..)`
+ /// Checks for usage of `.then_some(..).unwrap_or(..)`
///
/// ### Why is this bad?
/// This can be written more clearly with `if .. else ..`
@@ -2553,7 +2531,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for using `x.get(0)` instead of
+ /// Checks for usage of `x.get(0)` instead of
/// `x.first()`.
///
/// ### Why is this bad?
@@ -2957,7 +2935,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Detects uses of `Vec::sort_by` passing in a closure
+ /// Checks for usage of `Vec::sort_by` passing in a closure
/// which compares the two arguments, either directly or indirectly.
///
/// ### Why is this bad?
@@ -3013,7 +2991,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of File::read_to_end and File::read_to_string.
+ /// Checks for usage of File::read_to_end and File::read_to_string.
///
/// ### Why is this bad?
/// `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values.
@@ -3155,8 +3133,11 @@ declare_clippy_lint! {
/// ### Example
/// ```rust
/// # let iterator = vec![1].into_iter();
- /// let len = iterator.clone().collect::<Vec<_>>().len();
- /// // should be
+ /// let len = iterator.collect::<Vec<_>>().len();
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # let iterator = vec![1].into_iter();
/// let len = iterator.count();
/// ```
#[clippy::version = "1.30.0"]
@@ -3185,7 +3166,7 @@ declare_clippy_lint! {
/// ```rust
/// std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap();
/// ```
- #[clippy::version = "1.67.0"]
+ #[clippy::version = "1.69.0"]
pub SUSPICIOUS_COMMAND_ARG_SPACE,
suspicious,
"single command line argument that looks like it should be multiple arguments"
@@ -3216,6 +3197,29 @@ declare_clippy_lint! {
"calling `drain` in order to `clear` a container"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for `.rev().next()` on a `DoubleEndedIterator`
+ ///
+ /// ### Why is this bad?
+ /// `.next_back()` is cleaner.
+ ///
+ /// ### Example
+ /// ```rust
+ /// # let foo = [0; 10];
+ /// foo.iter().rev().next();
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # let foo = [0; 10];
+ /// foo.iter().next_back();
+ /// ```
+ #[clippy::version = "1.71.0"]
+ pub MANUAL_NEXT_BACK,
+ style,
+ "manual reverse iteration of `DoubleEndedIterator`"
+}
+
pub struct Methods {
avoid_breaking_exported_api: bool,
msrv: Msrv,
@@ -3258,7 +3262,6 @@ impl_lint_pass!(Methods => [
CHARS_LAST_CMP,
CLONE_ON_COPY,
CLONE_ON_REF_PTR,
- CLONE_DOUBLE_REF,
COLLAPSIBLE_STR_REPLACE,
ITER_OVEREAGER_CLONED,
CLONED_INSTEAD_OF_COPIED,
@@ -3345,6 +3348,7 @@ impl_lint_pass!(Methods => [
NEEDLESS_COLLECT,
SUSPICIOUS_COMMAND_ARG_SPACE,
CLEAR_WITH_DRAIN,
+ MANUAL_NEXT_BACK,
]);
/// Extracts a method call name, args, and `Span` of the method name.
@@ -3500,8 +3504,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
let first_arg_span = first_arg_ty.span;
let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty);
let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id())
- .self_ty()
- .skip_binder();
+ .self_ty();
wrong_self_convention::check(
cx,
item.ident.name.as_str(),
@@ -3519,8 +3522,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
if let TraitItemKind::Fn(_, _) = item.kind;
let ret_ty = return_ty(cx, item.owner_id);
let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id())
- .self_ty()
- .skip_binder();
+ .self_ty();
if !ret_ty.contains(self_ty);
then {
@@ -3703,6 +3705,7 @@ impl Methods {
("iter", []) => iter_next_slice::check(cx, expr, recv2),
("skip", [arg]) => iter_skip_next::check(cx, expr, recv2, arg),
("skip_while", [_]) => skip_while_next::check(cx, expr),
+ ("rev", [])=> manual_next_back::check(cx, expr, recv, recv2),
_ => {},
}
}
@@ -3767,13 +3770,13 @@ impl Methods {
unnecessary_sort_by::check(cx, expr, recv, arg, true);
},
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
- if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+ if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
suspicious_splitn::check(cx, name, expr, recv, count);
str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv);
}
},
("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
- if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+ if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
suspicious_splitn::check(cx, name, expr, recv, count);
}
},
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 0b0c6adc5..6841aaf62 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -1,6 +1,5 @@
use super::NEEDLESS_COLLECT;
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
-use clippy_utils::higher;
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
@@ -8,6 +7,7 @@ use clippy_utils::{
can_move_expr_to_closure, get_enclosing_block, get_parent_node, is_trait_method, path_to_local, path_to_local_id,
CaptureKind,
};
+use clippy_utils::{fn_def_id, higher};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, MultiSpan};
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
@@ -16,7 +16,7 @@ use rustc_hir::{
};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, AssocKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
+use rustc_middle::ty::{self, AssocKind, Clause, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty};
use rustc_span::symbol::Ident;
use rustc_span::{sym, Span, Symbol};
@@ -32,6 +32,8 @@ pub(super) fn check<'tcx>(
if let Some(parent) = get_parent_node(cx.tcx, collect_expr.hir_id) {
match parent {
Node::Expr(parent) => {
+ check_collect_into_intoiterator(cx, parent, collect_expr, call_span, iter_expr);
+
if let ExprKind::MethodCall(name, _, args @ ([] | [_]), _) = parent.kind {
let mut app = Applicability::MachineApplicable;
let name = name.ident.as_str();
@@ -134,6 +136,68 @@ pub(super) fn check<'tcx>(
}
}
+/// checks for for collecting into a (generic) method or function argument
+/// taking an `IntoIterator`
+fn check_collect_into_intoiterator<'tcx>(
+ cx: &LateContext<'tcx>,
+ parent: &'tcx Expr<'tcx>,
+ collect_expr: &'tcx Expr<'tcx>,
+ call_span: Span,
+ iter_expr: &'tcx Expr<'tcx>,
+) {
+ if let Some(id) = fn_def_id(cx, parent) {
+ let args = match parent.kind {
+ ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => args,
+ _ => &[],
+ };
+ // find the argument index of the `collect_expr` in the
+ // function / method call
+ if let Some(arg_idx) = args.iter().position(|e| e.hir_id == collect_expr.hir_id).map(|i| {
+ if matches!(parent.kind, ExprKind::MethodCall(_, _, _, _)) {
+ i + 1
+ } else {
+ i
+ }
+ }) {
+ // extract the input types of the function/method call
+ // that contains `collect_expr`
+ let inputs = cx
+ .tcx
+ .liberate_late_bound_regions(id, cx.tcx.fn_sig(id).subst_identity())
+ .inputs();
+
+ // map IntoIterator generic bounds to their signature
+ // types and check whether the argument type is an
+ // `IntoIterator`
+ if cx
+ .tcx
+ .param_env(id)
+ .caller_bounds()
+ .into_iter()
+ .filter_map(|p| {
+ if let PredicateKind::Clause(Clause::Trait(t)) = p.kind().skip_binder()
+ && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) {
+ Some(t.self_ty())
+ } else {
+ None
+ }
+ })
+ .any(|ty| ty == inputs[arg_idx])
+ {
+ span_lint_and_sugg(
+ cx,
+ NEEDLESS_COLLECT,
+ call_span.with_lo(iter_expr.span.hi()),
+ NEEDLESS_COLLECT_MSG,
+ "remove this call",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ }
+}
+
/// Checks if the given method call matches the expected signature of `([&[mut]] self) -> bool`
fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
cx.typeck_results().type_dependent_def_id(call_id).map_or(false, |id| {
diff --git a/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs b/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
index 4d7427b26..eada530d6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
@@ -1,5 +1,3 @@
-// run-rustfix
-
use super::OBFUSCATED_IF_ELSE;
use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_with_applicability};
use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index c6a27cdd6..bd625a691 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -42,13 +42,13 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec
// Only proceed if this is a call on some object of type std::fs::OpenOptions
if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && !arguments.is_empty() {
let argument_option = match arguments[0].kind {
- ExprKind::Lit(ref span) => {
+ ExprKind::Lit(span) => {
if let Spanned {
node: LitKind::Bool(lit),
..
- } = *span
+ } = span
{
- if lit { Argument::True } else { Argument::False }
+ if *lit { Argument::True } else { Argument::False }
} else {
// The function is called with a literal which is not a boolean literal.
// This is theoretically possible, but not very likely.
diff --git a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
index e3f2de3cd..0284d9dea 100644
--- a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
@@ -15,7 +15,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::PathBuf);
- if let ExprKind::Lit(ref lit) = arg.kind;
+ if let ExprKind::Lit(lit) = arg.kind;
if let LitKind::Str(ref path_lit, _) = lit.node;
if let pushed_path = Path::new(path_lit.as_str());
if let Some(pushed_path_lit) = pushed_path.to_str();
diff --git a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
index a345ec813..bb4cdd2a6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_lang_item;
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(
recv: &'tcx Expr<'_>,
repeat_arg: &'tcx Expr<'_>,
) {
- if constant_context(cx, cx.typeck_results()).expr(repeat_arg) == Some(Constant::Int(1)) {
+ if constant(cx, cx.typeck_results(), repeat_arg) == Some(Constant::Int(1)) {
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
if ty.is_str() {
span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
index 361a3082f..c028e9543 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
@@ -38,7 +38,7 @@ fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)
match_def_path(cx, def_id, &paths::STD_IO_SEEK_FROM_CURRENT) {
// check if argument of `SeekFrom::Current` is `0`
if args.len() == 1 &&
- let ExprKind::Lit(ref lit) = args[0].kind &&
+ let ExprKind::Lit(lit) = args[0].kind &&
let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node {
return true
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
index 660b7049c..787e9e0eb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(
let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id() &&
match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START) &&
args1.len() == 1 &&
- let ExprKind::Lit(ref lit) = args1[0].kind &&
+ let ExprKind::Lit(lit) = args1[0].kind &&
let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
{
let method_call_span = expr.span.with_lo(name_span.lo());
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index d00708e82..5ea12c441 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -175,13 +175,13 @@ fn check_manual_split_once_indirect(
let remove_msg = format!("remove the `{iter_ident}` usages");
diag.span_suggestion(
first.span,
- &remove_msg,
+ remove_msg.clone(),
"",
app,
);
diag.span_suggestion(
second.span,
- &remove_msg,
+ remove_msg,
"",
app,
);
@@ -316,7 +316,7 @@ fn parse_iter_usage<'tcx>(
};
},
("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
- if let Some((Constant::Int(idx), _)) = constant(cx, cx.typeck_results(), idx_expr) {
+ if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) {
let span = if name.ident.as_str() == "nth" {
e.span
} else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index aa87dead3..5a3d12fd7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -78,7 +78,7 @@ pub(super) fn check(
}
// Check if the first argument to .fold is a suitable literal
- if let hir::ExprKind::Lit(ref lit) = init.kind {
+ if let hir::ExprKind::Lit(lit) = init.kind {
match lit.node {
ast::LitKind::Bool(false) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, "any", true),
ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true),
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 4c4c003ca..67b7d3691 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
@@ -385,6 +385,9 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
Node::Expr(parent_expr) => {
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
{
+ // FIXME: the `subst_identity()` below seems incorrect, since we eventually
+ // call `tcx.try_subst_and_normalize_erasing_regions` further down
+ // (i.e., we are explicitly not in the identity context).
let fn_sig = cx.tcx.fn_sig(callee_def_id).subst_identity().skip_binder();
if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
&& let Some(param_ty) = fn_sig.inputs().get(arg_index)
@@ -435,7 +438,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
let output_ty = fn_sig.output();
if output_ty.contains(*param_ty) {
if let Ok(new_ty) = cx.tcx.try_subst_and_normalize_erasing_regions(
- new_subst, cx.param_env, output_ty) {
+ new_subst, cx.param_env, EarlyBinder(output_ty)) {
expr = parent_expr;
ty = new_ty;
continue;
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 3752b9a94..303f01256 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -16,9 +16,12 @@ use rustc_span::source_map::{ExpnKind, Span};
use clippy_utils::sugg::Sugg;
use clippy_utils::{
- get_parent_expr, in_constant, is_integer_literal, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
+ get_parent_expr, in_constant, is_integer_literal, is_lint_allowed, is_no_std_crate, iter_input_pats,
+ last_path_segment, SpanlessEq,
};
+use crate::ref_patterns::REF_PATTERNS;
+
declare_clippy_lint! {
/// ### What it does
/// Checks for function arguments and let bindings denoted as
@@ -162,6 +165,10 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
return;
}
for arg in iter_input_pats(decl, body) {
+ // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
+ if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) {
+ return;
+ }
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind {
span_lint(
cx,
@@ -180,6 +187,8 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
if let StmtKind::Local(local) = stmt.kind;
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind;
if let Some(init) = local.init;
+ // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
+ if is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id);
then {
let ctxt = local.span.ctxt();
let mut app = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
index e99081ad0..1adecd2ca 100644
--- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
@@ -12,7 +12,7 @@ declare_clippy_lint! {
/// Checks if a provided method is used implicitly by a trait
/// implementation. A usage example would be a wrapper where every method
/// should perform some operation before delegating to the inner type's
- /// implemenation.
+ /// implementation.
///
/// This lint should typically be enabled on a specific trait `impl` item
/// rather than globally.
diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index 5418616de..2abdfacd2 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -59,7 +59,7 @@ declare_clippy_lint! {
/// unsafe { char::from_u32_unchecked(int_value) }
/// }
/// ```
- #[clippy::version = "1.68.0"]
+ #[clippy::version = "1.69.0"]
pub MULTIPLE_UNSAFE_OPS_PER_BLOCK,
restriction,
"more than one unsafe operation per `unsafe` block"
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index dc866ab63..99394b9e5 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -1,4 +1,4 @@
-//! Checks for uses of mutex where an atomic value could be used
+//! Checks for usage of mutex where an atomic value could be used
//!
//! This lint is **allow** by default
@@ -12,7 +12,7 @@ use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `Mutex<X>` where an atomic will do.
+ /// Checks for usage of `Mutex<X>` where an atomic will do.
///
/// ### Why is this bad?
/// Using a mutex just to make access to a plain bool or
@@ -49,7 +49,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of `Mutex<X>` where `X` is an integral
+ /// Checks for usage of `Mutex<X>` where `X` is an integral
/// type.
///
/// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index c87059bf6..62af42a39 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -3,10 +3,12 @@
//! This lint is **warn** by default
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
-use clippy_utils::higher;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
-use clippy_utils::{get_parent_node, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt};
+use clippy_utils::{
+ get_parent_node, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt, span_extract_comment,
+};
+use clippy_utils::{higher, SpanlessEq};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Node, UnOp};
@@ -77,7 +79,39 @@ declare_clippy_lint! {
"comparing a variable to a boolean, e.g., `if x == true` or `if x != true`"
}
-declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]);
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for expressions of the form `if c { x = true } else { x = false }`
+ /// (or vice versa) and suggest assigning the variable directly from the
+ /// condition.
+ ///
+ /// ### Why is this bad?
+ /// Redundant code.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// # fn must_keep(x: i32, y: i32) -> bool { x == y }
+ /// # let x = 32; let y = 10;
+ /// # let mut skip: bool;
+ /// if must_keep(x, y) {
+ /// skip = false;
+ /// } else {
+ /// skip = true;
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust,ignore
+ /// # fn must_keep(x: i32, y: i32) -> bool { x == y }
+ /// # let x = 32; let y = 10;
+ /// # let mut skip: bool;
+ /// skip = !must_keep(x, y);
+ /// ```
+ #[clippy::version = "1.69.0"]
+ pub NEEDLESS_BOOL_ASSIGN,
+ complexity,
+ "setting the same boolean variable in both branches of an if-statement"
+}
+declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL, NEEDLESS_BOOL_ASSIGN]);
fn condition_needs_parentheses(e: &Expr<'_>) -> bool {
let mut inner = e;
@@ -112,7 +146,7 @@ fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
use self::Expression::{Bool, RetBool};
- if e.span.from_expansion() {
+ if e.span.from_expansion() || !span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty() {
return;
}
if let Some(higher::If {
@@ -173,6 +207,28 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
_ => (),
}
}
+ if let Some((lhs_a, a)) = fetch_assign(then) &&
+ let Some((lhs_b, b)) = fetch_assign(r#else) &&
+ SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b)
+ {
+ let mut applicability = Applicability::MachineApplicable;
+ let cond = Sugg::hir_with_applicability(cx, cond, "..", &mut applicability);
+ let lhs = snippet_with_applicability(cx, lhs_a.span, "..", &mut applicability);
+ let sugg = if a == b {
+ format!("{cond}; {lhs} = {a:?};")
+ } else {
+ format!("{lhs} = {};", if a { cond } else { !cond })
+ };
+ span_lint_and_sugg(
+ cx,
+ NEEDLESS_BOOL_ASSIGN,
+ e.span,
+ "this if-then-else expression assigns a bool literal",
+ "you can reduce it to",
+ sugg,
+ applicability
+ );
+ }
}
}
}
@@ -369,10 +425,18 @@ fn fetch_bool_block(expr: &Expr<'_>) -> Option<Expression> {
}
fn fetch_bool_expr(expr: &Expr<'_>) -> Option<bool> {
- if let ExprKind::Lit(ref lit_ptr) = peel_blocks(expr).kind {
+ if let ExprKind::Lit(lit_ptr) = peel_blocks(expr).kind {
if let LitKind::Bool(value) = lit_ptr.node {
return Some(value);
}
}
None
}
+
+fn fetch_assign<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, bool)> {
+ if let ExprKind::Assign(lhs, rhs, _) = peel_blocks_with_stmt(expr).kind {
+ fetch_bool_expr(rhs).map(|b| (lhs, b))
+ } else {
+ None
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs b/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs
index 6e54b243c..da1b9d999 100644
--- a/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs
@@ -49,14 +49,14 @@ fn snippet_enclosed_in_parenthesis(snippet: &str) -> bool {
fn check_for_parens(cx: &LateContext<'_>, e: &Expr<'_>, is_start: bool) {
if is_start &&
- let ExprKind::Lit(ref literal) = e.kind &&
+ let ExprKind::Lit(literal) = e.kind &&
let ast::LitKind::Float(_sym, ast::LitFloatType::Unsuffixed) = literal.node
{
// don't check floating point literals on the start expression of a range
return;
}
if_chain! {
- if let ExprKind::Lit(ref literal) = e.kind;
+ if let ExprKind::Lit(literal) = e.kind;
// the indicator that parenthesis surround the literal is that the span of the expression and the literal differ
if (literal.span.data().hi - literal.span.data().lo) != (e.span.data().hi - e.span.data().lo);
// inspect the source code of the expression for parenthesis
diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
index ed3e2c6e7..db0e22842 100644
--- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
@@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply {
fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
if_chain! {
- if let ExprKind::Lit(ref l) = lit.kind;
+ if let ExprKind::Lit(l) = lit.kind;
if consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1);
if cx.typeck_results().expr_ty(exp).is_integral();
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 0bedab05e..58590df1f 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -1,4 +1,4 @@
-//! Checks for uses of const which the type is not `Freeze` (`Cell`-free).
+//! Checks for usage of const which the type is not `Freeze` (`Cell`-free).
//!
//! This lint is **warn** by default.
@@ -196,11 +196,9 @@ fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<
fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
let substs = cx.typeck_results().node_substs(hir_id);
- let result = cx.tcx.const_eval_resolve(
- cx.param_env,
- mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs),
- None,
- );
+ let result = cx
+ .tcx
+ .const_eval_resolve(cx.param_env, mir::UnevaluatedConst::new(def_id, substs), None);
is_value_unfrozen_raw(cx, result, ty)
}
diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
index 839c3a381..7eaa7db78 100644
--- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -131,13 +131,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
for field in non_send_fields {
diag.span_note(
field.def.span,
- &format!("it is not safe to send field `{}` to another thread", field.def.ident.name),
+ format!("it is not safe to send field `{}` to another thread", field.def.ident.name),
);
match field.generic_params.len() {
0 => diag.help("use a thread-safe type that implements `Send`"),
- 1 if is_ty_param(field.ty) => diag.help(&format!("add `{}: Send` bound in `Send` impl", field.ty)),
- _ => diag.help(&format!(
+ 1 if is_ty_param(field.ty) => diag.help(format!("add `{}: Send` bound in `Send` impl", field.ty)),
+ _ => diag.help(format!(
"add bounds on type parameter{} `{}` that satisfy `{}: Send`",
if field.generic_params.len() > 1 { "s" } else { "" },
field.generic_params_string(),
diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
index 7376ab0c8..6d3865080 100644
--- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs
+++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
@@ -76,8 +76,8 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
if ch == '\\' {
if let Some((_, '0')) = iter.next() {
// collect up to two further octal digits
- if let Some((mut to, '0'..='7')) = iter.next() {
- if let Some((_, '0'..='7')) = iter.peek() {
+ if let Some((mut to, _)) = iter.next_if(|(_, ch)| matches!(ch, '0'..='7')) {
+ if iter.next_if(|(_, ch)| matches!(ch, '0'..='7')).is_some() {
to += 1;
}
found.push((from, to + 1));
@@ -90,32 +90,6 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
return;
}
- // construct two suggestion strings, one with \x escapes with octal meaning
- // as in C, and one with \x00 for null bytes.
- let mut suggest_1 = if is_string { "\"" } else { "b\"" }.to_string();
- let mut suggest_2 = suggest_1.clone();
- let mut index = 0;
- for (from, to) in found {
- suggest_1.push_str(&contents[index..from]);
- suggest_2.push_str(&contents[index..from]);
-
- // construct a replacement escape
- // the maximum value is \077, or \x3f, so u8 is sufficient here
- if let Ok(n) = u8::from_str_radix(&contents[from + 1..to], 8) {
- write!(suggest_1, "\\x{n:02x}").unwrap();
- }
-
- // append the null byte as \x00 and the following digits literally
- suggest_2.push_str("\\x00");
- suggest_2.push_str(&contents[from + 2..to]);
-
- index = to;
- }
- suggest_1.push_str(&contents[index..]);
- suggest_1.push('"');
- suggest_2.push_str(&contents[index..]);
- suggest_2.push('"');
-
span_lint_and_then(
cx,
OCTAL_ESCAPES,
@@ -129,23 +103,53 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
"octal escapes are not supported, `\\0` is always a null {}",
if is_string { "character" } else { "byte" }
));
- // suggestion 1: equivalent hex escape
- diag.span_suggestion(
- span,
- "if an octal escape was intended, use the hexadecimal representation instead",
- suggest_1,
- Applicability::MaybeIncorrect,
- );
- // suggestion 2: unambiguous null byte
- diag.span_suggestion(
- span,
- format!(
- "if the null {} is intended, disambiguate using",
- if is_string { "character" } else { "byte" }
- ),
- suggest_2,
- Applicability::MaybeIncorrect,
- );
+
+ // Generate suggestions if the string is not too long (~ 5 lines)
+ if contents.len() < 400 {
+ // construct two suggestion strings, one with \x escapes with octal meaning
+ // as in C, and one with \x00 for null bytes.
+ let mut suggest_1 = if is_string { "\"" } else { "b\"" }.to_string();
+ let mut suggest_2 = suggest_1.clone();
+ let mut index = 0;
+ for (from, to) in found {
+ suggest_1.push_str(&contents[index..from]);
+ suggest_2.push_str(&contents[index..from]);
+
+ // construct a replacement escape
+ // the maximum value is \077, or \x3f, so u8 is sufficient here
+ if let Ok(n) = u8::from_str_radix(&contents[from + 1..to], 8) {
+ write!(suggest_1, "\\x{n:02x}").unwrap();
+ }
+
+ // append the null byte as \x00 and the following digits literally
+ suggest_2.push_str("\\x00");
+ suggest_2.push_str(&contents[from + 2..to]);
+
+ index = to;
+ }
+ suggest_1.push_str(&contents[index..]);
+ suggest_2.push_str(&contents[index..]);
+
+ suggest_1.push('"');
+ suggest_2.push('"');
+ // suggestion 1: equivalent hex escape
+ diag.span_suggestion(
+ span,
+ "if an octal escape was intended, use the hexadecimal representation instead",
+ suggest_1,
+ Applicability::MaybeIncorrect,
+ );
+ // suggestion 2: unambiguous null byte
+ diag.span_suggestion(
+ span,
+ format!(
+ "if the null {} is intended, disambiguate using",
+ if is_string { "character" } else { "byte" }
+ ),
+ suggest_2,
+ Applicability::MaybeIncorrect,
+ );
+ }
},
);
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index d29ca37ea..f4863600c 100644
--- a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -121,7 +121,7 @@ fn detect_absurd_comparison<'tcx>(
fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
let ty = cx.typeck_results().expr_ty(expr);
- let cv = constant(cx, cx.typeck_results(), expr)?.0;
+ let cv = constant(cx, cx.typeck_results(), expr)?;
let which = match (ty.kind(), cv) {
(&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum,
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index e57137356..5c240276b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -1,4 +1,5 @@
use super::ARITHMETIC_SIDE_EFFECTS;
+use clippy_utils::is_from_proc_macro;
use clippy_utils::{
consts::{constant, constant_simple, Constant},
diagnostics::span_lint,
@@ -10,16 +11,20 @@ use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::impl_lint_pass;
-use rustc_span::source_map::{Span, Spanned};
+use rustc_span::{
+ source_map::{Span, Spanned},
+ Symbol,
+};
const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[
["f32", "f32"],
["f64", "f64"],
["std::num::Saturating", "std::num::Saturating"],
["std::num::Wrapping", "std::num::Wrapping"],
- ["std::string::String", "&str"],
+ ["std::string::String", "str"],
];
const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
+const INTEGER_METHODS: &[&str] = &["saturating_div", "wrapping_div", "wrapping_rem", "wrapping_rem_euclid"];
#[derive(Debug)]
pub struct ArithmeticSideEffects {
@@ -28,6 +33,7 @@ pub struct ArithmeticSideEffects {
// Used to check whether expressions are constants, such as in enum discriminants and consts
const_span: Option<Span>,
expr_span: Option<Span>,
+ integer_methods: FxHashSet<Symbol>,
}
impl_lint_pass!(ArithmeticSideEffects => [ARITHMETIC_SIDE_EFFECTS]);
@@ -53,6 +59,7 @@ impl ArithmeticSideEffects {
allowed_unary,
const_span: None,
expr_span: None,
+ integer_methods: INTEGER_METHODS.iter().map(|el| Symbol::intern(el)).collect(),
}
}
@@ -103,10 +110,10 @@ impl ArithmeticSideEffects {
/// like `i32::MAX` or constant references like `N` from `const N: i32 = 1;`,
fn literal_integer(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<u128> {
let actual = peel_hir_expr_unary(expr).0;
- if let hir::ExprKind::Lit(ref lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
+ if let hir::ExprKind::Lit(lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
return Some(n)
}
- if let Some((Constant::Int(n), _)) = constant(cx, cx.typeck_results(), expr) {
+ if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) {
return Some(n);
}
None
@@ -137,8 +144,10 @@ impl ArithmeticSideEffects {
) {
return;
};
- let lhs_ty = cx.typeck_results().expr_ty(lhs);
- let rhs_ty = cx.typeck_results().expr_ty(rhs);
+ let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
+ let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
+ let lhs_ty = cx.typeck_results().expr_ty(actual_lhs).peel_refs();
+ let rhs_ty = cx.typeck_results().expr_ty(actual_rhs).peel_refs();
if self.has_allowed_binary(lhs_ty, rhs_ty) {
return;
}
@@ -147,8 +156,6 @@ impl ArithmeticSideEffects {
// At least for integers, shifts are already handled by the CTFE
return;
}
- let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
- let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
match (
Self::literal_integer(cx, actual_lhs),
Self::literal_integer(cx, actual_rhs),
@@ -184,6 +191,33 @@ impl ArithmeticSideEffects {
}
}
+ /// There are some integer methods like `wrapping_div` that will panic depending on the
+ /// provided input.
+ fn manage_method_call<'tcx>(
+ &mut self,
+ args: &[hir::Expr<'tcx>],
+ cx: &LateContext<'tcx>,
+ ps: &hir::PathSegment<'tcx>,
+ receiver: &hir::Expr<'tcx>,
+ ) {
+ let Some(arg) = args.first() else { return; };
+ if constant_simple(cx, cx.typeck_results(), receiver).is_some() {
+ return;
+ }
+ let instance_ty = cx.typeck_results().expr_ty(receiver);
+ if !Self::is_integral(instance_ty) {
+ return;
+ }
+ if !self.integer_methods.contains(&ps.ident.name) {
+ return;
+ }
+ let (actual_arg, _) = peel_hir_expr_refs(arg);
+ match Self::literal_integer(cx, actual_arg) {
+ None | Some(0) => self.issue_lint(cx, arg),
+ Some(_) => {},
+ }
+ }
+
fn manage_unary_ops<'tcx>(
&mut self,
cx: &LateContext<'tcx>,
@@ -206,8 +240,9 @@ impl ArithmeticSideEffects {
self.issue_lint(cx, expr);
}
- fn should_skip_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+ fn should_skip_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool {
is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id)
+ || is_from_proc_macro(cx, expr)
|| self.expr_span.is_some()
|| self.const_span.map_or(false, |sp| sp.contains(expr.span))
}
@@ -222,6 +257,9 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => {
self.manage_bin_ops(cx, expr, op, lhs, rhs);
},
+ hir::ExprKind::MethodCall(ps, receiver, args, _) => {
+ self.manage_method_call(args, cx, ps, receiver);
+ },
hir::ExprKind::Unary(un_op, un_expr) => {
self.manage_unary_ops(cx, expr, un_expr, *un_op);
},
diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
index 1369b3e74..1fddf0f50 100644
--- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
@@ -166,7 +166,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
}
fn fetch_int_literal(cx: &LateContext<'_>, lit: &Expr<'_>) -> Option<u128> {
- match constant(cx, cx.typeck_results(), lit)?.0 {
+ match constant(cx, cx.typeck_results(), lit)? {
Constant::Int(n) => Some(n),
_ => None,
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
index 786ae1552..e18064b70 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
@@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Exp
}
fn is_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
- if let Some((value, _)) = constant(cx, cx.typeck_results(), e) {
+ if let Some(value) = constant(cx, cx.typeck_results(), e) {
match value {
Constant::F32(num) => num.is_nan(),
Constant::F64(num) => num.is_nan(),
diff --git a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
index 49e662cac..f120be138 100644
--- a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
@@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(
if op == BinOpKind::Div
&& let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
- && let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right)
+ && let Some(Constant::Int(divisor)) = constant(cx, cx.typeck_results(), right)
{
let suggested_fn = match (method_path.ident.as_str(), divisor) {
("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
index 97ddcdb24..15dff126b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{constant_with_source, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::get_item_name;
use clippy_utils::sugg::Sugg;
@@ -18,9 +18,16 @@ pub(crate) fn check<'tcx>(
right: &'tcx Expr<'_>,
) {
if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
- if is_allowed(cx, left) || is_allowed(cx, right) {
- return;
- }
+ let left_is_local = match constant_with_source(cx, cx.typeck_results(), left) {
+ Some((c, s)) if !is_allowed(&c) => s.is_local(),
+ Some(_) => return,
+ None => true,
+ };
+ let right_is_local = match constant_with_source(cx, cx.typeck_results(), right) {
+ Some((c, s)) if !is_allowed(&c) => s.is_local(),
+ Some(_) => return,
+ None => true,
+ };
// Allow comparing the results of signum()
if is_signum(cx, left) && is_signum(cx, right) {
@@ -34,10 +41,7 @@ pub(crate) fn check<'tcx>(
}
}
let is_comparing_arrays = is_array(cx, left) || is_array(cx, right);
- let (lint, msg) = get_lint_and_message(
- is_named_constant(cx, left) || is_named_constant(cx, right),
- is_comparing_arrays,
- );
+ let (lint, msg) = get_lint_and_message(left_is_local && right_is_local, is_comparing_arrays);
span_lint_and_then(cx, lint, expr.span, msg, |diag| {
let lhs = Sugg::hir(cx, left, "..");
let rhs = Sugg::hir(cx, right, "..");
@@ -59,44 +63,33 @@ pub(crate) fn check<'tcx>(
}
}
-fn get_lint_and_message(
- is_comparing_constants: bool,
- is_comparing_arrays: bool,
-) -> (&'static rustc_lint::Lint, &'static str) {
- if is_comparing_constants {
+fn get_lint_and_message(is_local: bool, is_comparing_arrays: bool) -> (&'static rustc_lint::Lint, &'static str) {
+ if is_local {
(
- FLOAT_CMP_CONST,
+ FLOAT_CMP,
if is_comparing_arrays {
- "strict comparison of `f32` or `f64` constant arrays"
+ "strict comparison of `f32` or `f64` arrays"
} else {
- "strict comparison of `f32` or `f64` constant"
+ "strict comparison of `f32` or `f64`"
},
)
} else {
(
- FLOAT_CMP,
+ FLOAT_CMP_CONST,
if is_comparing_arrays {
- "strict comparison of `f32` or `f64` arrays"
+ "strict comparison of `f32` or `f64` constant arrays"
} else {
- "strict comparison of `f32` or `f64`"
+ "strict comparison of `f32` or `f64` constant"
},
)
}
}
-fn is_named_constant<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
- if let Some((_, res)) = constant(cx, cx.typeck_results(), expr) {
- res
- } else {
- false
- }
-}
-
-fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
- match constant(cx, cx.typeck_results(), expr) {
- Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(),
- Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(),
- Some((Constant::Vec(vec), _)) => vec.iter().all(|f| match f {
+fn is_allowed(val: &Constant) -> bool {
+ match val {
+ &Constant::F32(f) => f == 0.0 || f.is_infinite(),
+ &Constant::F64(f) => f == 0.0 || f.is_infinite(),
+ Constant::Vec(vec) => vec.iter().all(|f| match f {
Constant::F32(f) => *f == 0.0 || (*f).is_infinite(),
Constant::F64(f) => *f == 0.0 || (*f).is_infinite(),
_ => false,
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index eba230da6..d63a836e7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -98,32 +98,6 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for integer arithmetic operations which could overflow or panic.
- ///
- /// Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable
- /// of overflowing according to the [Rust
- /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
- /// or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is
- /// attempted.
- ///
- /// ### Why is this bad?
- /// Integer overflow will trigger a panic in debug builds or will wrap in
- /// release mode. Division by zero will cause a panic in either mode. In some applications one
- /// wants explicitly checked, wrapping or saturating arithmetic.
- ///
- /// ### Example
- /// ```rust
- /// # let a = 0;
- /// a + 1;
- /// ```
- #[clippy::version = "pre 1.29.0"]
- pub INTEGER_ARITHMETIC,
- restriction,
- "any integer arithmetic expression which could overflow or panic"
-}
-
-declare_clippy_lint! {
- /// ### What it does
/// Checks for float arithmetic.
///
/// ### Why is this bad?
@@ -685,7 +659,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using
+ /// Checks for usage of bitwise and/or operators between booleans, where performance may be improved by using
/// a lazy and.
///
/// ### Why is this bad?
@@ -787,7 +761,6 @@ pub struct Operators {
impl_lint_pass!(Operators => [
ABSURD_EXTREME_COMPARISONS,
ARITHMETIC_SIDE_EFFECTS,
- INTEGER_ARITHMETIC,
FLOAT_ARITHMETIC,
ASSIGN_OP_PATTERN,
MISREFACTORED_ASSIGN_OP,
diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
index af4e74947..a2c3a4d8b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -40,7 +40,7 @@ struct OperandInfo {
fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
match constant(cx, cx.typeck_results(), operand) {
- Some((Constant::Int(v), _)) => match *cx.typeck_results().expr_ty(expr).kind() {
+ Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() {
ty::Int(ity) => {
let value = sext(cx.tcx, v, ity);
return Some(OperandInfo {
@@ -58,10 +58,10 @@ fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) ->
},
_ => {},
},
- Some((Constant::F32(f), _)) => {
+ Some(Constant::F32(f)) => {
return Some(floating_point_operand_info(&f));
},
- Some((Constant::F64(f), _)) => {
+ Some(Constant::F64(f)) => {
return Some(floating_point_operand_info(&f));
},
_ => {},
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index 777395f45..102845cee 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -1,12 +1,10 @@
+use super::FLOAT_ARITHMETIC;
use clippy_utils::consts::constant_simple;
use clippy_utils::diagnostics::span_lint;
-use clippy_utils::is_integer_literal;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::source_map::Span;
-use super::{FLOAT_ARITHMETIC, INTEGER_ARITHMETIC};
-
#[derive(Default)]
pub struct Context {
expr_id: Option<hir::HirId>,
@@ -45,28 +43,8 @@ impl Context {
_ => (),
}
- let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
- if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() {
- match op {
- hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
- hir::ExprKind::Lit(_lit) => (),
- hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
- if is_integer_literal(expr, 1) {
- span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
- self.expr_id = Some(expr.hir_id);
- }
- },
- _ => {
- span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
- self.expr_id = Some(expr.hir_id);
- },
- },
- _ => {
- span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
- self.expr_id = Some(expr.hir_id);
- },
- }
- } else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
+ let (_, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
+ if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
self.expr_id = Some(expr.hir_id);
}
@@ -77,14 +55,9 @@ impl Context {
return;
}
let ty = cx.typeck_results().expr_ty(arg);
- if constant_simple(cx, cx.typeck_results(), expr).is_none() {
- if ty.is_integral() {
- span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
- self.expr_id = Some(expr.hir_id);
- } else if ty.is_floating_point() {
- span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
- self.expr_id = Some(expr.hir_id);
- }
+ if constant_simple(cx, cx.typeck_results(), expr).is_none() && ty.is_floating_point() {
+ span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
+ self.expr_id = Some(expr.hir_id);
}
}
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 bbbcda069..aa6d40042 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
@@ -122,7 +122,7 @@ fn try_get_option_occurrence<'tcx>(
ExprKind::Unary(UnOp::Deref, inner_expr) | ExprKind::AddrOf(_, _, inner_expr) => inner_expr,
_ => expr,
};
- let inner_pat = try_get_inner_pat(cx, pat)?;
+ let (inner_pat, is_result) = try_get_inner_pat_and_is_result(cx, pat)?;
if_chain! {
if let PatKind::Binding(bind_annotation, _, id, None) = inner_pat.kind;
if let Some(some_captures) = can_move_expr_to_closure(cx, if_then);
@@ -176,7 +176,7 @@ fn try_get_option_occurrence<'tcx>(
),
none_expr: format!(
"{}{}",
- if method_sugg == "map_or" { "" } else { "|| " },
+ if method_sugg == "map_or" { "" } else if is_result { "|_| " } else { "|| "},
Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app),
),
});
@@ -186,11 +186,13 @@ fn try_get_option_occurrence<'tcx>(
None
}
-fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'tcx Pat<'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);
- if is_res_lang_ctor(cx, res, OptionSome) || is_res_lang_ctor(cx, res, ResultOk) {
- return Some(inner_pat);
+ if is_res_lang_ctor(cx, res, OptionSome) {
+ return Some((inner_pat, false));
+ } else if is_res_lang_ctor(cx, res, ResultOk) {
+ return Some((inner_pat, true));
}
}
None
diff --git a/src/tools/clippy/clippy_lints/src/question_mark_used.rs b/src/tools/clippy/clippy_lints/src/question_mark_used.rs
index 9b678e8d7..ff66b8a00 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark_used.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark_used.rs
@@ -24,7 +24,7 @@ declare_clippy_lint! {
/// ```ignore
/// utility_macro!(expr);
/// ```
- #[clippy::version = "pre 1.29.0"]
+ #[clippy::version = "1.69.0"]
pub QUESTION_MARK_USED,
restriction,
"complains if the question mark operator is used"
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index fc655fe2d..dd7ded491 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -319,7 +319,7 @@ fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<R
_ => return None,
};
if let Some(id) = path_to_local(l) {
- if let Some((c, _)) = constant(cx, cx.typeck_results(), r) {
+ if let Some(c) = constant(cx, cx.typeck_results(), r) {
return Some(RangeBounds {
val: c,
expr: r,
@@ -331,7 +331,7 @@ fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<R
});
}
} else if let Some(id) = path_to_local(r) {
- if let Some((c, _)) = constant(cx, cx.typeck_results(), l) {
+ if let Some(c) = constant(cx, cx.typeck_results(), l) {
return Some(RangeBounds {
val: c,
expr: l,
@@ -451,8 +451,8 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::Range::hir(expr);
let ty = cx.typeck_results().expr_ty(start);
if let ty::Int(_) | ty::Uint(_) = ty.kind();
- if let Some((start_idx, _)) = constant(cx, cx.typeck_results(), start);
- if let Some((end_idx, _)) = constant(cx, cx.typeck_results(), end);
+ if let Some(start_idx) = constant(cx, cx.typeck_results(), start);
+ if let Some(end_idx) = constant(cx, cx.typeck_results(), end);
if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
if is_empty_range(limits, ordering);
then {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 944a33cc3..685d738cb 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -57,7 +57,7 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "1.32.0"]
pub REDUNDANT_CLONE,
- perf,
+ nursery,
"`clone()` of an owned value that is going to be dropped immediately"
}
diff --git a/src/tools/clippy/clippy_lints/src/ref_patterns.rs b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
new file mode 100644
index 000000000..b1530eed1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
@@ -0,0 +1,44 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_ast::ast::{BindingAnnotation, Pat, PatKind};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for usages of the `ref` keyword.
+ /// ### Why is this bad?
+ /// The `ref` keyword can be confusing for people unfamiliar with it, and often
+ /// it is more concise to use `&` instead.
+ /// ### Example
+ /// ```rust
+ /// let opt = Some(5);
+ /// if let Some(ref foo) = opt {}
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// let opt = Some(5);
+ /// if let Some(foo) = &opt {}
+ /// ```
+ #[clippy::version = "1.71.0"]
+ pub REF_PATTERNS,
+ restriction,
+ "use of a ref pattern, e.g. Some(ref value)"
+}
+declare_lint_pass!(RefPatterns => [REF_PATTERNS]);
+
+impl EarlyLintPass for RefPatterns {
+ fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
+ if let PatKind::Ident(BindingAnnotation::REF, _, _) = pat.kind
+ && !pat.span.from_expansion()
+ {
+ span_lint_and_help(
+ cx,
+ REF_PATTERNS,
+ pat.span,
+ "usage of ref pattern",
+ None,
+ "consider using `&` for clarity instead",
+ );
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index 9e6c6c73d..ef19c6f46 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -122,37 +122,39 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: &regex_syntax::Error, unescape
}
fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
- constant(cx, cx.typeck_results(), e).and_then(|(c, _)| match c {
+ constant(cx, cx.typeck_results(), e).and_then(|c| match c {
Constant::Str(s) => Some(s),
_ => None,
})
}
fn is_trivial_regex(s: &regex_syntax::hir::Hir) -> Option<&'static str> {
- use regex_syntax::hir::Anchor::{EndText, StartText};
- use regex_syntax::hir::HirKind::{Alternation, Anchor, Concat, Empty, Literal};
+ use regex_syntax::hir::HirKind::{Alternation, Concat, Empty, Literal, Look};
+ use regex_syntax::hir::Look as HirLook;
let is_literal = |e: &[regex_syntax::hir::Hir]| e.iter().all(|e| matches!(*e.kind(), Literal(_)));
match *s.kind() {
- Empty | Anchor(_) => Some("the regex is unlikely to be useful as it is"),
+ Empty | Look(_) => Some("the regex is unlikely to be useful as it is"),
Literal(_) => Some("consider using `str::contains`"),
Alternation(ref exprs) => {
- if exprs.iter().all(|e| e.kind().is_empty()) {
+ if exprs.iter().all(|e| matches!(e.kind(), Empty)) {
Some("the regex is unlikely to be useful as it is")
} else {
None
}
},
Concat(ref exprs) => match (exprs[0].kind(), exprs[exprs.len() - 1].kind()) {
- (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => {
+ (&Look(HirLook::Start), &Look(HirLook::End)) if exprs[1..(exprs.len() - 1)].is_empty() => {
Some("consider using `str::is_empty`")
},
- (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+ (&Look(HirLook::Start), &Look(HirLook::End)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
Some("consider using `==` on `str`s")
},
- (&Anchor(StartText), &Literal(_)) if is_literal(&exprs[1..]) => Some("consider using `str::starts_with`"),
- (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+ (&Look(HirLook::Start), &Literal(_)) if is_literal(&exprs[1..]) => {
+ Some("consider using `str::starts_with`")
+ },
+ (&Literal(_), &Look(HirLook::End)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
Some("consider using `str::ends_with`")
},
_ if is_literal(exprs) => Some("consider using `str::contains`"),
@@ -175,12 +177,9 @@ fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
}
fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
- let mut parser = regex_syntax::ParserBuilder::new()
- .unicode(true)
- .allow_invalid_utf8(!utf8)
- .build();
+ let mut parser = regex_syntax::ParserBuilder::new().unicode(true).utf8(!utf8).build();
- if let ExprKind::Lit(ref lit) = expr.kind {
+ if let ExprKind::Lit(lit) = expr.kind {
if let LitKind::Str(ref r, style) = lit.node {
let r = r.as_str();
let offset = if let StrStyle::Raw(n) = style { 2 + n } else { 1 };
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 9f487dedb..b0db56bb4 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -15,6 +15,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
("clippy::identity_conversion", "clippy::useless_conversion"),
("clippy::if_let_some_result", "clippy::match_result_ok"),
+ ("clippy::integer_arithmetic", "clippy::arithmetic_side_effects"),
("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
("clippy::new_without_default_derive", "clippy::new_without_default"),
("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
@@ -30,10 +31,15 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
("clippy::stutter", "clippy::module_name_repetitions"),
("clippy::to_string_in_display", "clippy::recursive_format_impl"),
("clippy::zero_width_space", "clippy::invisible_characters"),
+ ("clippy::clone_double_ref", "suspicious_double_ref_op"),
("clippy::drop_bounds", "drop_bounds"),
+ ("clippy::drop_copy", "dropping_copy_types"),
+ ("clippy::drop_ref", "dropping_references"),
("clippy::for_loop_over_option", "for_loops_over_fallibles"),
("clippy::for_loop_over_result", "for_loops_over_fallibles"),
("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
+ ("clippy::forget_copy", "forgetting_copy_types"),
+ ("clippy::forget_ref", "forgetting_references"),
("clippy::into_iter_on_array", "array_into_iter"),
("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
("clippy::invalid_ref", "invalid_value"),
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
index 34a3e5ddf..419d7991f 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_block.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and
use rustc_errors::Applicability;
use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
declare_clippy_lint! {
@@ -64,7 +64,78 @@ declare_clippy_lint! {
restriction,
"add a semicolon outside the block"
}
-declare_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]);
+impl_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]);
+
+#[derive(Copy, Clone)]
+pub struct SemicolonBlock {
+ semicolon_inside_block_ignore_singleline: bool,
+ semicolon_outside_block_ignore_multiline: bool,
+}
+
+impl SemicolonBlock {
+ pub fn new(semicolon_inside_block_ignore_singleline: bool, semicolon_outside_block_ignore_multiline: bool) -> Self {
+ Self {
+ semicolon_inside_block_ignore_singleline,
+ semicolon_outside_block_ignore_multiline,
+ }
+ }
+
+ fn semicolon_inside_block(self, cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) {
+ let insert_span = tail.span.source_callsite().shrink_to_hi();
+ let remove_span = semi_span.with_lo(block.span.hi());
+
+ if self.semicolon_inside_block_ignore_singleline && get_line(cx, remove_span) == get_line(cx, insert_span) {
+ return;
+ }
+
+ span_lint_and_then(
+ cx,
+ SEMICOLON_INSIDE_BLOCK,
+ semi_span,
+ "consider moving the `;` inside the block for consistent formatting",
+ |diag| {
+ multispan_sugg_with_applicability(
+ diag,
+ "put the `;` here",
+ Applicability::MachineApplicable,
+ [(remove_span, String::new()), (insert_span, ";".to_owned())],
+ );
+ },
+ );
+ }
+
+ fn semicolon_outside_block(
+ self,
+ cx: &LateContext<'_>,
+ block: &Block<'_>,
+ tail_stmt_expr: &Expr<'_>,
+ semi_span: Span,
+ ) {
+ let insert_span = block.span.with_lo(block.span.hi());
+ // account for macro calls
+ let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span);
+ let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi());
+
+ if self.semicolon_outside_block_ignore_multiline && get_line(cx, remove_span) != get_line(cx, insert_span) {
+ return;
+ }
+
+ span_lint_and_then(
+ cx,
+ SEMICOLON_OUTSIDE_BLOCK,
+ block.span,
+ "consider moving the `;` outside the block for consistent formatting",
+ |diag| {
+ multispan_sugg_with_applicability(
+ diag,
+ "put the `;` here",
+ Applicability::MachineApplicable,
+ [(remove_span, String::new()), (insert_span, ";".to_owned())],
+ );
+ },
+ );
+ }
+}
impl LateLintPass<'_> for SemicolonBlock {
fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
@@ -83,55 +154,23 @@ impl LateLintPass<'_> for SemicolonBlock {
span,
..
} = stmt else { return };
- semicolon_outside_block(cx, block, expr, span);
+ self.semicolon_outside_block(cx, block, expr, span);
},
StmtKind::Semi(Expr {
kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _),
..
- }) if !block.span.from_expansion() => semicolon_inside_block(cx, block, tail, stmt.span),
+ }) if !block.span.from_expansion() => {
+ self.semicolon_inside_block(cx, block, tail, stmt.span);
+ },
_ => (),
}
}
}
-fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) {
- let insert_span = tail.span.source_callsite().shrink_to_hi();
- let remove_span = semi_span.with_lo(block.span.hi());
-
- span_lint_and_then(
- cx,
- SEMICOLON_INSIDE_BLOCK,
- semi_span,
- "consider moving the `;` inside the block for consistent formatting",
- |diag| {
- multispan_sugg_with_applicability(
- diag,
- "put the `;` here",
- Applicability::MachineApplicable,
- [(remove_span, String::new()), (insert_span, ";".to_owned())],
- );
- },
- );
-}
-
-fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) {
- let insert_span = block.span.with_lo(block.span.hi());
- // account for macro calls
- let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span);
- let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi());
+fn get_line(cx: &LateContext<'_>, span: Span) -> Option<usize> {
+ if let Ok(line) = cx.sess().source_map().lookup_line(span.lo()) {
+ return Some(line.line);
+ }
- span_lint_and_then(
- cx,
- SEMICOLON_OUTSIDE_BLOCK,
- block.span,
- "consider moving the `;` outside the block for consistent formatting",
- |diag| {
- multispan_sugg_with_applicability(
- diag,
- "put the `;` here",
- Applicability::MachineApplicable,
- [(remove_span, String::new()), (insert_span, ";".to_owned())],
- );
- },
- );
+ None
}
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index ae7d19624..993f9373d 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
let PatKind::Binding(_, id, ident, _) = pat.kind else { return };
- if pat.span.desugaring_kind().is_some() {
+ if pat.span.desugaring_kind().is_some() || pat.span.from_expansion() {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index 869358fb1..b930b2c8d 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -17,7 +17,7 @@ use rustc_span::{symbol::Ident, Span, DUMMY_SP};
declare_clippy_lint! {
/// ### What it does
///
- /// Searches for elements marked with `#[clippy::significant_drop]` that could be early
+ /// Searches for elements marked with `#[clippy::has_significant_drop]` that could be early
/// dropped but are in fact dropped at the end of their scopes. In other words, enforces the
/// "tightening" of their possible lifetimes.
///
@@ -46,7 +46,7 @@ declare_clippy_lint! {
/// do_heavy_computation_that_takes_time(owned_rslt);
/// }
/// ```
- #[clippy::version = "1.67.0"]
+ #[clippy::version = "1.69.0"]
pub SIGNIFICANT_DROP_TIGHTENING,
nursery,
"Searches for elements marked with `#[clippy::has_significant_drop]` that could be early dropped but are in fact dropped at the end of their scopes"
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index a2109038a..858135c8d 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -74,7 +74,7 @@ enum InitializationType<'tcx> {
impl<'tcx> LateLintPass<'tcx> for SlowVectorInit {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- // Matches initialization on reassignements. For example: `vec = Vec::with_capacity(100)`
+ // Matches initialization on reassignments. For example: `vec = Vec::with_capacity(100)`
if_chain! {
if let ExprKind::Assign(left, right, _) = expr.kind;
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index b2f4b3109..483f860a8 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -132,7 +132,7 @@ declare_clippy_lint! {
/// Probably lots of false positives. If an index comes from a known valid position (e.g.
/// obtained via `char_indices` over the same string), it is totally OK.
///
- /// # Example
+ /// ### Example
/// ```rust,should_panic
/// &"Ölkanne"[1..];
/// ```
@@ -292,6 +292,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
}
if_chain! {
+ if !in_external_macro(cx.sess(), e.span);
if let ExprKind::MethodCall(path, receiver, ..) = &e.kind;
if path.ident.name == sym!(as_bytes);
if let ExprKind::Lit(lit) = &receiver.kind;
diff --git a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
index 03324c66e..2f2e84fa3 100644
--- a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
@@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::visitors::is_expr_unsafe;
use clippy_utils::{get_parent_node, match_libc_symbol};
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, Node, UnsafeSource};
+use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, LangItem, Node, UnsafeSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::sym;
@@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings {
let val_name = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0;
let method_name = if is_type_diagnostic_item(cx, ty, sym::cstring_type) {
"as_bytes"
- } else if is_type_diagnostic_item(cx, ty, sym::CStr) {
+ } else if is_type_lang_item(cx, ty, LangItem::CStr) {
"to_bytes"
} else {
return;
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index fab8e9c2e..e2cdc48b5 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -577,7 +577,7 @@ fn ident_difference_expr_with_base_location(
| (AssignOp(_, _, _), AssignOp(_, _, _))
| (Assign(_, _, _), Assign(_, _, _))
| (TryBlock(_), TryBlock(_))
- | (Await(_), Await(_))
+ | (Await(_, _), Await(_, _))
| (Async(_, _), Async(_, _))
| (Block(_, _), Block(_, _))
| (Closure(_), Closure(_))
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 1382c1a40..bb9da3a20 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
None,
&format!(
"consider annotating `{}` with `#[repr(C)]` or another `repr` attribute",
- cx.tcx.def_path_str(item.owner_id.to_def_id())
+ cx.tcx.def_path_str(item.owner_id)
),
);
}
@@ -60,7 +60,7 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_
if let Some(last_field) = data.fields().last();
if let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind;
- // Then check if that that array zero-sized
+ // Then check if that array is zero-sized
let length = Const::from_anon_const(cx.tcx, length.def_id);
let length = length.try_eval_target_usize(cx.tcx, cx.param_env);
if let Some(length) = length;
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index b5f11b4ac..4ccda1506 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -37,12 +37,12 @@ declare_clippy_lint! {
#[clippy::version = "1.38.0"]
pub TYPE_REPETITION_IN_BOUNDS,
nursery,
- "types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
+ "types are repeated unnecessarily in trait bounds, use `+` instead of using `T: _, T: _`"
}
declare_clippy_lint! {
/// ### What it does
- /// Checks for cases where generics are being used and multiple
+ /// Checks for cases where generics or trait objects are being used and multiple
/// syntax specifications for trait bounds are used simultaneously.
///
/// ### Why is this bad?
@@ -167,6 +167,61 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
}
}
}
+
+ fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
+ if_chain! {
+ if let TyKind::Ref(.., mut_ty) = &ty.kind;
+ if let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind;
+ if bounds.len() > 2;
+ then {
+
+ // Build up a hash of every trait we've seen
+ // When we see a trait for the first time, add it to unique_traits
+ // so we can later use it to build a string of all traits exactly once, without duplicates
+
+ let mut seen_def_ids = FxHashSet::default();
+ let mut unique_traits = Vec::new();
+
+ // Iterate the bounds and add them to our seen hash
+ // If we haven't yet seen it, add it to the fixed traits
+ for bound in bounds.iter() {
+ let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; };
+
+ let new_trait = seen_def_ids.insert(def_id);
+
+ if new_trait {
+ unique_traits.push(bound);
+ }
+ }
+
+ // If the number of unique traits isn't the same as the number of traits in the bounds,
+ // there must be 1 or more duplicates
+ if bounds.len() != unique_traits.len() {
+ let mut bounds_span = bounds[0].span;
+
+ for bound in bounds.iter().skip(1) {
+ bounds_span = bounds_span.to(bound.span);
+ }
+
+ let fixed_trait_snippet = unique_traits
+ .iter()
+ .filter_map(|b| snippet_opt(cx, b.span))
+ .collect::<Vec<_>>()
+ .join(" + ");
+
+ span_lint_and_sugg(
+ cx,
+ TRAIT_DUPLICATION_IN_BOUNDS,
+ bounds_span,
+ "this trait bound is already specified in trait declaration",
+ "try",
+ fixed_trait_snippet,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+ }
}
impl TraitBounds {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
index e75d7f6bf..4944381da 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
@@ -31,9 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
match arg.kind {
// Catching:
// transmute over constants that resolve to `null`.
- ExprKind::Path(ref _qpath)
- if matches!(constant(cx, cx.typeck_results(), arg), Some((Constant::RawPtr(0), _))) =>
- {
+ ExprKind::Path(ref _qpath) if matches!(constant(cx, cx.typeck_results(), arg), Some(Constant::RawPtr(0))) => {
lint_expr(cx, expr);
true
},
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
index 1e407fc41..770914e99 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
use rustc_hir::{Expr, ExprKind};
@@ -16,9 +16,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
}
// Catching transmute over constants that resolve to `null`.
- let mut const_eval_context = constant_context(cx, cx.typeck_results());
if let ExprKind::Path(ref _qpath) = arg.kind &&
- let Some(Constant::RawPtr(0)) = const_eval_context.expr(arg)
+ let Some(Constant::RawPtr(0)) = constant(cx, cx.typeck_results(), arg)
{
span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
return true;
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index c1f228d5f..3c873a590 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -22,7 +22,7 @@ use rustc_span::source_map::Span;
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `Box<T>` where T is a collection such as Vec anywhere in the code.
+ /// Checks for usage of `Box<T>` where T is a collection such as Vec anywhere in the code.
/// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
///
/// ### Why is this bad?
@@ -52,7 +52,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `Vec<Box<T>>` where T: Sized anywhere in the code.
+ /// Checks for usage of `Vec<Box<T>>` where T: Sized anywhere in the code.
/// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
///
/// ### Why is this bad?
@@ -85,13 +85,13 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `Option<Option<_>>` in function signatures and type
+ /// Checks for usage of `Option<Option<_>>` in function signatures and type
/// definitions
///
/// ### Why is this bad?
/// `Option<_>` represents an optional value. `Option<Option<_>>`
- /// represents an optional optional value which is logically the same thing as an optional
- /// value but has an unneeded extra level of wrapping.
+ /// represents an optional value which itself wraps an optional. This is logically the
+ /// same thing as an optional value but has an unneeded extra level of wrapping.
///
/// If you have a case where `Some(Some(_))`, `Some(None)` and `None` are distinct cases,
/// consider a custom `enum` instead, with clear names for each case.
@@ -164,7 +164,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `&Box<T>` anywhere in the code.
+ /// Checks for usage of `&Box<T>` anywhere in the code.
/// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
///
/// ### Why is this bad?
@@ -190,7 +190,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of redundant allocations anywhere in the code.
+ /// Checks for usage of redundant allocations anywhere in the code.
///
/// ### Why is this bad?
/// Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, `Arc<&T>`, `Arc<Rc<T>>`,
diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs
index 8980283e5..e275bfd37 100644
--- a/src/tools/clippy/clippy_lints/src/unicode.rs
+++ b/src/tools/clippy/clippy_lints/src/unicode.rs
@@ -76,7 +76,7 @@ declare_lint_pass!(Unicode => [INVISIBLE_CHARACTERS, NON_ASCII_LITERAL, UNICODE_
impl LateLintPass<'_> for Unicode {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
- if let ExprKind::Lit(ref lit) = expr.kind {
+ if let ExprKind::Lit(lit) = expr.kind {
if let LitKind::Str(_, _) | LitKind::Char(_) = lit.node {
check_str(cx, lit.span, expr.hir_id);
}
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 912bcda63..e7449639f 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{diagnostics::span_lint_and_then, ty::approx_ty_size};
use rustc_errors::Applicability;
use rustc_hir::{def_id::LocalDefId, FnDecl, FnRetTy, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind};
use rustc_lint::{LateContext, LateLintPass};
@@ -10,6 +10,9 @@ declare_clippy_lint! {
///
/// Checks for a return type containing a `Box<T>` where `T` implements `Sized`
///
+ /// The lint ignores `Box<T>` where `T` is larger than `unnecessary_box_size`,
+ /// as returning a large `T` directly may be detrimental to performance.
+ ///
/// ### Why is this bad?
///
/// It's better to just return `T` in these cases. The caller may not need
@@ -36,14 +39,16 @@ declare_clippy_lint! {
pub struct UnnecessaryBoxReturns {
avoid_breaking_exported_api: bool,
+ maximum_size: u64,
}
impl_lint_pass!(UnnecessaryBoxReturns => [UNNECESSARY_BOX_RETURNS]);
impl UnnecessaryBoxReturns {
- pub fn new(avoid_breaking_exported_api: bool) -> Self {
+ pub fn new(avoid_breaking_exported_api: bool, maximum_size: u64) -> Self {
Self {
avoid_breaking_exported_api,
+ maximum_size,
}
}
@@ -71,8 +76,10 @@ impl UnnecessaryBoxReturns {
let boxed_ty = return_ty.boxed_ty();
- // it's sometimes useful to return Box<T> if T is unsized, so don't lint those
- if boxed_ty.is_sized(cx.tcx, cx.param_env) {
+ // It's sometimes useful to return Box<T> if T is unsized, so don't lint those.
+ // Also, don't lint if we know that T is very large, in which case returning
+ // a Box<T> may be beneficial.
+ if boxed_ty.is_sized(cx.tcx, cx.param_env) && approx_ty_size(cx, boxed_ty) <= self.maximum_size {
span_lint_and_then(
cx,
UNNECESSARY_BOX_RETURNS,
@@ -102,7 +109,7 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns {
fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'_>) {
// Ignore implementations of traits, because the lint should be on the
- // trait, not on the implmentation of it.
+ // trait, not on the implementation of it.
let Node::Item(parent) = cx.tcx.hir().get_parent(item.hir_id()) else { return };
let ItemKind::Impl(parent) = parent.kind else { return };
if parent.of_trait.is_some() {
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index ddbe6b2c7..28c3fc859 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -1,4 +1,5 @@
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::is_ty_alias;
use clippy_utils::source::{snippet, snippet_with_context};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
@@ -138,6 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
if_chain! {
if let ExprKind::Path(ref qpath) = path.kind;
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
+ if !is_ty_alias(qpath);
then {
let a = cx.typeck_results().expr_ty(e);
let b = cx.typeck_results().expr_ty(arg);
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index bc4adf159..3c2bf5aba 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -304,6 +304,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
kind!("ByteStr(ref {vec})");
chain!(self, "let [{:?}] = **{vec}", vec.value);
},
+ LitKind::CStr(ref vec, _) => {
+ bind!(self, vec);
+ kind!("CStr(ref {vec})");
+ chain!(self, "let [{:?}] = **{vec}", vec.value);
+ },
LitKind::Str(s, _) => {
bind!(self, s);
kind!("Str({s}, _)");
@@ -333,7 +338,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
#[allow(clippy::too_many_lines)]
fn expr(&self, expr: &Binding<&hir::Expr<'_>>) {
- if let Some(higher::While { condition, body }) = higher::While::hir(expr.value) {
+ if let Some(higher::While { condition, body, .. }) = higher::While::hir(expr.value) {
bind!(self, condition, body);
chain!(
self,
@@ -430,7 +435,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
kind!("Unary(UnOp::{op:?}, {inner})");
self.expr(inner);
},
- ExprKind::Lit(ref lit) => {
+ ExprKind::Lit(lit) => {
bind!(self, lit);
kind!("Lit(ref {lit})");
self.lit(lit);
@@ -558,6 +563,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
kind!("InlineAsm(_)");
out!("// unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment");
},
+ ExprKind::OffsetOf(container, ref fields) => {
+ bind!(self, container, fields);
+ kind!("OffsetOf({container}, {fields})");
+ },
ExprKind::Struct(qpath, fields, base) => {
bind!(self, qpath, fields);
opt_bind!(self, base);
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 896a01af3..f6de66bb5 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -174,16 +174,15 @@ macro_rules! define_Conf {
}
}
- #[cfg(feature = "internal")]
pub mod metadata {
- use crate::utils::internal_lints::metadata_collector::ClippyConfiguration;
+ use crate::utils::ClippyConfiguration;
macro_rules! wrap_option {
() => (None);
($x:literal) => (Some($x));
}
- pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
+ pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
vec![
$(
{
@@ -277,6 +276,14 @@ define_Conf! {
/// `".."` can be used as part of the list to indicate, that the configured values should be appended to the
/// default configuration of Clippy. By default, any configuration will replace the default value.
(disallowed_names: Vec<String> = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()),
+ /// Lint: SEMICOLON_INSIDE_BLOCK.
+ ///
+ /// Whether to lint only if it's multiline.
+ (semicolon_inside_block_ignore_singleline: bool = false),
+ /// Lint: SEMICOLON_OUTSIDE_BLOCK.
+ ///
+ /// Whether to lint only if it's singleline.
+ (semicolon_outside_block_ignore_multiline: bool = false),
/// Lint: DOC_MARKDOWN.
///
/// The list of words this lint should not consider as identifiers needing ticks. The value
@@ -463,6 +470,10 @@ define_Conf! {
///
/// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
(future_size_threshold: u64 = 16 * 1024),
+ /// Lint: UNNECESSARY_BOX_RETURNS.
+ ///
+ /// The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
+ (unnecessary_box_size: u64 = 128),
}
/// Search for the configuration file.
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 3d0d4a525..7a1cd3eff 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -8,7 +8,11 @@
//! a simple mistake)
use crate::renamed_lints::RENAMED_LINTS;
-use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
+use crate::utils::{
+ collect_configs,
+ internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type},
+ ClippyConfiguration,
+};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
@@ -520,111 +524,6 @@ impl Serialize for ApplicabilityInfo {
}
}
-// ==================================================================
-// Configuration
-// ==================================================================
-#[derive(Debug, Clone, Default)]
-pub struct ClippyConfiguration {
- name: String,
- config_type: &'static str,
- default: String,
- lints: Vec<String>,
- doc: String,
- #[allow(dead_code)]
- deprecation_reason: Option<&'static str>,
-}
-
-impl ClippyConfiguration {
- pub fn new(
- name: &'static str,
- config_type: &'static str,
- default: String,
- doc_comment: &'static str,
- deprecation_reason: Option<&'static str>,
- ) -> Self {
- let (lints, doc) = parse_config_field_doc(doc_comment)
- .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
-
- Self {
- name: to_kebab(name),
- lints,
- doc,
- config_type,
- default,
- deprecation_reason,
- }
- }
-
- fn to_markdown_paragraph(&self) -> String {
- format!(
- "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
- self.name,
- self.doc
- .lines()
- .map(|line| line.strip_prefix(" ").unwrap_or(line))
- .join("\n"),
- self.default,
- self.config_type,
- self.lints
- .iter()
- .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
- .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
- .join("\n"),
- )
- }
-
- fn to_markdown_table_entry(&self) -> String {
- format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
- }
-}
-
-fn collect_configs() -> Vec<ClippyConfiguration> {
- crate::utils::conf::metadata::get_configuration_metadata()
-}
-
-/// This parses the field documentation of the config struct.
-///
-/// ```rust, ignore
-/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
-/// ```
-///
-/// Would yield:
-/// ```rust, ignore
-/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
-/// ```
-fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
- const DOC_START: &str = " Lint: ";
- if_chain! {
- if doc_comment.starts_with(DOC_START);
- if let Some(split_pos) = doc_comment.find('.');
- then {
- let mut doc_comment = doc_comment.to_string();
- let mut documentation = doc_comment.split_off(split_pos);
-
- // Extract lints
- doc_comment.make_ascii_lowercase();
- let lints: Vec<String> = doc_comment
- .split_off(DOC_START.len())
- .split(", ")
- .map(str::to_string)
- .collect();
-
- // Format documentation correctly
- // split off leading `.` from lint name list and indent for correct formatting
- documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
-
- Some((lints, documentation))
- } else {
- None
- }
- }
-}
-
-/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
-fn to_kebab(config_name: &str) -> String {
- config_name.replace('_', "-")
-}
-
impl fmt::Display for ClippyConfiguration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
writeln!(
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 14ed1368e..008423766 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -20,7 +20,7 @@ use std::str;
declare_clippy_lint! {
/// ### What it does
- /// Checks for usages of def paths when a diagnostic item or a `LangItem` could be used.
+ /// Checks for usage of def paths when a diagnostic item or a `LangItem` could be used.
///
/// ### Why is this bad?
/// The path for an item is subject to change and is less efficient to look up than a
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index dc647af26..d3ea7cafa 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -4,3 +4,143 @@ pub mod dump_hir;
pub mod format_args_collector;
#[cfg(feature = "internal")]
pub mod internal_lints;
+#[cfg(feature = "internal")]
+use itertools::Itertools;
+
+/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
+fn to_kebab(config_name: &str) -> String {
+ config_name.replace('_', "-")
+}
+
+// ==================================================================
+// Configuration
+// ==================================================================
+#[derive(Debug, Clone, Default)] //~ ERROR no such field
+pub struct ClippyConfiguration {
+ pub name: String,
+ #[allow(dead_code)]
+ config_type: &'static str,
+ pub default: String,
+ pub lints: Vec<String>,
+ pub doc: String,
+ #[allow(dead_code)]
+ deprecation_reason: Option<&'static str>,
+}
+
+impl ClippyConfiguration {
+ pub fn new(
+ name: &'static str,
+ config_type: &'static str,
+ default: String,
+ doc_comment: &'static str,
+ deprecation_reason: Option<&'static str>,
+ ) -> Self {
+ let (lints, doc) = parse_config_field_doc(doc_comment)
+ .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
+
+ Self {
+ name: to_kebab(name),
+ lints,
+ doc,
+ config_type,
+ default,
+ deprecation_reason,
+ }
+ }
+
+ #[cfg(feature = "internal")]
+ fn to_markdown_paragraph(&self) -> String {
+ format!(
+ "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
+ self.name,
+ self.doc
+ .lines()
+ .map(|line| line.strip_prefix(" ").unwrap_or(line))
+ .join("\n"),
+ self.default,
+ self.config_type,
+ self.lints
+ .iter()
+ .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
+ .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
+ .join("\n"),
+ )
+ }
+
+ #[cfg(feature = "internal")]
+ fn to_markdown_table_entry(&self) -> String {
+ format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
+ }
+}
+
+#[cfg(feature = "internal")]
+fn collect_configs() -> Vec<ClippyConfiguration> {
+ crate::utils::conf::metadata::get_configuration_metadata()
+}
+
+/// This parses the field documentation of the config struct.
+///
+/// ```rust, ignore
+/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
+/// ```
+///
+/// Would yield:
+/// ```rust, ignore
+/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
+/// ```
+fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
+ const DOC_START: &str = " Lint: ";
+ if_chain! {
+ if doc_comment.starts_with(DOC_START);
+ if let Some(split_pos) = doc_comment.find('.');
+ then {
+ let mut doc_comment = doc_comment.to_string();
+ let mut documentation = doc_comment.split_off(split_pos);
+
+ // Extract lints
+ doc_comment.make_ascii_lowercase();
+ let lints: Vec<String> = doc_comment
+ .split_off(DOC_START.len())
+ .split(", ")
+ .map(str::to_string)
+ .collect();
+
+ // Format documentation correctly
+ // split off leading `.` from lint name list and indent for correct formatting
+ documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
+
+ Some((lints, documentation))
+ } else {
+ None
+ }
+ }
+}
+
+// Shamelessly stolen from find_all (https://github.com/nectariner/find_all)
+pub trait FindAll: Iterator + Sized {
+ fn find_all<P>(&mut self, predicate: P) -> Option<Vec<usize>>
+ where
+ P: FnMut(&Self::Item) -> bool;
+}
+
+impl<I> FindAll for I
+where
+ I: Iterator,
+{
+ fn find_all<P>(&mut self, mut predicate: P) -> Option<Vec<usize>>
+ where
+ P: FnMut(&Self::Item) -> bool,
+ {
+ let mut occurences = Vec::<usize>::default();
+ for (index, element) in self.enumerate() {
+ if predicate(&element) {
+ occurences.push(index);
+ }
+ }
+
+ match occurences.len() {
+ 0 => None,
+ _ => Some(occurences),
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index 297a80e57..7329e5081 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -84,7 +84,7 @@ impl UselessVec {
let mut applicability = Applicability::MachineApplicable;
let snippet = match *vec_args {
higher::VecArgs::Repeat(elem, len) => {
- if let Some((Constant::Int(len_constant), _)) = constant(cx, cx.typeck_results(), len) {
+ if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
#[expect(clippy::cast_possible_truncation)]
if len_constant as u64 * size_of(cx, elem) > self.too_large_for_stack {
return;
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 36f910c98..a9089fba3 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -7,7 +7,7 @@ use rustc_hir::{
def::{DefKind, Res},
Item, ItemKind, PathSegment, UseKind,
};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::kw;
@@ -117,6 +117,10 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);
impl LateLintPass<'_> for WildcardImports {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+ if cx.sess().is_test_crate() {
+ return;
+ }
+
if is_test_module_or_function(cx.tcx, item) {
self.test_modules_deep = self.test_modules_deep.saturating_add(1);
}
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index d7c94b909..f194dc5d4 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -104,7 +104,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for use of `Debug` formatting. The purpose of this
+ /// Checks for usage of `Debug` formatting. The purpose of this
/// lint is to catch debugging remnants.
///
/// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index 124ebd164..66a5079fa 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy_utils"
-version = "0.1.70"
+version = "0.1.71"
edition = "2021"
publish = false
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 1f15598db..8cc01f1ef 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -143,7 +143,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
(Paren(l), _) => eq_expr(l, r),
(_, Paren(r)) => eq_expr(l, r),
(Err, Err) => true,
- (Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r),
+ (Try(l), Try(r)) | (Await(l, _), Await(r, _)) => eq_expr(l, r),
(Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)),
(Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
(Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs
index b4ad42a50..49cb9718e 100644
--- a/src/tools/clippy/clippy_utils/src/attrs.rs
+++ b/src/tools/clippy/clippy_utils/src/attrs.rs
@@ -133,7 +133,7 @@ pub fn get_unique_attr<'a>(
let mut unique_attr: Option<&ast::Attribute> = None;
for attr in get_attr(sess, attrs, name) {
if let Some(duplicate) = unique_attr {
- sess.struct_span_err(attr.span, &format!("`{name}` is defined multiple times"))
+ sess.struct_span_err(attr.span, format!("`{name}` is defined multiple times"))
.span_note(duplicate.span, "first definition found here")
.emit();
} else {
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 d3a6929f6..9edaae853 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -117,7 +117,7 @@ fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1),
ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat(tcx, e).1),
ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1),
- ExprKind::Lit(ref lit) => lit_search_pat(&lit.node),
+ ExprKind::Lit(lit) => lit_search_pat(&lit.node),
ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")),
ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")),
ExprKind::Call(first, [.., last])
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index bb8890dca..fb772644c 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -1,18 +1,21 @@
#![allow(clippy::float_cmp)]
+use crate::source::{get_source_text, walk_span_to_context};
use crate::{clip, is_direct_expn_of, sext, unsext};
use if_chain::if_chain;
use rustc_ast::ast::{self, LitFloatType, LitKind};
use rustc_data_structures::sync::Lrc;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
+use rustc_lexer::tokenize;
use rustc_lint::LateContext;
use rustc_middle::mir;
use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::{List, SubstsRef};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Symbol;
+use rustc_span::SyntaxContext;
use std::cmp::Ordering::{self, Equal};
use std::hash::{Hash, Hasher};
use std::iter;
@@ -210,7 +213,7 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
match *lit {
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
LitKind::Byte(b) => Constant::Int(u128::from(b)),
- LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
+ LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
LitKind::Char(c) => Constant::Char(c),
LitKind::Int(n, _) => Constant::Int(n),
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
@@ -227,27 +230,46 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
}
}
+/// The source of a constant value.
+pub enum ConstantSource {
+ /// The value is determined solely from the expression.
+ Local,
+ /// The value is dependent on a defined constant.
+ Constant,
+}
+impl ConstantSource {
+ pub fn is_local(&self) -> bool {
+ matches!(self, Self::Local)
+ }
+}
+
+/// Attempts to evaluate the expression as a constant.
pub fn constant<'tcx>(
lcx: &LateContext<'tcx>,
typeck_results: &ty::TypeckResults<'tcx>,
e: &Expr<'_>,
-) -> Option<(Constant, bool)> {
- let mut cx = ConstEvalLateContext {
- lcx,
- typeck_results,
- param_env: lcx.param_env,
- needed_resolution: false,
- substs: ty::List::empty(),
- };
- cx.expr(e).map(|cst| (cst, cx.needed_resolution))
+) -> Option<Constant> {
+ ConstEvalLateContext::new(lcx, typeck_results).expr(e)
+}
+
+/// Attempts to evaluate the expression as a constant.
+pub fn constant_with_source<'tcx>(
+ lcx: &LateContext<'tcx>,
+ typeck_results: &ty::TypeckResults<'tcx>,
+ e: &Expr<'_>,
+) -> Option<(Constant, ConstantSource)> {
+ let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results);
+ let res = ctxt.expr(e);
+ res.map(|x| (x, ctxt.source))
}
+/// Attempts to evaluate an expression only if it's value is not dependent on other items.
pub fn constant_simple<'tcx>(
lcx: &LateContext<'tcx>,
typeck_results: &ty::TypeckResults<'tcx>,
e: &Expr<'_>,
) -> Option<Constant> {
- constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
+ constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c))
}
pub fn constant_full_int<'tcx>(
@@ -296,35 +318,31 @@ impl Ord for FullInt {
}
}
-/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
-pub fn constant_context<'a, 'tcx>(
- lcx: &'a LateContext<'tcx>,
- typeck_results: &'a ty::TypeckResults<'tcx>,
-) -> ConstEvalLateContext<'a, 'tcx> {
- ConstEvalLateContext {
- lcx,
- typeck_results,
- param_env: lcx.param_env,
- needed_resolution: false,
- substs: ty::List::empty(),
- }
-}
-
pub struct ConstEvalLateContext<'a, 'tcx> {
lcx: &'a LateContext<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- needed_resolution: bool,
+ source: ConstantSource,
substs: SubstsRef<'tcx>,
}
impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
+ fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self {
+ Self {
+ lcx,
+ typeck_results,
+ param_env: lcx.param_env,
+ source: ConstantSource::Local,
+ substs: List::empty(),
+ }
+ }
+
/// Simple constant folding: Insert an expression, get a constant or none.
pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
match e.kind {
ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)),
ExprKind::Block(block, _) => self.block(block),
- ExprKind::Lit(ref lit) => {
+ ExprKind::Lit(lit) => {
if is_direct_expn_of(e.span, "cfg").is_some() {
None
} else {
@@ -450,18 +468,12 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
let result = self
.lcx
.tcx
- .const_eval_resolve(
- self.param_env,
- mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs),
- None,
- )
+ .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None)
.ok()
.map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
- let result = miri_to_const(self.lcx.tcx, result);
- if result.is_some() {
- self.needed_resolution = true;
- }
- result
+ let result = miri_to_const(self.lcx.tcx, result)?;
+ self.source = ConstantSource::Constant;
+ Some(result)
},
// FIXME: cover all usable cases.
_ => None,
@@ -495,8 +507,33 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
/// A block can only yield a constant if it only has one constant expression.
fn block(&mut self, block: &Block<'_>) -> Option<Constant> {
- if block.stmts.is_empty() {
- block.expr.as_ref().and_then(|b| self.expr(b))
+ if block.stmts.is_empty()
+ && let Some(expr) = block.expr
+ {
+ // Try to detect any `cfg`ed statements or empty macro expansions.
+ let span = block.span.data();
+ if span.ctxt == SyntaxContext::root() {
+ if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt)
+ && let expr_lo = expr_span.lo()
+ && expr_lo >= span.lo
+ && let Some(src) = get_source_text(self.lcx, span.lo..expr_lo)
+ && let Some(src) = src.as_str()
+ {
+ use rustc_lexer::TokenKind::{Whitespace, LineComment, BlockComment, Semi, OpenBrace};
+ if !tokenize(src)
+ .map(|t| t.kind)
+ .filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi))
+ .eq([OpenBrace])
+ {
+ self.source = ConstantSource::Constant;
+ }
+ } else {
+ // Unable to access the source. Assume a non-local dependency.
+ self.source = ConstantSource::Constant;
+ }
+ }
+
+ self.expr(expr)
} else {
None
}
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 28c857170..3df40942e 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -218,7 +218,8 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
| ExprKind::AddrOf(..)
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
- | ExprKind::Block(Block { stmts: [], .. }, _) => (),
+ | ExprKind::Block(Block { stmts: [], .. }, _)
+ | ExprKind::OffsetOf(..) => (),
// Assignment might be to a local defined earlier, so don't eagerly evaluate.
// Blocks with multiple statements might be expensive, so don't eagerly evaluate.
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 50bef3709..a61e4c380 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -311,6 +311,8 @@ pub struct While<'hir> {
pub condition: &'hir Expr<'hir>,
/// `while` loop body
pub body: &'hir Expr<'hir>,
+ /// Span of the loop header
+ pub span: Span,
}
impl<'hir> While<'hir> {
@@ -336,10 +338,10 @@ impl<'hir> While<'hir> {
},
_,
LoopSource::While,
- _,
+ span,
) = expr.kind
{
- return Some(Self { condition, body });
+ return Some(Self { condition, body, span });
}
None
}
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 3ee714782..a49246a78 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1,6 +1,7 @@
use crate::consts::constant_simple;
use crate::macros::macro_backtrace;
-use crate::source::snippet_opt;
+use crate::source::{get_source_text, snippet_opt, walk_span_to_context, SpanRange};
+use crate::tokenize_with_text;
use rustc_ast::ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxHasher;
use rustc_hir::def::Res;
@@ -13,8 +14,9 @@ use rustc_hir::{
use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::LateContext;
use rustc_middle::ty::TypeckResults;
-use rustc_span::{sym, Symbol};
+use rustc_span::{sym, BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext};
use std::hash::{Hash, Hasher};
+use std::ops::Range;
/// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but
/// other conditions would make them equal.
@@ -65,6 +67,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
pub fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> {
HirEqInterExpr {
inner: self,
+ left_ctxt: SyntaxContext::root(),
+ right_ctxt: SyntaxContext::root(),
locals: HirIdMap::default(),
}
}
@@ -92,6 +96,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
pub struct HirEqInterExpr<'a, 'b, 'tcx> {
inner: &'a mut SpanlessEq<'b, 'tcx>,
+ left_ctxt: SyntaxContext,
+ right_ctxt: SyntaxContext,
// When binding are declared, the binding ID in the left expression is mapped to the one on the
// right. For example, when comparing `{ let x = 1; x + 2 }` and `{ let y = 1; y + 2 }`,
@@ -126,52 +132,88 @@ impl HirEqInterExpr<'_, '_, '_> {
}
/// Checks whether two blocks are the same.
+ #[expect(clippy::similar_names)]
fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool {
- match (left.stmts, left.expr, right.stmts, right.expr) {
- ([], None, [], None) => {
- // For empty blocks, check to see if the tokens are equal. This will catch the case where a macro
- // expanded to nothing, or the cfg attribute was used.
- let (Some(left), Some(right)) = (
- snippet_opt(self.inner.cx, left.span),
- snippet_opt(self.inner.cx, right.span),
- ) else { return true };
- let mut left_pos = 0;
- let left = tokenize(&left)
- .map(|t| {
- let end = left_pos + t.len as usize;
- let s = &left[left_pos..end];
- left_pos = end;
- (t, s)
- })
- .filter(|(t, _)| {
- !matches!(
- t.kind,
- TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
- )
- })
- .map(|(_, s)| s);
- let mut right_pos = 0;
- let right = tokenize(&right)
- .map(|t| {
- let end = right_pos + t.len as usize;
- let s = &right[right_pos..end];
- right_pos = end;
- (t, s)
- })
- .filter(|(t, _)| {
- !matches!(
- t.kind,
- TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
- )
- })
- .map(|(_, s)| s);
- left.eq(right)
- },
- _ => {
- over(left.stmts, right.stmts, |l, r| self.eq_stmt(l, r))
- && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r))
- },
+ use TokenKind::{BlockComment, LineComment, Semi, Whitespace};
+ if left.stmts.len() != right.stmts.len() {
+ return false;
+ }
+ let lspan = left.span.data();
+ let rspan = right.span.data();
+ if lspan.ctxt != SyntaxContext::root() && rspan.ctxt != SyntaxContext::root() {
+ // Don't try to check in between statements inside macros.
+ return over(left.stmts, right.stmts, |left, right| self.eq_stmt(left, right))
+ && both(&left.expr, &right.expr, |left, right| self.eq_expr(left, right));
+ }
+ if lspan.ctxt != rspan.ctxt {
+ return false;
+ }
+
+ let mut lstart = lspan.lo;
+ let mut rstart = rspan.lo;
+
+ for (left, right) in left.stmts.iter().zip(right.stmts) {
+ if !self.eq_stmt(left, right) {
+ return false;
+ }
+
+ // Try to detect any `cfg`ed statements or empty macro expansions.
+ let Some(lstmt_span) = walk_span_to_context(left.span, lspan.ctxt) else {
+ return false;
+ };
+ let Some(rstmt_span) = walk_span_to_context(right.span, rspan.ctxt) else {
+ return false;
+ };
+ let lstmt_span = lstmt_span.data();
+ let rstmt_span = rstmt_span.data();
+
+ if lstmt_span.lo < lstart && rstmt_span.lo < rstart {
+ // Can happen when macros expand to multiple statements, or rearrange statements.
+ // Nothing in between the statements to check in this case.
+ continue;
+ }
+ if lstmt_span.lo < lstart || rstmt_span.lo < rstart {
+ // Only one of the blocks had a weird macro.
+ return false;
+ }
+ if !eq_span_tokens(self.inner.cx, lstart..lstmt_span.lo, rstart..rstmt_span.lo, |t| {
+ !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+ }) {
+ return false;
+ }
+
+ lstart = lstmt_span.hi;
+ rstart = rstmt_span.hi;
+ }
+
+ let (lend, rend) = match (left.expr, right.expr) {
+ (Some(left), Some(right)) => {
+ if !self.eq_expr(left, right) {
+ return false;
+ }
+ let Some(lexpr_span) = walk_span_to_context(left.span, lspan.ctxt) else {
+ return false;
+ };
+ let Some(rexpr_span) = walk_span_to_context(right.span, rspan.ctxt) else {
+ return false;
+ };
+ (lexpr_span.lo(), rexpr_span.lo())
+ },
+ (None, None) => (lspan.hi, rspan.hi),
+ (Some(_), None) | (None, Some(_)) => return false,
+ };
+
+ if lend < lstart && rend < rstart {
+ // Can happen when macros rearrange the input.
+ // Nothing in between the statements to check in this case.
+ return true;
+ } else if lend < lstart || rend < rstart {
+ // Only one of the blocks had a weird macro
+ return false;
}
+ eq_span_tokens(self.inner.cx, lstart..lend, rstart..rend, |t| {
+ !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+ })
}
fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
@@ -207,7 +249,7 @@ impl HirEqInterExpr<'_, '_, '_> {
#[expect(clippy::similar_names)]
pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
- if !self.inner.allow_side_effects && left.span.ctxt() != right.span.ctxt() {
+ if !self.check_ctxt(left.span.ctxt(), right.span.ctxt()) {
return false;
}
@@ -301,6 +343,9 @@ impl HirEqInterExpr<'_, '_, '_> {
(&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
(&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r),
(&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re),
+ (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => {
+ self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name)
+ },
_ => false,
};
(is_eq && (!self.should_ignore(left) || !self.should_ignore(right)))
@@ -437,6 +482,45 @@ impl HirEqInterExpr<'_, '_, '_> {
fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -> bool {
left.ident.name == right.ident.name && self.eq_ty(left.ty(), right.ty())
}
+
+ fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool {
+ if self.left_ctxt == left && self.right_ctxt == right {
+ return true;
+ } else if self.left_ctxt == left || self.right_ctxt == right {
+ // Only one context has changed. This can only happen if the two nodes are written differently.
+ return false;
+ } else if left != SyntaxContext::root() {
+ let mut left_data = left.outer_expn_data();
+ let mut right_data = right.outer_expn_data();
+ loop {
+ use TokenKind::{BlockComment, LineComment, Whitespace};
+ if left_data.macro_def_id != right_data.macro_def_id
+ || (matches!(left_data.kind, ExpnKind::Macro(MacroKind::Bang, name) if name == sym::cfg)
+ && !eq_span_tokens(self.inner.cx, left_data.call_site, right_data.call_site, |t| {
+ !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. })
+ }))
+ {
+ // Either a different chain of macro calls, or different arguments to the `cfg` macro.
+ return false;
+ }
+ let left_ctxt = left_data.call_site.ctxt();
+ let right_ctxt = right_data.call_site.ctxt();
+ if left_ctxt == SyntaxContext::root() && right_ctxt == SyntaxContext::root() {
+ break;
+ }
+ if left_ctxt == SyntaxContext::root() || right_ctxt == SyntaxContext::root() {
+ // Different lengths for the expansion stack. This can only happen if nodes are written differently,
+ // or shouldn't be compared to start with.
+ return false;
+ }
+ left_data = left_ctxt.outer_expn_data();
+ right_data = right_ctxt.outer_expn_data();
+ }
+ }
+ self.left_ctxt = left;
+ self.right_ctxt = right;
+ true
+ }
}
/// Some simple reductions like `{ return }` => `return`
@@ -701,6 +785,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
}
},
+ ExprKind::OffsetOf(container, fields) => {
+ self.hash_ty(container);
+ for field in fields {
+ self.hash_name(field.name);
+ }
+ },
ExprKind::Let(Let { pat, init, ty, .. }) => {
self.hash_expr(init);
if let Some(ty) = ty {
@@ -709,7 +799,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_pat(pat);
},
ExprKind::Err(_) => {},
- ExprKind::Lit(ref l) => {
+ ExprKind::Lit(l) => {
l.node.hash(&mut self.s);
},
ExprKind::Loop(b, ref i, ..) => {
@@ -1029,3 +1119,34 @@ pub fn hash_expr(cx: &LateContext<'_>, e: &Expr<'_>) -> u64 {
h.hash_expr(e);
h.finish()
}
+
+#[expect(clippy::similar_names)]
+fn eq_span_tokens(
+ cx: &LateContext<'_>,
+ left: impl SpanRange,
+ right: impl SpanRange,
+ pred: impl Fn(TokenKind) -> bool,
+) -> bool {
+ fn f(cx: &LateContext<'_>, left: Range<BytePos>, right: Range<BytePos>, pred: impl Fn(TokenKind) -> bool) -> bool {
+ if let Some(lsrc) = get_source_text(cx, left)
+ && let Some(lsrc) = lsrc.as_str()
+ && let Some(rsrc) = get_source_text(cx, right)
+ && let Some(rsrc) = rsrc.as_str()
+ {
+ let pred = |t: &(_, _)| pred(t.0);
+ let map = |(_, x)| x;
+
+ let ltok = tokenize_with_text(lsrc)
+ .filter(pred)
+ .map(map);
+ let rtok = tokenize_with_text(rsrc)
+ .filter(pred)
+ .map(map);
+ ltok.eq(rtok)
+ } else {
+ // Unable to access the source. Conservatively assume the blocks aren't equal.
+ false
+ }
+ }
+ f(cx, left.into_range(), right.into_range(), pred)
+}
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 6b677df46..8c883445a 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,5 +1,6 @@
#![feature(array_chunks)]
#![feature(box_patterns)]
+#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(lint_reasons)]
#![feature(never_type)]
@@ -76,6 +77,7 @@ use std::sync::OnceLock;
use std::sync::{Mutex, MutexGuard};
use if_chain::if_chain;
+use itertools::Itertools;
use rustc_ast::ast::{self, LitKind, RangeLimits};
use rustc_ast::Attribute;
use rustc_data_structures::fx::FxHashMap;
@@ -86,10 +88,10 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
use rustc_hir::{
- self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness, Destination,
- Expr, ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, ItemKind, LangItem, Local,
+ self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr,
+ ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, ItemKind, LangItem, Local,
MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind,
- TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
+ TraitItem, TraitItemRef, TraitRef, TyKind, UnOp,
};
use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -197,31 +199,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
/// }
/// ```
pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
- let parent_id = cx.tcx.hir().get_parent_item(id).def_id;
- match cx.tcx.hir().get_by_def_id(parent_id) {
- Node::Item(&Item {
- kind: ItemKind::Const(..) | ItemKind::Static(..) | ItemKind::Enum(..),
- ..
- })
- | Node::TraitItem(&TraitItem {
- kind: TraitItemKind::Const(..),
- ..
- })
- | Node::ImplItem(&ImplItem {
- kind: ImplItemKind::Const(..),
- ..
- })
- | Node::AnonConst(_) => true,
- Node::Item(&Item {
- kind: ItemKind::Fn(ref sig, ..),
- ..
- })
- | Node::ImplItem(&ImplItem {
- kind: ImplItemKind::Fn(ref sig, _),
- ..
- }) => sig.header.constness == Constness::Const,
- _ => false,
- }
+ cx.tcx.hir().is_inside_const_context(id)
}
/// Checks if a `Res` refers to a constructor of a `LangItem`
@@ -306,6 +284,15 @@ pub fn is_wild(pat: &Pat<'_>) -> bool {
matches!(pat.kind, PatKind::Wild)
}
+/// Checks if the given `QPath` belongs to a type alias.
+pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
+ match *qpath {
+ QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias | DefKind::AssocTy, ..)),
+ QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) },
+ _ => false,
+ }
+}
+
/// Checks if the method call given in `expr` belongs to the given trait.
/// This is a deprecated function, consider using [`is_trait_method`].
pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
@@ -846,7 +833,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
},
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
ExprKind::Repeat(x, ArrayLen::Body(len)) => if_chain! {
- if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind;
+ if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind;
if let LitKind::Int(v, _) = const_lit.node;
if v <= 32 && is_default_equivalent(cx, x);
then {
@@ -875,7 +862,7 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
}) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
ExprKind::Repeat(_, ArrayLen::Body(len)) => {
- if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind &&
+ if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind &&
let LitKind::Int(v, _) = const_lit.node
{
return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
@@ -1512,7 +1499,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
&& let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
&& let min_const_kind = ConstantKind::from_value(const_val, bnd_ty)
&& let Some(min_const) = miri_to_const(cx.tcx, min_const_kind)
- && let Some((start_const, _)) = constant(cx, cx.typeck_results(), start)
+ && let Some(start_const) = constant(cx, cx.typeck_results(), start)
{
start_const == min_const
} else {
@@ -1528,7 +1515,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
&& let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
&& let max_const_kind = ConstantKind::from_value(const_val, bnd_ty)
&& let Some(max_const) = miri_to_const(cx.tcx, max_const_kind)
- && let Some((end_const, _)) = constant(cx, cx.typeck_results(), end)
+ && let Some(end_const) = constant(cx, cx.typeck_results(), end)
{
end_const == max_const
} else {
@@ -1560,7 +1547,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
return true;
}
let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
- if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
+ if let Some(Constant::Int(v)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
return value == v;
}
false
@@ -1569,7 +1556,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
/// Checks whether the given expression is a constant literal of the given value.
pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
// FIXME: use constant folding
- if let ExprKind::Lit(ref spanned) = expr.kind {
+ if let ExprKind::Lit(spanned) = expr.kind {
if let LitKind::Int(v, _) = spanned.node {
return v == value;
}
@@ -2165,10 +2152,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
.predicates
.iter()
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
- traits::impossible_predicates(
- cx.tcx,
- traits::elaborate(cx.tcx, predicates).collect::<Vec<_>>(),
- )
+ traits::impossible_predicates(cx.tcx, traits::elaborate(cx.tcx, predicates).collect::<Vec<_>>())
}
/// Returns the `DefId` of the callee if the given expression is a function or method call.
@@ -2233,8 +2217,12 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S
None
}
-/// returns list of all pairs (a, b) from `exprs` such that `eq(a, b)`
-/// `hash` must be comformed with `eq`
+/// Returns list of all pairs `(a, b)` where `eq(a, b) == true`
+/// and `a` is before `b` in `exprs` for all `a` and `b` in
+/// `exprs`
+///
+/// Given functions `eq` and `hash` such that `eq(a, b) == true`
+/// implies `hash(a) == hash(b)`
pub fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)>
where
Hash: Fn(&T) -> u64,
@@ -2503,6 +2491,17 @@ pub fn walk_to_expr_usage<'tcx, T>(
None
}
+/// Tokenizes the input while keeping the text associated with each token.
+pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str)> {
+ let mut pos = 0;
+ tokenize(s).map(move |t| {
+ let end = pos + t.len;
+ let range = pos as usize..end as usize;
+ pos = end;
+ (t.kind, s.get(range).unwrap_or_default())
+ })
+}
+
/// Checks whether a given span has any comment token
/// This checks for all types of comment: line "//", block "/**", doc "///" "//!"
pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
@@ -2519,23 +2518,11 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
/// Comments are returned wrapped with their relevant delimiters
pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
let snippet = sm.span_to_snippet(span).unwrap_or_default();
- let mut comments_buf: Vec<String> = Vec::new();
- let mut index: usize = 0;
-
- for token in tokenize(&snippet) {
- let token_range = index..(index + token.len as usize);
- index += token.len as usize;
- match token.kind {
- TokenKind::BlockComment { .. } | TokenKind::LineComment { .. } => {
- if let Some(comment) = snippet.get(token_range) {
- comments_buf.push(comment.to_string());
- }
- },
- _ => (),
- }
- }
-
- comments_buf.join("\n")
+ let res = tokenize_with_text(&snippet)
+ .filter(|(t, _)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
+ .map(|(_, s)| s)
+ .join("\n");
+ res
}
pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 62d388a5e..e4a4936ff 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -362,7 +362,7 @@ thread_local! {
/// able to access the many features of a [`LateContext`].
///
/// A thread local is used because [`FormatArgs`] is `!Send` and `!Sync`, we are making an
- /// assumption that the early pass the populates the map and the later late passes will all be
+ /// assumption that the early pass that populates the map and the later late passes will all be
/// running on the same thread.
static AST_FORMAT_ARGS: RefCell<FxHashMap<Span, FormatArgs>> = {
static CALLED: AtomicBool = AtomicBool::new(false);
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 9be2d0eae..0f0792fda 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -159,3 +159,7 @@ pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
pub const PTR_NON_NULL: [&str; 4] = ["core", "ptr", "non_null", "NonNull"];
pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
pub const INSTANT: [&str; 3] = ["std", "time", "Instant"];
+pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];
+pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"];
+pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
+pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
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 354b6d71a..c0d2c835d 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
@@ -194,7 +194,9 @@ fn check_rvalue<'tcx>(
))
}
},
- Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => Ok(()),
+ Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) | Rvalue::ShallowInitBox(_, _) => {
+ Ok(())
+ },
Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(body, tcx);
if ty.is_integral() || ty.is_bool() {
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 62fa37660..0f6029064 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -2,14 +2,64 @@
#![allow(clippy::module_name_repetitions)]
+use rustc_data_structures::sync::Lrc;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LintContext};
use rustc_session::Session;
-use rustc_span::hygiene;
use rustc_span::source_map::{original_sp, SourceMap};
+use rustc_span::{hygiene, SourceFile};
use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
use std::borrow::Cow;
+use std::ops::Range;
+
+/// A type which can be converted to the range portion of a `Span`.
+pub trait SpanRange {
+ fn into_range(self) -> Range<BytePos>;
+}
+impl SpanRange for Span {
+ fn into_range(self) -> Range<BytePos> {
+ let data = self.data();
+ data.lo..data.hi
+ }
+}
+impl SpanRange for SpanData {
+ fn into_range(self) -> Range<BytePos> {
+ self.lo..self.hi
+ }
+}
+impl SpanRange for Range<BytePos> {
+ fn into_range(self) -> Range<BytePos> {
+ self
+ }
+}
+
+pub struct SourceFileRange {
+ pub sf: Lrc<SourceFile>,
+ pub range: Range<usize>,
+}
+impl SourceFileRange {
+ /// Attempts to get the text from the source file. This can fail if the source text isn't
+ /// loaded.
+ pub fn as_str(&self) -> Option<&str> {
+ self.sf.src.as_ref().and_then(|x| x.get(self.range.clone()))
+ }
+}
+
+/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
+/// extends through multiple files, or is malformed.
+pub fn get_source_text(cx: &impl LintContext, sp: impl SpanRange) -> Option<SourceFileRange> {
+ fn f(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> {
+ let start = sm.lookup_byte_offset(sp.start);
+ let end = sm.lookup_byte_offset(sp.end);
+ if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos {
+ return None;
+ }
+ let range = start.pos.to_usize()..end.pos.to_usize();
+ Some(SourceFileRange { sf: start.sf, range })
+ }
+ f(cx.sess().source_map(), sp.into_range())
+}
/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
pub fn expr_block<T: LintContext>(
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index a5a4a921d..14f7f0301 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -139,6 +139,7 @@ impl<'a> Sugg<'a> {
| hir::ExprKind::Field(..)
| hir::ExprKind::Index(..)
| hir::ExprKind::InlineAsm(..)
+ | hir::ExprKind::OffsetOf(..)
| hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Lit(..)
| hir::ExprKind::Loop(..)
@@ -161,8 +162,9 @@ impl<'a> Sugg<'a> {
get_snippet(lhs.span),
get_snippet(rhs.span),
),
- hir::ExprKind::Cast(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)),
- hir::ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::Colon, get_snippet(lhs.span), get_snippet(ty.span)),
+ hir::ExprKind::Cast(lhs, ty) |
+ //FIXME(chenyukang), remove this after type ascription is removed from AST
+ hir::ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)),
}
}
@@ -197,6 +199,7 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::ForLoop(..)
| ast::ExprKind::Index(..)
| ast::ExprKind::InlineAsm(..)
+ | ast::ExprKind::OffsetOf(..)
| ast::ExprKind::ConstBlock(..)
| ast::ExprKind::Lit(..)
| ast::ExprKind::IncludedBytes(..)
@@ -251,13 +254,10 @@ impl<'a> Sugg<'a> {
snippet_with_context(cx, lhs.span, ctxt, default, app).0,
snippet_with_context(cx, rhs.span, ctxt, default, app).0,
),
- ast::ExprKind::Cast(ref lhs, ref ty) => Sugg::BinOp(
- AssocOp::As,
- snippet_with_context(cx, lhs.span, ctxt, default, app).0,
- snippet_with_context(cx, ty.span, ctxt, default, app).0,
- ),
+ ast::ExprKind::Cast(ref lhs, ref ty) |
+ //FIXME(chenyukang), remove this after type ascription is removed from AST
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
- AssocOp::Colon,
+ AssocOp::As,
snippet_with_context(cx, lhs.span, ctxt, default, app).0,
snippet_with_context(cx, ty.span, ctxt, default, app).0,
),
@@ -390,7 +390,6 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
AssocOp::As => format!("{lhs} as {rhs}"),
AssocOp::DotDot => format!("{lhs}..{rhs}"),
AssocOp::DotDotEq => format!("{lhs}..={rhs}"),
- AssocOp::Colon => format!("{lhs}: {rhs}"),
}
}
@@ -600,13 +599,13 @@ enum Associativity {
#[must_use]
fn associativity(op: AssocOp) -> Associativity {
use rustc_ast::util::parser::AssocOp::{
- Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Colon, Divide, DotDot, DotDotEq, Equal, Greater,
- GreaterEqual, LAnd, LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract,
+ Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Divide, DotDot, DotDotEq, Equal, Greater, GreaterEqual, LAnd,
+ LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract,
};
match op {
Assign | AssignOp(_) => Associativity::Right,
- Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both,
+ Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As => Associativity::Both,
Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight
| Subtract => Associativity::Left,
DotDot | DotDotEq => Associativity::None,
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 9449f0b55..7b4ed77e8 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -90,10 +90,10 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
return false;
}
- for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
+ for (predicate, _span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() {
match predicate.kind().skip_binder() {
// For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
- // and check substituions to find `U`.
+ // and check substitutions to find `U`.
ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
if trait_predicate
.trait_ref
@@ -226,7 +226,7 @@ pub fn implements_trait_with_env<'tcx>(
ty_params: impl IntoIterator<Item = Option<GenericArg<'tcx>>>,
) -> bool {
// Clippy shouldn't have infer types
- assert!(!ty.needs_infer());
+ assert!(!ty.has_infer());
let ty = tcx.erase_regions(ty);
if ty.has_escaping_bound_vars() {
@@ -267,7 +267,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
},
ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
- for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
+ for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() {
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() {
if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
return true;
@@ -743,7 +743,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
for (pred, _) in cx
.tcx
- .bound_explicit_item_bounds(ty.def_id)
+ .explicit_item_bounds(ty.def_id)
.subst_iter_copied(cx.tcx, ty.substs)
{
match pred.kind().skip_binder() {
@@ -837,7 +837,7 @@ pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
if let ty::Adt(adt, _) = ty.kind()
&& let &[krate, .., name] = &*cx.get_def_path(adt.did())
&& let sym::libc | sym::core | sym::std = krate
- && name.as_str() == "c_void"
+ && name == rustc_span::sym::c_void
{
true
} else {
@@ -975,7 +975,7 @@ pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 {
}
match (cx.layout_of(ty).map(|layout| layout.size.bytes()), ty.kind()) {
(Ok(size), _) => size,
- (Err(_), ty::Tuple(list)) => list.as_substs().types().map(|t| approx_ty_size(cx, t)).sum(),
+ (Err(_), ty::Tuple(list)) => list.iter().map(|t| approx_ty_size(cx, t)).sum(),
(Err(_), ty::Array(t, n)) => {
n.try_eval_target_usize(cx.tcx, cx.param_env).unwrap_or_default() * approx_ty_size(cx, *t)
},
@@ -1101,7 +1101,7 @@ pub fn make_projection<'tcx>(
///
/// This function is for associated types which are "known" to be valid with the given
/// substitutions, and as such, will only return `None` when debug assertions are disabled in order
-/// to prevent ICE's. With debug assertions enabled this will check that that type normalization
+/// to prevent ICE's. With debug assertions enabled this will check that type normalization
/// succeeds as well as everything checked by `make_projection`.
pub fn make_normalized_projection<'tcx>(
tcx: TyCtxt<'tcx>,
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 1dc19bac9..5dcd71cef 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -662,6 +662,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
| ExprKind::Path(_)
| ExprKind::Continue(_)
| ExprKind::InlineAsm(_)
+ | ExprKind::OffsetOf(..)
| ExprKind::Err(_) => (),
}
ControlFlow::Continue(())
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index 5c9f76dbb..139102798 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "declare_clippy_lint"
-version = "0.1.70"
+version = "0.1.71"
edition = "2021"
publish = false
@@ -10,7 +10,7 @@ proc-macro = true
[dependencies]
itertools = "0.10.1"
quote = "1.0.21"
-syn = "1.0.100"
+syn = "2.0"
[features]
deny-warnings = []
diff --git a/src/tools/clippy/declare_clippy_lint/src/lib.rs b/src/tools/clippy/declare_clippy_lint/src/lib.rs
index 26210556d..5232e4ab7 100644
--- a/src/tools/clippy/declare_clippy_lint/src/lib.rs
+++ b/src/tools/clippy/declare_clippy_lint/src/lib.rs
@@ -6,16 +6,16 @@
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse::{Parse, ParseStream};
-use syn::{parse_macro_input, Attribute, Error, Ident, Lit, LitStr, Meta, Result, Token};
+use syn::{parse_macro_input, Attribute, Error, Expr, ExprLit, Ident, Lit, LitStr, Meta, Result, Token};
fn parse_attr<const LEN: usize>(path: [&'static str; LEN], attr: &Attribute) -> Option<LitStr> {
- if let Meta::NameValue(name_value) = attr.parse_meta().ok()? {
+ if let Meta::NameValue(name_value) = &attr.meta {
let path_idents = name_value.path.segments.iter().map(|segment| &segment.ident);
if itertools::equal(path_idents, path)
- && let Lit::Str(lit) = name_value.lit
+ && let Expr::Lit(ExprLit { lit: Lit::Str(s), .. }) = &name_value.value
{
- return Some(lit);
+ return Some(s.clone());
}
}
diff --git a/src/tools/clippy/lintcheck/README.md b/src/tools/clippy/lintcheck/README.md
index faf3ce909..37cc04538 100644
--- a/src/tools/clippy/lintcheck/README.md
+++ b/src/tools/clippy/lintcheck/README.md
@@ -79,9 +79,11 @@ is explicitly specified in the options.
### Fix mode
You can run `cargo lintcheck --fix` which will run Clippy with `--fix` and
-print a warning if Clippy's suggestions fail to apply (if the resulting code does not build).
+print a warning if Clippy's suggestions fail to apply (if the resulting code does not build).
This lets us spot bad suggestions or false positives automatically in some cases.
+> Note: Fix mode implies `--all-targets`, so it can fix as much code as it can.
+
Please note that the target dir should be cleaned afterwards since clippy will modify
the downloaded sources which can lead to unexpected results when running lintcheck again afterwards.
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index 23c852980..03d1877d6 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -421,7 +421,7 @@ impl Crate {
{
let subcrate = &stderr[63..];
println!(
- "ERROR: failed to apply some suggetion to {} / to (sub)crate {subcrate}",
+ "ERROR: failed to apply some suggestion to {} / to (sub)crate {subcrate}",
self.name
);
}
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 91e8ccea1..bc7fb711e 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2023-04-06"
+channel = "nightly-2023-05-20"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 718bc41fb..59bf447a7 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -11,7 +11,6 @@
// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
extern crate rustc_driver;
-extern crate rustc_errors;
extern crate rustc_interface;
extern crate rustc_session;
extern crate rustc_span;
@@ -20,13 +19,10 @@ use rustc_interface::interface;
use rustc_session::parse::ParseSess;
use rustc_span::symbol::Symbol;
-use std::borrow::Cow;
use std::env;
use std::ops::Deref;
-use std::panic;
use std::path::Path;
use std::process::exit;
-use std::sync::LazyLock;
/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
@@ -160,6 +156,9 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
// MIR passes can be enabled / disabled separately, we should figure out, what passes to
// use for Clippy.
config.opts.unstable_opts.mir_opt_level = Some(0);
+
+ // Disable flattening and inlining of format_args!(), so the HIR matches with the AST.
+ config.opts.unstable_opts.flatten_format_args = false;
}
}
@@ -195,66 +194,18 @@ You can use tool lints to allow or deny lints from your code, eg.:
const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new";
-type PanicCallback = dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static;
-static ICE_HOOK: LazyLock<Box<PanicCallback>> = LazyLock::new(|| {
- let hook = panic::take_hook();
- panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL)));
- hook
-});
-
-fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
- // Invoke our ICE handler, which prints the actual panic message and optionally a backtrace
- (*ICE_HOOK)(info);
-
- // Separate the output with an empty line
- eprintln!();
-
- let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
- let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
- rustc_errors::ColorConfig::Auto,
- None,
- None,
- fallback_bundle,
- false,
- false,
- None,
- false,
- false,
- rustc_errors::TerminalUrl::No,
- ));
- let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-
- // a .span_bug or .bug call has already printed what
- // it wants to print.
- if !info.payload().is::<rustc_errors::ExplicitBug>() {
- let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
- handler.emit_diagnostic(&mut d);
- }
-
- let version_info = rustc_tools_util::get_version_info!();
-
- let xs: Vec<Cow<'static, str>> = vec![
- "the compiler unexpectedly panicked. this is a bug.".into(),
- format!("we would appreciate a bug report: {bug_report_url}").into(),
- format!("Clippy version: {version_info}").into(),
- ];
-
- for note in &xs {
- handler.note_without_error(note.as_ref());
- }
-
- // If backtraces are enabled, also print the query stack
- let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
-
- let num_frames = if backtrace { None } else { Some(2) };
-
- interface::try_print_query_stack(&handler, num_frames);
-}
-
#[allow(clippy::too_many_lines)]
pub fn main() {
rustc_driver::init_rustc_env_logger();
- LazyLock::force(&ICE_HOOK);
+
+ rustc_driver::install_ice_hook(BUG_REPORT_URL, |handler| {
+ // FIXME: this macro calls unwrap internally but is called in a panicking context! It's not
+ // as simple as moving the call from the hook to main, because `install_ice_hook` doesn't
+ // accept a generic closure.
+ let version_info = rustc_tools_util::get_version_info!();
+ handler.note_without_error(format!("Clippy version: {version_info}"));
+ });
+
exit(rustc_driver::catch_with_exit_code(move || {
let mut orig_args: Vec<String> = env::args().collect();
let has_sysroot_arg = arg_value(&orig_args, "--sysroot", |_| true).is_some();
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index c5e9b96cf..188ff87ab 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -13,7 +13,7 @@ Usage:
Common options:
--no-deps Run Clippy only on the given crate, without linting the dependencies
- --fix Automatically apply lint suggestions. This flag implies `--no-deps`
+ --fix Automatically apply lint suggestions. This flag implies `--no-deps` and `--all-targets`
-h, --help Print this message
-V, --version Print version info and exit
--explain LINT Print the documentation for a given lint
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 57890ff31..35d75cc51 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -126,6 +126,7 @@ fn base_config(test_dir: &str) -> compiletest::Config {
let mut config = compiletest::Config {
edition: Some("2021".into()),
mode: TestMode::Ui,
+ strict_headers: true,
..Default::default()
};
@@ -424,7 +425,7 @@ fn check_rustfix_coverage() {
.binary_search_by_key(&filename, Path::new)
.is_ok(),
"`{rs_file}` runs `MachineApplicable` diagnostics but is missing a `run-rustfix` annotation. \
- Please either add `// run-rustfix` at the top of the file or add the file to \
+ Please either add `//@run-rustfix` at the top of the file or add the file to \
`RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS` in `tests/compile-test.rs`.",
);
}
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 68a878e9a..afde31fac 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -39,7 +39,7 @@ fn dogfood_clippy() {
assert!(
failed_packages.is_empty(),
"Dogfood failed for packages `{}`",
- failed_packages.iter().format(", "),
+ failed_packages.iter().join(", "),
);
}
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs
index 27841e18a..1a69bb241 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=cargo_common_metadata
+//@compile-flags: --crate-name=cargo_common_metadata
#![warn(clippy::cargo_common_metadata)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs
index 27841e18a..1a69bb241 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=cargo_common_metadata
+//@compile-flags: --crate-name=cargo_common_metadata
#![warn(clippy::cargo_common_metadata)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs
index 27841e18a..1a69bb241 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=cargo_common_metadata
+//@compile-flags: --crate-name=cargo_common_metadata
#![warn(clippy::cargo_common_metadata)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs
index 27841e18a..1a69bb241 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=cargo_common_metadata
+//@compile-flags: --crate-name=cargo_common_metadata
#![warn(clippy::cargo_common_metadata)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs
index 27841e18a..1a69bb241 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=cargo_common_metadata
+//@compile-flags: --crate-name=cargo_common_metadata
#![warn(clippy::cargo_common_metadata)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs
index 27841e18a..1a69bb241 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=cargo_common_metadata
+//@compile-flags: --crate-name=cargo_common_metadata
#![warn(clippy::cargo_common_metadata)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs
index 64f01a98c..4dd9582af 100644
--- a/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=feature_name
+//@compile-flags: --crate-name=feature_name
#![warn(clippy::redundant_feature_names)]
#![warn(clippy::negative_feature_names)]
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs b/src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs
index 64f01a98c..4dd9582af 100644
--- a/src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=feature_name
+//@compile-flags: --crate-name=feature_name
#![warn(clippy::redundant_feature_names)]
#![warn(clippy::negative_feature_names)]
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs
index ba4c8c873..c70d92e35 100644
--- a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --remap-path-prefix {{src-base}}=/remapped
+//@compile-flags: --remap-path-prefix {{src-base}}=/remapped
#![warn(clippy::self_named_module_files)]
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs
index 1b2d3ec94..ece260b74 100644
--- a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=multiple_crate_versions
+//@compile-flags: --crate-name=multiple_crate_versions
#![warn(clippy::multiple_crate_versions)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs
index 1b2d3ec94..ece260b74 100644
--- a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=multiple_crate_versions
+//@compile-flags: --crate-name=multiple_crate_versions
#![warn(clippy::multiple_crate_versions)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs
index 1b2d3ec94..ece260b74 100644
--- a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=multiple_crate_versions
+//@compile-flags: --crate-name=multiple_crate_versions
#![warn(clippy::multiple_crate_versions)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs b/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs
index 581babfea..bb3a39d07 100644
--- a/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=wildcard_dependencies
+//@compile-flags: --crate-name=wildcard_dependencies
#![warn(clippy::wildcard_dependencies)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs b/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs
index 581babfea..bb3a39d07 100644
--- a/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs
+++ b/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=wildcard_dependencies
+//@compile-flags: --crate-name=wildcard_dependencies
#![warn(clippy::wildcard_dependencies)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed
index 9f299d7de..72c04bf80 100644
--- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed
+++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)]
#![feature(rustc_private)]
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 2b113f555..76f7c3ce9 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
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)]
#![feature(rustc_private)]
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 837811bdf..99ce70283 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -1,9 +1,10 @@
-// rustc-env:RUST_BACKTRACE=0
-// normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo"
-// normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs"
-// normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
-// normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
-// normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
+//@rustc-env:RUST_BACKTRACE=0
+//@normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo"
+//@normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs"
+//@normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
+//@normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
+//@normalize-stderr-test: "running on .*" -> "running on <target>"
+//@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)]
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 b4619e980..0fc385cd6 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -1,12 +1,14 @@
thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: internal compiler error: unexpected panic
-
-note: the compiler unexpectedly panicked. this is a bug.
+error: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new
+note: rustc 1.71.0-nightly (521f4dae1 2023-05-19) running on <target>
+
+note: compiler flags: -C prefer-dynamic -Z ui-testing
+
note: Clippy version: foo
thread panicked while panicking. aborting.
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 eaea218e1..a1a10c079 100644
--- a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed
+++ b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)]
#![feature(rustc_private)]
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 7efebb8fa..32dbfe5dc 100644
--- a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs
+++ b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)]
#![feature(rustc_private)]
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 08634063a..ac0752774 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
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)]
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 f8af77e6d..56f778621 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
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)]
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 bb82faf0c..d8a08bc99 100644
--- a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed
+++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)]
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 187d468b3..f7af0e9d8 100644
--- a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs
+++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)]
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 e474f370a..fce24412f 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:paths.rs
+//@run-rustfix
+//@aux-build:paths.rs
#![deny(clippy::internal)]
#![feature(rustc_private)]
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 f17fed6c6..b10bc9e46 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:paths.rs
+//@run-rustfix
+//@aux-build:paths.rs
#![deny(clippy::internal)]
#![feature(rustc_private)]
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 6033d06e4..b802de1cb 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(rustc_private)]
#![deny(clippy::internal)]
#![allow(
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 1bb5d55f0..c1bead5bd 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(rustc_private)]
#![deny(clippy::internal)]
#![allow(
diff --git a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed
index aa8b45b5f..23e7bc16d 100644
--- a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed
+++ b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::uninlined_format_args)]
fn main() {
diff --git a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs
index ad2e4863e..d66b2b8ff 100644
--- a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs
+++ b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::uninlined_format_args)]
fn main() {
diff --git a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs
index 5d9ce18f6..21e4fce26 100644
--- a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs
@@ -1,4 +1,4 @@
-// compile-flags: --test
+//@compile-flags: --test
#![warn(clippy::dbg_macro)]
fn foo(n: u32) -> u32 {
diff --git a/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs
index 2bb537607..ba919b487 100644
--- a/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs
+++ b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs
@@ -1,4 +1,4 @@
-// aux-build:macros.rs
+//@aux-build:macros.rs
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
index 89f142a15..9e267c893 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
@@ -1,4 +1,4 @@
-// compile-flags: --test
+//@compile-flags: --test
#![warn(clippy::expect_used)]
fn expect_option() {
diff --git a/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs b/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs
index 667c51cb4..095e0d154 100644
--- a/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs
+++ b/src/tools/clippy/tests/ui-toml/mut_key/mut_key.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name mut_key
+//@compile-flags: --crate-name mut_key
#![warn(clippy::mutable_key_type)]
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs
index 6452189a4..f5761c6af 100644
--- a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs
@@ -1,5 +1,5 @@
-// compile-flags: --emit=link
-// no-prefer-dynamic
+//@compile-flags: --emit=link
+//@no-prefer-dynamic
#![crate_type = "proc-macro"]
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed
index 01d135764..e4747bedd 100644
--- a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed
@@ -1,5 +1,5 @@
-// aux-build:proc_macro_derive.rs
-// run-rustfix
+//@aux-build:proc_macro_derive.rs
+//@run-rustfix
#![warn(clippy::nonstandard_macro_braces)]
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
index 72883e827..54edded99 100644
--- a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
@@ -1,5 +1,5 @@
-// aux-build:proc_macro_derive.rs
-// run-rustfix
+//@aux-build:proc_macro_derive.rs
+//@run-rustfix
#![warn(clippy::nonstandard_macro_braces)]
diff --git a/src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs b/src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs
index 5aefb6a6b..3a8b30cca 100644
--- a/src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs
+++ b/src/tools/clippy/tests/ui-toml/print_macro/print_macro.rs
@@ -1,4 +1,4 @@
-// compile-flags: --test
+//@compile-flags: --test
#![warn(clippy::print_stdout)]
#![warn(clippy::print_stderr)]
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/both.fixed b/src/tools/clippy/tests/ui-toml/semicolon_block/both.fixed
new file mode 100644
index 000000000..fc8038a09
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/both.fixed
@@ -0,0 +1,86 @@
+//@run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()) };
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/both.rs b/src/tools/clippy/tests/ui-toml/semicolon_block/both.rs
new file mode 100644
index 000000000..52ce1f038
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/both.rs
@@ -0,0 +1,86 @@
+//@run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/both.stderr b/src/tools/clippy/tests/ui-toml/semicolon_block/both.stderr
new file mode 100644
index 000000000..2f58842ea
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/both.stderr
@@ -0,0 +1,55 @@
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/both.rs:43:5
+ |
+LL | { unit_fn_block(); }
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::semicolon-outside-block` implied by `-D warnings`
+help: put the `;` here
+ |
+LL - { unit_fn_block(); }
+LL + { unit_fn_block() };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/both.rs:44:5
+ |
+LL | unsafe { unit_fn_block(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - unsafe { unit_fn_block(); }
+LL + unsafe { unit_fn_block() };
+ |
+
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/both.rs:49:5
+ |
+LL | / {
+LL | | unit_fn_block();
+LL | | unit_fn_block()
+LL | | };
+ | |______^
+ |
+ = note: `-D clippy::semicolon-inside-block` implied by `-D warnings`
+help: put the `;` here
+ |
+LL ~ unit_fn_block();
+LL ~ }
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/both.rs:63:5
+ |
+LL | { m!(()); }
+ | ^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - { m!(()); }
+LL + { m!(()) };
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/clippy.toml b/src/tools/clippy/tests/ui-toml/semicolon_block/clippy.toml
new file mode 100644
index 000000000..4d03e88de
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/clippy.toml
@@ -0,0 +1,2 @@
+semicolon-inside-block-ignore-singleline = true
+semicolon-outside-block-ignore-multiline = true
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed
new file mode 100644
index 000000000..23df98301
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed
@@ -0,0 +1,85 @@
+//@run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.rs b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.rs
new file mode 100644
index 000000000..e8516f79b
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.rs
@@ -0,0 +1,85 @@
+//@run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr
new file mode 100644
index 000000000..2569dc4b4
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr
@@ -0,0 +1,18 @@
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:48:5
+ |
+LL | / {
+LL | | unit_fn_block();
+LL | | unit_fn_block()
+LL | | };
+ | |______^
+ |
+ = note: `-D clippy::semicolon-inside-block` implied by `-D warnings`
+help: put the `;` here
+ |
+LL ~ unit_fn_block();
+LL ~ }
+ |
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed
new file mode 100644
index 000000000..7e9055e71
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed
@@ -0,0 +1,85 @@
+//@run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()) };
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.rs b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.rs
new file mode 100644
index 000000000..4dc956d8a
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.rs
@@ -0,0 +1,85 @@
+//@run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr
new file mode 100644
index 000000000..6dd3577dd
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr
@@ -0,0 +1,39 @@
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:42:5
+ |
+LL | { unit_fn_block(); }
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::semicolon-outside-block` implied by `-D warnings`
+help: put the `;` here
+ |
+LL - { unit_fn_block(); }
+LL + { unit_fn_block() };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:43:5
+ |
+LL | unsafe { unit_fn_block(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - unsafe { unit_fn_block(); }
+LL + unsafe { unit_fn_block() };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:62:5
+ |
+LL | { m!(()); }
+ | ^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - { m!(()); }
+LL + { m!(()) };
+ |
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
index 2f3160c83..8e1a1710a 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name conf_disallowed_methods
+//@compile-flags: --crate-name conf_disallowed_methods
#![warn(clippy::disallowed_methods)]
diff --git a/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs b/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs
index fb0e226f3..179b12661 100644
--- a/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs
@@ -1,5 +1,5 @@
-// normalize-stderr-test "\(\d+ byte\)" -> "(N byte)"
-// normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)"
+//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
+//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
#![deny(clippy::trivially_copy_pass_by_ref)]
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
index f328e4d9d..569fd2c35 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
@@ -1 +1,3 @@
+//@error-pattern: unknown field `foobar`, expected one of
+
fn main() {}
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 8447c3172..44710b096 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
@@ -37,6 +37,8 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
missing-docs-in-crate-items
msrv
pass-by-value-size-limit
+ semicolon-inside-block-ignore-singleline
+ semicolon-outside-block-ignore-multiline
single-char-binding-names-threshold
standard-macro-braces
suppress-restriction-lint-in-const
@@ -46,6 +48,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
too-many-lines-threshold
trivial-copy-size-limit
type-complexity-threshold
+ unnecessary-box-size
unreadable-literal-lint-fractions
upper-case-acronyms-aggressive
vec-box-size-threshold
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
index 6525ea5bf..5d3e800ca 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
@@ -1,4 +1,4 @@
-// compile-flags: --test
+//@compile-flags: --test
#![allow(unused_mut, clippy::get_first, clippy::from_iter_instead_of_collect)]
#![warn(clippy::unwrap_used)]
diff --git a/src/tools/clippy/tests/ui/allow_attributes.fixed b/src/tools/clippy/tests/ui/allow_attributes.fixed
index b8dd0619e..f0936b260 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.fixed
+++ b/src/tools/clippy/tests/ui/allow_attributes.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::allow_attributes)]
#![feature(lint_reasons)]
diff --git a/src/tools/clippy/tests/ui/allow_attributes.rs b/src/tools/clippy/tests/ui/allow_attributes.rs
index 295f56090..2fb9e8612 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.rs
+++ b/src/tools/clippy/tests/ui/allow_attributes.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::allow_attributes)]
#![feature(lint_reasons)]
diff --git a/src/tools/clippy/tests/ui/allow_attributes_false_positive.rs b/src/tools/clippy/tests/ui/allow_attributes_false_positive.rs
new file mode 100644
index 000000000..5c3407628
--- /dev/null
+++ b/src/tools/clippy/tests/ui/allow_attributes_false_positive.rs
@@ -0,0 +1,5 @@
+#![warn(clippy::allow_attributes)]
+#![feature(lint_reasons)]
+#![crate_type = "proc-macro"]
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.fixed b/src/tools/clippy/tests/ui/almost_complete_range.fixed
index a4bf7fe18..5cd0dcce6 100644
--- a/src/tools/clippy/tests/ui/almost_complete_range.fixed
+++ b/src/tools/clippy/tests/ui/almost_complete_range.fixed
@@ -1,6 +1,6 @@
-// run-rustfix
-// edition:2018
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@edition:2018
+//@aux-build:proc_macros.rs
#![feature(exclusive_range_pattern)]
#![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.rs b/src/tools/clippy/tests/ui/almost_complete_range.rs
index 8237c3a13..db0bfc8af 100644
--- a/src/tools/clippy/tests/ui/almost_complete_range.rs
+++ b/src/tools/clippy/tests/ui/almost_complete_range.rs
@@ -1,6 +1,6 @@
-// run-rustfix
-// edition:2018
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@edition:2018
+//@aux-build:proc_macros.rs
#![feature(exclusive_range_pattern)]
#![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index 3c06676d7..f95af1017 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -1,3 +1,5 @@
+//@aux-build:proc_macro_derive.rs
+
#![allow(
clippy::assign_op_pattern,
clippy::erasing_op,
@@ -11,6 +13,8 @@
#![feature(const_mut_refs, inline_const, saturating_int_impl)]
#![warn(clippy::arithmetic_side_effects)]
+extern crate proc_macro_derive;
+
use core::num::{Saturating, Wrapping};
const ONE: i32 = 1;
@@ -19,6 +23,9 @@ const ZERO: i32 = 0;
#[derive(Clone, Copy)]
pub struct Custom;
+#[derive(proc_macro_derive::ShadowDerive)]
+pub struct Nothing;
+
macro_rules! impl_arith {
( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
$(
@@ -269,6 +276,17 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
_n = &1 * _n;
_n = 23 + 85;
+ // Method
+ _n.saturating_div(1);
+ _n.wrapping_div(1);
+ _n.wrapping_rem(1);
+ _n.wrapping_rem_euclid(1);
+
+ _n.saturating_div(1);
+ _n.checked_div(1);
+ _n.checked_rem(1);
+ _n.checked_rem_euclid(1);
+
// Unary
_n = -2147483647;
_n = -i32::MAX;
@@ -376,6 +394,17 @@ pub fn unknown_ops_or_runtime_ops_that_can_overflow() {
_custom = Custom << _custom;
_custom = &Custom << _custom;
+ // Method
+ _n.saturating_div(0);
+ _n.wrapping_div(0);
+ _n.wrapping_rem(0);
+ _n.wrapping_rem_euclid(0);
+
+ _n.saturating_div(_n);
+ _n.wrapping_div(_n);
+ _n.wrapping_rem(_n);
+ _n.wrapping_rem_euclid(_n);
+
// Unary
_n = -_n;
_n = -&_n;
@@ -429,4 +458,12 @@ pub fn issue_10583(a: u16) -> u16 {
10 / a
}
+pub fn issue_10767() {
+ let n = &1.0;
+ n + n;
+ 3.1_f32 + &1.2_f32;
+ &3.4_f32 + 1.5_f32;
+ &3.5_f32 + &1.3_f32;
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 2c8ee2884..e9a626643 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,5 +1,5 @@
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:286:5
+ --> $DIR/arithmetic_side_effects.rs:304:5
|
LL | _n += 1;
| ^^^^^^^
@@ -7,652 +7,700 @@ LL | _n += 1;
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:287:5
+ --> $DIR/arithmetic_side_effects.rs:305:5
|
LL | _n += &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:288:5
+ --> $DIR/arithmetic_side_effects.rs:306:5
|
LL | _n -= 1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:289:5
+ --> $DIR/arithmetic_side_effects.rs:307:5
|
LL | _n -= &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:290:5
+ --> $DIR/arithmetic_side_effects.rs:308:5
|
LL | _n /= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:291:5
+ --> $DIR/arithmetic_side_effects.rs:309:5
|
LL | _n /= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:292:5
+ --> $DIR/arithmetic_side_effects.rs:310:5
|
LL | _n %= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:293:5
+ --> $DIR/arithmetic_side_effects.rs:311:5
|
LL | _n %= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:294:5
+ --> $DIR/arithmetic_side_effects.rs:312:5
|
LL | _n *= 2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:295:5
+ --> $DIR/arithmetic_side_effects.rs:313:5
|
LL | _n *= &2;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:296:5
+ --> $DIR/arithmetic_side_effects.rs:314:5
|
LL | _n += -1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:297:5
+ --> $DIR/arithmetic_side_effects.rs:315:5
|
LL | _n += &-1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:298:5
+ --> $DIR/arithmetic_side_effects.rs:316:5
|
LL | _n -= -1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:299:5
+ --> $DIR/arithmetic_side_effects.rs:317:5
|
LL | _n -= &-1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:300:5
+ --> $DIR/arithmetic_side_effects.rs:318:5
|
LL | _n /= -0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:301:5
+ --> $DIR/arithmetic_side_effects.rs:319:5
|
LL | _n /= &-0;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:302:5
+ --> $DIR/arithmetic_side_effects.rs:320:5
|
LL | _n %= -0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:303:5
+ --> $DIR/arithmetic_side_effects.rs:321:5
|
LL | _n %= &-0;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:304:5
+ --> $DIR/arithmetic_side_effects.rs:322:5
|
LL | _n *= -2;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:305:5
+ --> $DIR/arithmetic_side_effects.rs:323:5
|
LL | _n *= &-2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:306:5
+ --> $DIR/arithmetic_side_effects.rs:324:5
|
LL | _custom += Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:307:5
+ --> $DIR/arithmetic_side_effects.rs:325:5
|
LL | _custom += &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:308:5
+ --> $DIR/arithmetic_side_effects.rs:326:5
|
LL | _custom -= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:309:5
+ --> $DIR/arithmetic_side_effects.rs:327:5
|
LL | _custom -= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:310:5
+ --> $DIR/arithmetic_side_effects.rs:328:5
|
LL | _custom /= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:311:5
+ --> $DIR/arithmetic_side_effects.rs:329:5
|
LL | _custom /= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:312:5
+ --> $DIR/arithmetic_side_effects.rs:330:5
|
LL | _custom %= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:313:5
+ --> $DIR/arithmetic_side_effects.rs:331:5
|
LL | _custom %= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:314:5
+ --> $DIR/arithmetic_side_effects.rs:332:5
|
LL | _custom *= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:315:5
+ --> $DIR/arithmetic_side_effects.rs:333:5
|
LL | _custom *= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:316:5
+ --> $DIR/arithmetic_side_effects.rs:334:5
|
LL | _custom >>= Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:317:5
+ --> $DIR/arithmetic_side_effects.rs:335:5
|
LL | _custom >>= &Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:318:5
+ --> $DIR/arithmetic_side_effects.rs:336:5
|
LL | _custom <<= Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:319:5
+ --> $DIR/arithmetic_side_effects.rs:337:5
|
LL | _custom <<= &Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:320:5
+ --> $DIR/arithmetic_side_effects.rs:338:5
|
LL | _custom += -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:321:5
+ --> $DIR/arithmetic_side_effects.rs:339:5
|
LL | _custom += &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:322:5
+ --> $DIR/arithmetic_side_effects.rs:340:5
|
LL | _custom -= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:323:5
+ --> $DIR/arithmetic_side_effects.rs:341:5
|
LL | _custom -= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:324:5
+ --> $DIR/arithmetic_side_effects.rs:342:5
|
LL | _custom /= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:325:5
+ --> $DIR/arithmetic_side_effects.rs:343:5
|
LL | _custom /= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:326:5
+ --> $DIR/arithmetic_side_effects.rs:344:5
|
LL | _custom %= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:327:5
+ --> $DIR/arithmetic_side_effects.rs:345:5
|
LL | _custom %= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:328:5
+ --> $DIR/arithmetic_side_effects.rs:346:5
|
LL | _custom *= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:329:5
+ --> $DIR/arithmetic_side_effects.rs:347:5
|
LL | _custom *= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:330:5
+ --> $DIR/arithmetic_side_effects.rs:348:5
|
LL | _custom >>= -Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:331:5
+ --> $DIR/arithmetic_side_effects.rs:349:5
|
LL | _custom >>= &-Custom;
| ^^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:332:5
+ --> $DIR/arithmetic_side_effects.rs:350:5
|
LL | _custom <<= -Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:333:5
+ --> $DIR/arithmetic_side_effects.rs:351:5
|
LL | _custom <<= &-Custom;
| ^^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:336:10
+ --> $DIR/arithmetic_side_effects.rs:354:10
|
LL | _n = _n + 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:337:10
+ --> $DIR/arithmetic_side_effects.rs:355:10
|
LL | _n = _n + &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:338:10
+ --> $DIR/arithmetic_side_effects.rs:356:10
|
LL | _n = 1 + _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:339:10
+ --> $DIR/arithmetic_side_effects.rs:357:10
|
LL | _n = &1 + _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:340:10
+ --> $DIR/arithmetic_side_effects.rs:358:10
|
LL | _n = _n - 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:341:10
+ --> $DIR/arithmetic_side_effects.rs:359:10
|
LL | _n = _n - &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:342:10
+ --> $DIR/arithmetic_side_effects.rs:360:10
|
LL | _n = 1 - _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:343:10
+ --> $DIR/arithmetic_side_effects.rs:361:10
|
LL | _n = &1 - _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:344:10
+ --> $DIR/arithmetic_side_effects.rs:362:10
|
LL | _n = _n / 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:345:10
+ --> $DIR/arithmetic_side_effects.rs:363:10
|
LL | _n = _n / &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:346:10
+ --> $DIR/arithmetic_side_effects.rs:364:10
|
LL | _n = _n % 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:347:10
+ --> $DIR/arithmetic_side_effects.rs:365:10
|
LL | _n = _n % &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:348:10
+ --> $DIR/arithmetic_side_effects.rs:366:10
|
LL | _n = _n * 2;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:349:10
+ --> $DIR/arithmetic_side_effects.rs:367:10
|
LL | _n = _n * &2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:350:10
+ --> $DIR/arithmetic_side_effects.rs:368:10
|
LL | _n = 2 * _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:351:10
+ --> $DIR/arithmetic_side_effects.rs:369:10
|
LL | _n = &2 * _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:352:10
+ --> $DIR/arithmetic_side_effects.rs:370:10
|
LL | _n = 23 + &85;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:353:10
+ --> $DIR/arithmetic_side_effects.rs:371:10
|
LL | _n = &23 + 85;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:354:10
+ --> $DIR/arithmetic_side_effects.rs:372:10
|
LL | _n = &23 + &85;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:355:15
+ --> $DIR/arithmetic_side_effects.rs:373:15
|
LL | _custom = _custom + _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:356:15
+ --> $DIR/arithmetic_side_effects.rs:374:15
|
LL | _custom = _custom + &_custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:357:15
+ --> $DIR/arithmetic_side_effects.rs:375:15
|
LL | _custom = Custom + _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:358:15
+ --> $DIR/arithmetic_side_effects.rs:376:15
|
LL | _custom = &Custom + _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:359:15
+ --> $DIR/arithmetic_side_effects.rs:377:15
|
LL | _custom = _custom - Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:360:15
+ --> $DIR/arithmetic_side_effects.rs:378:15
|
LL | _custom = _custom - &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:361:15
+ --> $DIR/arithmetic_side_effects.rs:379:15
|
LL | _custom = Custom - _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:362:15
+ --> $DIR/arithmetic_side_effects.rs:380:15
|
LL | _custom = &Custom - _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:363:15
+ --> $DIR/arithmetic_side_effects.rs:381:15
|
LL | _custom = _custom / Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:364:15
+ --> $DIR/arithmetic_side_effects.rs:382:15
|
LL | _custom = _custom / &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:365:15
+ --> $DIR/arithmetic_side_effects.rs:383:15
|
LL | _custom = _custom % Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:366:15
+ --> $DIR/arithmetic_side_effects.rs:384:15
|
LL | _custom = _custom % &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:367:15
+ --> $DIR/arithmetic_side_effects.rs:385:15
|
LL | _custom = _custom * Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:368:15
+ --> $DIR/arithmetic_side_effects.rs:386:15
|
LL | _custom = _custom * &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:369:15
+ --> $DIR/arithmetic_side_effects.rs:387:15
|
LL | _custom = Custom * _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:370:15
+ --> $DIR/arithmetic_side_effects.rs:388:15
|
LL | _custom = &Custom * _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:371:15
+ --> $DIR/arithmetic_side_effects.rs:389:15
|
LL | _custom = Custom + &Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:372:15
+ --> $DIR/arithmetic_side_effects.rs:390:15
|
LL | _custom = &Custom + Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:373:15
+ --> $DIR/arithmetic_side_effects.rs:391:15
|
LL | _custom = &Custom + &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:374:15
+ --> $DIR/arithmetic_side_effects.rs:392:15
|
LL | _custom = _custom >> _custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:375:15
+ --> $DIR/arithmetic_side_effects.rs:393:15
|
LL | _custom = _custom >> &_custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:376:15
+ --> $DIR/arithmetic_side_effects.rs:394:15
|
LL | _custom = Custom << _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:377:15
+ --> $DIR/arithmetic_side_effects.rs:395:15
|
LL | _custom = &Custom << _custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:380:10
+ --> $DIR/arithmetic_side_effects.rs:398:23
+ |
+LL | _n.saturating_div(0);
+ | ^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:399:21
+ |
+LL | _n.wrapping_div(0);
+ | ^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:400:21
+ |
+LL | _n.wrapping_rem(0);
+ | ^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:401:28
+ |
+LL | _n.wrapping_rem_euclid(0);
+ | ^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:403:23
+ |
+LL | _n.saturating_div(_n);
+ | ^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:404:21
+ |
+LL | _n.wrapping_div(_n);
+ | ^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:405:21
+ |
+LL | _n.wrapping_rem(_n);
+ | ^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:406:28
+ |
+LL | _n.wrapping_rem_euclid(_n);
+ | ^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:409:10
|
LL | _n = -_n;
| ^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:381:10
+ --> $DIR/arithmetic_side_effects.rs:410:10
|
LL | _n = -&_n;
| ^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:382:15
+ --> $DIR/arithmetic_side_effects.rs:411:15
|
LL | _custom = -_custom;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:383:15
+ --> $DIR/arithmetic_side_effects.rs:412:15
|
LL | _custom = -&_custom;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:392:5
+ --> $DIR/arithmetic_side_effects.rs:421:5
|
LL | 1 + i;
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:393:5
+ --> $DIR/arithmetic_side_effects.rs:422:5
|
LL | i * 2;
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:394:5
+ --> $DIR/arithmetic_side_effects.rs:423:5
|
LL | 1 % i / 2;
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:395:5
+ --> $DIR/arithmetic_side_effects.rs:424:5
|
LL | i - 2 + 2 - i;
| ^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:396:5
+ --> $DIR/arithmetic_side_effects.rs:425:5
|
LL | -i;
| ^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:407:5
+ --> $DIR/arithmetic_side_effects.rs:436:5
|
LL | i += 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:408:5
+ --> $DIR/arithmetic_side_effects.rs:437:5
|
LL | i -= 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:409:5
+ --> $DIR/arithmetic_side_effects.rs:438:5
|
LL | i *= 2;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:411:5
+ --> $DIR/arithmetic_side_effects.rs:440:5
|
LL | i /= 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:413:5
+ --> $DIR/arithmetic_side_effects.rs:442:5
|
LL | i /= var1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:414:5
+ --> $DIR/arithmetic_side_effects.rs:443:5
|
LL | i /= var2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:416:5
+ --> $DIR/arithmetic_side_effects.rs:445:5
|
LL | i %= 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:418:5
+ --> $DIR/arithmetic_side_effects.rs:447:5
|
LL | i %= var1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:419:5
+ --> $DIR/arithmetic_side_effects.rs:448:5
|
LL | i %= var2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:429:5
+ --> $DIR/arithmetic_side_effects.rs:458:5
|
LL | 10 / a
| ^^^^^^
-error: aborting due to 109 previous errors
+error: aborting due to 117 previous errors
diff --git a/src/tools/clippy/tests/ui/as_conversions.rs b/src/tools/clippy/tests/ui/as_conversions.rs
index c50d4088b..890bf0b0a 100644
--- a/src/tools/clippy/tests/ui/as_conversions.rs
+++ b/src/tools/clippy/tests/ui/as_conversions.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![warn(clippy::as_conversions)]
#![allow(clippy::borrow_as_ptr)]
diff --git a/src/tools/clippy/tests/ui/as_underscore.fixed b/src/tools/clippy/tests/ui/as_underscore.fixed
index 948f6d8e6..69af84a0e 100644
--- a/src/tools/clippy/tests/ui/as_underscore.fixed
+++ b/src/tools/clippy/tests/ui/as_underscore.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::as_underscore)]
diff --git a/src/tools/clippy/tests/ui/as_underscore.rs b/src/tools/clippy/tests/ui/as_underscore.rs
index 97785ed08..a8cfb81d9 100644
--- a/src/tools/clippy/tests/ui/as_underscore.rs
+++ b/src/tools/clippy/tests/ui/as_underscore.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::as_underscore)]
diff --git a/src/tools/clippy/tests/ui/asm_syntax.rs b/src/tools/clippy/tests/ui/asm_syntax.rs
index 0220bf333..c93995f93 100644
--- a/src/tools/clippy/tests/ui/asm_syntax.rs
+++ b/src/tools/clippy/tests/ui/asm_syntax.rs
@@ -1,5 +1,5 @@
-// only-x86_64
-// ignore-aarch64
+//@only-x86_64
+//@ignore-aarch64
#[warn(clippy::inline_asm_x86_intel_syntax)]
mod warn_intel {
diff --git a/src/tools/clippy/tests/ui/assertions_on_result_states.fixed b/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
index 2bb755290..ea8b89566 100644
--- a/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
+++ b/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::assertions_on_result_states)]
use std::result::Result;
diff --git a/src/tools/clippy/tests/ui/assertions_on_result_states.rs b/src/tools/clippy/tests/ui/assertions_on_result_states.rs
index d8a9bd2f1..6fc20f859 100644
--- a/src/tools/clippy/tests/ui/assertions_on_result_states.rs
+++ b/src/tools/clippy/tests/ui/assertions_on_result_states.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::assertions_on_result_states)]
use std::result::Result;
diff --git a/src/tools/clippy/tests/ui/assign_ops.fixed b/src/tools/clippy/tests/ui/assign_ops.fixed
index da034b51c..b50682ea0 100644
--- a/src/tools/clippy/tests/ui/assign_ops.fixed
+++ b/src/tools/clippy/tests/ui/assign_ops.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
use core::num::Wrapping;
diff --git a/src/tools/clippy/tests/ui/assign_ops.rs b/src/tools/clippy/tests/ui/assign_ops.rs
index 337bb02c8..780d2d040 100644
--- a/src/tools/clippy/tests/ui/assign_ops.rs
+++ b/src/tools/clippy/tests/ui/assign_ops.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
use core::num::Wrapping;
diff --git a/src/tools/clippy/tests/ui/async_yields_async.fixed b/src/tools/clippy/tests/ui/async_yields_async.fixed
index 579a63ea4..8d9b02389 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.fixed
+++ b/src/tools/clippy/tests/ui/async_yields_async.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![feature(async_closure)]
#![warn(clippy::async_yields_async)]
diff --git a/src/tools/clippy/tests/ui/async_yields_async.rs b/src/tools/clippy/tests/ui/async_yields_async.rs
index 5aec2fb50..bed79062f 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.rs
+++ b/src/tools/clippy/tests/ui/async_yields_async.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![feature(async_closure)]
#![warn(clippy::async_yields_async)]
diff --git a/src/tools/clippy/tests/ui/author/blocks.rs b/src/tools/clippy/tests/ui/author/blocks.rs
index a7335c01b..164f7d0d9 100644
--- a/src/tools/clippy/tests/ui/author/blocks.rs
+++ b/src/tools/clippy/tests/ui/author/blocks.rs
@@ -1,4 +1,4 @@
-// edition:2018
+//@edition:2018
#![allow(redundant_semicolons, clippy::no_effect)]
#![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
index a9bb61451..e5bb90666 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
@@ -22,6 +22,13 @@ macro_rules! string_add {
}
#[macro_export]
+macro_rules! string_lit_as_bytes {
+ ($s:literal) => {
+ const C: &[u8] = $s.as_bytes();
+ };
+}
+
+#[macro_export]
macro_rules! mut_mut {
() => {
let mut_mut_ty: &mut &mut u32 = &mut &mut 1u32;
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
index 4914f14b5..d164dd0e5 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
@@ -1,5 +1,5 @@
-// compile-flags: --emit=link
-// no-prefer-dynamic
+//@compile-flags: --emit=link
+//@no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)]
@@ -28,7 +28,7 @@ pub fn dummy(_args: TokenStream, input: TokenStream) -> TokenStream {
pub fn fake_async_trait(_args: TokenStream, input: TokenStream) -> TokenStream {
let mut item = parse_macro_input!(input as ItemTrait);
for inner in &mut item.items {
- if let TraitItem::Method(method) = inner {
+ if let TraitItem::Fn(method) = inner {
let sig = &method.sig;
let block = &mut method.default;
if let Some(block) = block {
@@ -70,7 +70,7 @@ pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStrea
// Look for methods having arbitrary self type taken by &mut ref
for inner in &mut item.items {
- if let ImplItem::Method(method) = inner {
+ if let ImplItem::Fn(method) = inner {
if let Some(FnArg::Typed(pat_type)) = mut_receiver_of(&mut method.sig) {
if let box Type::Reference(reference) = &mut pat_type.ty {
// Target only unnamed lifetimes
@@ -82,7 +82,7 @@ pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStrea
elided += 1;
// HACK: Syn uses `Span` from the proc_macro2 crate, and does not seem to reexport it.
- // In order to avoid adding the dependency, get a default span from a non-existent token.
+ // In order to avoid adding the dependency, get a default span from a nonexistent token.
// A default span is needed to mark the code as coming from expansion.
let span = Star::default().span();
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
index a89a06308..5a924ca18 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
@@ -1,5 +1,5 @@
-// compile-flags: --emit=link
-// no-prefer-dynamic
+//@compile-flags: --emit=link
+//@no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(repr128, proc_macro_quote)]
@@ -9,7 +9,7 @@
extern crate proc_macro;
-use proc_macro::{quote, TokenStream};
+use proc_macro::{quote, Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
#[proc_macro_derive(DeriveSomething)]
pub fn derive(_: TokenStream) -> TokenStream {
@@ -86,3 +86,74 @@ pub fn extra_lifetime(_input: TokenStream) -> TokenStream {
}
)
}
+
+#[allow(unused)]
+#[proc_macro_derive(ArithmeticDerive)]
+pub fn arithmetic_derive(_: TokenStream) -> TokenStream {
+ <TokenStream as FromIterator<TokenTree>>::from_iter(
+ [
+ Ident::new("fn", Span::call_site()).into(),
+ Ident::new("_foo", Span::call_site()).into(),
+ Group::new(Delimiter::Parenthesis, TokenStream::new()).into(),
+ Group::new(
+ Delimiter::Brace,
+ <TokenStream as FromIterator<TokenTree>>::from_iter(
+ [
+ Ident::new("let", Span::call_site()).into(),
+ Ident::new("mut", Span::call_site()).into(),
+ Ident::new("_n", Span::call_site()).into(),
+ Punct::new('=', Spacing::Alone).into(),
+ Literal::i32_unsuffixed(9).into(),
+ Punct::new(';', Spacing::Alone).into(),
+ Ident::new("_n", Span::call_site()).into(),
+ Punct::new('=', Spacing::Alone).into(),
+ Literal::i32_unsuffixed(9).into(),
+ Punct::new('/', Spacing::Alone).into(),
+ Literal::i32_unsuffixed(2).into(),
+ Punct::new(';', Spacing::Alone).into(),
+ Ident::new("_n", Span::call_site()).into(),
+ Punct::new('=', Spacing::Alone).into(),
+ Punct::new('-', Spacing::Alone).into(),
+ Ident::new("_n", Span::call_site()).into(),
+ Punct::new(';', Spacing::Alone).into(),
+ ]
+ .into_iter(),
+ ),
+ )
+ .into(),
+ ]
+ .into_iter(),
+ )
+}
+
+#[allow(unused)]
+#[proc_macro_derive(ShadowDerive)]
+pub fn shadow_derive(_: TokenStream) -> TokenStream {
+ <TokenStream as FromIterator<TokenTree>>::from_iter(
+ [
+ Ident::new("fn", Span::call_site()).into(),
+ Ident::new("_foo", Span::call_site()).into(),
+ Group::new(Delimiter::Parenthesis, TokenStream::new()).into(),
+ Group::new(
+ Delimiter::Brace,
+ <TokenStream as FromIterator<TokenTree>>::from_iter(
+ [
+ Ident::new("let", Span::call_site()).into(),
+ Ident::new("_x", Span::call_site()).into(),
+ Punct::new('=', Spacing::Alone).into(),
+ Literal::i32_unsuffixed(2).into(),
+ Punct::new(';', Spacing::Alone).into(),
+ Ident::new("let", Span::call_site()).into(),
+ Ident::new("_x", Span::call_site()).into(),
+ Punct::new('=', Spacing::Alone).into(),
+ Ident::new("_x", Span::call_site()).into(),
+ Punct::new(';', Spacing::Alone).into(),
+ ]
+ .into_iter(),
+ ),
+ )
+ .into(),
+ ]
+ .into_iter(),
+ )
+}
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
index a2ef0fe82..f13b76e44 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
@@ -1,5 +1,5 @@
-// compile-flags: --emit=link
-// no-prefer-dynamic
+//@compile-flags: --emit=link
+//@no-prefer-dynamic
#![crate_type = "proc-macro"]
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs
index 3c40f7746..c2326678d 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs
@@ -1,5 +1,5 @@
-// compile-flags: --emit=link
-// no-prefer-dynamic
+//@compile-flags: --emit=link
+//@no-prefer-dynamic
#![crate_type = "proc-macro"]
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
index 3d5beab1e..94f075ed0 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
@@ -1,5 +1,5 @@
-// compile-flags: --emit=link
-// no-prefer-dynamic
+//@compile-flags: --emit=link
+//@no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(let_chains)]
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map.fixed b/src/tools/clippy/tests/ui/bind_instead_of_map.fixed
index d94e2ac60..ea2dc2e22 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map.fixed
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::bind_instead_of_map)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map.rs b/src/tools/clippy/tests/ui/bind_instead_of_map.rs
index 86f31f582..1db58dae5 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map.rs
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::bind_instead_of_map)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.fixed b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.fixed
index e15898432..63c7aafcd 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.fixed
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::bind_instead_of_map)]
#![allow(clippy::blocks_in_if_conditions)]
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.rs b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.rs
index 49944403f..69b982fa8 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.rs
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::bind_instead_of_map)]
#![allow(clippy::blocks_in_if_conditions)]
diff --git a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs
index 554745368..e1ff25c54 100644
--- a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs
+++ b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.rs
@@ -1,4 +1,4 @@
-// compile-flags: -W clippy::restriction
+//@compile-flags: -W clippy::restriction
#![warn(clippy::blanket_clippy_restriction_lints)]
diff --git a/src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed b/src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed
index e6e40a994..a9f18782e 100644
--- a/src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed
+++ b/src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::blocks_in_if_conditions)]
#![allow(unused, clippy::let_and_return)]
#![warn(clippy::nonminimal_bool)]
diff --git a/src/tools/clippy/tests/ui/blocks_in_if_conditions.rs b/src/tools/clippy/tests/ui/blocks_in_if_conditions.rs
index 69387ff57..0a70317c4 100644
--- a/src/tools/clippy/tests/ui/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/tests/ui/blocks_in_if_conditions.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::blocks_in_if_conditions)]
#![allow(unused, clippy::let_and_return)]
#![warn(clippy::nonminimal_bool)]
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
index b8dd92906..53f63444a 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::assertions_on_constants)]
#![warn(clippy::bool_assert_comparison)]
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.rs b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
index 0a8ad34fd..151d93a92 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.rs
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::assertions_on_constants)]
#![warn(clippy::bool_assert_comparison)]
diff --git a/src/tools/clippy/tests/ui/bool_comparison.fixed b/src/tools/clippy/tests/ui/bool_comparison.fixed
index 5a012ff4d..670eef6a2 100644
--- a/src/tools/clippy/tests/ui/bool_comparison.fixed
+++ b/src/tools/clippy/tests/ui/bool_comparison.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::bool_comparison)]
diff --git a/src/tools/clippy/tests/ui/bool_comparison.rs b/src/tools/clippy/tests/ui/bool_comparison.rs
index c534bc25c..72851be63 100644
--- a/src/tools/clippy/tests/ui/bool_comparison.rs
+++ b/src/tools/clippy/tests/ui/bool_comparison.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::bool_comparison)]
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
index 37d3e3286..fbb10a133 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
@@ -1,6 +1,6 @@
-// run-rustfix
+//@run-rustfix
-#![feature(let_chains)]
+#![feature(let_chains, inline_const)]
#![warn(clippy::bool_to_int_with_if)]
#![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)]
@@ -79,6 +79,13 @@ fn main() {
pub const SHOULD_NOT_LINT: usize = if true { 1 } else { 0 };
+ // https://github.com/rust-lang/rust-clippy/issues/10452
+ let should_not_lint = [(); if true { 1 } else { 0 }];
+
+ let should_not_lint = const {
+ if true { 1 } else { 0 }
+ };
+
some_fn(a);
}
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
index ebdf86fd1..709a18d63 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
@@ -1,6 +1,6 @@
-// run-rustfix
+//@run-rustfix
-#![feature(let_chains)]
+#![feature(let_chains, inline_const)]
#![warn(clippy::bool_to_int_with_if)]
#![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)]
@@ -111,6 +111,13 @@ fn main() {
pub const SHOULD_NOT_LINT: usize = if true { 1 } else { 0 };
+ // https://github.com/rust-lang/rust-clippy/issues/10452
+ let should_not_lint = [(); if true { 1 } else { 0 }];
+
+ let should_not_lint = const {
+ if true { 1 } else { 0 }
+ };
+
some_fn(a);
}
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr b/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
index 5cfb75cc0..3bdae75ca 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
@@ -98,7 +98,7 @@ LL | | };
= note: `!b as i32` or `(!b).into()` can also be valid options
error: boolean to int conversion using if
- --> $DIR/bool_to_int_with_if.rs:119:5
+ --> $DIR/bool_to_int_with_if.rs:126:5
|
LL | if a { 1 } else { 0 }
| ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)`
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.fixed b/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
index ff5c6a8c3..3f440ce00 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::borrow_as_ptr)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.rs b/src/tools/clippy/tests/ui/borrow_as_ptr.rs
index 0f62ec6ee..c1ca9180e 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr.rs
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::borrow_as_ptr)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed
index eaba3b1c2..10f2727c7 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::borrow_as_ptr)]
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs
index d83f9d1f8..311e9341a 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::borrow_as_ptr)]
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
index bf4691c5b..755264617 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
@@ -1,7 +1,11 @@
-// run-rustfix
+//@run-rustfix
+//@aux-build: proc_macros.rs
#![allow(dead_code, unused_variables)]
+extern crate proc_macros;
+use proc_macros::with_span;
+
fn main() {}
mod should_lint {
@@ -47,6 +51,17 @@ mod should_not_lint2 {
}
}
+with_span!(
+ span
+
+ fn just_returning(x: &u32) -> &u32 {
+ x
+ }
+
+ fn dont_lint_proc_macro() {
+ let a = &mut &*just_returning(&12);
+ }
+);
// this mod explains why we should not lint `& &* (&T)`
mod false_negative {
fn foo() {
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.rs b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
index 28c005fdb..e319d365f 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.rs
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
@@ -1,7 +1,11 @@
-// run-rustfix
+//@run-rustfix
+//@aux-build: proc_macros.rs
#![allow(dead_code, unused_variables)]
+extern crate proc_macros;
+use proc_macros::with_span;
+
fn main() {}
mod should_lint {
@@ -47,6 +51,17 @@ mod should_not_lint2 {
}
}
+with_span!(
+ span
+
+ fn just_returning(x: &u32) -> &u32 {
+ x
+ }
+
+ fn dont_lint_proc_macro() {
+ let a = &mut &*just_returning(&12);
+ }
+);
// this mod explains why we should not lint `& &* (&T)`
mod false_negative {
fn foo() {
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
index d72de37c6..1e47cda67 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
@@ -1,5 +1,5 @@
error: deref on an immutable reference
- --> $DIR/borrow_deref_ref.rs:10:17
+ --> $DIR/borrow_deref_ref.rs:14:17
|
LL | let b = &*a;
| ^^^ help: if you would like to reborrow, try removing `&*`: `a`
@@ -7,13 +7,13 @@ LL | let b = &*a;
= note: `-D clippy::borrow-deref-ref` implied by `-D warnings`
error: deref on an immutable reference
- --> $DIR/borrow_deref_ref.rs:12:22
+ --> $DIR/borrow_deref_ref.rs:16:22
|
LL | let b = &mut &*bar(&12);
| ^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `bar(&12)`
error: deref on an immutable reference
- --> $DIR/borrow_deref_ref.rs:55:23
+ --> $DIR/borrow_deref_ref.rs:70:23
|
LL | let addr_y = &&*x as *const _ as usize; // assert ok
| ^^^ help: if you would like to reborrow, try removing `&*`: `x`
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
index 5027db445..29b08ab36 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
@@ -1,4 +1,4 @@
-// aux-build:helper.rs
+//@aux-build:helper.rs
#![warn(clippy::borrow_interior_mutable_const)]
#![allow(clippy::declare_interior_mutable_const)]
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
index 59c0baf87..840902b53 100644
--- a/src/tools/clippy/tests/ui/box_default.fixed
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -1,5 +1,6 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::box_default)]
+#![allow(clippy::default_constructed_unit_structs)]
#[derive(Default)]
struct ImplementsDefault;
@@ -34,6 +35,13 @@ fn main() {
let _more = ret_ty_fn();
call_ty_fn(Box::default());
issue_10381();
+
+ // `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
+ // `Box::<Option<[closure@...]>::default()`
+ //
+ // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
+ let mut unnameable = Box::new(Option::default());
+ let _ = unnameable.insert(|| {});
}
fn ret_ty_fn() -> Box<bool> {
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
index f7d832193..3618486a4 100644
--- a/src/tools/clippy/tests/ui/box_default.rs
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -1,5 +1,6 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::box_default)]
+#![allow(clippy::default_constructed_unit_structs)]
#[derive(Default)]
struct ImplementsDefault;
@@ -34,6 +35,13 @@ fn main() {
let _more = ret_ty_fn();
call_ty_fn(Box::new(u8::default()));
issue_10381();
+
+ // `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
+ // `Box::<Option<[closure@...]>::default()`
+ //
+ // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
+ let mut unnameable = Box::new(Option::default());
+ let _ = unnameable.insert(|| {});
}
fn ret_ty_fn() -> Box<bool> {
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
index 78e17b9f0..13dfc5ae4 100644
--- a/src/tools/clippy/tests/ui/box_default.stderr
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -1,5 +1,5 @@
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:22:32
+ --> $DIR/box_default.rs:23:32
|
LL | let _string: Box<String> = Box::new(Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
@@ -7,91 +7,91 @@ LL | let _string: Box<String> = Box::new(Default::default());
= note: `-D clippy::box-default` implied by `-D warnings`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:23:17
+ --> $DIR/box_default.rs:24:17
|
LL | let _byte = Box::new(u8::default());
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<u8>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:24:16
+ --> $DIR/box_default.rs:25:16
|
LL | let _vec = Box::new(Vec::<u8>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<u8>>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:25:17
+ --> $DIR/box_default.rs:26:17
|
LL | let _impl = Box::new(ImplementsDefault::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:26:18
+ --> $DIR/box_default.rs:27:18
|
LL | let _impl2 = Box::new(<ImplementsDefault as Default>::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:27:42
+ --> $DIR/box_default.rs:28:42
|
LL | let _impl3: Box<ImplementsDefault> = Box::new(Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:29:28
+ --> $DIR/box_default.rs:30:28
|
LL | let _in_macro = outer!(Box::new(String::new()));
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:30:34
+ --> $DIR/box_default.rs:31:34
|
LL | let _string_default = outer!(Box::new(String::from("")));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:31:46
+ --> $DIR/box_default.rs:32:46
|
LL | let _vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
| ^^^^^^^^^^^^^^^^ help: try: `Box::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:32:33
+ --> $DIR/box_default.rs:33:33
|
LL | let _vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:33:25
+ --> $DIR/box_default.rs:34:25
|
LL | let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<bool>>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:35:16
+ --> $DIR/box_default.rs:36:16
|
LL | call_ty_fn(Box::new(u8::default()));
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:40:5
+ --> $DIR/box_default.rs:48:5
|
LL | Box::new(bool::default())
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:57:28
+ --> $DIR/box_default.rs:65:28
|
LL | let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:66:17
+ --> $DIR/box_default.rs:74:17
|
LL | let _ = Box::new(WeirdPathed::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:78:18
+ --> $DIR/box_default.rs:86:18
|
LL | Some(Box::new(Foo::default()))
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()`
diff --git a/src/tools/clippy/tests/ui/bytes_count_to_len.fixed b/src/tools/clippy/tests/ui/bytes_count_to_len.fixed
index 860642363..fb3d521ba 100644
--- a/src/tools/clippy/tests/ui/bytes_count_to_len.fixed
+++ b/src/tools/clippy/tests/ui/bytes_count_to_len.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::bytes_count_to_len)]
use std::fs::File;
use std::io::Read;
diff --git a/src/tools/clippy/tests/ui/bytes_count_to_len.rs b/src/tools/clippy/tests/ui/bytes_count_to_len.rs
index 162730c28..8e256b8f0 100644
--- a/src/tools/clippy/tests/ui/bytes_count_to_len.rs
+++ b/src/tools/clippy/tests/ui/bytes_count_to_len.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::bytes_count_to_len)]
use std::fs::File;
use std::io::Read;
diff --git a/src/tools/clippy/tests/ui/bytes_nth.fixed b/src/tools/clippy/tests/ui/bytes_nth.fixed
index a35c679af..d3e0f676b 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.fixed
+++ b/src/tools/clippy/tests/ui/bytes_nth.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::unnecessary_operation)]
#![warn(clippy::bytes_nth)]
diff --git a/src/tools/clippy/tests/ui/bytes_nth.rs b/src/tools/clippy/tests/ui/bytes_nth.rs
index 1ecffea53..b7d813fe2 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.rs
+++ b/src/tools/clippy/tests/ui/bytes_nth.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::unnecessary_operation)]
#![warn(clippy::bytes_nth)]
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
index 5fbaa64db..d5af22aef 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::case_sensitive_file_extension_comparisons)]
use std::string::String;
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
index 3c0d4821f..f5f0a0022 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::case_sensitive_file_extension_comparisons)]
use std::string::String;
diff --git a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed
index 8676b562b..ef0a93b01 100644
--- a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed
+++ b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::cast_abs_to_unsigned)]
#![allow(clippy::uninlined_format_args, unused)]
diff --git a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs
index 5775af874..96ced670a 100644
--- a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs
+++ b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::cast_abs_to_unsigned)]
#![allow(clippy::uninlined_format_args, unused)]
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.fixed b/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
index 13b3cf838..c321cc644 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::cast_lossless)]
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.rs b/src/tools/clippy/tests/ui/cast_lossless_bool.rs
index 3eed21355..632a71892 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::cast_lossless)]
diff --git a/src/tools/clippy/tests/ui/cast_lossless_float.fixed b/src/tools/clippy/tests/ui/cast_lossless_float.fixed
index 32a9c1c4a..e72a0096a 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_float.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_float.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
#![warn(clippy::cast_lossless)]
diff --git a/src/tools/clippy/tests/ui/cast_lossless_float.rs b/src/tools/clippy/tests/ui/cast_lossless_float.rs
index 6f5ddcfe0..dbcbaa9b8 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_float.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_float.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
#![warn(clippy::cast_lossless)]
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
index 925cbf253..7dab02084 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
#![warn(clippy::cast_lossless)]
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.rs b/src/tools/clippy/tests/ui/cast_lossless_integer.rs
index c82bd9108..c24f73960 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
#![warn(clippy::cast_lossless)]
diff --git a/src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.fixed b/src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.fixed
index b70c19129..9b6fee270 100644
--- a/src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.fixed
+++ b/src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::cast_slice_from_raw_parts)]
#[allow(unused_imports, unused_unsafe)]
diff --git a/src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.rs b/src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.rs
index c1b316765..c0bb81379 100644
--- a/src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.rs
+++ b/src/tools/clippy/tests/ui/cast_raw_slice_pointer_cast.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::cast_slice_from_raw_parts)]
#[allow(unused_imports, unused_unsafe)]
diff --git a/src/tools/clippy/tests/ui/cast_size.rs b/src/tools/clippy/tests/ui/cast_size.rs
index 595109be4..cd2184aea 100644
--- a/src/tools/clippy/tests/ui/cast_size.rs
+++ b/src/tools/clippy/tests/ui/cast_size.rs
@@ -1,4 +1,4 @@
-// ignore-32bit
+//@ignore-32bit
#[warn(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
diff --git a/src/tools/clippy/tests/ui/cast_size_32bit.rs b/src/tools/clippy/tests/ui/cast_size_32bit.rs
index 99aac6dec..7ca20d3ca 100644
--- a/src/tools/clippy/tests/ui/cast_size_32bit.rs
+++ b/src/tools/clippy/tests/ui/cast_size_32bit.rs
@@ -1,4 +1,4 @@
-// ignore-64bit
+//@ignore-64bit
#[warn(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
diff --git a/src/tools/clippy/tests/ui/cast_size_32bit.stderr b/src/tools/clippy/tests/ui/cast_size_32bit.stderr
index 8990c3ba7..fb51783a4 100644
--- a/src/tools/clippy/tests/ui/cast_size_32bit.stderr
+++ b/src/tools/clippy/tests/ui/cast_size_32bit.stderr
@@ -4,7 +4,12 @@ error: casting `isize` to `i8` may truncate the value
LL | 1isize as i8;
| ^^^^^^^^^^^^
|
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i8::try_from(1isize);
+ | ~~~~~~~~~~~~~~~~~~~~
error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
--> $DIR/cast_size_32bit.rs:15:5
@@ -37,24 +42,48 @@ error: casting `isize` to `i32` may truncate the value on targets with 64-bit wi
|
LL | 1isize as i32;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i32::try_from(1isize);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size_32bit.rs:20:5
|
LL | 1isize as u32;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u32::try_from(1isize);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size_32bit.rs:21:5
|
LL | 1usize as u32;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u32::try_from(1usize);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size_32bit.rs:22:5
|
LL | 1usize as i32;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i32::try_from(1usize);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
--> $DIR/cast_size_32bit.rs:22:5
@@ -69,18 +98,36 @@ error: casting `i64` to `isize` may truncate the value on targets with 32-bit wi
|
LL | 1i64 as isize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | isize::try_from(1i64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast_size_32bit.rs:25:5
|
LL | 1i64 as usize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | usize::try_from(1i64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast_size_32bit.rs:26:5
|
LL | 1u64 as isize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | isize::try_from(1u64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
--> $DIR/cast_size_32bit.rs:26:5
@@ -93,6 +140,12 @@ error: casting `u64` to `usize` may truncate the value on targets with 32-bit wi
|
LL | 1u64 as usize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | usize::try_from(1u64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
--> $DIR/cast_size_32bit.rs:28:5
diff --git a/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs b/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs
index 24d7eb28a..b77f01883 100644
--- a/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs
+++ b/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs
@@ -23,7 +23,7 @@ fn main() {
r_x as *const [i32]
} as *const [u8];
- // Check that resores of the same size are detected through blocks
+ // Check that resources of the same size are detected through blocks
let restore_block_1 = { r_x as *const [i32] } as *const [u8] as *const [u32];
let restore_block_2 = { ({ r_x as *const [i32] }) as *const [u8] } as *const [u32];
let restore_block_3 = {
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
index b970b1209..13aadb7d3 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(stmt_expr_attributes)]
#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)]
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
index 0a8e6a89d..769c5d22b 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(stmt_expr_attributes)]
#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)]
diff --git a/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.fixed b/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.fixed
index 3dc3cb4e7..ce2f149dc 100644
--- a/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.fixed
+++ b/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::char_lit_as_u8)]
diff --git a/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.rs b/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.rs
index d379a0234..ffad12fc6 100644
--- a/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.rs
+++ b/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::char_lit_as_u8)]
diff --git a/src/tools/clippy/tests/ui/checked_conversions.fixed b/src/tools/clippy/tests/ui/checked_conversions.fixed
index e279ba314..188e6d975 100644
--- a/src/tools/clippy/tests/ui/checked_conversions.fixed
+++ b/src/tools/clippy/tests/ui/checked_conversions.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
clippy::cast_lossless,
diff --git a/src/tools/clippy/tests/ui/checked_conversions.rs b/src/tools/clippy/tests/ui/checked_conversions.rs
index 9d7a40995..70f0f0975 100644
--- a/src/tools/clippy/tests/ui/checked_conversions.rs
+++ b/src/tools/clippy/tests/ui/checked_conversions.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
clippy::cast_lossless,
diff --git a/src/tools/clippy/tests/ui/clear_with_drain.fixed b/src/tools/clippy/tests/ui/clear_with_drain.fixed
index 2d9545eee..b68c7d867 100644
--- a/src/tools/clippy/tests/ui/clear_with_drain.fixed
+++ b/src/tools/clippy/tests/ui/clear_with_drain.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::clear_with_drain)]
diff --git a/src/tools/clippy/tests/ui/clear_with_drain.rs b/src/tools/clippy/tests/ui/clear_with_drain.rs
index 4d60ee46e..0f6562eca 100644
--- a/src/tools/clippy/tests/ui/clear_with_drain.rs
+++ b/src/tools/clippy/tests/ui/clear_with_drain.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::clear_with_drain)]
diff --git a/src/tools/clippy/tests/ui/clone_on_copy.fixed b/src/tools/clippy/tests/ui/clone_on_copy.fixed
index 72b122270..a72071158 100644
--- a/src/tools/clippy/tests/ui/clone_on_copy.fixed
+++ b/src/tools/clippy/tests/ui/clone_on_copy.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
unused,
diff --git a/src/tools/clippy/tests/ui/clone_on_copy.rs b/src/tools/clippy/tests/ui/clone_on_copy.rs
index 03e210eba..2c5fac8fa 100644
--- a/src/tools/clippy/tests/ui/clone_on_copy.rs
+++ b/src/tools/clippy/tests/ui/clone_on_copy.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
unused,
diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed b/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
index ecbfc1fee..b6e09ab31 100644
--- a/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
+++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::cloned_instead_of_copied)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs b/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
index 163dc3ddd..fa9e1a996 100644
--- a/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
+++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::cloned_instead_of_copied)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed
index abd059c23..3bf3deb9b 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed
+++ b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700
// Define the types in each module to avoid trait impls leaking between modules.
diff --git a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs
index 020ef5f84..10107dc8f 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs
+++ b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700
// Define the types in each module to avoid trait impls leaking between modules.
diff --git a/src/tools/clippy/tests/ui/cmp_owned/comparison_flip.fixed b/src/tools/clippy/tests/ui/cmp_owned/comparison_flip.fixed
index 44e41bdd1..b1133f2a5 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/comparison_flip.fixed
+++ b/src/tools/clippy/tests/ui/cmp_owned/comparison_flip.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
use std::fmt::{self, Display};
diff --git a/src/tools/clippy/tests/ui/cmp_owned/comparison_flip.rs b/src/tools/clippy/tests/ui/cmp_owned/comparison_flip.rs
index 662673abb..091a9aa65 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/comparison_flip.rs
+++ b/src/tools/clippy/tests/ui/cmp_owned/comparison_flip.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
use std::fmt::{self, Display};
diff --git a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
index b28c4378e..76f90ab2a 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
+++ b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[warn(clippy::cmp_owned)]
#[allow(clippy::unnecessary_operation, clippy::no_effect, unused_must_use, clippy::eq_op)]
diff --git a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs
index c1089010f..f3f663670 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs
+++ b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[warn(clippy::cmp_owned)]
#[allow(clippy::unnecessary_operation, clippy::no_effect, unused_must_use, clippy::eq_op)]
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.fixed b/src/tools/clippy/tests/ui/collapsible_else_if.fixed
index d6a5a7850..8302cec45 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
#[rustfmt::skip]
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.rs b/src/tools/clippy/tests/ui/collapsible_else_if.rs
index 4399fc8b2..5913dcf41 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
#[rustfmt::skip]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed
index 6bb7682ba..c6514a559 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_if.fixed
@@ -1,5 +1,10 @@
-// run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+//@run-rustfix
+#![allow(
+ clippy::assertions_on_constants,
+ clippy::equatable_if_let,
+ clippy::nonminimal_bool,
+ clippy::eq_op
+)]
#[rustfmt::skip]
#[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs
index e216a9ee5..2c85b68df 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_if.rs
@@ -1,5 +1,10 @@
-// run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+//@run-rustfix
+#![allow(
+ clippy::assertions_on_constants,
+ clippy::equatable_if_let,
+ clippy::nonminimal_bool,
+ clippy::eq_op
+)]
#[rustfmt::skip]
#[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr
index 6327444df..c687bae1a 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_if.stderr
@@ -1,5 +1,5 @@
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:9:5
+ --> $DIR/collapsible_if.rs:14:5
|
LL | / if x == "hello" {
LL | | if y == "world" {
@@ -17,7 +17,7 @@ LL + }
|
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:15:5
+ --> $DIR/collapsible_if.rs:20:5
|
LL | / if x == "hello" || x == "world" {
LL | | if y == "world" || y == "hello" {
@@ -34,7 +34,7 @@ LL + }
|
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:21:5
+ --> $DIR/collapsible_if.rs:26:5
|
LL | / if x == "hello" && x == "world" {
LL | | if y == "world" || y == "hello" {
@@ -51,7 +51,7 @@ LL + }
|
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:27:5
+ --> $DIR/collapsible_if.rs:32:5
|
LL | / if x == "hello" || x == "world" {
LL | | if y == "world" && y == "hello" {
@@ -68,7 +68,7 @@ LL + }
|
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:33:5
+ --> $DIR/collapsible_if.rs:38:5
|
LL | / if x == "hello" && x == "world" {
LL | | if y == "world" && y == "hello" {
@@ -85,7 +85,7 @@ LL + }
|
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:39:5
+ --> $DIR/collapsible_if.rs:44:5
|
LL | / if 42 == 1337 {
LL | | if 'a' != 'A' {
@@ -102,7 +102,7 @@ LL + }
|
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:95:5
+ --> $DIR/collapsible_if.rs:100:5
|
LL | / if x == "hello" {
LL | | if y == "world" { // Collapsible
@@ -119,7 +119,7 @@ LL + }
|
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:154:5
+ --> $DIR/collapsible_if.rs:159:5
|
LL | / if matches!(true, true) {
LL | | if matches!(true, true) {}
@@ -127,7 +127,7 @@ LL | | }
| |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
error: this `if` statement can be collapsed
- --> $DIR/collapsible_if.rs:159:5
+ --> $DIR/collapsible_if.rs:164:5
|
LL | / if matches!(true, true) && truth() {
LL | | if matches!(true, true) {}
diff --git a/src/tools/clippy/tests/ui/collapsible_str_replace.fixed b/src/tools/clippy/tests/ui/collapsible_str_replace.fixed
index 9792ae9ed..ba6c1769a 100644
--- a/src/tools/clippy/tests/ui/collapsible_str_replace.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_str_replace.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::collapsible_str_replace)]
diff --git a/src/tools/clippy/tests/ui/collapsible_str_replace.rs b/src/tools/clippy/tests/ui/collapsible_str_replace.rs
index baee185b7..f5871be65 100644
--- a/src/tools/clippy/tests/ui/collapsible_str_replace.rs
+++ b/src/tools/clippy/tests/ui/collapsible_str_replace.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::collapsible_str_replace)]
diff --git a/src/tools/clippy/tests/ui/collection_is_never_read.rs b/src/tools/clippy/tests/ui/collection_is_never_read.rs
index 01259a983..2c1a42a72 100644
--- a/src/tools/clippy/tests/ui/collection_is_never_read.rs
+++ b/src/tools/clippy/tests/ui/collection_is_never_read.rs
@@ -169,22 +169,35 @@ fn function_argument() {
foo(&x);
}
-fn string() {
- // Do lint (write without read)
- let mut s = String::new();
- s.push_str("Hello, World!");
-
- // Do not lint (read without write)
- let mut s = String::from("Hello, World!");
- let _ = s.len();
-
- // Do not lint (write and read)
- let mut s = String::from("Hello, World!");
- s.push_str("foo, bar");
- let _ = s.len();
-
- // Do lint the first line, but not the second
- let mut s = String::from("Hello, World!");
- let t = String::from("foo, bar");
- s = t;
+fn supported_types() {
+ let mut x = std::collections::BTreeMap::new(); // WARNING
+ x.insert(true, 1);
+
+ let mut x = std::collections::BTreeSet::new(); // WARNING
+ x.insert(1);
+
+ let mut x = std::collections::BinaryHeap::new(); // WARNING
+ x.push(1);
+
+ let mut x = std::collections::HashMap::new(); // WARNING
+ x.insert(1, 2);
+
+ let mut x = std::collections::HashSet::new(); // WARNING
+ x.insert(1);
+
+ let mut x = std::collections::LinkedList::new(); // WARNING
+ x.push_front(1);
+
+ let mut x = Some(true); // WARNING
+ x.insert(false);
+
+ let mut x = String::from("hello"); // WARNING
+ x.push('!');
+
+ let mut x = Vec::new(); // WARNING
+ x.clear();
+ x.push(1);
+
+ let mut x = std::collections::VecDeque::new(); // WARNING
+ x.push_front(1);
}
diff --git a/src/tools/clippy/tests/ui/collection_is_never_read.stderr b/src/tools/clippy/tests/ui/collection_is_never_read.stderr
index cf51a5368..982cb4455 100644
--- a/src/tools/clippy/tests/ui/collection_is_never_read.stderr
+++ b/src/tools/clippy/tests/ui/collection_is_never_read.stderr
@@ -61,16 +61,64 @@ LL | let x = vec![1, 2, 3]; // WARNING
| ^^^^^^^^^^^^^^^^^^^^^^
error: collection is never read
- --> $DIR/collection_is_never_read.rs:174:5
+ --> $DIR/collection_is_never_read.rs:173:5
|
-LL | let mut s = String::new();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let mut x = std::collections::BTreeMap::new(); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+ --> $DIR/collection_is_never_read.rs:176:5
+ |
+LL | let mut x = std::collections::BTreeSet::new(); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+ --> $DIR/collection_is_never_read.rs:179:5
+ |
+LL | let mut x = std::collections::BinaryHeap::new(); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+ --> $DIR/collection_is_never_read.rs:182:5
+ |
+LL | let mut x = std::collections::HashMap::new(); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+ --> $DIR/collection_is_never_read.rs:185:5
+ |
+LL | let mut x = std::collections::HashSet::new(); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+ --> $DIR/collection_is_never_read.rs:188:5
+ |
+LL | let mut x = std::collections::LinkedList::new(); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+ --> $DIR/collection_is_never_read.rs:191:5
+ |
+LL | let mut x = Some(true); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+ --> $DIR/collection_is_never_read.rs:194:5
+ |
+LL | let mut x = String::from("hello"); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+ --> $DIR/collection_is_never_read.rs:197:5
+ |
+LL | let mut x = Vec::new(); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^
error: collection is never read
- --> $DIR/collection_is_never_read.rs:187:5
+ --> $DIR/collection_is_never_read.rs:201:5
|
-LL | let mut s = String::from("Hello, World!");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let mut x = std::collections::VecDeque::new(); // WARNING
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 12 previous errors
+error: aborting due to 20 previous errors
diff --git a/src/tools/clippy/tests/ui/comparison_to_empty.fixed b/src/tools/clippy/tests/ui/comparison_to_empty.fixed
index 261024cac..dd2615ab2 100644
--- a/src/tools/clippy/tests/ui/comparison_to_empty.fixed
+++ b/src/tools/clippy/tests/ui/comparison_to_empty.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::comparison_to_empty)]
diff --git a/src/tools/clippy/tests/ui/comparison_to_empty.rs b/src/tools/clippy/tests/ui/comparison_to_empty.rs
index 98ddd9749..5462784c6 100644
--- a/src/tools/clippy/tests/ui/comparison_to_empty.rs
+++ b/src/tools/clippy/tests/ui/comparison_to_empty.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::comparison_to_empty)]
diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
index 5ff2af7cd..66419656a 100644
--- a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
+++ b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
@@ -1,5 +1,5 @@
-// compile-flags: --emit=link
-// no-prefer-dynamic
+//@compile-flags: --emit=link
+//@no-prefer-dynamic
// ^ compiletest by default builds all aux files as dylibs, but we don't want that for proc-macro
// crates. If we don't set this, compiletest will override the `crate_type` attribute below and
// compile this as dylib. Removing this then causes the test to fail because a `dylib` crate can't
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10148.rs b/src/tools/clippy/tests/ui/crashes/ice-10148.rs
index 1ab3570c9..c7f022482 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-10148.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-10148.rs
@@ -1,4 +1,4 @@
-// aux-build:../../auxiliary/proc_macros.rs
+//@aux-build:../../auxiliary/proc_macros.rs
extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.rs b/src/tools/clippy/tests/ui/crashes/ice-10645.rs
new file mode 100644
index 000000000..4d8698d38
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-10645.rs
@@ -0,0 +1,7 @@
+// compile-flags: --cap-lints=warn
+// https://github.com/rust-lang/rust-clippy/issues/10645
+
+#![warn(clippy::future_not_send)]
+pub async fn bar<'a, T: 'a>(_: T) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
new file mode 100644
index 000000000..fc084e30d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
@@ -0,0 +1,16 @@
+error: future cannot be sent between threads safely
+ --> $DIR/ice-10645.rs:5:35
+ |
+LL | pub async fn bar<'a, T: 'a>(_: T) {}
+ | ^ future returned by `bar` is not `Send`
+ |
+note: captured value is not `Send`
+ --> $DIR/ice-10645.rs:5:29
+ |
+LL | pub async fn bar<'a, T: 'a>(_: T) {}
+ | ^ has type `T` which is not `Send`
+ = note: `T` doesn't implement `std::marker::Send`
+ = note: `-D clippy::future-not-send` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3741.rs b/src/tools/clippy/tests/ui/crashes/ice-3741.rs
index 1253ddcfa..3106a2e72 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3741.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3741.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macro_crash.rs
+//@aux-build:proc_macro_crash.rs
#![warn(clippy::suspicious_else_formatting)]
diff --git a/src/tools/clippy/tests/ui/crashes/ice-4968.rs b/src/tools/clippy/tests/ui/crashes/ice-4968.rs
index e0510d942..ac724ac93 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-4968.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-4968.rs
@@ -1,4 +1,4 @@
-// check-pass
+//@check-pass
// Test for https://github.com/rust-lang/rust-clippy/issues/4968
diff --git a/src/tools/clippy/tests/ui/crashes/ice-5207.rs b/src/tools/clippy/tests/ui/crashes/ice-5207.rs
index f463f78a9..0df8b88fe 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-5207.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-5207.rs
@@ -1,5 +1,4 @@
// Regression test for https://github.com/rust-lang/rust-clippy/issues/5207
-
pub async fn bar<'a, T: 'a>(_: T) {}
fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7272.rs b/src/tools/clippy/tests/ui/crashes/ice-7272.rs
index 57ab6ca14..e949038c8 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7272.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7272.rs
@@ -1,4 +1,4 @@
-// aux-build:ice-7272-aux.rs
+//@aux-build:ice-7272-aux.rs
#![allow(clippy::no_effect)]
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7410.rs b/src/tools/clippy/tests/ui/crashes/ice-7410.rs
index 85fa42103..ffe20ab1c 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7410.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7410.rs
@@ -1,6 +1,6 @@
-// compile-flags: -Clink-arg=-nostartfiles
-// ignore-macos
-// ignore-windows
+//@compile-flags: -Clink-arg=-nostartfiles
+//@ignore-macos
+//@ignore-windows
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/crashes/ice-8681.rs b/src/tools/clippy/tests/ui/crashes/ice-8681.rs
index ee14f011f..607b9caa3 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-8681.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-8681.rs
@@ -1,4 +1,4 @@
-// aux-build: ice-8681-aux.rs
+//@aux-build: ice-8681-aux.rs
#![warn(clippy::undocumented_unsafe_blocks)]
diff --git a/src/tools/clippy/tests/ui/crashes/ice_exacte_size.rs b/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs
index 30e4b11ec..30e4b11ec 100644
--- a/src/tools/clippy/tests/ui/crashes/ice_exacte_size.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs
diff --git a/src/tools/clippy/tests/ui/crate_in_macro_def.fixed b/src/tools/clippy/tests/ui/crate_in_macro_def.fixed
index 9fc594be3..12a7b9470 100644
--- a/src/tools/clippy/tests/ui/crate_in_macro_def.fixed
+++ b/src/tools/clippy/tests/ui/crate_in_macro_def.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::crate_in_macro_def)]
mod hygienic {
diff --git a/src/tools/clippy/tests/ui/crate_in_macro_def.rs b/src/tools/clippy/tests/ui/crate_in_macro_def.rs
index ac456108e..a1a9eabf6 100644
--- a/src/tools/clippy/tests/ui/crate_in_macro_def.rs
+++ b/src/tools/clippy/tests/ui/crate_in_macro_def.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::crate_in_macro_def)]
mod hygienic {
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
index 1b3bcece6..d6cd594d7 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
@@ -1,4 +1,4 @@
-// ignore-macos
+//@ignore-macos
#![feature(rustc_attrs)]
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
index e1c9fe30a..a382135bb 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
@@ -1,5 +1,5 @@
-// compile-flags: -Clink-arg=-nostartfiles
-// ignore-macos
+//@compile-flags: -Clink-arg=-nostartfiles
+//@ignore-macos
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/create_dir.fixed b/src/tools/clippy/tests/ui/create_dir.fixed
index 8ed53a56a..5de3e9fea 100644
--- a/src/tools/clippy/tests/ui/create_dir.fixed
+++ b/src/tools/clippy/tests/ui/create_dir.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_must_use)]
#![warn(clippy::create_dir)]
diff --git a/src/tools/clippy/tests/ui/create_dir.rs b/src/tools/clippy/tests/ui/create_dir.rs
index 19c8fc24b..d375bfb4a 100644
--- a/src/tools/clippy/tests/ui/create_dir.rs
+++ b/src/tools/clippy/tests/ui/create_dir.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_must_use)]
#![warn(clippy::create_dir)]
diff --git a/src/tools/clippy/tests/ui/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro.rs
index 25294e8c7..10788d404 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro.rs
@@ -1,9 +1,10 @@
-// compile-flags: --test
+//@compile-flags: --test
#![warn(clippy::dbg_macro)]
fn foo(n: u32) -> u32 {
if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
}
+fn bar(_: ()) {}
fn factorial(n: u32) -> u32 {
if dbg!(n <= 1) {
@@ -21,6 +22,32 @@ fn main() {
dbg!(1, 2, 3, 4, 5);
}
+fn issue9914() {
+ macro_rules! foo {
+ ($x:expr) => {
+ $x;
+ };
+ }
+ macro_rules! foo2 {
+ ($x:expr) => {
+ $x;
+ };
+ }
+ macro_rules! expand_to_dbg {
+ () => {
+ dbg!();
+ };
+ }
+
+ dbg!();
+ #[allow(clippy::let_unit_value)]
+ let _ = dbg!();
+ bar(dbg!());
+ foo!(dbg!());
+ foo2!(foo!(dbg!()));
+ expand_to_dbg!();
+}
+
mod issue7274 {
trait Thing<'b> {
fn foo(&self);
diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro.stderr
index ddb5f1342..530e76633 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro.stderr
@@ -11,7 +11,7 @@ LL | if let Some(n) = n.checked_sub(4) { n } else { n }
| ~~~~~~~~~~~~~~~~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:9:8
+ --> $DIR/dbg_macro.rs:10:8
|
LL | if dbg!(n <= 1) {
| ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | if n <= 1 {
| ~~~~~~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:10:9
+ --> $DIR/dbg_macro.rs:11:9
|
LL | dbg!(1)
| ^^^^^^^
@@ -33,7 +33,7 @@ LL | 1
|
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:12:9
+ --> $DIR/dbg_macro.rs:13:9
|
LL | dbg!(n * factorial(n - 1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL | n * factorial(n - 1)
|
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:17:5
+ --> $DIR/dbg_macro.rs:18:5
|
LL | dbg!(42);
| ^^^^^^^^
@@ -55,7 +55,7 @@ LL | 42;
| ~~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:18:5
+ --> $DIR/dbg_macro.rs:19:5
|
LL | dbg!(dbg!(dbg!(42)));
| ^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL | dbg!(dbg!(42));
| ~~~~~~~~~~~~~~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:19:14
+ --> $DIR/dbg_macro.rs:20:14
|
LL | foo(3) + dbg!(factorial(4));
| ^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL | foo(3) + factorial(4);
| ~~~~~~~~~~~~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:20:5
+ --> $DIR/dbg_macro.rs:21:5
|
LL | dbg!(1, 2, dbg!(3, 4));
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL | (1, 2, dbg!(3, 4));
| ~~~~~~~~~~~~~~~~~~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:21:5
+ --> $DIR/dbg_macro.rs:22:5
|
LL | dbg!(1, 2, 3, 4, 5);
| ^^^^^^^^^^^^^^^^^^^
@@ -99,7 +99,63 @@ LL | (1, 2, 3, 4, 5);
| ~~~~~~~~~~~~~~~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:41:9
+ --> $DIR/dbg_macro.rs:42:5
+ |
+LL | dbg!();
+ | ^^^^^^^
+ |
+help: remove the invocation before committing it to a version control system
+ |
+LL - dbg!();
+LL +
+ |
+
+error: the `dbg!` macro is intended as a debugging tool
+ --> $DIR/dbg_macro.rs:44:13
+ |
+LL | let _ = dbg!();
+ | ^^^^^^
+ |
+help: remove the invocation before committing it to a version control system
+ |
+LL | let _ = ();
+ | ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+ --> $DIR/dbg_macro.rs:45:9
+ |
+LL | bar(dbg!());
+ | ^^^^^^
+ |
+help: remove the invocation before committing it to a version control system
+ |
+LL | bar(());
+ | ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+ --> $DIR/dbg_macro.rs:46:10
+ |
+LL | foo!(dbg!());
+ | ^^^^^^
+ |
+help: remove the invocation before committing it to a version control system
+ |
+LL | foo!(());
+ | ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+ --> $DIR/dbg_macro.rs:47:16
+ |
+LL | foo2!(foo!(dbg!()));
+ | ^^^^^^
+ |
+help: remove the invocation before committing it to a version control system
+ |
+LL | foo2!(foo!(()));
+ | ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+ --> $DIR/dbg_macro.rs:68:9
|
LL | dbg!(2);
| ^^^^^^^
@@ -110,7 +166,7 @@ LL | 2;
| ~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:47:5
+ --> $DIR/dbg_macro.rs:74:5
|
LL | dbg!(1);
| ^^^^^^^
@@ -121,7 +177,7 @@ LL | 1;
| ~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:52:5
+ --> $DIR/dbg_macro.rs:79:5
|
LL | dbg!(1);
| ^^^^^^^
@@ -132,7 +188,7 @@ LL | 1;
| ~
error: the `dbg!` macro is intended as a debugging tool
- --> $DIR/dbg_macro.rs:58:9
+ --> $DIR/dbg_macro.rs:85:9
|
LL | dbg!(1);
| ^^^^^^^
@@ -142,5 +198,5 @@ help: remove the invocation before committing it to a version control system
LL | 1;
| ~
-error: aborting due to 13 previous errors
+error: aborting due to 18 previous errors
diff --git a/src/tools/clippy/tests/ui/decimal_literal_representation.fixed b/src/tools/clippy/tests/ui/decimal_literal_representation.fixed
index de3914651..a6eb8c214 100644
--- a/src/tools/clippy/tests/ui/decimal_literal_representation.fixed
+++ b/src/tools/clippy/tests/ui/decimal_literal_representation.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[warn(clippy::decimal_literal_representation)]
#[allow(unused_variables)]
diff --git a/src/tools/clippy/tests/ui/decimal_literal_representation.rs b/src/tools/clippy/tests/ui/decimal_literal_representation.rs
index 55d07698e..7c666d6d7 100644
--- a/src/tools/clippy/tests/ui/decimal_literal_representation.rs
+++ b/src/tools/clippy/tests/ui/decimal_literal_representation.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[warn(clippy::decimal_literal_representation)]
#[allow(unused_variables)]
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs
index 1af77d1a2..f7819068a 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.rs
+++ b/src/tools/clippy/tests/ui/def_id_nocore.rs
@@ -1,4 +1,4 @@
-// ignore-macos
+//@ignore-macos
#![feature(no_core, lang_items, start)]
#![no_core]
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
new file mode 100644
index 000000000..ac5fe38ff
--- /dev/null
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
@@ -0,0 +1,159 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::default_constructed_unit_structs)]
+use std::marker::PhantomData;
+
+#[derive(Default)]
+struct UnitStruct;
+
+impl UnitStruct {
+ fn new() -> Self {
+ //should lint
+ Self
+ }
+}
+
+#[derive(Default)]
+struct TupleStruct(usize);
+
+impl TupleStruct {
+ fn new() -> Self {
+ // should not lint
+ Self(Default::default())
+ }
+}
+
+// no lint for derived impl
+#[derive(Default)]
+struct NormalStruct {
+ inner: PhantomData<usize>,
+}
+
+struct NonDefaultStruct;
+
+impl NonDefaultStruct {
+ fn default() -> Self {
+ Self
+ }
+}
+
+#[derive(Default)]
+enum SomeEnum {
+ #[default]
+ Unit,
+ Tuple(UnitStruct),
+ Struct {
+ inner: usize,
+ },
+}
+
+impl NormalStruct {
+ fn new() -> Self {
+ // should lint
+ Self {
+ inner: PhantomData,
+ }
+ }
+
+ fn new2() -> Self {
+ // should not lint
+ Self {
+ inner: Default::default(),
+ }
+ }
+}
+
+#[derive(Default)]
+struct GenericStruct<T> {
+ t: T,
+}
+
+impl<T: Default> GenericStruct<T> {
+ fn new() -> Self {
+ // should not lint
+ Self { t: T::default() }
+ }
+
+ fn new2() -> Self {
+ // should not lint
+ Self { t: Default::default() }
+ }
+}
+
+struct FakeDefault;
+impl FakeDefault {
+ fn default() -> Self {
+ Self
+ }
+}
+
+impl Default for FakeDefault {
+ fn default() -> Self {
+ Self
+ }
+}
+
+#[derive(Default)]
+struct EmptyStruct {}
+
+#[derive(Default)]
+#[non_exhaustive]
+struct NonExhaustiveStruct;
+
+mod issue_10755 {
+ struct Sqlite {}
+
+ trait HasArguments<'q> {
+ type Arguments;
+ }
+
+ impl<'q> HasArguments<'q> for Sqlite {
+ type Arguments = std::marker::PhantomData<&'q ()>;
+ }
+
+ type SqliteArguments<'q> = <Sqlite as HasArguments<'q>>::Arguments;
+
+ fn foo() {
+ // should not lint
+ // type alias cannot be used as a constructor
+ let _ = <Sqlite as HasArguments>::Arguments::default();
+
+ let _ = SqliteArguments::default();
+ }
+}
+
+fn main() {
+ // should lint
+ let _ = PhantomData::<usize>;
+ let _: PhantomData<i32> = PhantomData;
+ let _: PhantomData<i32> = std::marker::PhantomData;
+ let _ = UnitStruct;
+
+ // should not lint
+ let _ = TupleStruct::default();
+ let _ = NormalStruct::default();
+ let _ = NonExhaustiveStruct::default();
+ let _ = SomeEnum::default();
+ let _ = NonDefaultStruct::default();
+ let _ = EmptyStruct::default();
+ let _ = FakeDefault::default();
+ let _ = <FakeDefault as Default>::default();
+
+ macro_rules! in_macro {
+ ($i:ident) => {{
+ let _ = UnitStruct::default();
+ let _ = $i::default();
+ }};
+ }
+
+ in_macro!(UnitStruct);
+
+ macro_rules! struct_from_macro {
+ () => {
+ UnitStruct
+ };
+ }
+
+ let _ = <struct_from_macro!()>::default();
+}
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
new file mode 100644
index 000000000..de7f14ffb
--- /dev/null
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
@@ -0,0 +1,159 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::default_constructed_unit_structs)]
+use std::marker::PhantomData;
+
+#[derive(Default)]
+struct UnitStruct;
+
+impl UnitStruct {
+ fn new() -> Self {
+ //should lint
+ Self::default()
+ }
+}
+
+#[derive(Default)]
+struct TupleStruct(usize);
+
+impl TupleStruct {
+ fn new() -> Self {
+ // should not lint
+ Self(Default::default())
+ }
+}
+
+// no lint for derived impl
+#[derive(Default)]
+struct NormalStruct {
+ inner: PhantomData<usize>,
+}
+
+struct NonDefaultStruct;
+
+impl NonDefaultStruct {
+ fn default() -> Self {
+ Self
+ }
+}
+
+#[derive(Default)]
+enum SomeEnum {
+ #[default]
+ Unit,
+ Tuple(UnitStruct),
+ Struct {
+ inner: usize,
+ },
+}
+
+impl NormalStruct {
+ fn new() -> Self {
+ // should lint
+ Self {
+ inner: PhantomData::default(),
+ }
+ }
+
+ fn new2() -> Self {
+ // should not lint
+ Self {
+ inner: Default::default(),
+ }
+ }
+}
+
+#[derive(Default)]
+struct GenericStruct<T> {
+ t: T,
+}
+
+impl<T: Default> GenericStruct<T> {
+ fn new() -> Self {
+ // should not lint
+ Self { t: T::default() }
+ }
+
+ fn new2() -> Self {
+ // should not lint
+ Self { t: Default::default() }
+ }
+}
+
+struct FakeDefault;
+impl FakeDefault {
+ fn default() -> Self {
+ Self
+ }
+}
+
+impl Default for FakeDefault {
+ fn default() -> Self {
+ Self
+ }
+}
+
+#[derive(Default)]
+struct EmptyStruct {}
+
+#[derive(Default)]
+#[non_exhaustive]
+struct NonExhaustiveStruct;
+
+mod issue_10755 {
+ struct Sqlite {}
+
+ trait HasArguments<'q> {
+ type Arguments;
+ }
+
+ impl<'q> HasArguments<'q> for Sqlite {
+ type Arguments = std::marker::PhantomData<&'q ()>;
+ }
+
+ type SqliteArguments<'q> = <Sqlite as HasArguments<'q>>::Arguments;
+
+ fn foo() {
+ // should not lint
+ // type alias cannot be used as a constructor
+ let _ = <Sqlite as HasArguments>::Arguments::default();
+
+ let _ = SqliteArguments::default();
+ }
+}
+
+fn main() {
+ // should lint
+ let _ = PhantomData::<usize>::default();
+ let _: PhantomData<i32> = PhantomData::default();
+ let _: PhantomData<i32> = std::marker::PhantomData::default();
+ let _ = UnitStruct::default();
+
+ // should not lint
+ let _ = TupleStruct::default();
+ let _ = NormalStruct::default();
+ let _ = NonExhaustiveStruct::default();
+ let _ = SomeEnum::default();
+ let _ = NonDefaultStruct::default();
+ let _ = EmptyStruct::default();
+ let _ = FakeDefault::default();
+ let _ = <FakeDefault as Default>::default();
+
+ macro_rules! in_macro {
+ ($i:ident) => {{
+ let _ = UnitStruct::default();
+ let _ = $i::default();
+ }};
+ }
+
+ in_macro!(UnitStruct);
+
+ macro_rules! struct_from_macro {
+ () => {
+ UnitStruct
+ };
+ }
+
+ let _ = <struct_from_macro!()>::default();
+}
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
new file mode 100644
index 000000000..13abb9149
--- /dev/null
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
@@ -0,0 +1,40 @@
+error: use of `default` to create a unit struct
+ --> $DIR/default_constructed_unit_structs.rs:13:13
+ |
+LL | Self::default()
+ | ^^^^^^^^^^^ help: remove this call to `default`
+ |
+ = note: `-D clippy::default-constructed-unit-structs` implied by `-D warnings`
+
+error: use of `default` to create a unit struct
+ --> $DIR/default_constructed_unit_structs.rs:55:31
+ |
+LL | inner: PhantomData::default(),
+ | ^^^^^^^^^^^ help: remove this call to `default`
+
+error: use of `default` to create a unit struct
+ --> $DIR/default_constructed_unit_structs.rs:128:33
+ |
+LL | let _ = PhantomData::<usize>::default();
+ | ^^^^^^^^^^^ help: remove this call to `default`
+
+error: use of `default` to create a unit struct
+ --> $DIR/default_constructed_unit_structs.rs:129:42
+ |
+LL | let _: PhantomData<i32> = PhantomData::default();
+ | ^^^^^^^^^^^ help: remove this call to `default`
+
+error: use of `default` to create a unit struct
+ --> $DIR/default_constructed_unit_structs.rs:130:55
+ |
+LL | let _: PhantomData<i32> = std::marker::PhantomData::default();
+ | ^^^^^^^^^^^ help: remove this call to `default`
+
+error: use of `default` to create a unit struct
+ --> $DIR/default_constructed_unit_structs.rs:131:23
+ |
+LL | let _ = UnitStruct::default();
+ | ^^^^^^^^^^^ help: remove this call to `default`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/default_instead_of_iter_empty.fixed b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.fixed
index f1abfdcd6..f44d34576 100644
--- a/src/tools/clippy/tests/ui/default_instead_of_iter_empty.fixed
+++ b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::default_instead_of_iter_empty)]
#![allow(dead_code)]
use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/default_instead_of_iter_empty.rs b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.rs
index 2630519c4..1c649df25 100644
--- a/src/tools/clippy/tests/ui/default_instead_of_iter_empty.rs
+++ b/src/tools/clippy/tests/ui/default_instead_of_iter_empty.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::default_instead_of_iter_empty)]
#![allow(dead_code)]
use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
index 42c15d6a7..9520efe63 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::default_numeric_fallback)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
index 7da7ea254..cacbdb4a9 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::default_numeric_fallback)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
index b7485b73d..fbabb8bcf 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![feature(lint_reasons)]
#![warn(clippy::default_numeric_fallback)]
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
index 7307d3135..7bfc390e4 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![feature(lint_reasons)]
#![warn(clippy::default_numeric_fallback)]
diff --git a/src/tools/clippy/tests/ui/default_trait_access.fixed b/src/tools/clippy/tests/ui/default_trait_access.fixed
index 7842ef3ec..bf5dca976 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.fixed
+++ b/src/tools/clippy/tests/ui/default_trait_access.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build: proc_macros.rs
+//@run-rustfix
+//@aux-build: proc_macros.rs
#![deny(clippy::default_trait_access)]
#![allow(dead_code, unused_imports)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/default_trait_access.rs b/src/tools/clippy/tests/ui/default_trait_access.rs
index cbb3e59c9..5e8e9ce85 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.rs
+++ b/src/tools/clippy/tests/ui/default_trait_access.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build: proc_macros.rs
+//@run-rustfix
+//@aux-build: proc_macros.rs
#![deny(clippy::default_trait_access)]
#![allow(dead_code, unused_imports)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/deref_addrof.fixed b/src/tools/clippy/tests/ui/deref_addrof.fixed
index ca5c03304..b27d3bc10 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.fixed
+++ b/src/tools/clippy/tests/ui/deref_addrof.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![allow(clippy::return_self_not_must_use)]
#![warn(clippy::deref_addrof)]
diff --git a/src/tools/clippy/tests/ui/deref_addrof.rs b/src/tools/clippy/tests/ui/deref_addrof.rs
index 3db5fafe9..825090c7c 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.rs
+++ b/src/tools/clippy/tests/ui/deref_addrof.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![allow(clippy::return_self_not_must_use)]
#![warn(clippy::deref_addrof)]
diff --git a/src/tools/clippy/tests/ui/deref_addrof_macro.rs b/src/tools/clippy/tests/ui/deref_addrof_macro.rs
index 57c0be3f5..c7e60f365 100644
--- a/src/tools/clippy/tests/ui/deref_addrof_macro.rs
+++ b/src/tools/clippy/tests/ui/deref_addrof_macro.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![warn(clippy::deref_addrof)]
diff --git a/src/tools/clippy/tests/ui/deref_by_slicing.fixed b/src/tools/clippy/tests/ui/deref_by_slicing.fixed
index 257393e56..f91a425c6 100644
--- a/src/tools/clippy/tests/ui/deref_by_slicing.fixed
+++ b/src/tools/clippy/tests/ui/deref_by_slicing.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::deref_by_slicing)]
#![allow(clippy::borrow_deref_ref)]
diff --git a/src/tools/clippy/tests/ui/deref_by_slicing.rs b/src/tools/clippy/tests/ui/deref_by_slicing.rs
index e288046f9..1bfdd0a98 100644
--- a/src/tools/clippy/tests/ui/deref_by_slicing.rs
+++ b/src/tools/clippy/tests/ui/deref_by_slicing.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::deref_by_slicing)]
#![allow(clippy::borrow_deref_ref)]
diff --git a/src/tools/clippy/tests/ui/derivable_impls.fixed b/src/tools/clippy/tests/ui/derivable_impls.fixed
index 89ec33a0d..aa0efb85c 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.fixed
+++ b/src/tools/clippy/tests/ui/derivable_impls.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs
index def6e4116..8dc999ad5 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.rs
+++ b/src/tools/clippy/tests/ui/derivable_impls.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
index bbbe46759..a1f29430c 100644
--- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
+++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::derive_partial_eq_without_eq)]
diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
index 88d6fbd1a..ff4d88855 100644
--- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
+++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::derive_partial_eq_without_eq)]
diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
index 9c91d9357..51a3b0d97 100644
--- a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
+++ b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
@@ -31,18 +31,10 @@ LL | 3 => true || diverge(),
| ^^^^^^^^^
error: sub-expression diverges
- --> $DIR/diverging_sub_expression.rs:36:30
- |
-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
--> $DIR/diverging_sub_expression.rs:38:26
|
LL | _ => true || break,
| ^^^^^
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index ecb0bf364..d3aa2816c 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
//! This file tests for the `DOC_MARKDOWN` lint.
#![allow(dead_code, incomplete_features)]
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index 11c48dd10..d1e7d8017 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
//! This file tests for the `DOC_MARKDOWN` lint.
#![allow(dead_code, incomplete_features)]
diff --git a/src/tools/clippy/tests/ui/doc_unsafe.rs b/src/tools/clippy/tests/ui/doc_unsafe.rs
index 30674ce37..0c8eac5cc 100644
--- a/src/tools/clippy/tests/ui/doc_unsafe.rs
+++ b/src/tools/clippy/tests/ui/doc_unsafe.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![allow(clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/double_comparison.fixed b/src/tools/clippy/tests/ui/double_comparison.fixed
index bb6cdaa66..c80ff671a 100644
--- a/src/tools/clippy/tests/ui/double_comparison.fixed
+++ b/src/tools/clippy/tests/ui/double_comparison.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
fn main() {
let x = 1;
diff --git a/src/tools/clippy/tests/ui/double_comparison.rs b/src/tools/clippy/tests/ui/double_comparison.rs
index 9a2a9068a..bc78694aa 100644
--- a/src/tools/clippy/tests/ui/double_comparison.rs
+++ b/src/tools/clippy/tests/ui/double_comparison.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
fn main() {
let x = 1;
diff --git a/src/tools/clippy/tests/ui/drop_forget_copy.rs b/src/tools/clippy/tests/ui/drop_forget_copy.rs
deleted file mode 100644
index a7276dd59..000000000
--- a/src/tools/clippy/tests/ui/drop_forget_copy.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-#![warn(clippy::drop_copy, clippy::forget_copy)]
-#![allow(clippy::toplevel_ref_arg, clippy::drop_ref, clippy::forget_ref, unused_mut)]
-
-use std::mem::{drop, forget};
-use std::vec::Vec;
-
-#[derive(Copy, Clone)]
-struct SomeStruct;
-
-struct AnotherStruct {
- x: u8,
- y: u8,
- z: Vec<u8>,
-}
-
-impl Clone for AnotherStruct {
- fn clone(&self) -> AnotherStruct {
- AnotherStruct {
- x: self.x,
- y: self.y,
- z: self.z.clone(),
- }
- }
-}
-
-fn main() {
- let s1 = SomeStruct {};
- let s2 = s1;
- let s3 = &s1;
- let mut s4 = s1;
- let ref s5 = s1;
-
- drop(s1);
- drop(s2);
- drop(s3);
- drop(s4);
- drop(s5);
-
- forget(s1);
- forget(s2);
- forget(s3);
- forget(s4);
- forget(s5);
-
- let a1 = AnotherStruct {
- x: 255,
- y: 0,
- z: vec![1, 2, 3],
- };
- let a2 = &a1;
- let mut a3 = a1.clone();
- let ref a4 = a1;
- let a5 = a1.clone();
-
- drop(a2);
- drop(a3);
- drop(a4);
- drop(a5);
-
- forget(a2);
- let a3 = &a1;
- forget(a3);
- forget(a4);
- let a5 = a1.clone();
- forget(a5);
-}
-
-#[allow(unused)]
-#[allow(clippy::unit_cmp)]
-fn issue9482(x: u8) {
- fn println_and<T>(t: T) -> T {
- println!("foo");
- t
- }
-
- match x {
- 0 => drop(println_and(12)), // Don't lint (copy type), we only care about side-effects
- 1 => drop(println_and(String::new())), // Don't lint (no copy type), we only care about side-effects
- 2 => {
- drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
- },
- 3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
- 4 => drop(2), // Lint, not a fn/method call
- _ => (),
- }
-}
diff --git a/src/tools/clippy/tests/ui/drop_forget_copy.stderr b/src/tools/clippy/tests/ui/drop_forget_copy.stderr
deleted file mode 100644
index 90bef1c3c..000000000
--- a/src/tools/clippy/tests/ui/drop_forget_copy.stderr
+++ /dev/null
@@ -1,112 +0,0 @@
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:33:5
- |
-LL | drop(s1);
- | ^^^^^^^^
- |
-note: argument has type `SomeStruct`
- --> $DIR/drop_forget_copy.rs:33:10
- |
-LL | drop(s1);
- | ^^
- = note: `-D clippy::drop-copy` implied by `-D warnings`
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:34:5
- |
-LL | drop(s2);
- | ^^^^^^^^
- |
-note: argument has type `SomeStruct`
- --> $DIR/drop_forget_copy.rs:34:10
- |
-LL | drop(s2);
- | ^^
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:36:5
- |
-LL | drop(s4);
- | ^^^^^^^^
- |
-note: argument has type `SomeStruct`
- --> $DIR/drop_forget_copy.rs:36:10
- |
-LL | drop(s4);
- | ^^
-
-error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:39:5
- |
-LL | forget(s1);
- | ^^^^^^^^^^
- |
-note: argument has type `SomeStruct`
- --> $DIR/drop_forget_copy.rs:39:12
- |
-LL | forget(s1);
- | ^^
- = note: `-D clippy::forget-copy` implied by `-D warnings`
-
-error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:40:5
- |
-LL | forget(s2);
- | ^^^^^^^^^^
- |
-note: argument has type `SomeStruct`
- --> $DIR/drop_forget_copy.rs:40:12
- |
-LL | forget(s2);
- | ^^
-
-error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:42:5
- |
-LL | forget(s4);
- | ^^^^^^^^^^
- |
-note: argument has type `SomeStruct`
- --> $DIR/drop_forget_copy.rs:42:12
- |
-LL | forget(s4);
- | ^^
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:80:13
- |
-LL | drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
- | ^^^^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `i32`
- --> $DIR/drop_forget_copy.rs:80:18
- |
-LL | drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
- | ^^^^^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:82:14
- |
-LL | 3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
- | ^^^^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `i32`
- --> $DIR/drop_forget_copy.rs:82:19
- |
-LL | 3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
- | ^^^^^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
- --> $DIR/drop_forget_copy.rs:83:14
- |
-LL | 4 => drop(2), // Lint, not a fn/method call
- | ^^^^^^^
- |
-note: argument has type `i32`
- --> $DIR/drop_forget_copy.rs:83:19
- |
-LL | 4 => drop(2), // Lint, not a fn/method call
- | ^
-
-error: aborting due to 9 previous errors
-
diff --git a/src/tools/clippy/tests/ui/drop_ref.rs b/src/tools/clippy/tests/ui/drop_ref.rs
deleted file mode 100644
index 10044e65f..000000000
--- a/src/tools/clippy/tests/ui/drop_ref.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-#![warn(clippy::drop_ref)]
-#![allow(clippy::toplevel_ref_arg)]
-#![allow(clippy::map_err_ignore)]
-#![allow(clippy::unnecessary_wraps, clippy::drop_non_drop)]
-
-use std::mem::drop;
-
-struct SomeStruct;
-
-fn main() {
- drop(&SomeStruct);
-
- let mut owned1 = SomeStruct;
- drop(&owned1);
- drop(&&owned1);
- drop(&mut owned1);
- drop(owned1); //OK
-
- let reference1 = &SomeStruct;
- drop(reference1);
-
- let reference2 = &mut SomeStruct;
- drop(reference2);
-
- let ref reference3 = SomeStruct;
- drop(reference3);
-}
-
-#[allow(dead_code)]
-fn test_generic_fn_drop<T>(val: T) {
- drop(&val);
- drop(val); //OK
-}
-
-#[allow(dead_code)]
-fn test_similarly_named_function() {
- fn drop<T>(_val: T) {}
- drop(&SomeStruct); //OK; call to unrelated function which happens to have the same name
- std::mem::drop(&SomeStruct);
-}
-
-#[derive(Copy, Clone)]
-pub struct Error;
-fn produce_half_owl_error() -> Result<(), Error> {
- Ok(())
-}
-
-fn produce_half_owl_ok() -> Result<bool, ()> {
- Ok(true)
-}
-
-#[allow(dead_code)]
-fn test_owl_result() -> Result<(), ()> {
- produce_half_owl_error().map_err(|_| ())?;
- produce_half_owl_ok().map(|_| ())?;
- // the following should not be linted,
- // we should not force users to use toilet closures
- // to produce owl results when drop is more convenient
- produce_half_owl_error().map_err(drop)?;
- produce_half_owl_ok().map_err(drop)?;
- Ok(())
-}
-
-#[allow(dead_code)]
-fn test_owl_result_2() -> Result<u8, ()> {
- produce_half_owl_error().map_err(|_| ())?;
- produce_half_owl_ok().map(|_| ())?;
- // the following should not be linted,
- // we should not force users to use toilet closures
- // to produce owl results when drop is more convenient
- produce_half_owl_error().map_err(drop)?;
- produce_half_owl_ok().map(drop)?;
- Ok(1)
-}
-
-#[allow(unused)]
-#[allow(clippy::unit_cmp)]
-fn issue10122(x: u8) {
- // This is a function which returns a reference and has a side-effect, which means
- // that calling drop() on the function is considered an idiomatic way of achieving the side-effect
- // in a match arm.
- fn println_and<T>(t: &T) -> &T {
- println!("foo");
- t
- }
-
- match x {
- 0 => drop(println_and(&12)), // Don't lint (copy type), we only care about side-effects
- 1 => drop(println_and(&String::new())), // Don't lint (no copy type), we only care about side-effects
- 2 => {
- drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
- },
- 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
- 4 => drop(&2), // Lint, not a fn/method call
- _ => (),
- }
-}
diff --git a/src/tools/clippy/tests/ui/drop_ref.stderr b/src/tools/clippy/tests/ui/drop_ref.stderr
deleted file mode 100644
index 293b9f6de..000000000
--- a/src/tools/clippy/tests/ui/drop_ref.stderr
+++ /dev/null
@@ -1,147 +0,0 @@
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:11:5
- |
-LL | drop(&SomeStruct);
- | ^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/drop_ref.rs:11:10
- |
-LL | drop(&SomeStruct);
- | ^^^^^^^^^^^
- = note: `-D clippy::drop-ref` implied by `-D warnings`
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:14:5
- |
-LL | drop(&owned1);
- | ^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/drop_ref.rs:14:10
- |
-LL | drop(&owned1);
- | ^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:15:5
- |
-LL | drop(&&owned1);
- | ^^^^^^^^^^^^^^
- |
-note: argument has type `&&SomeStruct`
- --> $DIR/drop_ref.rs:15:10
- |
-LL | drop(&&owned1);
- | ^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:16:5
- |
-LL | drop(&mut owned1);
- | ^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&mut SomeStruct`
- --> $DIR/drop_ref.rs:16:10
- |
-LL | drop(&mut owned1);
- | ^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:20:5
- |
-LL | drop(reference1);
- | ^^^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/drop_ref.rs:20:10
- |
-LL | drop(reference1);
- | ^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:23:5
- |
-LL | drop(reference2);
- | ^^^^^^^^^^^^^^^^
- |
-note: argument has type `&mut SomeStruct`
- --> $DIR/drop_ref.rs:23:10
- |
-LL | drop(reference2);
- | ^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:26:5
- |
-LL | drop(reference3);
- | ^^^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/drop_ref.rs:26:10
- |
-LL | drop(reference3);
- | ^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:31:5
- |
-LL | drop(&val);
- | ^^^^^^^^^^
- |
-note: argument has type `&T`
- --> $DIR/drop_ref.rs:31:10
- |
-LL | drop(&val);
- | ^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:39:5
- |
-LL | std::mem::drop(&SomeStruct);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/drop_ref.rs:39:20
- |
-LL | std::mem::drop(&SomeStruct);
- | ^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:91:13
- |
-LL | drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
- | ^^^^^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&i32`
- --> $DIR/drop_ref.rs:91:18
- |
-LL | drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
- | ^^^^^^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:93:14
- |
-LL | 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
- | ^^^^^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&i32`
- --> $DIR/drop_ref.rs:93:19
- |
-LL | 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
- | ^^^^^^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
- --> $DIR/drop_ref.rs:94:14
- |
-LL | 4 => drop(&2), // Lint, not a fn/method call
- | ^^^^^^^^
- |
-note: argument has type `&i32`
- --> $DIR/drop_ref.rs:94:19
- |
-LL | 4 => drop(&2), // Lint, not a fn/method call
- | ^^
-
-error: aborting due to 12 previous errors
-
diff --git a/src/tools/clippy/tests/ui/duration_subsec.fixed b/src/tools/clippy/tests/ui/duration_subsec.fixed
index d92b8998e..bfd30f004 100644
--- a/src/tools/clippy/tests/ui/duration_subsec.fixed
+++ b/src/tools/clippy/tests/ui/duration_subsec.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, clippy::needless_borrow)]
#![warn(clippy::duration_subsec)]
diff --git a/src/tools/clippy/tests/ui/duration_subsec.rs b/src/tools/clippy/tests/ui/duration_subsec.rs
index 08da80499..860233f08 100644
--- a/src/tools/clippy/tests/ui/duration_subsec.rs
+++ b/src/tools/clippy/tests/ui/duration_subsec.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, clippy::needless_borrow)]
#![warn(clippy::duration_subsec)]
diff --git a/src/tools/clippy/tests/ui/empty_drop.fixed b/src/tools/clippy/tests/ui/empty_drop.fixed
index 2e1b76846..fd0a9a708 100644
--- a/src/tools/clippy/tests/ui/empty_drop.fixed
+++ b/src/tools/clippy/tests/ui/empty_drop.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::empty_drop)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/empty_drop.rs b/src/tools/clippy/tests/ui/empty_drop.rs
index 75232b033..6c15cb933 100644
--- a/src/tools/clippy/tests/ui/empty_drop.rs
+++ b/src/tools/clippy/tests/ui/empty_drop.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::empty_drop)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
new file mode 100644
index 000000000..e843770f5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
@@ -0,0 +1,132 @@
+//@aux-build:proc_macro_attr.rs
+#![warn(clippy::empty_line_after_doc_comments)]
+#![allow(clippy::assertions_on_constants)]
+#![feature(custom_inner_attributes)]
+#![rustfmt::skip]
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+mod some_mod {
+ //! This doc comment should *NOT* produce a warning
+
+ mod some_inner_mod {
+ fn some_noop() {}
+ }
+}
+
+/// This should produce a warning
+
+fn with_doc_and_newline() { assert!(true)}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+/// some comment
+fn with_one_newline_and_comment() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() { assert!(true) }
+
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+fn with_one_newline() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+
+fn with_two_newlines() { assert!(true) }
+
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+enum Baz {
+ One,
+ Two
+}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+struct Foo {
+ one: isize,
+ two: isize
+}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+mod foo {
+}
+
+/// This doc comment should produce a warning
+
+/** This is also a doc comment and should produce a warning
+ */
+
+// This should *NOT* produce a warning
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(missing_docs)]
+fn three_attributes() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+ true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+ Bar1,
+
+ Bar2,
+
+ Bar3,
+
+ Bar4
+}
+
+// This should *NOT* produce a warning because the empty line is inside a block comment
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct S;
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/* test */
+pub struct T;
+
+// This should *NOT* produce a warning
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[fake_async_trait]
+pub trait Bazz {
+ fn foo() -> Vec<u8> {
+ let _i = "";
+
+
+
+ vec![]
+ }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
new file mode 100644
index 000000000..2ca1b5167
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
@@ -0,0 +1,36 @@
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+ --> $DIR/empty_line_after_doc_comments.rs:18:1
+ |
+LL | / /// This should produce a warning
+LL | |
+LL | | fn with_doc_and_newline() { assert!(true)}
+ | |_
+ |
+ = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
+
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+ --> $DIR/empty_line_after_doc_comments.rs:68:1
+ |
+LL | / /// This doc comment should produce a warning
+LL | |
+LL | | /** This is also a doc comment and should produce a warning
+LL | | */
+... |
+LL | | #[allow(missing_docs)]
+LL | | fn three_attributes() { assert!(true) }
+ | |_
+
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+ --> $DIR/empty_line_after_doc_comments.rs:70:1
+ |
+LL | / /** This is also a doc comment and should produce a warning
+LL | | */
+LL | |
+LL | | // This should *NOT* produce a warning
+... |
+LL | | #[allow(missing_docs)]
+LL | | fn three_attributes() { assert!(true) }
+ | |_
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
index 697412c00..269e66ea0 100644
--- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
+++ b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macro_attr.rs
+//@aux-build:proc_macro_attr.rs
#![warn(clippy::empty_line_after_outer_attr)]
#![allow(clippy::assertions_on_constants)]
#![feature(custom_inner_attributes)]
diff --git a/src/tools/clippy/tests/ui/empty_loop.rs b/src/tools/clippy/tests/ui/empty_loop.rs
index 6a8e6b550..54e8fb490 100644
--- a/src/tools/clippy/tests/ui/empty_loop.rs
+++ b/src/tools/clippy/tests/ui/empty_loop.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![warn(clippy::empty_loop)]
diff --git a/src/tools/clippy/tests/ui/empty_loop_no_std.rs b/src/tools/clippy/tests/ui/empty_loop_no_std.rs
index e742b396f..d564b2d24 100644
--- a/src/tools/clippy/tests/ui/empty_loop_no_std.rs
+++ b/src/tools/clippy/tests/ui/empty_loop_no_std.rs
@@ -1,5 +1,5 @@
-// compile-flags: -Clink-arg=-nostartfiles
-// ignore-macos
+//@compile-flags: -Clink-arg=-nostartfiles
+//@ignore-macos
#![warn(clippy::empty_loop)]
#![feature(lang_items, start, libc)]
diff --git a/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed b/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed
index 80f07603b..6fab30208 100644
--- a/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed
+++ b/src/tools/clippy/tests/ui/empty_structs_with_brackets.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::empty_structs_with_brackets)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs b/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs
index 1d1ed4c76..0caa3c49c 100644
--- a/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs
+++ b/src/tools/clippy/tests/ui/empty_structs_with_brackets.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::empty_structs_with_brackets)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed
index dbe09e0ff..7e8239060 100644
--- a/src/tools/clippy/tests/ui/entry.fixed
+++ b/src/tools/clippy/tests/ui/entry.fixed
@@ -1,5 +1,5 @@
-// needs-asm-support
-// run-rustfix
+//@needs-asm-support
+//@run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]
#![warn(clippy::map_entry)]
diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs
index 30fed34fc..742c93225 100644
--- a/src/tools/clippy/tests/ui/entry.rs
+++ b/src/tools/clippy/tests/ui/entry.rs
@@ -1,5 +1,5 @@
-// needs-asm-support
-// run-rustfix
+//@needs-asm-support
+//@run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]
#![warn(clippy::map_entry)]
diff --git a/src/tools/clippy/tests/ui/entry_btree.fixed b/src/tools/clippy/tests/ui/entry_btree.fixed
index 949791045..3baaacffd 100644
--- a/src/tools/clippy/tests/ui/entry_btree.fixed
+++ b/src/tools/clippy/tests/ui/entry_btree.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::map_entry)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/entry_btree.rs b/src/tools/clippy/tests/ui/entry_btree.rs
index 080c1d959..770e8e91d 100644
--- a/src/tools/clippy/tests/ui/entry_btree.rs
+++ b/src/tools/clippy/tests/ui/entry_btree.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::map_entry)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/entry_with_else.fixed b/src/tools/clippy/tests/ui/entry_with_else.fixed
index 2332fa631..71fe04fd6 100644
--- a/src/tools/clippy/tests/ui/entry_with_else.fixed
+++ b/src/tools/clippy/tests/ui/entry_with_else.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]
#![warn(clippy::map_entry)]
diff --git a/src/tools/clippy/tests/ui/entry_with_else.rs b/src/tools/clippy/tests/ui/entry_with_else.rs
index 2ff0c038e..80f74649a 100644
--- a/src/tools/clippy/tests/ui/entry_with_else.rs
+++ b/src/tools/clippy/tests/ui/entry_with_else.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]
#![warn(clippy::map_entry)]
diff --git a/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs b/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
index 7d6842f5b..f17556ea9 100644
--- a/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
+++ b/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
@@ -1,4 +1,4 @@
-// ignore-x86
+//@ignore-x86
#![warn(clippy::enum_clike_unportable_variant)]
#![allow(unused, non_upper_case_globals)]
diff --git a/src/tools/clippy/tests/ui/enum_glob_use.fixed b/src/tools/clippy/tests/ui/enum_glob_use.fixed
index a98216758..419370ffb 100644
--- a/src/tools/clippy/tests/ui/enum_glob_use.fixed
+++ b/src/tools/clippy/tests/ui/enum_glob_use.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::enum_glob_use)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/enum_glob_use.rs b/src/tools/clippy/tests/ui/enum_glob_use.rs
index 5d929c973..645ed9832 100644
--- a/src/tools/clippy/tests/ui/enum_glob_use.rs
+++ b/src/tools/clippy/tests/ui/enum_glob_use.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::enum_glob_use)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/enum_variants.rs b/src/tools/clippy/tests/ui/enum_variants.rs
index efed12ee2..531652a0e 100644
--- a/src/tools/clippy/tests/ui/enum_variants.rs
+++ b/src/tools/clippy/tests/ui/enum_variants.rs
@@ -179,4 +179,14 @@ mod issue9018 {
}
}
+mod allow_attributes_on_variants {
+ enum Enum {
+ #[allow(clippy::enum_variant_names)]
+ EnumStartsWith,
+ #[allow(clippy::enum_variant_names)]
+ EndsWithEnum,
+ Foo,
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/eq_op.rs b/src/tools/clippy/tests/ui/eq_op.rs
index e73795502..cdd33ebe5 100644
--- a/src/tools/clippy/tests/ui/eq_op.rs
+++ b/src/tools/clippy/tests/ui/eq_op.rs
@@ -1,4 +1,4 @@
-// compile-flags: --test
+//@compile-flags: --test
#![warn(clippy::eq_op)]
#![allow(clippy::double_parens, clippy::identity_op, clippy::nonminimal_bool)]
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.fixed b/src/tools/clippy/tests/ui/equatable_if_let.fixed
index 007702ab5..53e62760b 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.fixed
+++ b/src/tools/clippy/tests/ui/equatable_if_let.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
#![warn(clippy::equatable_if_let)]
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.rs b/src/tools/clippy/tests/ui/equatable_if_let.rs
index 3bda79776..55918a5bb 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.rs
+++ b/src/tools/clippy/tests/ui/equatable_if_let.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
#![warn(clippy::equatable_if_let)]
diff --git a/src/tools/clippy/tests/ui/err_expect.fixed b/src/tools/clippy/tests/ui/err_expect.fixed
index b63cbd8a8..6ade6f546 100644
--- a/src/tools/clippy/tests/ui/err_expect.fixed
+++ b/src/tools/clippy/tests/ui/err_expect.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/err_expect.rs b/src/tools/clippy/tests/ui/err_expect.rs
index c081a745f..a93fb5949 100644
--- a/src/tools/clippy/tests/ui/err_expect.rs
+++ b/src/tools/clippy/tests/ui/err_expect.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed
index dc129591e..b1baf462c 100644
--- a/src/tools/clippy/tests/ui/eta.fixed
+++ b/src/tools/clippy/tests/ui/eta.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
#![allow(unused)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs
index 025fd6a0b..e113c3d6c 100644
--- a/src/tools/clippy/tests/ui/eta.rs
+++ b/src/tools/clippy/tests/ui/eta.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
#![allow(unused)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/excessive_precision.fixed b/src/tools/clippy/tests/ui/excessive_precision.fixed
index b74bda182..0a0795738 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.fixed
+++ b/src/tools/clippy/tests/ui/excessive_precision.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::excessive_precision)]
#![allow(dead_code, unused_variables, clippy::print_literal)]
diff --git a/src/tools/clippy/tests/ui/excessive_precision.rs b/src/tools/clippy/tests/ui/excessive_precision.rs
index 6e84a71f2..62a832caa 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.rs
+++ b/src/tools/clippy/tests/ui/excessive_precision.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::excessive_precision)]
#![allow(dead_code, unused_variables, clippy::print_literal)]
diff --git a/src/tools/clippy/tests/ui/exhaustive_items.fixed b/src/tools/clippy/tests/ui/exhaustive_items.fixed
index c209f5b4b..6c7b1cab6 100644
--- a/src/tools/clippy/tests/ui/exhaustive_items.fixed
+++ b/src/tools/clippy/tests/ui/exhaustive_items.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/exhaustive_items.rs b/src/tools/clippy/tests/ui/exhaustive_items.rs
index 6f59dbf2d..d205bac2d 100644
--- a/src/tools/clippy/tests/ui/exhaustive_items.rs
+++ b/src/tools/clippy/tests/ui/exhaustive_items.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.fixed b/src/tools/clippy/tests/ui/expect_fun_call.fixed
index 15172ae34..8e97054fb 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/expect_fun_call.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::expect_fun_call)]
#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.rs b/src/tools/clippy/tests/ui/expect_fun_call.rs
index 0f448d004..31e6bcc7f 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.rs
+++ b/src/tools/clippy/tests/ui/expect_fun_call.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::expect_fun_call)]
#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
index 5d40c8504..71a5ed96d 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(closure_lifetime_binder)]
#![warn(clippy::explicit_auto_deref)]
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.rs b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
index 79e03f4d7..9d0cafa15 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.rs
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(closure_lifetime_binder)]
#![warn(clippy::explicit_auto_deref)]
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
index 6d32bbece..60482c66d 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
@@ -1,9 +1,9 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::explicit_deref_methods)]
#![allow(unused_variables)]
#![allow(
clippy::borrow_deref_ref,
- clippy::clone_double_ref,
+ suspicious_double_ref_op,
clippy::explicit_auto_deref,
clippy::needless_borrow,
clippy::uninlined_format_args
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
index 779909e42..e3613e216 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.rs
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
@@ -1,9 +1,9 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::explicit_deref_methods)]
#![allow(unused_variables)]
#![allow(
clippy::borrow_deref_ref,
- clippy::clone_double_ref,
+ suspicious_double_ref_op,
clippy::explicit_auto_deref,
clippy::needless_borrow,
clippy::uninlined_format_args
diff --git a/src/tools/clippy/tests/ui/explicit_write.fixed b/src/tools/clippy/tests/ui/explicit_write.fixed
index 862c3fea9..213485bc2 100644
--- a/src/tools/clippy/tests/ui/explicit_write.fixed
+++ b/src/tools/clippy/tests/ui/explicit_write.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::explicit_write)]
#![allow(unused_imports)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/explicit_write.rs b/src/tools/clippy/tests/ui/explicit_write.rs
index 41d7c2255..64acd7108 100644
--- a/src/tools/clippy/tests/ui/explicit_write.rs
+++ b/src/tools/clippy/tests/ui/explicit_write.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::explicit_write)]
#![allow(unused_imports)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/extend_with_drain.fixed b/src/tools/clippy/tests/ui/extend_with_drain.fixed
index 71ebad24c..594f2f6d4 100644
--- a/src/tools/clippy/tests/ui/extend_with_drain.fixed
+++ b/src/tools/clippy/tests/ui/extend_with_drain.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::extend_with_drain)]
#![allow(clippy::iter_with_drain)]
use std::collections::BinaryHeap;
diff --git a/src/tools/clippy/tests/ui/extend_with_drain.rs b/src/tools/clippy/tests/ui/extend_with_drain.rs
index e9f011abb..3e2ad0205 100644
--- a/src/tools/clippy/tests/ui/extend_with_drain.rs
+++ b/src/tools/clippy/tests/ui/extend_with_drain.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::extend_with_drain)]
#![allow(clippy::iter_with_drain)]
use std::collections::BinaryHeap;
diff --git a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
index d6631e012..cdfaf8d3a 100644
--- a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs
#![allow(
unused,
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed b/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed
index 19e718625..adcd1f6d4 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::needless_lifetimes)]
#![warn(clippy::extra_unused_type_parameters)]
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
index e53bb587e..c4c5227ac 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::needless_lifetimes)]
#![warn(clippy::extra_unused_type_parameters)]
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
index 0e208b3ed..2045b1eeb 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -1,5 +1,5 @@
-// aux-build:proc_macro_derive.rs
-// aux-build:proc_macros.rs
+//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macros.rs
#![warn(clippy::field_reassign_with_default)]
diff --git a/src/tools/clippy/tests/ui/filter_map_identity.fixed b/src/tools/clippy/tests/ui/filter_map_identity.fixed
index a5860aa49..44665b451 100644
--- a/src/tools/clippy/tests/ui/filter_map_identity.fixed
+++ b/src/tools/clippy/tests/ui/filter_map_identity.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_imports, clippy::needless_return)]
#![warn(clippy::filter_map_identity)]
diff --git a/src/tools/clippy/tests/ui/filter_map_identity.rs b/src/tools/clippy/tests/ui/filter_map_identity.rs
index 7e998b9cd..9832acb01 100644
--- a/src/tools/clippy/tests/ui/filter_map_identity.rs
+++ b/src/tools/clippy/tests/ui/filter_map_identity.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_imports, clippy::needless_return)]
#![warn(clippy::filter_map_identity)]
diff --git a/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed b/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
index 462d46169..efb37f8b1 100644
--- a/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
+++ b/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all, clippy::pedantic)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/filter_map_next_fixable.rs b/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
index 2ea00cf73..b10e20d35 100644
--- a/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
+++ b/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all, clippy::pedantic)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/flat_map_identity.fixed b/src/tools/clippy/tests/ui/flat_map_identity.fixed
index 1f4b880ef..97091d6f1 100644
--- a/src/tools/clippy/tests/ui/flat_map_identity.fixed
+++ b/src/tools/clippy/tests/ui/flat_map_identity.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_imports, clippy::needless_return)]
#![warn(clippy::flat_map_identity)]
diff --git a/src/tools/clippy/tests/ui/flat_map_identity.rs b/src/tools/clippy/tests/ui/flat_map_identity.rs
index de14a06d4..5607683a5 100644
--- a/src/tools/clippy/tests/ui/flat_map_identity.rs
+++ b/src/tools/clippy/tests/ui/flat_map_identity.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_imports, clippy::needless_return)]
#![warn(clippy::flat_map_identity)]
diff --git a/src/tools/clippy/tests/ui/flat_map_option.fixed b/src/tools/clippy/tests/ui/flat_map_option.fixed
index 6a34f0089..eeab864c4 100644
--- a/src/tools/clippy/tests/ui/flat_map_option.fixed
+++ b/src/tools/clippy/tests/ui/flat_map_option.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::flat_map_option)]
#![allow(clippy::redundant_closure, clippy::unnecessary_filter_map)]
diff --git a/src/tools/clippy/tests/ui/flat_map_option.rs b/src/tools/clippy/tests/ui/flat_map_option.rs
index 2479abddb..ebc389f7f 100644
--- a/src/tools/clippy/tests/ui/flat_map_option.rs
+++ b/src/tools/clippy/tests/ui/flat_map_option.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::flat_map_option)]
#![allow(clippy::redundant_closure, clippy::unnecessary_filter_map)]
diff --git a/src/tools/clippy/tests/ui/float_arithmetic.rs b/src/tools/clippy/tests/ui/float_arithmetic.rs
index 60fa7569e..a928c35e8 100644
--- a/src/tools/clippy/tests/ui/float_arithmetic.rs
+++ b/src/tools/clippy/tests/ui/float_arithmetic.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)]
+#![warn(clippy::arithmetic_side_effects, clippy::float_arithmetic)]
#![allow(
unused,
clippy::shadow_reuse,
diff --git a/src/tools/clippy/tests/ui/floating_point_abs.fixed b/src/tools/clippy/tests/ui/floating_point_abs.fixed
index ca747fefc..0cc572822 100644
--- a/src/tools/clippy/tests/ui/floating_point_abs.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_abs.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(const_fn_floating_point_arithmetic)]
#![warn(clippy::suboptimal_flops)]
diff --git a/src/tools/clippy/tests/ui/floating_point_abs.rs b/src/tools/clippy/tests/ui/floating_point_abs.rs
index e4b606574..6c732d398 100644
--- a/src/tools/clippy/tests/ui/floating_point_abs.rs
+++ b/src/tools/clippy/tests/ui/floating_point_abs.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(const_fn_floating_point_arithmetic)]
#![warn(clippy::suboptimal_flops)]
diff --git a/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs b/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs
new file mode 100644
index 000000000..a42c6383c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs
@@ -0,0 +1,31 @@
+#![feature(lang_items, start)]
+#![warn(clippy::imprecise_flops)]
+#![warn(clippy::suboptimal_flops)]
+#![no_std]
+
+// The following should not lint, as the suggested methods {f32,f64}.mul_add()
+// and {f32,f64}::abs() are not available in no_std
+
+pub fn mul_add() {
+ let a: f64 = 1234.567;
+ let b: f64 = 45.67834;
+ let c: f64 = 0.0004;
+ let _ = a * b + c;
+}
+
+fn fake_abs1(num: f64) -> f64 {
+ if num >= 0.0 { num } else { -num }
+}
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ 0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
diff --git a/src/tools/clippy/tests/ui/floating_point_exp.fixed b/src/tools/clippy/tests/ui/floating_point_exp.fixed
index b9e3d89c2..1a33b8153 100644
--- a/src/tools/clippy/tests/ui/floating_point_exp.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_exp.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::imprecise_flops)]
#![allow(clippy::unnecessary_cast)]
diff --git a/src/tools/clippy/tests/ui/floating_point_exp.rs b/src/tools/clippy/tests/ui/floating_point_exp.rs
index ef008dd9b..4f4a5ec81 100644
--- a/src/tools/clippy/tests/ui/floating_point_exp.rs
+++ b/src/tools/clippy/tests/ui/floating_point_exp.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::imprecise_flops)]
#![allow(clippy::unnecessary_cast)]
diff --git a/src/tools/clippy/tests/ui/floating_point_hypot.fixed b/src/tools/clippy/tests/ui/floating_point_hypot.fixed
index bbe411b3f..431cb2709 100644
--- a/src/tools/clippy/tests/ui/floating_point_hypot.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_hypot.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::imprecise_flops)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/floating_point_hypot.rs b/src/tools/clippy/tests/ui/floating_point_hypot.rs
index 586fd170e..e5506ed39 100644
--- a/src/tools/clippy/tests/ui/floating_point_hypot.rs
+++ b/src/tools/clippy/tests/ui/floating_point_hypot.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::imprecise_flops)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/floating_point_log.fixed b/src/tools/clippy/tests/ui/floating_point_log.fixed
index ee5406461..6582c0a0f 100644
--- a/src/tools/clippy/tests/ui/floating_point_log.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_log.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, clippy::double_parens, clippy::unnecessary_cast)]
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
diff --git a/src/tools/clippy/tests/ui/floating_point_log.rs b/src/tools/clippy/tests/ui/floating_point_log.rs
index 0590670a5..854d269ff 100644
--- a/src/tools/clippy/tests/ui/floating_point_log.rs
+++ b/src/tools/clippy/tests/ui/floating_point_log.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, clippy::double_parens, clippy::unnecessary_cast)]
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
diff --git a/src/tools/clippy/tests/ui/floating_point_logbase.fixed b/src/tools/clippy/tests/ui/floating_point_logbase.fixed
index 7347bf72c..0783ecee1 100644
--- a/src/tools/clippy/tests/ui/floating_point_logbase.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_logbase.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::suboptimal_flops)]
#![allow(clippy::unnecessary_cast)]
diff --git a/src/tools/clippy/tests/ui/floating_point_logbase.rs b/src/tools/clippy/tests/ui/floating_point_logbase.rs
index ba5b8d406..80fcfab68 100644
--- a/src/tools/clippy/tests/ui/floating_point_logbase.rs
+++ b/src/tools/clippy/tests/ui/floating_point_logbase.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::suboptimal_flops)]
#![allow(clippy::unnecessary_cast)]
diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed
index d3e536ba3..8848981a1 100644
--- a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(const_fn_floating_point_arithmetic)]
#![warn(clippy::suboptimal_flops)]
diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.rs b/src/tools/clippy/tests/ui/floating_point_mul_add.rs
index 5d4a9e35c..b0edf5cb2 100644
--- a/src/tools/clippy/tests/ui/floating_point_mul_add.rs
+++ b/src/tools/clippy/tests/ui/floating_point_mul_add.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(const_fn_floating_point_arithmetic)]
#![warn(clippy::suboptimal_flops)]
diff --git a/src/tools/clippy/tests/ui/floating_point_powf.fixed b/src/tools/clippy/tests/ui/floating_point_powf.fixed
index f7f93de29..1e660b140 100644
--- a/src/tools/clippy/tests/ui/floating_point_powf.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_powf.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
#![allow(clippy::unnecessary_cast)]
diff --git a/src/tools/clippy/tests/ui/floating_point_powf.rs b/src/tools/clippy/tests/ui/floating_point_powf.rs
index 499fc0e15..71c2f5292 100644
--- a/src/tools/clippy/tests/ui/floating_point_powf.rs
+++ b/src/tools/clippy/tests/ui/floating_point_powf.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
#![allow(clippy::unnecessary_cast)]
diff --git a/src/tools/clippy/tests/ui/floating_point_powi.fixed b/src/tools/clippy/tests/ui/floating_point_powi.fixed
index 8ffd4cc51..41d5288d6 100644
--- a/src/tools/clippy/tests/ui/floating_point_powi.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_powi.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::suboptimal_flops)]
#![allow(clippy::unnecessary_cast)]
diff --git a/src/tools/clippy/tests/ui/floating_point_powi.rs b/src/tools/clippy/tests/ui/floating_point_powi.rs
index 9ae3455a1..7951aab31 100644
--- a/src/tools/clippy/tests/ui/floating_point_powi.rs
+++ b/src/tools/clippy/tests/ui/floating_point_powi.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::suboptimal_flops)]
#![allow(clippy::unnecessary_cast)]
diff --git a/src/tools/clippy/tests/ui/floating_point_rad.fixed b/src/tools/clippy/tests/ui/floating_point_rad.fixed
index 27674b8a4..af2364527 100644
--- a/src/tools/clippy/tests/ui/floating_point_rad.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_rad.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(const_fn_floating_point_arithmetic)]
#![warn(clippy::suboptimal_flops)]
diff --git a/src/tools/clippy/tests/ui/floating_point_rad.rs b/src/tools/clippy/tests/ui/floating_point_rad.rs
index f1ea73df3..d7612c56a 100644
--- a/src/tools/clippy/tests/ui/floating_point_rad.rs
+++ b/src/tools/clippy/tests/ui/floating_point_rad.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(const_fn_floating_point_arithmetic)]
#![warn(clippy::suboptimal_flops)]
diff --git a/src/tools/clippy/tests/ui/fn_to_numeric_cast.rs b/src/tools/clippy/tests/ui/fn_to_numeric_cast.rs
index a456c085c..4f6af8708 100644
--- a/src/tools/clippy/tests/ui/fn_to_numeric_cast.rs
+++ b/src/tools/clippy/tests/ui/fn_to_numeric_cast.rs
@@ -1,4 +1,4 @@
-// ignore-32bit
+//@ignore-32bit
#![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)]
diff --git a/src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.rs b/src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.rs
index 04ee985c0..62ce97f09 100644
--- a/src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.rs
+++ b/src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.rs
@@ -1,4 +1,4 @@
-// ignore-64bit
+//@ignore-64bit
#![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)]
diff --git a/src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.stderr b/src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.stderr
index 08dd611d6..671347d2b 100644
--- a/src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.stderr
+++ b/src/tools/clippy/tests/ui/fn_to_numeric_cast_32bit.stderr
@@ -12,19 +12,19 @@ error: casting function pointer `foo` to `i16`, which truncates the value
LL | let _ = foo as i16;
| ^^^^^^^^^^ help: try: `foo as usize`
-error: casting function pointer `foo` to `i32`
+error: casting function pointer `foo` to `i32`, which truncates the value
--> $DIR/fn_to_numeric_cast_32bit.rs:12:13
|
LL | let _ = foo as i32;
| ^^^^^^^^^^ help: try: `foo as usize`
- |
- = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings`
error: casting function pointer `foo` to `i64`
--> $DIR/fn_to_numeric_cast_32bit.rs:13:13
|
LL | let _ = foo as i64;
| ^^^^^^^^^^ help: try: `foo as usize`
+ |
+ = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings`
error: casting function pointer `foo` to `i128`
--> $DIR/fn_to_numeric_cast_32bit.rs:14:13
@@ -50,7 +50,7 @@ error: casting function pointer `foo` to `u16`, which truncates the value
LL | let _ = foo as u16;
| ^^^^^^^^^^ help: try: `foo as usize`
-error: casting function pointer `foo` to `u32`
+error: casting function pointer `foo` to `u32`, which truncates the value
--> $DIR/fn_to_numeric_cast_32bit.rs:19:13
|
LL | let _ = foo as u32;
@@ -80,7 +80,7 @@ error: casting function pointer `abc` to `i16`, which truncates the value
LL | let _ = abc as i16;
| ^^^^^^^^^^ help: try: `abc as usize`
-error: casting function pointer `abc` to `i32`
+error: casting function pointer `abc` to `i32`, which truncates the value
--> $DIR/fn_to_numeric_cast_32bit.rs:36:13
|
LL | let _ = abc as i32;
@@ -116,7 +116,7 @@ error: casting function pointer `abc` to `u16`, which truncates the value
LL | let _ = abc as u16;
| ^^^^^^^^^^ help: try: `abc as usize`
-error: casting function pointer `abc` to `u32`
+error: casting function pointer `abc` to `u32`, which truncates the value
--> $DIR/fn_to_numeric_cast_32bit.rs:43:13
|
LL | let _ = abc as u32;
@@ -134,7 +134,7 @@ error: casting function pointer `abc` to `u128`
LL | let _ = abc as u128;
| ^^^^^^^^^^^ help: try: `abc as usize`
-error: casting function pointer `f` to `i32`
+error: casting function pointer `f` to `i32`, which truncates the value
--> $DIR/fn_to_numeric_cast_32bit.rs:52:5
|
LL | f as i32
diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.fixed b/src/tools/clippy/tests/ui/for_loop_fixable.fixed
index e9dd38fe4..f578c98da 100644
--- a/src/tools/clippy/tests/ui/for_loop_fixable.fixed
+++ b/src/tools/clippy/tests/ui/for_loop_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, unused)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.rs b/src/tools/clippy/tests/ui/for_loop_fixable.rs
index 534fb4dd4..42bc6de0c 100644
--- a/src/tools/clippy/tests/ui/for_loop_fixable.rs
+++ b/src/tools/clippy/tests/ui/for_loop_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, unused)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/forget_ref.rs b/src/tools/clippy/tests/ui/forget_ref.rs
deleted file mode 100644
index 031b415f5..000000000
--- a/src/tools/clippy/tests/ui/forget_ref.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-#![warn(clippy::forget_ref)]
-#![allow(clippy::toplevel_ref_arg)]
-#![allow(clippy::unnecessary_wraps, clippy::forget_non_drop)]
-#![allow(clippy::borrow_deref_ref)]
-
-use std::mem::forget;
-
-struct SomeStruct;
-
-fn main() {
- forget(&SomeStruct);
-
- let mut owned = SomeStruct;
- forget(&owned);
- forget(&&owned);
- forget(&mut owned);
- forget(owned); //OK
-
- let reference1 = &SomeStruct;
- forget(&*reference1);
-
- let reference2 = &mut SomeStruct;
- forget(reference2);
-
- let ref reference3 = SomeStruct;
- forget(reference3);
-}
-
-#[allow(dead_code)]
-fn test_generic_fn_forget<T>(val: T) {
- forget(&val);
- forget(val); //OK
-}
-
-#[allow(dead_code)]
-fn test_similarly_named_function() {
- fn forget<T>(_val: T) {}
- forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name
- std::mem::forget(&SomeStruct);
-}
-
-#[derive(Copy, Clone)]
-pub struct Error;
-fn produce_half_owl_error() -> Result<(), Error> {
- Ok(())
-}
-
-fn produce_half_owl_ok() -> Result<bool, ()> {
- Ok(true)
-}
diff --git a/src/tools/clippy/tests/ui/forget_ref.stderr b/src/tools/clippy/tests/ui/forget_ref.stderr
deleted file mode 100644
index 011cdefc6..000000000
--- a/src/tools/clippy/tests/ui/forget_ref.stderr
+++ /dev/null
@@ -1,111 +0,0 @@
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:11:5
- |
-LL | forget(&SomeStruct);
- | ^^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/forget_ref.rs:11:12
- |
-LL | forget(&SomeStruct);
- | ^^^^^^^^^^^
- = note: `-D clippy::forget-ref` implied by `-D warnings`
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:14:5
- |
-LL | forget(&owned);
- | ^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/forget_ref.rs:14:12
- |
-LL | forget(&owned);
- | ^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:15:5
- |
-LL | forget(&&owned);
- | ^^^^^^^^^^^^^^^
- |
-note: argument has type `&&SomeStruct`
- --> $DIR/forget_ref.rs:15:12
- |
-LL | forget(&&owned);
- | ^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:16:5
- |
-LL | forget(&mut owned);
- | ^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&mut SomeStruct`
- --> $DIR/forget_ref.rs:16:12
- |
-LL | forget(&mut owned);
- | ^^^^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:20:5
- |
-LL | forget(&*reference1);
- | ^^^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/forget_ref.rs:20:12
- |
-LL | forget(&*reference1);
- | ^^^^^^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:23:5
- |
-LL | forget(reference2);
- | ^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&mut SomeStruct`
- --> $DIR/forget_ref.rs:23:12
- |
-LL | forget(reference2);
- | ^^^^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:26:5
- |
-LL | forget(reference3);
- | ^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/forget_ref.rs:26:12
- |
-LL | forget(reference3);
- | ^^^^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:31:5
- |
-LL | forget(&val);
- | ^^^^^^^^^^^^
- |
-note: argument has type `&T`
- --> $DIR/forget_ref.rs:31:12
- |
-LL | forget(&val);
- | ^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
- --> $DIR/forget_ref.rs:39:5
- |
-LL | std::mem::forget(&SomeStruct);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: argument has type `&SomeStruct`
- --> $DIR/forget_ref.rs:39:22
- |
-LL | std::mem::forget(&SomeStruct);
- | ^^^^^^^^^^^
-
-error: aborting due to 9 previous errors
-
diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed
index beedf2c1d..9288956f5 100644
--- a/src/tools/clippy/tests/ui/format.fixed
+++ b/src/tools/clippy/tests/ui/format.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::useless_format)]
#![allow(
unused_tuple_struct_fields,
diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs
index e805f1818..b2b817e0f 100644
--- a/src/tools/clippy/tests/ui/format.rs
+++ b/src/tools/clippy/tests/ui/format.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::useless_format)]
#![allow(
unused_tuple_struct_fields,
diff --git a/src/tools/clippy/tests/ui/format_args.fixed b/src/tools/clippy/tests/ui/format_args.fixed
index 825e122be..ea3836861 100644
--- a/src/tools/clippy/tests/ui/format_args.fixed
+++ b/src/tools/clippy/tests/ui/format_args.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::to_string_in_format_args)]
#![allow(unused)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/format_args.rs b/src/tools/clippy/tests/ui/format_args.rs
index a41e53389..bfb324492 100644
--- a/src/tools/clippy/tests/ui/format_args.rs
+++ b/src/tools/clippy/tests/ui/format_args.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::to_string_in_format_args)]
#![allow(unused)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
index 48f809331..915ff4fb0 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::from_iter_instead_of_collect)]
#![allow(unused_imports, unused_tuple_struct_fields)]
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
index ebe0ad278..e926f8c52 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::from_iter_instead_of_collect)]
#![allow(unused_imports, unused_tuple_struct_fields)]
diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed
index 72d635c2c..d18f93875 100644
--- a/src/tools/clippy/tests/ui/from_over_into.fixed
+++ b/src/tools/clippy/tests/ui/from_over_into.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(type_alias_impl_trait)]
#![warn(clippy::from_over_into)]
@@ -32,7 +32,7 @@ struct SelfKeywords;
impl From<X> for SelfKeywords {
fn from(val: X) -> Self {
- let _ = X::default();
+ let _ = X;
let _ = X::FOO;
let _: X = val;
diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs
index 965f4d5d7..de8ff0b06 100644
--- a/src/tools/clippy/tests/ui/from_over_into.rs
+++ b/src/tools/clippy/tests/ui/from_over_into.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(type_alias_impl_trait)]
#![warn(clippy::from_over_into)]
@@ -32,7 +32,7 @@ struct SelfKeywords;
impl Into<SelfKeywords> for X {
fn into(self) -> SelfKeywords {
- let _ = Self::default();
+ let _ = Self;
let _ = Self::FOO;
let _: Self = self;
diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr
index 3c4d011d6..6039f86fe 100644
--- a/src/tools/clippy/tests/ui/from_over_into.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into.stderr
@@ -5,7 +5,7 @@ LL | impl Into<StringWrapper> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::from-over-into` implied by `-D warnings`
-help: replace the `Into` implentation with `From<std::string::String>`
+help: replace the `Into` implementation with `From<std::string::String>`
|
LL ~ impl From<String> for StringWrapper {
LL ~ fn from(val: String) -> Self {
@@ -18,7 +18,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for
LL | impl Into<SelfType> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace the `Into` implentation with `From<std::string::String>`
+help: replace the `Into` implementation with `From<std::string::String>`
|
LL ~ impl From<String> for SelfType {
LL ~ fn from(val: String) -> Self {
@@ -31,11 +31,11 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for
LL | impl Into<SelfKeywords> for X {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace the `Into` implentation with `From<X>`
+help: replace the `Into` implementation with `From<X>`
|
LL ~ impl From<X> for SelfKeywords {
LL ~ fn from(val: X) -> Self {
-LL ~ let _ = X::default();
+LL ~ let _ = X;
LL ~ let _ = X::FOO;
LL ~ let _: X = val;
|
@@ -48,7 +48,7 @@ LL | impl core::convert::Into<bool> for crate::ExplicitPaths {
|
= 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` implentation with `From<ExplicitPaths>`
+help: replace the `Into` implementation with `From<ExplicitPaths>`
|
LL ~ impl core::convert::From<crate::ExplicitPaths> for bool {
LL ~ fn from(mut val: crate::ExplicitPaths) -> Self {
@@ -64,7 +64,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for
LL | impl<T> Into<FromOverInto<T>> for Vec<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace the `Into` implentation with `From<std::vec::Vec<T>>`
+help: replace the `Into` implementation with `From<std::vec::Vec<T>>`
|
LL ~ impl<T> From<Vec<T>> for FromOverInto<T> {
LL ~ fn from(val: Vec<T>) -> Self {
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
index 6f6ce3519..251f1d84e 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
@@ -4,7 +4,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for
LL | impl Into<InMacro> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: replace the `Into` implentation with `From<std::string::String>`
+ = help: replace the `Into` implementation with `From<std::string::String>`
= note: `-D clippy::from-over-into` implied by `-D warnings`
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
@@ -13,7 +13,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for
LL | impl Into<WeirdUpperSelf> for &'static [u8] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: replace the `Into` implentation with `From<&'static [u8]>`
+ = help: replace the `Into` implementation with `From<&'static [u8]>`
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
--> $DIR/from_over_into_unfixable.rs:28:1
@@ -23,7 +23,7 @@ LL | impl Into<u8> for ContainsVal {
|
= 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` implentation with `From<ContainsVal>`
+ = help: replace the `Into` implementation with `From<ContainsVal>`
error: aborting due to 3 previous errors
diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr
index 5b6858e45..5c6348962 100644
--- a/src/tools/clippy/tests/ui/future_not_send.stderr
+++ b/src/tools/clippy/tests/ui/future_not_send.stderr
@@ -5,22 +5,22 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| ^^^^ future returned by `private_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:8:19
+ --> $DIR/future_not_send.rs:8:20
|
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| -- has type `std::rc::Rc<[u8]>` which is not `Send`
LL | async { true }.await
- | ^^^^^^ await occurs here, with `rc` maybe used later
+ | ^^^^^ await occurs here, with `rc` maybe used later
LL | }
| - `rc` is later dropped here
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:8:19
+ --> $DIR/future_not_send.rs:8:20
|
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| ---- has type `&std::cell::Cell<usize>` which is not `Send`
LL | async { true }.await
- | ^^^^^^ await occurs here, with `cell` maybe used later
+ | ^^^^^ await occurs here, with `cell` maybe used later
LL | }
| - `cell` is later dropped here
= note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
@@ -33,12 +33,12 @@ LL | pub async fn public_future(rc: Rc<[u8]>) {
| ^ future returned by `public_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:12:19
+ --> $DIR/future_not_send.rs:12:20
|
LL | pub async fn public_future(rc: Rc<[u8]>) {
| -- has type `std::rc::Rc<[u8]>` which is not `Send`
LL | async { true }.await;
- | ^^^^^^ await occurs here, with `rc` maybe used later
+ | ^^^^^ await occurs here, with `rc` maybe used later
LL | }
| - `rc` is later dropped here
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
@@ -82,12 +82,12 @@ LL | async fn private_future(&self) -> usize {
| ^^^^^ future returned by `private_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:35:23
+ --> $DIR/future_not_send.rs:35:24
|
LL | async fn private_future(&self) -> usize {
| ----- has type `&Dummy` which is not `Send`
LL | async { true }.await;
- | ^^^^^^ await occurs here, with `&self` maybe used later
+ | ^^^^^ await occurs here, with `&self` maybe used later
LL | self.rc.len()
LL | }
| - `&self` is later dropped here
@@ -100,12 +100,12 @@ LL | pub async fn public_future(&self) {
| ^ future returned by `public_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:40:30
+ --> $DIR/future_not_send.rs:40:31
|
LL | pub async fn public_future(&self) {
| ----- has type `&Dummy` which is not `Send`
LL | self.private_future().await;
- | ^^^^^^ await occurs here, with `&self` maybe used later
+ | ^^^^^ await occurs here, with `&self` maybe used later
LL | }
| - `&self` is later dropped here
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
@@ -117,12 +117,12 @@ LL | async fn generic_future<T>(t: T) -> T
| ^ future returned by `generic_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:54:19
+ --> $DIR/future_not_send.rs:54:20
|
LL | let rt = &t;
| -- has type `&T` which is not `Send`
LL | async { true }.await;
- | ^^^^^^ await occurs here, with `rt` maybe used later
+ | ^^^^^ await occurs here, with `rt` maybe used later
LL | t
LL | }
| - `rt` is later dropped here
diff --git a/src/tools/clippy/tests/ui/get_first.fixed b/src/tools/clippy/tests/ui/get_first.fixed
index def58afa4..ef132b796 100644
--- a/src/tools/clippy/tests/ui/get_first.fixed
+++ b/src/tools/clippy/tests/ui/get_first.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::get_first)]
use std::collections::BTreeMap;
use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/get_first.rs b/src/tools/clippy/tests/ui/get_first.rs
index 85a381854..4d8722356 100644
--- a/src/tools/clippy/tests/ui/get_first.rs
+++ b/src/tools/clippy/tests/ui/get_first.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::get_first)]
use std::collections::BTreeMap;
use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/get_last_with_len.fixed b/src/tools/clippy/tests/ui/get_last_with_len.fixed
index 1e90b3768..a58dfda79 100644
--- a/src/tools/clippy/tests/ui/get_last_with_len.fixed
+++ b/src/tools/clippy/tests/ui/get_last_with_len.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::get_last_with_len)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/get_last_with_len.rs b/src/tools/clippy/tests/ui/get_last_with_len.rs
index d63a731bd..d626656c7 100644
--- a/src/tools/clippy/tests/ui/get_last_with_len.rs
+++ b/src/tools/clippy/tests/ui/get_last_with_len.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::get_last_with_len)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/get_unwrap.fixed b/src/tools/clippy/tests/ui/get_unwrap.fixed
index 5827fc7d7..4950c47dd 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.fixed
+++ b/src/tools/clippy/tests/ui/get_unwrap.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)]
#![warn(clippy::unwrap_used)]
diff --git a/src/tools/clippy/tests/ui/get_unwrap.rs b/src/tools/clippy/tests/ui/get_unwrap.rs
index a2a323c14..6b1e8edb7 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.rs
+++ b/src/tools/clippy/tests/ui/get_unwrap.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)]
#![warn(clippy::unwrap_used)]
diff --git a/src/tools/clippy/tests/ui/identity_op.fixed b/src/tools/clippy/tests/ui/identity_op.fixed
index cac69ef42..beb16000e 100644
--- a/src/tools/clippy/tests/ui/identity_op.fixed
+++ b/src/tools/clippy/tests/ui/identity_op.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::identity_op)]
#![allow(unused)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs
index 33201aad4..072e00c00 100644
--- a/src/tools/clippy/tests/ui/identity_op.rs
+++ b/src/tools/clippy/tests/ui/identity_op.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::identity_op)]
#![allow(unused)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/implicit_clone.fixed b/src/tools/clippy/tests/ui/implicit_clone.fixed
index 8ccc3da7b..e62db8b40 100644
--- a/src/tools/clippy/tests/ui/implicit_clone.fixed
+++ b/src/tools/clippy/tests/ui/implicit_clone.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::implicit_clone)]
#![allow(clippy::clone_on_copy, clippy::redundant_clone)]
use std::borrow::Borrow;
diff --git a/src/tools/clippy/tests/ui/implicit_clone.rs b/src/tools/clippy/tests/ui/implicit_clone.rs
index 593333126..88352b06a 100644
--- a/src/tools/clippy/tests/ui/implicit_clone.rs
+++ b/src/tools/clippy/tests/ui/implicit_clone.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::implicit_clone)]
#![allow(clippy::clone_on_copy, clippy::redundant_clone)]
use std::borrow::Borrow;
diff --git a/src/tools/clippy/tests/ui/implicit_hasher.rs b/src/tools/clippy/tests/ui/implicit_hasher.rs
index 35d08a07b..ca7c12213 100644
--- a/src/tools/clippy/tests/ui/implicit_hasher.rs
+++ b/src/tools/clippy/tests/ui/implicit_hasher.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![deny(clippy::implicit_hasher)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/implicit_return.fixed b/src/tools/clippy/tests/ui/implicit_return.fixed
index 5e55b8b67..64813eafd 100644
--- a/src/tools/clippy/tests/ui/implicit_return.fixed
+++ b/src/tools/clippy/tests/ui/implicit_return.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![warn(clippy::implicit_return)]
#![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)]
diff --git a/src/tools/clippy/tests/ui/implicit_return.rs b/src/tools/clippy/tests/ui/implicit_return.rs
index 76f0a9803..39d47b110 100644
--- a/src/tools/clippy/tests/ui/implicit_return.rs
+++ b/src/tools/clippy/tests/ui/implicit_return.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![warn(clippy::implicit_return)]
#![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)]
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_add.fixed b/src/tools/clippy/tests/ui/implicit_saturating_add.fixed
index 7d363d59a..7fc510d6b 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_add.fixed
+++ b/src/tools/clippy/tests/ui/implicit_saturating_add.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::implicit_saturating_add)]
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_add.rs b/src/tools/clippy/tests/ui/implicit_saturating_add.rs
index 31a591627..3dcd91f42 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_add.rs
+++ b/src/tools/clippy/tests/ui/implicit_saturating_add.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::implicit_saturating_add)]
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
index 93df81b1a..1a11db098 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_assignments, unused_mut, clippy::assign_op_pattern)]
#![warn(clippy::implicit_saturating_sub)]
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
index 8340bc826..9369df674 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_assignments, unused_mut, clippy::assign_op_pattern)]
#![warn(clippy::implicit_saturating_sub)]
diff --git a/src/tools/clippy/tests/ui/inconsistent_digit_grouping.fixed b/src/tools/clippy/tests/ui/inconsistent_digit_grouping.fixed
index dd683e7f7..06919809e 100644
--- a/src/tools/clippy/tests/ui/inconsistent_digit_grouping.fixed
+++ b/src/tools/clippy/tests/ui/inconsistent_digit_grouping.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[warn(clippy::inconsistent_digit_grouping)]
#[deny(clippy::unreadable_literal)]
#[allow(unused_variables, clippy::excessive_precision)]
diff --git a/src/tools/clippy/tests/ui/inconsistent_digit_grouping.rs b/src/tools/clippy/tests/ui/inconsistent_digit_grouping.rs
index d5d27c853..04d9125f2 100644
--- a/src/tools/clippy/tests/ui/inconsistent_digit_grouping.rs
+++ b/src/tools/clippy/tests/ui/inconsistent_digit_grouping.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[warn(clippy::inconsistent_digit_grouping)]
#[deny(clippy::unreadable_literal)]
#[allow(unused_variables, clippy::excessive_precision)]
diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
index 5aaa00f85..620d45e68 100644
--- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
+++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::inconsistent_struct_constructor)]
#![allow(clippy::redundant_field_names)]
diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
index 2b2dd7f59..10ffadcb2 100644
--- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::inconsistent_struct_constructor)]
#![allow(clippy::redundant_field_names)]
diff --git a/src/tools/clippy/tests/ui/inefficient_to_string.fixed b/src/tools/clippy/tests/ui/inefficient_to_string.fixed
index c972b9419..557f7fb73 100644
--- a/src/tools/clippy/tests/ui/inefficient_to_string.fixed
+++ b/src/tools/clippy/tests/ui/inefficient_to_string.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::inefficient_to_string)]
use std::borrow::Cow;
diff --git a/src/tools/clippy/tests/ui/inefficient_to_string.rs b/src/tools/clippy/tests/ui/inefficient_to_string.rs
index acdc55aa0..6503001e3 100644
--- a/src/tools/clippy/tests/ui/inefficient_to_string.rs
+++ b/src/tools/clippy/tests/ui/inefficient_to_string.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::inefficient_to_string)]
use std::borrow::Cow;
diff --git a/src/tools/clippy/tests/ui/infallible_destructuring_match.fixed b/src/tools/clippy/tests/ui/infallible_destructuring_match.fixed
index 61985e56b..e396ae94a 100644
--- a/src/tools/clippy/tests/ui/infallible_destructuring_match.fixed
+++ b/src/tools/clippy/tests/ui/infallible_destructuring_match.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(exhaustive_patterns, never_type)]
#![allow(dead_code, unreachable_code, unused_variables)]
#![allow(clippy::let_and_return)]
diff --git a/src/tools/clippy/tests/ui/infallible_destructuring_match.rs b/src/tools/clippy/tests/ui/infallible_destructuring_match.rs
index f2768245b..3fce7bbb6 100644
--- a/src/tools/clippy/tests/ui/infallible_destructuring_match.rs
+++ b/src/tools/clippy/tests/ui/infallible_destructuring_match.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(exhaustive_patterns, never_type)]
#![allow(dead_code, unreachable_code, unused_variables)]
#![allow(clippy::let_and_return)]
diff --git a/src/tools/clippy/tests/ui/inline_fn_without_body.fixed b/src/tools/clippy/tests/ui/inline_fn_without_body.fixed
index fe21a71a4..9c5819558 100644
--- a/src/tools/clippy/tests/ui/inline_fn_without_body.fixed
+++ b/src/tools/clippy/tests/ui/inline_fn_without_body.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::inline_fn_without_body)]
#![allow(clippy::inline_always)]
diff --git a/src/tools/clippy/tests/ui/inline_fn_without_body.rs b/src/tools/clippy/tests/ui/inline_fn_without_body.rs
index 507469894..43ffaf812 100644
--- a/src/tools/clippy/tests/ui/inline_fn_without_body.rs
+++ b/src/tools/clippy/tests/ui/inline_fn_without_body.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::inline_fn_without_body)]
#![allow(clippy::inline_always)]
diff --git a/src/tools/clippy/tests/ui/int_plus_one.fixed b/src/tools/clippy/tests/ui/int_plus_one.fixed
index 642830f24..5a36ec462 100644
--- a/src/tools/clippy/tests/ui/int_plus_one.fixed
+++ b/src/tools/clippy/tests/ui/int_plus_one.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[allow(clippy::no_effect, clippy::unnecessary_operation)]
#[warn(clippy::int_plus_one)]
diff --git a/src/tools/clippy/tests/ui/int_plus_one.rs b/src/tools/clippy/tests/ui/int_plus_one.rs
index 0755a0c79..bffa4afd6 100644
--- a/src/tools/clippy/tests/ui/int_plus_one.rs
+++ b/src/tools/clippy/tests/ui/int_plus_one.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[allow(clippy::no_effect, clippy::unnecessary_operation)]
#[warn(clippy::int_plus_one)]
diff --git a/src/tools/clippy/tests/ui/integer_arithmetic.rs b/src/tools/clippy/tests/ui/integer_arithmetic.rs
deleted file mode 100644
index 8dfdee662..000000000
--- a/src/tools/clippy/tests/ui/integer_arithmetic.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::op_ref)]
-
-#[rustfmt::skip]
-fn main() {
- let mut i = 1i32;
- let mut var1 = 13i32;
- let mut var2 = -1i32;
- 1 + i;
- i * 2;
- 1 %
- i / 2; // no error, this is part of the expression in the preceding line
- i - 2 + 2 - i;
- -i;
- i >> 1;
- i << 1;
-
- // no error, overflows are checked by `overflowing_literals`
- -1;
- -(-1);
-
- i & 1; // no wrapping
- i | 1;
- i ^ 1;
-
- i += 1;
- i -= 1;
- i *= 2;
- i /= 2;
- i /= 0;
- i /= -1;
- i /= var1;
- i /= var2;
- i %= 2;
- i %= 0;
- i %= -1;
- i %= var1;
- i %= var2;
- i <<= 3;
- i >>= 2;
-
- // no errors
- i |= 1;
- i &= 1;
- i ^= i;
-
- // No errors for the following items because they are constant expressions
- enum Foo {
- Bar = -2,
- }
- struct Baz([i32; 1 + 1]);
- union Qux {
- field: [i32; 1 + 1],
- }
- type Alias = [i32; 1 + 1];
-
- const FOO: i32 = -2;
- static BAR: i32 = -2;
-
- let _: [i32; 1 + 1] = [0, 0];
-
- let _: [i32; 1 + 1] = {
- let a: [i32; 1 + 1] = [0, 0];
- a
- };
-
- trait Trait {
- const ASSOC: i32 = 1 + 1;
- }
-
- impl Trait for Foo {
- const ASSOC: i32 = {
- let _: [i32; 1 + 1];
- fn foo() {}
- 1 + 1
- };
- }
-}
-
-// warn on references as well! (#5328)
-pub fn int_arith_ref() {
- 3 + &1;
- &3 + 1;
- &3 + &1;
-}
-
-pub fn foo(x: &i32) -> i32 {
- let a = 5;
- a + x
-}
-
-pub fn bar(x: &i32, y: &i32) -> i32 {
- x + y
-}
-
-pub fn baz(x: i32, y: &i32) -> i32 {
- x + y
-}
-
-pub fn qux(x: i32, y: i32) -> i32 {
- (&x + &y)
-}
diff --git a/src/tools/clippy/tests/ui/integer_arithmetic.stderr b/src/tools/clippy/tests/ui/integer_arithmetic.stderr
deleted file mode 100644
index 9a795b1f2..000000000
--- a/src/tools/clippy/tests/ui/integer_arithmetic.stderr
+++ /dev/null
@@ -1,169 +0,0 @@
-error: this operation will panic at runtime
- --> $DIR/integer_arithmetic.rs:30:5
- |
-LL | i /= 0;
- | ^^^^^^ attempt to divide `_` by zero
- |
- = note: `#[deny(unconditional_panic)]` on by default
-
-error: this operation will panic at runtime
- --> $DIR/integer_arithmetic.rs:35:5
- |
-LL | i %= 0;
- | ^^^^^^ attempt to calculate the remainder of `_` with a divisor of zero
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:9:5
- |
-LL | 1 + i;
- | ^^^^^
- |
- = note: `-D clippy::integer-arithmetic` implied by `-D warnings`
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:10:5
- |
-LL | i * 2;
- | ^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:11:5
- |
-LL | / 1 %
-LL | | i / 2; // no error, this is part of the expression in the preceding line
- | |_____^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:13:5
- |
-LL | i - 2 + 2 - i;
- | ^^^^^^^^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:14:5
- |
-LL | -i;
- | ^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:15:5
- |
-LL | i >> 1;
- | ^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:16:5
- |
-LL | i << 1;
- | ^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:26:5
- |
-LL | i += 1;
- | ^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:27:5
- |
-LL | i -= 1;
- | ^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:28:5
- |
-LL | i *= 2;
- | ^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:31:11
- |
-LL | i /= -1;
- | ^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:32:5
- |
-LL | i /= var1;
- | ^^^^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:33:5
- |
-LL | i /= var2;
- | ^^^^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:36:11
- |
-LL | i %= -1;
- | ^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:37:5
- |
-LL | i %= var1;
- | ^^^^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:38:5
- |
-LL | i %= var2;
- | ^^^^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:39:5
- |
-LL | i <<= 3;
- | ^^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:40:5
- |
-LL | i >>= 2;
- | ^^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:82:5
- |
-LL | 3 + &1;
- | ^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:83:5
- |
-LL | &3 + 1;
- | ^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:84:5
- |
-LL | &3 + &1;
- | ^^^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:89:5
- |
-LL | a + x
- | ^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:93:5
- |
-LL | x + y
- | ^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:97:5
- |
-LL | x + y
- | ^^^^^
-
-error: integer arithmetic detected
- --> $DIR/integer_arithmetic.rs:101:5
- |
-LL | (&x + &y)
- | ^^^^^^^^^
-
-error: aborting due to 27 previous errors
-
diff --git a/src/tools/clippy/tests/ui/into_iter_on_ref.fixed b/src/tools/clippy/tests/ui/into_iter_on_ref.fixed
index b77f17944..9f550acb1 100644
--- a/src/tools/clippy/tests/ui/into_iter_on_ref.fixed
+++ b/src/tools/clippy/tests/ui/into_iter_on_ref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::useless_vec, clippy::needless_borrow)]
#![warn(clippy::into_iter_on_ref)]
diff --git a/src/tools/clippy/tests/ui/into_iter_on_ref.rs b/src/tools/clippy/tests/ui/into_iter_on_ref.rs
index 3854bb05a..3381ae04d 100644
--- a/src/tools/clippy/tests/ui/into_iter_on_ref.rs
+++ b/src/tools/clippy/tests/ui/into_iter_on_ref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::useless_vec, clippy::needless_borrow)]
#![warn(clippy::into_iter_on_ref)]
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed
index 4f5322ebf..9264fb7e9 100644
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed
+++ b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
fn main() {
unsafe {
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs
index ae51c52d8..80c942d77 100644
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs
+++ b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
fn main() {
unsafe {
diff --git a/src/tools/clippy/tests/ui/is_digit_ascii_radix.fixed b/src/tools/clippy/tests/ui/is_digit_ascii_radix.fixed
index c0ba647d7..bc43303a6 100644
--- a/src/tools/clippy/tests/ui/is_digit_ascii_radix.fixed
+++ b/src/tools/clippy/tests/ui/is_digit_ascii_radix.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::is_digit_ascii_radix)]
diff --git a/src/tools/clippy/tests/ui/is_digit_ascii_radix.rs b/src/tools/clippy/tests/ui/is_digit_ascii_radix.rs
index 68e3f3243..93cba5c8e 100644
--- a/src/tools/clippy/tests/ui/is_digit_ascii_radix.rs
+++ b/src/tools/clippy/tests/ui/is_digit_ascii_radix.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::is_digit_ascii_radix)]
diff --git a/src/tools/clippy/tests/ui/issue-111399.rs b/src/tools/clippy/tests/ui/issue-111399.rs
new file mode 100644
index 000000000..b65e6c726
--- /dev/null
+++ b/src/tools/clippy/tests/ui/issue-111399.rs
@@ -0,0 +1,13 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that rustc doesn't crash on the trait bound `Self::Ty: std::marker::Freeze`.
+
+pub struct Struct;
+
+impl Struct {
+ pub type Ty = usize;
+ pub const CT: Self::Ty = 42;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/issue_2356.fixed b/src/tools/clippy/tests/ui/issue_2356.fixed
index a73ee0fb2..a69f5ebdc 100644
--- a/src/tools/clippy/tests/ui/issue_2356.fixed
+++ b/src/tools/clippy/tests/ui/issue_2356.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::while_let_on_iterator)]
#![allow(unused_mut)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/issue_2356.rs b/src/tools/clippy/tests/ui/issue_2356.rs
index 9dd906960..50e1bce1f 100644
--- a/src/tools/clippy/tests/ui/issue_2356.rs
+++ b/src/tools/clippy/tests/ui/issue_2356.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::while_let_on_iterator)]
#![allow(unused_mut)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/tests.rs b/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/tests.rs
new file mode 100644
index 000000000..f328e4d9d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/auxiliary/tests.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/block_module.rs b/src/tools/clippy/tests/ui/items_after_test_module/block_module.rs
new file mode 100644
index 000000000..5136b2557
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/block_module.rs
@@ -0,0 +1,23 @@
+//@compile-flags: --test
+#![allow(unused)]
+#![warn(clippy::items_after_test_module)]
+
+fn main() {}
+
+fn should_not_lint() {}
+
+#[allow(dead_code)]
+#[allow(unused)] // Some attributes to check that span replacement is good enough
+#[allow(clippy::allow_attributes)]
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn hi() {}
+}
+
+fn should_lint() {}
+
+const SHOULD_ALSO_LINT: usize = 1;
+macro_rules! should_not_lint {
+ () => {};
+}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr b/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr
new file mode 100644
index 000000000..597f1b951
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr
@@ -0,0 +1,17 @@
+error: items were found after the testing module
+ --> $DIR/block_module.rs:13:1
+ |
+LL | / mod tests {
+LL | | #[test]
+LL | | fn hi() {}
+LL | | }
+... |
+LL | | () => {};
+LL | | }
+ | |_^
+ |
+ = help: move the items to before the testing module was defined
+ = note: `-D clippy::items-after-test-module` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/imported_module.rs b/src/tools/clippy/tests/ui/items_after_test_module/imported_module.rs
new file mode 100644
index 000000000..6a757aef4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/items_after_test_module/imported_module.rs
@@ -0,0 +1,20 @@
+//@compile-flags: --test
+#![allow(unused)]
+#![warn(clippy::items_after_test_module)]
+
+// Nothing here should lint, as `tests` is an imported module (that has no body).
+
+fn main() {}
+
+fn should_not_lint() {}
+
+#[path = "auxiliary/tests.rs"]
+#[cfg(test)]
+mod tests; // Should not lint
+
+fn should_not_lint2() {}
+
+const SHOULD_ALSO_NOT_LINT: usize = 1;
+macro_rules! should_not_lint {
+ () => {};
+}
diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.fixed b/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
index 9b8621335..88f08bb99 100644
--- a/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
+++ b/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.rs b/src/tools/clippy/tests/ui/iter_cloned_collect.rs
index 639f50665..d3438b7f5 100644
--- a/src/tools/clippy/tests/ui/iter_cloned_collect.rs
+++ b/src/tools/clippy/tests/ui/iter_cloned_collect.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/iter_count.fixed b/src/tools/clippy/tests/ui/iter_count.fixed
index 90a6eef75..4367a12f8 100644
--- a/src/tools/clippy/tests/ui/iter_count.fixed
+++ b/src/tools/clippy/tests/ui/iter_count.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:option_helpers.rs
+//@run-rustfix
+//@aux-build:option_helpers.rs
#![warn(clippy::iter_count)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/iter_count.rs b/src/tools/clippy/tests/ui/iter_count.rs
index 6681a480a..8c7543cf0 100644
--- a/src/tools/clippy/tests/ui/iter_count.rs
+++ b/src/tools/clippy/tests/ui/iter_count.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:option_helpers.rs
+//@run-rustfix
+//@aux-build:option_helpers.rs
#![warn(clippy::iter_count)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.fixed b/src/tools/clippy/tests/ui/iter_kv_map.fixed
index f2a4c284c..64201b553 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.fixed
+++ b/src/tools/clippy/tests/ui/iter_kv_map.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_kv_map)]
#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.rs b/src/tools/clippy/tests/ui/iter_kv_map.rs
index ad6564df4..ec0231ba5 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.rs
+++ b/src/tools/clippy/tests/ui/iter_kv_map.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_kv_map)]
#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
diff --git a/src/tools/clippy/tests/ui/iter_next_slice.fixed b/src/tools/clippy/tests/ui/iter_next_slice.fixed
index f612d26aa..d862abc34 100644
--- a/src/tools/clippy/tests/ui/iter_next_slice.fixed
+++ b/src/tools/clippy/tests/ui/iter_next_slice.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_next_slice)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/iter_next_slice.rs b/src/tools/clippy/tests/ui/iter_next_slice.rs
index 5195f1c86..da6fc46e4 100644
--- a/src/tools/clippy/tests/ui/iter_next_slice.rs
+++ b/src/tools/clippy/tests/ui/iter_next_slice.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_next_slice)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/iter_nth.rs b/src/tools/clippy/tests/ui/iter_nth.rs
index 9c21dd82e..e7fb97d4f 100644
--- a/src/tools/clippy/tests/ui/iter_nth.rs
+++ b/src/tools/clippy/tests/ui/iter_nth.rs
@@ -1,4 +1,4 @@
-// aux-build:option_helpers.rs
+//@aux-build:option_helpers.rs
#![warn(clippy::iter_nth)]
diff --git a/src/tools/clippy/tests/ui/iter_nth_zero.fixed b/src/tools/clippy/tests/ui/iter_nth_zero.fixed
index f23671c26..587b0d1d3 100644
--- a/src/tools/clippy/tests/ui/iter_nth_zero.fixed
+++ b/src/tools/clippy/tests/ui/iter_nth_zero.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_nth_zero)]
use std::collections::HashSet;
diff --git a/src/tools/clippy/tests/ui/iter_nth_zero.rs b/src/tools/clippy/tests/ui/iter_nth_zero.rs
index 7c968d498..93b576ec5 100644
--- a/src/tools/clippy/tests/ui/iter_nth_zero.rs
+++ b/src/tools/clippy/tests/ui/iter_nth_zero.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_nth_zero)]
use std::collections::HashSet;
diff --git a/src/tools/clippy/tests/ui/iter_on_empty_collections.fixed b/src/tools/clippy/tests/ui/iter_on_empty_collections.fixed
index bd9b07aef..4616f0cdc 100644
--- a/src/tools/clippy/tests/ui/iter_on_empty_collections.fixed
+++ b/src/tools/clippy/tests/ui/iter_on_empty_collections.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_on_empty_collections)]
#![allow(clippy::iter_next_slice, clippy::redundant_clone)]
diff --git a/src/tools/clippy/tests/ui/iter_on_empty_collections.rs b/src/tools/clippy/tests/ui/iter_on_empty_collections.rs
index e15ba94bd..81cc7265e 100644
--- a/src/tools/clippy/tests/ui/iter_on_empty_collections.rs
+++ b/src/tools/clippy/tests/ui/iter_on_empty_collections.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_on_empty_collections)]
#![allow(clippy::iter_next_slice, clippy::redundant_clone)]
diff --git a/src/tools/clippy/tests/ui/iter_on_single_items.fixed b/src/tools/clippy/tests/ui/iter_on_single_items.fixed
index 1fa4b0364..80dbe454b 100644
--- a/src/tools/clippy/tests/ui/iter_on_single_items.fixed
+++ b/src/tools/clippy/tests/ui/iter_on_single_items.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_on_single_items)]
#![allow(clippy::iter_next_slice, clippy::redundant_clone)]
diff --git a/src/tools/clippy/tests/ui/iter_on_single_items.rs b/src/tools/clippy/tests/ui/iter_on_single_items.rs
index ea96d8066..71c8c7a3f 100644
--- a/src/tools/clippy/tests/ui/iter_on_single_items.rs
+++ b/src/tools/clippy/tests/ui/iter_on_single_items.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_on_single_items)]
#![allow(clippy::iter_next_slice, clippy::redundant_clone)]
diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed b/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
index c100705d0..bf576e9cb 100644
--- a/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
+++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)]
#![allow(dead_code, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.rs b/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
index 2caa88020..df42d88ef 100644
--- a/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
+++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)]
#![allow(dead_code, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/iter_skip_next.fixed b/src/tools/clippy/tests/ui/iter_skip_next.fixed
index d56d623b5..8f2cefc43 100644
--- a/src/tools/clippy/tests/ui/iter_skip_next.fixed
+++ b/src/tools/clippy/tests/ui/iter_skip_next.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:option_helpers.rs
+//@run-rustfix
+//@aux-build:option_helpers.rs
#![warn(clippy::iter_skip_next)]
#![allow(clippy::disallowed_names)]
diff --git a/src/tools/clippy/tests/ui/iter_skip_next.rs b/src/tools/clippy/tests/ui/iter_skip_next.rs
index 3ec5d1b82..71d83384f 100644
--- a/src/tools/clippy/tests/ui/iter_skip_next.rs
+++ b/src/tools/clippy/tests/ui/iter_skip_next.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:option_helpers.rs
+//@run-rustfix
+//@aux-build:option_helpers.rs
#![warn(clippy::iter_skip_next)]
#![allow(clippy::disallowed_names)]
diff --git a/src/tools/clippy/tests/ui/iter_with_drain.fixed b/src/tools/clippy/tests/ui/iter_with_drain.fixed
index 0330d5549..24a95c4d0 100644
--- a/src/tools/clippy/tests/ui/iter_with_drain.fixed
+++ b/src/tools/clippy/tests/ui/iter_with_drain.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
// will emits unused mut warnings after fixing
#![allow(unused_mut)]
// will emits needless collect warnings after fixing
diff --git a/src/tools/clippy/tests/ui/iter_with_drain.rs b/src/tools/clippy/tests/ui/iter_with_drain.rs
index 993936fb8..a118c981e 100644
--- a/src/tools/clippy/tests/ui/iter_with_drain.rs
+++ b/src/tools/clippy/tests/ui/iter_with_drain.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
// will emits unused mut warnings after fixing
#![allow(unused_mut)]
// will emits needless collect warnings after fixing
diff --git a/src/tools/clippy/tests/ui/large_const_arrays.fixed b/src/tools/clippy/tests/ui/large_const_arrays.fixed
index c5af07c8a..f7ce6fbe6 100644
--- a/src/tools/clippy/tests/ui/large_const_arrays.fixed
+++ b/src/tools/clippy/tests/ui/large_const_arrays.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::large_const_arrays)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/large_const_arrays.rs b/src/tools/clippy/tests/ui/large_const_arrays.rs
index a160b9f8a..002ac77dd 100644
--- a/src/tools/clippy/tests/ui/large_const_arrays.rs
+++ b/src/tools/clippy/tests/ui/large_const_arrays.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::large_const_arrays)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/large_digit_groups.fixed b/src/tools/clippy/tests/ui/large_digit_groups.fixed
index ea18dac06..f42fcd96d 100644
--- a/src/tools/clippy/tests/ui/large_digit_groups.fixed
+++ b/src/tools/clippy/tests/ui/large_digit_groups.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::large_digit_groups)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/large_digit_groups.rs b/src/tools/clippy/tests/ui/large_digit_groups.rs
index ac116d5db..3db9da6a3 100644
--- a/src/tools/clippy/tests/ui/large_digit_groups.rs
+++ b/src/tools/clippy/tests/ui/large_digit_groups.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::large_digit_groups)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/large_enum_variant.rs b/src/tools/clippy/tests/ui/large_enum_variant.rs
index f09f8ae0c..ea8bc5b4a 100644
--- a/src/tools/clippy/tests/ui/large_enum_variant.rs
+++ b/src/tools/clippy/tests/ui/large_enum_variant.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![allow(dead_code)]
#![allow(unused_variables)]
diff --git a/src/tools/clippy/tests/ui/large_types_passed_by_value.rs b/src/tools/clippy/tests/ui/large_types_passed_by_value.rs
index 7601b5c66..f9e3c7192 100644
--- a/src/tools/clippy/tests/ui/large_types_passed_by_value.rs
+++ b/src/tools/clippy/tests/ui/large_types_passed_by_value.rs
@@ -1,5 +1,5 @@
-// normalize-stderr-test "\(\d+ byte\)" -> "(N byte)"
-// normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)"
+//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
+//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
#![warn(clippy::large_types_passed_by_value)]
diff --git a/src/tools/clippy/tests/ui/len_zero.fixed b/src/tools/clippy/tests/ui/len_zero.fixed
index c1c0b5ae4..2c22abd7e 100644
--- a/src/tools/clippy/tests/ui/len_zero.fixed
+++ b/src/tools/clippy/tests/ui/len_zero.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::len_zero)]
#![allow(dead_code, unused, clippy::len_without_is_empty)]
@@ -176,6 +176,10 @@ fn main() {
// No error; `HasWrongIsEmpty` does not have `.is_empty()`.
println!("Or this!");
}
+
+ // issue #10529
+ (!has_is_empty.is_empty()).then(|| println!("This can happen."));
+ (has_is_empty.is_empty()).then(|| println!("Or this!"));
}
fn test_slice(b: &[u8]) {
diff --git a/src/tools/clippy/tests/ui/len_zero.rs b/src/tools/clippy/tests/ui/len_zero.rs
index cc2eb05b6..a011ff976 100644
--- a/src/tools/clippy/tests/ui/len_zero.rs
+++ b/src/tools/clippy/tests/ui/len_zero.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::len_zero)]
#![allow(dead_code, unused, clippy::len_without_is_empty)]
@@ -176,6 +176,10 @@ fn main() {
// No error; `HasWrongIsEmpty` does not have `.is_empty()`.
println!("Or this!");
}
+
+ // issue #10529
+ (has_is_empty.len() > 0).then(|| println!("This can happen."));
+ (has_is_empty.len() == 0).then(|| println!("Or this!"));
}
fn test_slice(b: &[u8]) {
diff --git a/src/tools/clippy/tests/ui/len_zero.stderr b/src/tools/clippy/tests/ui/len_zero.stderr
index b6f137802..396cfb75f 100644
--- a/src/tools/clippy/tests/ui/len_zero.stderr
+++ b/src/tools/clippy/tests/ui/len_zero.stderr
@@ -123,10 +123,22 @@ LL | if with_is_empty.len() == 0 {
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:182:8
+ --> $DIR/len_zero.rs:181:6
+ |
+LL | (has_is_empty.len() > 0).then(|| println!("This can happen."));
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
+
+error: length comparison to zero
+ --> $DIR/len_zero.rs:182:6
+ |
+LL | (has_is_empty.len() == 0).then(|| println!("Or this!"));
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
+
+error: length comparison to zero
+ --> $DIR/len_zero.rs:186:8
|
LL | if b.len() != 0 {}
| ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()`
-error: aborting due to 21 previous errors
+error: aborting due to 23 previous errors
diff --git a/src/tools/clippy/tests/ui/len_zero_ranges.fixed b/src/tools/clippy/tests/ui/len_zero_ranges.fixed
index 797817662..4b1241ec8 100644
--- a/src/tools/clippy/tests/ui/len_zero_ranges.fixed
+++ b/src/tools/clippy/tests/ui/len_zero_ranges.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::len_zero)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/len_zero_ranges.rs b/src/tools/clippy/tests/ui/len_zero_ranges.rs
index a0eb51cc9..4b47132c7 100644
--- a/src/tools/clippy/tests/ui/len_zero_ranges.rs
+++ b/src/tools/clippy/tests/ui/len_zero_ranges.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::len_zero)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
index bcb33c5c7..2c313ff35 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.rs
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
@@ -1,6 +1,12 @@
+//@aux-build: proc_macros.rs
+
#![allow(unused)]
#![warn(clippy::let_underscore_untyped)]
+extern crate proc_macros;
+use proc_macros::with_span;
+
+use clippy_utils::is_from_proc_macro;
use std::future::Future;
use std::{boxed::Box, fmt::Display};
@@ -28,6 +34,18 @@ fn f() -> Box<dyn Display> {
Box::new(1)
}
+fn g() -> impl Fn() {
+ || {}
+}
+
+with_span!(
+ span
+
+ fn dont_lint_proc_macro() {
+ let _ = a();
+ }
+);
+
fn main() {
let _ = a();
let _ = b(1);
@@ -35,6 +53,8 @@ fn main() {
let _ = d(&1);
let _ = e();
let _ = f();
+ let _ = g();
+ let closure = || {};
_ = a();
_ = b(1);
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
index 36c3d1214..bbf2508af 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
@@ -1,51 +1,63 @@
error: non-binding `let` without a type annotation
- --> $DIR/let_underscore_untyped.rs:32:5
+ --> $DIR/let_underscore_untyped.rs:50:5
|
LL | let _ = a();
| ^^^^^^^^^^^^
|
- = help: consider adding a type annotation or removing the `let` keyword
+help: consider adding a type annotation
+ --> $DIR/let_underscore_untyped.rs:50:10
+ |
+LL | let _ = a();
+ | ^
= note: `-D clippy::let-underscore-untyped` implied by `-D warnings`
error: non-binding `let` without a type annotation
- --> $DIR/let_underscore_untyped.rs:33:5
+ --> $DIR/let_underscore_untyped.rs:51:5
|
LL | let _ = b(1);
| ^^^^^^^^^^^^^
|
- = help: consider adding a type annotation or removing the `let` keyword
-
-error: non-binding `let` without a type annotation
- --> $DIR/let_underscore_untyped.rs:34:5
+help: consider adding a type annotation
+ --> $DIR/let_underscore_untyped.rs:51:10
|
-LL | let _ = c();
- | ^^^^^^^^^^^^
- |
- = help: consider adding a type annotation or removing the `let` keyword
+LL | let _ = b(1);
+ | ^
error: non-binding `let` without a type annotation
- --> $DIR/let_underscore_untyped.rs:35:5
+ --> $DIR/let_underscore_untyped.rs:53:5
|
LL | let _ = d(&1);
| ^^^^^^^^^^^^^^
|
- = help: consider adding a type annotation or removing the `let` keyword
+help: consider adding a type annotation
+ --> $DIR/let_underscore_untyped.rs:53:10
+ |
+LL | let _ = d(&1);
+ | ^
error: non-binding `let` without a type annotation
- --> $DIR/let_underscore_untyped.rs:36:5
+ --> $DIR/let_underscore_untyped.rs:54:5
|
LL | let _ = e();
| ^^^^^^^^^^^^
|
- = help: consider adding a type annotation or removing the `let` keyword
+help: consider adding a type annotation
+ --> $DIR/let_underscore_untyped.rs:54:10
+ |
+LL | let _ = e();
+ | ^
error: non-binding `let` without a type annotation
- --> $DIR/let_underscore_untyped.rs:37:5
+ --> $DIR/let_underscore_untyped.rs:55:5
|
LL | let _ = f();
| ^^^^^^^^^^^^
|
- = help: consider adding a type annotation or removing the `let` keyword
+help: consider adding a type annotation
+ --> $DIR/let_underscore_untyped.rs:55:10
+ |
+LL | let _ = f();
+ | ^
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/let_unit.fixed b/src/tools/clippy/tests/ui/let_unit.fixed
index 76ff0645f..8ba89ec78 100644
--- a/src/tools/clippy/tests/ui/let_unit.fixed
+++ b/src/tools/clippy/tests/ui/let_unit.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![warn(clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/let_unit.rs b/src/tools/clippy/tests/ui/let_unit.rs
index 895ccfe36..7e8764a48 100644
--- a/src/tools/clippy/tests/ui/let_unit.rs
+++ b/src/tools/clippy/tests/ui/let_unit.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![warn(clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/let_with_type_underscore.rs b/src/tools/clippy/tests/ui/let_with_type_underscore.rs
index 175718b94..ae1a480bc 100644
--- a/src/tools/clippy/tests/ui/let_with_type_underscore.rs
+++ b/src/tools/clippy/tests/ui/let_with_type_underscore.rs
@@ -1,19 +1,42 @@
+//@aux-build: proc_macros.rs
#![allow(unused)]
#![warn(clippy::let_with_type_underscore)]
-#![allow(clippy::let_unit_value)]
+#![allow(clippy::let_unit_value, clippy::needless_late_init)]
+
+extern crate proc_macros;
fn func() -> &'static str {
""
}
+#[rustfmt::skip]
fn main() {
// Will lint
let x: _ = 1;
let _: _ = 2;
let x: _ = func();
+ let x: _;
+ x = ();
- let x = 1; // Will not lint, Rust inferres this to an integer before Clippy
+ let x = 1; // Will not lint, Rust infers this to an integer before Clippy
let x = func();
let x: Vec<_> = Vec::<u32>::new();
let x: [_; 1] = [1];
+ let x : _ = 1;
+
+ // Do not lint from procedural macros
+ proc_macros::with_span! {
+ span
+ let x: _ = ();
+ // Late initialization
+ let x: _;
+ x = ();
+ // Ensure weird formatting will not break it (hopefully)
+ let x : _ = 1;
+ let x
+: _ = 1;
+ let x :
+ _;
+ x = ();
+ };
}
diff --git a/src/tools/clippy/tests/ui/let_with_type_underscore.stderr b/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
index 16bf83c70..a749552c7 100644
--- a/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
+++ b/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
@@ -1,39 +1,63 @@
error: variable declared with type underscore
- --> $DIR/let_with_type_underscore.rs:11:5
+ --> $DIR/let_with_type_underscore.rs:15:5
|
LL | let x: _ = 1;
| ^^^^^^^^^^^^^
|
help: remove the explicit type `_` declaration
- --> $DIR/let_with_type_underscore.rs:11:10
+ --> $DIR/let_with_type_underscore.rs:15:10
|
LL | let x: _ = 1;
| ^^^
= note: `-D clippy::let-with-type-underscore` implied by `-D warnings`
error: variable declared with type underscore
- --> $DIR/let_with_type_underscore.rs:12:5
+ --> $DIR/let_with_type_underscore.rs:16:5
|
LL | let _: _ = 2;
| ^^^^^^^^^^^^^
|
help: remove the explicit type `_` declaration
- --> $DIR/let_with_type_underscore.rs:12:10
+ --> $DIR/let_with_type_underscore.rs:16:10
|
LL | let _: _ = 2;
| ^^^
error: variable declared with type underscore
- --> $DIR/let_with_type_underscore.rs:13:5
+ --> $DIR/let_with_type_underscore.rs:17:5
|
LL | let x: _ = func();
| ^^^^^^^^^^^^^^^^^^
|
help: remove the explicit type `_` declaration
- --> $DIR/let_with_type_underscore.rs:13:10
+ --> $DIR/let_with_type_underscore.rs:17:10
|
LL | let x: _ = func();
| ^^^
-error: aborting due to 3 previous errors
+error: variable declared with type underscore
+ --> $DIR/let_with_type_underscore.rs:18:5
+ |
+LL | let x: _;
+ | ^^^^^^^^^
+ |
+help: remove the explicit type `_` declaration
+ --> $DIR/let_with_type_underscore.rs:18:10
+ |
+LL | let x: _;
+ | ^^^
+
+error: variable declared with type underscore
+ --> $DIR/let_with_type_underscore.rs:25:5
+ |
+LL | let x : _ = 1;
+ | ^^^^^^^^^^^^^^
+ |
+help: remove the explicit type `_` declaration
+ --> $DIR/let_with_type_underscore.rs:25:10
+ |
+LL | let x : _ = 1;
+ | ^^^^
+
+error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed b/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed
index f4033cd8e..64114f658 100644
--- a/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed
+++ b/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::map_identity)]
#![warn(clippy::lines_filter_map_ok)]
diff --git a/src/tools/clippy/tests/ui/lines_filter_map_ok.rs b/src/tools/clippy/tests/ui/lines_filter_map_ok.rs
index 7e11816b2..5aedc6863 100644
--- a/src/tools/clippy/tests/ui/lines_filter_map_ok.rs
+++ b/src/tools/clippy/tests/ui/lines_filter_map_ok.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::map_identity)]
#![warn(clippy::lines_filter_map_ok)]
diff --git a/src/tools/clippy/tests/ui/lossy_float_literal.fixed b/src/tools/clippy/tests/ui/lossy_float_literal.fixed
index 24e372354..a20885756 100644
--- a/src/tools/clippy/tests/ui/lossy_float_literal.fixed
+++ b/src/tools/clippy/tests/ui/lossy_float_literal.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::lossy_float_literal)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/lossy_float_literal.rs b/src/tools/clippy/tests/ui/lossy_float_literal.rs
index 3dcf98fa0..1a75f214c 100644
--- a/src/tools/clippy/tests/ui/lossy_float_literal.rs
+++ b/src/tools/clippy/tests/ui/lossy_float_literal.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::lossy_float_literal)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed
index a395e4f56..b4dabe3ca 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.fixed
+++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed
@@ -1,8 +1,8 @@
-// aux-build:macro_rules.rs
-// aux-build:macro_use_helper.rs
-// aux-build:proc_macro_derive.rs
-// run-rustfix
-// ignore-32bit
+//@aux-build:macro_rules.rs
+//@aux-build:macro_use_helper.rs
+//@aux-build:proc_macro_derive.rs
+//@run-rustfix
+//@ignore-32bit
#![feature(lint_reasons)]
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs
index b1a287332..925a2c61f 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.rs
+++ b/src/tools/clippy/tests/ui/macro_use_imports.rs
@@ -1,8 +1,8 @@
-// aux-build:macro_rules.rs
-// aux-build:macro_use_helper.rs
-// aux-build:proc_macro_derive.rs
-// run-rustfix
-// ignore-32bit
+//@aux-build:macro_rules.rs
+//@aux-build:macro_use_helper.rs
+//@aux-build:proc_macro_derive.rs
+//@run-rustfix
+//@ignore-32bit
#![feature(lint_reasons)]
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
diff --git a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
index 5aac5af26..b9677851b 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
+++ b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
@@ -1,7 +1,7 @@
-// aux-build:macro_rules.rs
-// aux-build:macro_use_helper.rs
-// aux-build:proc_macro_derive.rs
-// ignore-32bit
+//@aux-build:macro_rules.rs
+//@aux-build:macro_use_helper.rs
+//@aux-build:proc_macro_derive.rs
+//@ignore-32bit
#![feature(lint_reasons)]
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
index 8c7e919bf..ab9b375dc 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
@@ -1,7 +1,7 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
#![warn(clippy::manual_assert)]
#![allow(dead_code, unused_doc_comments)]
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
index 8c7e919bf..ab9b375dc 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
@@ -1,7 +1,7 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
#![warn(clippy::manual_assert)]
#![allow(dead_code, unused_doc_comments)]
diff --git a/src/tools/clippy/tests/ui/manual_assert.rs b/src/tools/clippy/tests/ui/manual_assert.rs
index f037c5b84..eac52d1b5 100644
--- a/src/tools/clippy/tests/ui/manual_assert.rs
+++ b/src/tools/clippy/tests/ui/manual_assert.rs
@@ -1,7 +1,7 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
#![warn(clippy::manual_assert)]
#![allow(dead_code, unused_doc_comments)]
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.fixed b/src/tools/clippy/tests/ui/manual_async_fn.fixed
index 5cc4a43af..e458f0d25 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.fixed
+++ b/src/tools/clippy/tests/ui/manual_async_fn.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_async_fn)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.rs b/src/tools/clippy/tests/ui/manual_async_fn.rs
index ba504b8a8..dd5ca1c9b 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.rs
+++ b/src/tools/clippy/tests/ui/manual_async_fn.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_async_fn)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/manual_bits.fixed b/src/tools/clippy/tests/ui/manual_bits.fixed
index e7f8cd878..037de0262 100644
--- a/src/tools/clippy/tests/ui/manual_bits.fixed
+++ b/src/tools/clippy/tests/ui/manual_bits.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_bits)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/manual_bits.rs b/src/tools/clippy/tests/ui/manual_bits.rs
index 7b1d15495..b15a531ec 100644
--- a/src/tools/clippy/tests/ui/manual_bits.rs
+++ b/src/tools/clippy/tests/ui/manual_bits.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_bits)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/manual_filter.fixed b/src/tools/clippy/tests/ui/manual_filter.fixed
index ef6780dc9..755caa664 100644
--- a/src/tools/clippy/tests/ui/manual_filter.fixed
+++ b/src/tools/clippy/tests/ui/manual_filter.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_filter)]
#![allow(unused_variables, dead_code)]
diff --git a/src/tools/clippy/tests/ui/manual_filter.rs b/src/tools/clippy/tests/ui/manual_filter.rs
index ea0ce8317..faccfe9db 100644
--- a/src/tools/clippy/tests/ui/manual_filter.rs
+++ b/src/tools/clippy/tests/ui/manual_filter.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_filter)]
#![allow(unused_variables, dead_code)]
diff --git a/src/tools/clippy/tests/ui/manual_filter_map.fixed b/src/tools/clippy/tests/ui/manual_filter_map.fixed
index 4936dc9b2..831323089 100644
--- a/src/tools/clippy/tests/ui/manual_filter_map.fixed
+++ b/src/tools/clippy/tests/ui/manual_filter_map.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::manual_filter_map)]
#![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
diff --git a/src/tools/clippy/tests/ui/manual_filter_map.rs b/src/tools/clippy/tests/ui/manual_filter_map.rs
index 8c67e827b..2692303d3 100644
--- a/src/tools/clippy/tests/ui/manual_filter_map.rs
+++ b/src/tools/clippy/tests/ui/manual_filter_map.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::manual_filter_map)]
#![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.fixed b/src/tools/clippy/tests/ui/manual_find_fixable.fixed
index 2bce6e624..9c5eb20c8 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.fixed
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_find)]
#![allow(unused)]
#![allow(clippy::needless_return, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.rs b/src/tools/clippy/tests/ui/manual_find_fixable.rs
index f5c6de37a..7b670320e 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.rs
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_find)]
#![allow(unused)]
#![allow(clippy::needless_return, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/manual_find_map.fixed b/src/tools/clippy/tests/ui/manual_find_map.fixed
index 54302bece..554613a30 100644
--- a/src/tools/clippy/tests/ui/manual_find_map.fixed
+++ b/src/tools/clippy/tests/ui/manual_find_map.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::manual_find_map)]
#![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
diff --git a/src/tools/clippy/tests/ui/manual_find_map.rs b/src/tools/clippy/tests/ui/manual_find_map.rs
index afcc1825a..d6245758f 100644
--- a/src/tools/clippy/tests/ui/manual_find_map.rs
+++ b/src/tools/clippy/tests/ui/manual_find_map.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::manual_find_map)]
#![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
diff --git a/src/tools/clippy/tests/ui/manual_instant_elapsed.fixed b/src/tools/clippy/tests/ui/manual_instant_elapsed.fixed
index 85a91543c..55073c3b5 100644
--- a/src/tools/clippy/tests/ui/manual_instant_elapsed.fixed
+++ b/src/tools/clippy/tests/ui/manual_instant_elapsed.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_instant_elapsed)]
#![allow(clippy::unnecessary_operation)]
#![allow(clippy::unchecked_duration_subtraction)]
diff --git a/src/tools/clippy/tests/ui/manual_instant_elapsed.rs b/src/tools/clippy/tests/ui/manual_instant_elapsed.rs
index c98cb15b9..c9029a049 100644
--- a/src/tools/clippy/tests/ui/manual_instant_elapsed.rs
+++ b/src/tools/clippy/tests/ui/manual_instant_elapsed.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_instant_elapsed)]
#![allow(clippy::unnecessary_operation)]
#![allow(clippy::unchecked_duration_subtraction)]
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
index 5b2b44c2f..87e866586 100644
--- a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, dead_code)]
#![warn(clippy::manual_is_ascii_check)]
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
index c9433f33a..931f0f202 100644
--- a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, dead_code)]
#![warn(clippy::manual_is_ascii_check)]
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index d175597a4..3996d775f 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -8,6 +8,12 @@
)]
#![warn(clippy::manual_let_else)]
+enum Variant {
+ A(usize, usize),
+ B(usize),
+ C,
+}
+
fn g() -> Option<()> {
None
}
@@ -135,6 +141,15 @@ fn fire() {
};
}
create_binding_if_some!(w, g());
+
+ fn e() -> Variant {
+ Variant::A(0, 0)
+ }
+
+ // Should not be renamed
+ let v = if let Variant::A(a, 0) = e() { a } else { return };
+ // Should be renamed
+ let v = if let Variant::B(b) = e() { b } else { return };
}
fn not_fire() {
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
index 52aac6bc6..f6f56f7b0 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -1,13 +1,13 @@
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:18:5
+ --> $DIR/manual_let_else.rs:24:5
|
LL | let v = if let Some(v_some) = g() { v_some } else { return };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { return };`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
|
= note: `-D clippy::manual-let-else` implied by `-D warnings`
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:19:5
+ --> $DIR/manual_let_else.rs:25:5
|
LL | / let v = if let Some(v_some) = g() {
LL | | v_some
@@ -18,13 +18,13 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g() else {
+LL ~ let Some(v) = g() else {
LL + return;
LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:25:5
+ --> $DIR/manual_let_else.rs:31:5
|
LL | / let v = if let Some(v) = g() {
LL | | // Blocks around the identity should have no impact
@@ -45,25 +45,25 @@ LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:38:9
+ --> $DIR/manual_let_else.rs:44:9
|
LL | let v = if let Some(v_some) = g() { v_some } else { continue };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { continue };`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:39:9
+ --> $DIR/manual_let_else.rs:45:9
|
LL | let v = if let Some(v_some) = g() { v_some } else { break };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { break };`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:43:5
+ --> $DIR/manual_let_else.rs:49:5
|
LL | let v = if let Some(v_some) = g() { v_some } else { panic!() };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { panic!() };`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:46:5
+ --> $DIR/manual_let_else.rs:52:5
|
LL | / let v = if let Some(v_some) = g() {
LL | | v_some
@@ -74,13 +74,13 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g() else {
+LL ~ let Some(v) = g() else {
LL + std::process::abort()
LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:53:5
+ --> $DIR/manual_let_else.rs:59:5
|
LL | / let v = if let Some(v_some) = g() {
LL | | v_some
@@ -91,13 +91,13 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g() else {
+LL ~ let Some(v) = g() else {
LL + if true { return } else { panic!() }
LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:60:5
+ --> $DIR/manual_let_else.rs:66:5
|
LL | / let v = if let Some(v_some) = g() {
LL | | v_some
@@ -109,14 +109,14 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g() else {
+LL ~ let Some(v) = g() else {
LL + if true {}
LL + panic!();
LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:70:5
+ --> $DIR/manual_let_else.rs:76:5
|
LL | / let v = if let Some(v_some) = g() {
LL | | v_some
@@ -129,7 +129,7 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g() else {
+LL ~ let Some(v) = g() else {
LL + match () {
LL + _ if panic!() => {},
LL + _ => panic!(),
@@ -138,13 +138,13 @@ LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:80:5
+ --> $DIR/manual_let_else.rs:86:5
|
LL | let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { if panic!() {} };`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };`
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:83:5
+ --> $DIR/manual_let_else.rs:89:5
|
LL | / let v = if let Some(v_some) = g() {
LL | | v_some
@@ -157,7 +157,7 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g() else {
+LL ~ let Some(v) = g() else {
LL + match panic!() {
LL + _ => {},
LL + }
@@ -165,7 +165,7 @@ LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:92:5
+ --> $DIR/manual_let_else.rs:98:5
|
LL | / let v = if let Some(v_some) = g() {
LL | | v_some
@@ -178,7 +178,7 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g() else { if true {
+LL ~ let Some(v) = g() else { if true {
LL + return;
LL + } else {
LL + panic!("diverge");
@@ -186,7 +186,7 @@ LL + } };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:101:5
+ --> $DIR/manual_let_else.rs:107:5
|
LL | / let v = if let Some(v_some) = g() {
LL | | v_some
@@ -199,7 +199,7 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g() else {
+LL ~ let Some(v) = g() else {
LL + match (g(), g()) {
LL + (Some(_), None) => return,
LL + (None, Some(_)) => {
@@ -215,7 +215,7 @@ LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:118:5
+ --> $DIR/manual_let_else.rs:124:5
|
LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
LL | | v_some
@@ -226,13 +226,13 @@ LL | | };
|
help: consider writing
|
-LL ~ let Some(v_some) = g().map(|v| (v, 42)) else {
+LL ~ let Some((v, w)) = g().map(|v| (v, 42)) else {
LL + return;
LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:125:5
+ --> $DIR/manual_let_else.rs:131:5
|
LL | / let v = if let (Some(v_some), w_some) = (g(), 0) {
LL | | (w_some, v_some)
@@ -249,10 +249,10 @@ LL + };
|
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:134:13
+ --> $DIR/manual_let_else.rs:140:13
|
LL | let $n = if let Some(v) = $e { v } else { return };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
...
LL | create_binding_if_some!(w, g());
| ------------------------------- in this macro invocation
@@ -260,13 +260,25 @@ LL | create_binding_if_some!(w, g());
= note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this could be rewritten as `let...else`
- --> $DIR/manual_let_else.rs:247:5
+ --> $DIR/manual_let_else.rs:150:5
+ |
+LL | let v = if let Variant::A(a, 0) = e() { a } else { return };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(a, 0) = e() else { return };`
+
+error: this could be rewritten as `let...else`
+ --> $DIR/manual_let_else.rs:152:5
+ |
+LL | let v = if let Variant::B(b) = e() { b } else { return };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(v) = e() else { return };`
+
+error: this could be rewritten as `let...else`
+ --> $DIR/manual_let_else.rs:262:5
|
LL | / let _ = match ff {
LL | | Some(value) => value,
LL | | _ => macro_call!(),
LL | | };
- | |______^ help: consider writing: `let Some(value) = ff else { macro_call!() };`
+ | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
-error: aborting due to 18 previous errors
+error: aborting due to 20 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index 7abaa0b85..bacc14dc9 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -5,7 +5,7 @@ LL | / let v = match g() {
LL | | Some(v_some) => v_some,
LL | | None => return,
LL | | };
- | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+ | |______^ help: consider writing: `let Some(v) = g() else { return };`
|
= note: `-D clippy::manual-let-else` implied by `-D warnings`
@@ -16,7 +16,7 @@ LL | / let v = match g() {
LL | | Some(v_some) => v_some,
LL | | _ => return,
LL | | };
- | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+ | |______^ help: consider writing: `let Some(v) = g() else { return };`
error: this could be rewritten as `let...else`
--> $DIR/manual_let_else_match.rs:44:9
diff --git a/src/tools/clippy/tests/ui/manual_main_separator_str.fixed b/src/tools/clippy/tests/ui/manual_main_separator_str.fixed
index 50f46d6b3..7e7da8f20 100644
--- a/src/tools/clippy/tests/ui/manual_main_separator_str.fixed
+++ b/src/tools/clippy/tests/ui/manual_main_separator_str.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::manual_main_separator_str)]
diff --git a/src/tools/clippy/tests/ui/manual_main_separator_str.rs b/src/tools/clippy/tests/ui/manual_main_separator_str.rs
index 2dbb9e661..cf90e12ef 100644
--- a/src/tools/clippy/tests/ui/manual_main_separator_str.rs
+++ b/src/tools/clippy/tests/ui/manual_main_separator_str.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::manual_main_separator_str)]
diff --git a/src/tools/clippy/tests/ui/manual_map_option.fixed b/src/tools/clippy/tests/ui/manual_map_option.fixed
index e12ea7ec1..e8ff65cad 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.fixed
+++ b/src/tools/clippy/tests/ui/manual_map_option.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_map)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs
index 325a6db06..b06a96451 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.rs
+++ b/src/tools/clippy/tests/ui/manual_map_option.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_map)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/manual_map_option_2.fixed b/src/tools/clippy/tests/ui/manual_map_option_2.fixed
index ebf3f8cab..dc7228782 100644
--- a/src/tools/clippy/tests/ui/manual_map_option_2.fixed
+++ b/src/tools/clippy/tests/ui/manual_map_option_2.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_map)]
#![allow(clippy::toplevel_ref_arg)]
diff --git a/src/tools/clippy/tests/ui/manual_map_option_2.rs b/src/tools/clippy/tests/ui/manual_map_option_2.rs
index 1382d9af0..c495ab0fa 100644
--- a/src/tools/clippy/tests/ui/manual_map_option_2.rs
+++ b/src/tools/clippy/tests/ui/manual_map_option_2.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_map)]
#![allow(clippy::toplevel_ref_arg)]
diff --git a/src/tools/clippy/tests/ui/manual_next_back.fixed b/src/tools/clippy/tests/ui/manual_next_back.fixed
new file mode 100644
index 000000000..e8a47063a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.fixed
@@ -0,0 +1,36 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_next_back)]
+
+struct FakeIter(std::ops::Range<i32>);
+
+impl FakeIter {
+ fn rev(self) -> Self {
+ self
+ }
+
+ fn next(&self) {}
+}
+
+impl DoubleEndedIterator for FakeIter {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.0.next_back()
+ }
+}
+
+impl Iterator for FakeIter {
+ type Item = i32;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next()
+ }
+}
+
+fn main() {
+ // should not lint
+ FakeIter(0..10).rev().next();
+
+ // should lint
+ let _ = (0..10).next_back().unwrap();
+ let _ = "something".bytes().next_back();
+}
diff --git a/src/tools/clippy/tests/ui/manual_next_back.rs b/src/tools/clippy/tests/ui/manual_next_back.rs
new file mode 100644
index 000000000..9ec892422
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.rs
@@ -0,0 +1,36 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_next_back)]
+
+struct FakeIter(std::ops::Range<i32>);
+
+impl FakeIter {
+ fn rev(self) -> Self {
+ self
+ }
+
+ fn next(&self) {}
+}
+
+impl DoubleEndedIterator for FakeIter {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.0.next_back()
+ }
+}
+
+impl Iterator for FakeIter {
+ type Item = i32;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next()
+ }
+}
+
+fn main() {
+ // should not lint
+ FakeIter(0..10).rev().next();
+
+ // should lint
+ let _ = (0..10).rev().next().unwrap();
+ let _ = "something".bytes().rev().next();
+}
diff --git a/src/tools/clippy/tests/ui/manual_next_back.stderr b/src/tools/clippy/tests/ui/manual_next_back.stderr
new file mode 100644
index 000000000..94ccaa9e4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.stderr
@@ -0,0 +1,16 @@
+error: manual backwards iteration
+ --> $DIR/manual_next_back.rs:34:20
+ |
+LL | let _ = (0..10).rev().next().unwrap();
+ | ^^^^^^^^^^^^^ help: use: `.next_back()`
+ |
+ = note: `-D clippy::manual-next-back` implied by `-D warnings`
+
+error: manual backwards iteration
+ --> $DIR/manual_next_back.rs:35:32
+ |
+LL | let _ = "something".bytes().rev().next();
+ | ^^^^^^^^^^^^^ help: use: `.next_back()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_ok_or.fixed b/src/tools/clippy/tests/ui/manual_ok_or.fixed
index fc8511626..d8901dc3b 100644
--- a/src/tools/clippy/tests/ui/manual_ok_or.fixed
+++ b/src/tools/clippy/tests/ui/manual_ok_or.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_ok_or)]
#![allow(clippy::or_fun_call)]
#![allow(clippy::disallowed_names)]
diff --git a/src/tools/clippy/tests/ui/manual_ok_or.rs b/src/tools/clippy/tests/ui/manual_ok_or.rs
index b5303d33f..7188a5213 100644
--- a/src/tools/clippy/tests/ui/manual_ok_or.rs
+++ b/src/tools/clippy/tests/ui/manual_ok_or.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_ok_or)]
#![allow(clippy::or_fun_call)]
#![allow(clippy::disallowed_names)]
diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.fixed b/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
index 1f6df1b0a..f2e44e56f 100644
--- a/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
+++ b/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::manual_rem_euclid)]
#![allow(clippy::let_with_type_underscore)]
diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.rs b/src/tools/clippy/tests/ui/manual_rem_euclid.rs
index b275e8a38..b2329c33a 100644
--- a/src/tools/clippy/tests/ui/manual_rem_euclid.rs
+++ b/src/tools/clippy/tests/ui/manual_rem_euclid.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::manual_rem_euclid)]
#![allow(clippy::let_with_type_underscore)]
diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed
index 8f25fea67..09fb0d758 100644
--- a/src/tools/clippy/tests/ui/manual_retain.fixed
+++ b/src/tools/clippy/tests/ui/manual_retain.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_retain)]
#![allow(unused, clippy::redundant_clone)]
use std::collections::BTreeMap;
@@ -23,8 +23,8 @@ fn main() {
}
fn binary_heap_retain() {
- // NOTE: Do not lint now, because binary_heap_retain is nighyly API.
- // And we need to add a test case for msrv if we update this implmention.
+ // NOTE: Do not lint now, because binary_heap_retain is nightly API.
+ // And we need to add a test case for msrv if we update this implementation.
// https://github.com/rust-lang/rust/issues/71503
let mut heap = BinaryHeap::from([1, 2, 3]);
heap = heap.into_iter().filter(|x| x % 2 == 0).collect();
diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs
index e6b3995a6..7fee4c95c 100644
--- a/src/tools/clippy/tests/ui/manual_retain.rs
+++ b/src/tools/clippy/tests/ui/manual_retain.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_retain)]
#![allow(unused, clippy::redundant_clone)]
use std::collections::BTreeMap;
@@ -23,8 +23,8 @@ fn main() {
}
fn binary_heap_retain() {
- // NOTE: Do not lint now, because binary_heap_retain is nighyly API.
- // And we need to add a test case for msrv if we update this implmention.
+ // NOTE: Do not lint now, because binary_heap_retain is nightly API.
+ // And we need to add a test case for msrv if we update this implementation.
// https://github.com/rust-lang/rust/issues/71503
let mut heap = BinaryHeap::from([1, 2, 3]);
heap = heap.into_iter().filter(|x| x % 2 == 0).collect();
diff --git a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed
index c4f53c446..7dd4521fa 100644
--- a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed
+++ b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_imports)]
diff --git a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs
index cd83cf6e6..463ee0692 100644
--- a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs
+++ b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_imports)]
diff --git a/src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed b/src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed
new file mode 100644
index 000000000..ac85bd8d3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed
@@ -0,0 +1,46 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs
+#![allow(unused)]
+#![warn(clippy::manual_slice_size_calculation)]
+
+extern crate proc_macros;
+
+use core::mem::{align_of, size_of};
+use proc_macros::external;
+
+fn main() {
+ let v_i32 = Vec::<i32>::new();
+ let s_i32 = v_i32.as_slice();
+
+ // True positives:
+ let _ = std::mem::size_of_val(s_i32); // WARNING
+ let _ = std::mem::size_of_val(s_i32); // WARNING
+ let _ = std::mem::size_of_val(s_i32) * 5; // WARNING
+
+ let len = s_i32.len();
+ let size = size_of::<i32>();
+ let _ = std::mem::size_of_val(s_i32); // WARNING
+ let _ = std::mem::size_of_val(s_i32); // WARNING
+ let _ = std::mem::size_of_val(s_i32); // WARNING
+
+ let _ = std::mem::size_of_val(external!(&[1u64][..]));
+
+ // True negatives:
+ let _ = size_of::<i32>() + s_i32.len(); // Ok, not a multiplication
+ let _ = size_of::<i32>() * s_i32.partition_point(|_| true); // Ok, not len()
+ let _ = size_of::<i32>() * v_i32.len(); // Ok, not a slice
+ let _ = align_of::<i32>() * s_i32.len(); // Ok, not size_of()
+ let _ = size_of::<u32>() * s_i32.len(); // Ok, different types
+
+ let _ = external!($s_i32.len() * size_of::<i32>());
+ let _ = external!($s_i32.len()) * size_of::<i32>();
+
+ // False negatives:
+ let _ = 5 * size_of::<i32>() * s_i32.len(); // Ok (MISSED OPPORTUNITY)
+ let _ = size_of::<i32>() * 5 * s_i32.len(); // Ok (MISSED OPPORTUNITY)
+}
+
+const fn _const(s_i32: &[i32]) {
+ // True negative:
+ let _ = s_i32.len() * size_of::<i32>(); // Ok, can't use size_of_val in const
+}
diff --git a/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs b/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs
index 5082f931f..1f824b12b 100644
--- a/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs
+++ b/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs
@@ -1,7 +1,12 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![allow(unused)]
#![warn(clippy::manual_slice_size_calculation)]
+extern crate proc_macros;
+
use core::mem::{align_of, size_of};
+use proc_macros::external;
fn main() {
let v_i32 = Vec::<i32>::new();
@@ -18,6 +23,8 @@ fn main() {
let _ = s_i32.len() * size; // WARNING
let _ = len * size; // WARNING
+ let _ = external!(&[1u64][..]).len() * size_of::<u64>();
+
// True negatives:
let _ = size_of::<i32>() + s_i32.len(); // Ok, not a multiplication
let _ = size_of::<i32>() * s_i32.partition_point(|_| true); // Ok, not len()
@@ -25,6 +32,9 @@ fn main() {
let _ = align_of::<i32>() * s_i32.len(); // Ok, not size_of()
let _ = size_of::<u32>() * s_i32.len(); // Ok, different types
+ let _ = external!($s_i32.len() * size_of::<i32>());
+ let _ = external!($s_i32.len()) * size_of::<i32>();
+
// False negatives:
let _ = 5 * size_of::<i32>() * s_i32.len(); // Ok (MISSED OPPORTUNITY)
let _ = size_of::<i32>() * 5 * s_i32.len(); // Ok (MISSED OPPORTUNITY)
diff --git a/src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr b/src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr
index 4a24fc60a..e09d8057a 100644
--- a/src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr
+++ b/src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr
@@ -1,51 +1,46 @@
error: manual slice size calculation
- --> $DIR/manual_slice_size_calculation.rs:11:13
+ --> $DIR/manual_slice_size_calculation.rs:16:13
|
LL | let _ = s_i32.len() * size_of::<i32>(); // WARNING
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
|
- = help: consider using std::mem::size_of_value instead
= note: `-D clippy::manual-slice-size-calculation` implied by `-D warnings`
error: manual slice size calculation
- --> $DIR/manual_slice_size_calculation.rs:12:13
+ --> $DIR/manual_slice_size_calculation.rs:17:13
|
LL | let _ = size_of::<i32>() * s_i32.len(); // WARNING
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider using std::mem::size_of_value instead
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
error: manual slice size calculation
- --> $DIR/manual_slice_size_calculation.rs:13:13
+ --> $DIR/manual_slice_size_calculation.rs:18:13
|
LL | let _ = size_of::<i32>() * s_i32.len() * 5; // WARNING
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider using std::mem::size_of_value instead
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
error: manual slice size calculation
- --> $DIR/manual_slice_size_calculation.rs:17:13
+ --> $DIR/manual_slice_size_calculation.rs:22:13
|
LL | let _ = len * size_of::<i32>(); // WARNING
- | ^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider using std::mem::size_of_value instead
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
error: manual slice size calculation
- --> $DIR/manual_slice_size_calculation.rs:18:13
+ --> $DIR/manual_slice_size_calculation.rs:23:13
|
LL | let _ = s_i32.len() * size; // WARNING
- | ^^^^^^^^^^^^^^^^^^
- |
- = help: consider using std::mem::size_of_value instead
+ | ^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
error: manual slice size calculation
- --> $DIR/manual_slice_size_calculation.rs:19:13
+ --> $DIR/manual_slice_size_calculation.rs:24:13
|
LL | let _ = len * size; // WARNING
- | ^^^^^^^^^^
+ | ^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
+
+error: manual slice size calculation
+ --> $DIR/manual_slice_size_calculation.rs:26:13
|
- = help: consider using std::mem::size_of_value instead
+LL | let _ = external!(&[1u64][..]).len() * size_of::<u64>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(external!(&[1u64][..]))`
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_split_once.fixed b/src/tools/clippy/tests/ui/manual_split_once.fixed
index 50b02019c..e317c5971 100644
--- a/src/tools/clippy/tests/ui/manual_split_once.fixed
+++ b/src/tools/clippy/tests/ui/manual_split_once.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_split_once)]
#![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)]
diff --git a/src/tools/clippy/tests/ui/manual_split_once.rs b/src/tools/clippy/tests/ui/manual_split_once.rs
index e1e8b71a9..7e2dc22bc 100644
--- a/src/tools/clippy/tests/ui/manual_split_once.rs
+++ b/src/tools/clippy/tests/ui/manual_split_once.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_split_once)]
#![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)]
diff --git a/src/tools/clippy/tests/ui/manual_str_repeat.fixed b/src/tools/clippy/tests/ui/manual_str_repeat.fixed
index 3d56f2a0d..9468c3df9 100644
--- a/src/tools/clippy/tests/ui/manual_str_repeat.fixed
+++ b/src/tools/clippy/tests/ui/manual_str_repeat.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_str_repeat)]
diff --git a/src/tools/clippy/tests/ui/manual_str_repeat.rs b/src/tools/clippy/tests/ui/manual_str_repeat.rs
index e8240a949..baa0a1026 100644
--- a/src/tools/clippy/tests/ui/manual_str_repeat.rs
+++ b/src/tools/clippy/tests/ui/manual_str_repeat.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_str_repeat)]
diff --git a/src/tools/clippy/tests/ui/manual_string_new.fixed b/src/tools/clippy/tests/ui/manual_string_new.fixed
index a376411bf..0d1bab233 100644
--- a/src/tools/clippy/tests/ui/manual_string_new.fixed
+++ b/src/tools/clippy/tests/ui/manual_string_new.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_string_new)]
diff --git a/src/tools/clippy/tests/ui/manual_string_new.rs b/src/tools/clippy/tests/ui/manual_string_new.rs
index 6bfc52fb1..2392ebfc3 100644
--- a/src/tools/clippy/tests/ui/manual_string_new.rs
+++ b/src/tools/clippy/tests/ui/manual_string_new.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_string_new)]
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
index 7d6897821..c17634bff 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![allow(unused_variables, clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
index b937fe6f9..6d49a6949 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![allow(unused_variables, clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/manual_while_let_some.fixed b/src/tools/clippy/tests/ui/manual_while_let_some.fixed
new file mode 100644
index 000000000..8b6109195
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_while_let_some.fixed
@@ -0,0 +1,93 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_while_let_some)]
+
+struct VecInStruct {
+ numbers: Vec<i32>,
+ unrelated: String,
+}
+
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn accept_i32(_: i32) {}
+fn accept_optional_i32(_: Option<i32>) {}
+fn accept_i32_tuple(_: (i32, i32)) {}
+
+fn main() {
+ let mut numbers = vec![1, 2, 3, 4, 5];
+ while let Some(number) = numbers.pop() {
+
+ }
+
+ let mut val = VecInStruct {
+ numbers: vec![1, 2, 3, 4, 5],
+ unrelated: String::new(),
+ };
+ while let Some(number) = val.numbers.pop() {
+
+ }
+
+ while let Some(element) = numbers.pop() {
+ accept_i32(element);
+ }
+
+ while let Some(element) = numbers.pop() {
+ accept_i32(element);
+ }
+
+ // This should not warn. It "conditionally" pops elements.
+ while !numbers.is_empty() {
+ if true {
+ accept_i32(numbers.pop().unwrap());
+ }
+ }
+
+ // This should also not warn. It conditionally pops elements.
+ while !numbers.is_empty() {
+ if false {
+ continue;
+ }
+ accept_i32(numbers.pop().unwrap());
+ }
+
+ // This should not warn. It pops elements, but does not unwrap it.
+ // Might handle the Option in some other arbitrary way.
+ while !numbers.is_empty() {
+ accept_optional_i32(numbers.pop());
+ }
+
+ let unrelated_vec: Vec<String> = Vec::new();
+ // This should not warn. It pops elements from a different vector.
+ while !unrelated_vec.is_empty() {
+ accept_i32(numbers.pop().unwrap());
+ }
+
+ macro_rules! generate_loop {
+ () => {
+ while !numbers.is_empty() {
+ accept_i32(numbers.pop().unwrap());
+ }
+ };
+ }
+ // Do not warn if the loop comes from a macro.
+ generate_loop!();
+
+ // Try other kinds of patterns
+ let mut numbers = vec![(0, 0), (1, 1), (2, 2)];
+ while let Some((a, b)) = numbers.pop() {
+
+ }
+
+ while let Some(element) = numbers.pop() {
+ accept_i32_tuple(element);
+ }
+
+ let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }];
+ while let Some(Foo { a, b }) = results.pop() {
+
+ }
+}
diff --git a/src/tools/clippy/tests/ui/manual_while_let_some.rs b/src/tools/clippy/tests/ui/manual_while_let_some.rs
new file mode 100644
index 000000000..85a0a084a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_while_let_some.rs
@@ -0,0 +1,93 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_while_let_some)]
+
+struct VecInStruct {
+ numbers: Vec<i32>,
+ unrelated: String,
+}
+
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn accept_i32(_: i32) {}
+fn accept_optional_i32(_: Option<i32>) {}
+fn accept_i32_tuple(_: (i32, i32)) {}
+
+fn main() {
+ let mut numbers = vec![1, 2, 3, 4, 5];
+ while !numbers.is_empty() {
+ let number = numbers.pop().unwrap();
+ }
+
+ let mut val = VecInStruct {
+ numbers: vec![1, 2, 3, 4, 5],
+ unrelated: String::new(),
+ };
+ while !val.numbers.is_empty() {
+ let number = val.numbers.pop().unwrap();
+ }
+
+ while !numbers.is_empty() {
+ accept_i32(numbers.pop().unwrap());
+ }
+
+ while !numbers.is_empty() {
+ accept_i32(numbers.pop().expect(""));
+ }
+
+ // This should not warn. It "conditionally" pops elements.
+ while !numbers.is_empty() {
+ if true {
+ accept_i32(numbers.pop().unwrap());
+ }
+ }
+
+ // This should also not warn. It conditionally pops elements.
+ while !numbers.is_empty() {
+ if false {
+ continue;
+ }
+ accept_i32(numbers.pop().unwrap());
+ }
+
+ // This should not warn. It pops elements, but does not unwrap it.
+ // Might handle the Option in some other arbitrary way.
+ while !numbers.is_empty() {
+ accept_optional_i32(numbers.pop());
+ }
+
+ let unrelated_vec: Vec<String> = Vec::new();
+ // This should not warn. It pops elements from a different vector.
+ while !unrelated_vec.is_empty() {
+ accept_i32(numbers.pop().unwrap());
+ }
+
+ macro_rules! generate_loop {
+ () => {
+ while !numbers.is_empty() {
+ accept_i32(numbers.pop().unwrap());
+ }
+ };
+ }
+ // Do not warn if the loop comes from a macro.
+ generate_loop!();
+
+ // Try other kinds of patterns
+ let mut numbers = vec![(0, 0), (1, 1), (2, 2)];
+ while !numbers.is_empty() {
+ let (a, b) = numbers.pop().unwrap();
+ }
+
+ while !numbers.is_empty() {
+ accept_i32_tuple(numbers.pop().unwrap());
+ }
+
+ let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }];
+ while !results.is_empty() {
+ let Foo { a, b } = results.pop().unwrap();
+ }
+}
diff --git a/src/tools/clippy/tests/ui/manual_while_let_some.stderr b/src/tools/clippy/tests/ui/manual_while_let_some.stderr
new file mode 100644
index 000000000..633fe05c4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_while_let_some.stderr
@@ -0,0 +1,87 @@
+error: you seem to be trying to pop elements from a `Vec` in a loop
+ --> $DIR/manual_while_let_some.rs:23:9
+ |
+LL | let number = numbers.pop().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::manual-while-let-some` implied by `-D warnings`
+help: consider using a `while..let` loop
+ |
+LL ~ while let Some(number) = numbers.pop() {
+LL ~
+ |
+
+error: you seem to be trying to pop elements from a `Vec` in a loop
+ --> $DIR/manual_while_let_some.rs:31:9
+ |
+LL | let number = val.numbers.pop().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider using a `while..let` loop
+ |
+LL ~ while let Some(number) = val.numbers.pop() {
+LL ~
+ |
+
+error: you seem to be trying to pop elements from a `Vec` in a loop
+ --> $DIR/manual_while_let_some.rs:35:20
+ |
+LL | accept_i32(numbers.pop().unwrap());
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider using a `while..let` loop
+ |
+LL ~ while let Some(element) = numbers.pop() {
+LL ~ accept_i32(element);
+ |
+
+error: you seem to be trying to pop elements from a `Vec` in a loop
+ --> $DIR/manual_while_let_some.rs:39:20
+ |
+LL | accept_i32(numbers.pop().expect(""));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider using a `while..let` loop
+ |
+LL ~ while let Some(element) = numbers.pop() {
+LL ~ accept_i32(element);
+ |
+
+error: you seem to be trying to pop elements from a `Vec` in a loop
+ --> $DIR/manual_while_let_some.rs:82:9
+ |
+LL | let (a, b) = numbers.pop().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider using a `while..let` loop
+ |
+LL ~ while let Some((a, b)) = numbers.pop() {
+LL ~
+ |
+
+error: you seem to be trying to pop elements from a `Vec` in a loop
+ --> $DIR/manual_while_let_some.rs:86:26
+ |
+LL | accept_i32_tuple(numbers.pop().unwrap());
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider using a `while..let` loop
+ |
+LL ~ while let Some(element) = numbers.pop() {
+LL ~ accept_i32_tuple(element);
+ |
+
+error: you seem to be trying to pop elements from a `Vec` in a loop
+ --> $DIR/manual_while_let_some.rs:91:9
+ |
+LL | let Foo { a, b } = results.pop().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider using a `while..let` loop
+ |
+LL ~ while let Some(Foo { a, b }) = results.pop() {
+LL ~
+ |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/map_clone.fixed b/src/tools/clippy/tests/ui/map_clone.fixed
index 0860dcf8e..d7474f357 100644
--- a/src/tools/clippy/tests/ui/map_clone.fixed
+++ b/src/tools/clippy/tests/ui/map_clone.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::map_clone)]
#![allow(
clippy::clone_on_copy,
diff --git a/src/tools/clippy/tests/ui/map_clone.rs b/src/tools/clippy/tests/ui/map_clone.rs
index b69873368..74978ae80 100644
--- a/src/tools/clippy/tests/ui/map_clone.rs
+++ b/src/tools/clippy/tests/ui/map_clone.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::map_clone)]
#![allow(
clippy::clone_on_copy,
diff --git a/src/tools/clippy/tests/ui/map_collect_result_unit.fixed b/src/tools/clippy/tests/ui/map_collect_result_unit.fixed
index e66c9cc24..b00c2cf28 100644
--- a/src/tools/clippy/tests/ui/map_collect_result_unit.fixed
+++ b/src/tools/clippy/tests/ui/map_collect_result_unit.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::map_collect_result_unit)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/map_collect_result_unit.rs b/src/tools/clippy/tests/ui/map_collect_result_unit.rs
index 6f08f4c3c..ad2198ec1 100644
--- a/src/tools/clippy/tests/ui/map_collect_result_unit.rs
+++ b/src/tools/clippy/tests/ui/map_collect_result_unit.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::map_collect_result_unit)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
index 8e2f11389..14816de1a 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::let_underscore_untyped)]
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.rs b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
index a783a99c4..f38a00a59 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.rs
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::let_underscore_untyped)]
diff --git a/src/tools/clippy/tests/ui/map_identity.fixed b/src/tools/clippy/tests/ui/map_identity.fixed
index 2256e51f2..7fb7d8c12 100644
--- a/src/tools/clippy/tests/ui/map_identity.fixed
+++ b/src/tools/clippy/tests/ui/map_identity.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::map_identity)]
#![allow(clippy::needless_return)]
diff --git a/src/tools/clippy/tests/ui/map_identity.rs b/src/tools/clippy/tests/ui/map_identity.rs
index ccfdc9ea7..7891c2426 100644
--- a/src/tools/clippy/tests/ui/map_identity.rs
+++ b/src/tools/clippy/tests/ui/map_identity.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::map_identity)]
#![allow(clippy::needless_return)]
diff --git a/src/tools/clippy/tests/ui/map_unwrap_or.rs b/src/tools/clippy/tests/ui/map_unwrap_or.rs
index 32631024c..cb25d8567 100644
--- a/src/tools/clippy/tests/ui/map_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/map_unwrap_or.rs
@@ -1,4 +1,4 @@
-// aux-build:option_helpers.rs
+//@aux-build:option_helpers.rs
#![warn(clippy::map_unwrap_or)]
#![allow(clippy::uninlined_format_args, clippy::unnecessary_lazy_evaluations)]
diff --git a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed
index bd5b4f716..ea5b6a669 100644
--- a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed
+++ b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:option_helpers.rs
+//@run-rustfix
+//@aux-build:option_helpers.rs
#![warn(clippy::map_unwrap_or)]
diff --git a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs
index 0b892caf2..f8bb9d8ca 100644
--- a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs
+++ b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:option_helpers.rs
+//@run-rustfix
+//@aux-build:option_helpers.rs
#![warn(clippy::map_unwrap_or)]
diff --git a/src/tools/clippy/tests/ui/match_as_ref.fixed b/src/tools/clippy/tests/ui/match_as_ref.fixed
index ddfa1e741..8fa3f5325 100644
--- a/src/tools/clippy/tests/ui/match_as_ref.fixed
+++ b/src/tools/clippy/tests/ui/match_as_ref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::match_as_ref)]
diff --git a/src/tools/clippy/tests/ui/match_as_ref.rs b/src/tools/clippy/tests/ui/match_as_ref.rs
index 025d475ae..02a177914 100644
--- a/src/tools/clippy/tests/ui/match_as_ref.rs
+++ b/src/tools/clippy/tests/ui/match_as_ref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::match_as_ref)]
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
index 55cd15bd5..60f590661 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_like_matches_macro)]
#![allow(
@@ -15,7 +15,7 @@ fn main() {
let _y = matches!(x, Some(0));
// Lint
- let _w = matches!(x, Some(_));
+ let _w = x.is_some();
// Turn into is_none
let _z = x.is_none();
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
index 5d645e108..afdf1069f 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_like_matches_macro)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
index 46f67ef49..b72fe10b7 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
@@ -10,7 +10,7 @@ LL | | };
|
= note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
-error: match expression looks like `matches!` macro
+error: redundant pattern matching, consider using `is_some()`
--> $DIR/match_expr_like_matches_macro.rs:21:14
|
LL | let _w = match x {
@@ -18,7 +18,9 @@ LL | let _w = match x {
LL | | Some(_) => true,
LL | | _ => false,
LL | | };
- | |_____^ help: try this: `matches!(x, Some(_))`
+ | |_____^ help: try this: `x.is_some()`
+ |
+ = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_none()`
--> $DIR/match_expr_like_matches_macro.rs:27:14
@@ -29,8 +31,6 @@ LL | | Some(_) => false,
LL | | None => true,
LL | | };
| |_____^ help: try this: `x.is_none()`
- |
- = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:33:15
diff --git a/src/tools/clippy/tests/ui/match_ref_pats.fixed b/src/tools/clippy/tests/ui/match_ref_pats.fixed
index cf37fc6dc..50c3dcc1e 100644
--- a/src/tools/clippy/tests/ui/match_ref_pats.fixed
+++ b/src/tools/clippy/tests/ui/match_ref_pats.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_ref_pats)]
#![allow(dead_code, unused_variables)]
#![allow(clippy::enum_variant_names, clippy::equatable_if_let, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/match_ref_pats.rs b/src/tools/clippy/tests/ui/match_ref_pats.rs
index 3220b97d1..d29ddacc0 100644
--- a/src/tools/clippy/tests/ui/match_ref_pats.rs
+++ b/src/tools/clippy/tests/ui/match_ref_pats.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_ref_pats)]
#![allow(dead_code, unused_variables)]
#![allow(clippy::enum_variant_names, clippy::equatable_if_let, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/match_result_ok.fixed b/src/tools/clippy/tests/ui/match_result_ok.fixed
index 10ae1ee52..fe67b225f 100644
--- a/src/tools/clippy/tests/ui/match_result_ok.fixed
+++ b/src/tools/clippy/tests/ui/match_result_ok.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_result_ok)]
#![allow(dead_code)]
#![allow(clippy::boxed_local, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/match_result_ok.rs b/src/tools/clippy/tests/ui/match_result_ok.rs
index bc2c4b50e..eac382e1f 100644
--- a/src/tools/clippy/tests/ui/match_result_ok.rs
+++ b/src/tools/clippy/tests/ui/match_result_ok.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_result_ok)]
#![allow(dead_code)]
#![allow(clippy::boxed_local, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/match_same_arms.rs b/src/tools/clippy/tests/ui/match_same_arms.rs
index 0b9342c9c..3914b4546 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms.rs
@@ -53,4 +53,84 @@ mod issue4244 {
}
}
-fn main() {}
+macro_rules! m {
+ (foo) => {};
+ (bar) => {};
+}
+macro_rules! foo {
+ () => {
+ 1
+ };
+}
+macro_rules! bar {
+ () => {
+ 1
+ };
+}
+
+fn main() {
+ let x = 0;
+ let _ = match 0 {
+ 0 => {
+ m!(foo);
+ x
+ },
+ 1 => {
+ m!(bar);
+ x
+ },
+ _ => 1,
+ };
+
+ let _ = match 0 {
+ 0 => {
+ m!(foo);
+ 0
+ },
+ 1 => {
+ m!(bar);
+ 0
+ },
+ _ => 1,
+ };
+
+ let _ = match 0 {
+ 0 => {
+ let mut x = 0;
+ #[cfg(not_enabled)]
+ {
+ x = 5;
+ }
+ #[cfg(not(not_enabled))]
+ {
+ x = 6;
+ }
+ x
+ },
+ 1 => {
+ let mut x = 0;
+ #[cfg(also_not_enabled)]
+ {
+ x = 5;
+ }
+ #[cfg(not(also_not_enabled))]
+ {
+ x = 6;
+ }
+ x
+ },
+ _ => 0,
+ };
+
+ let _ = match 0 {
+ 0 => foo!(),
+ 1 => bar!(),
+ _ => 1,
+ };
+
+ let _ = match 0 {
+ 0 => cfg!(not_enabled),
+ 1 => cfg!(also_not_enabled),
+ _ => false,
+ };
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 82b2c433d..60b2975be 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -239,4 +239,10 @@ fn main() {
3 => core::convert::identity::<u32>(todo!()),
_ => 5,
};
+
+ let _ = match 0 {
+ 0 => cfg!(not_enable),
+ 1 => cfg!(not_enable),
+ _ => false,
+ };
}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index 06cd43000..8fb461bd2 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -192,5 +192,20 @@ note: other arm here
LL | Some(Bar { x: 0, y: 5, .. }) => 1,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 12 previous errors
+error: this match arm has an identical body to another arm
+ --> $DIR/match_same_arms2.rs:245:9
+ |
+LL | 1 => cfg!(not_enable),
+ | -^^^^^^^^^^^^^^^^^^^^
+ | |
+ | help: try merging the arm patterns: `1 | 0`
+ |
+ = help: or try changing either arm body
+note: other arm here
+ --> $DIR/match_same_arms2.rs:244:9
+ |
+LL | 0 => cfg!(not_enable),
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
diff --git a/src/tools/clippy/tests/ui/match_single_binding.fixed b/src/tools/clippy/tests/ui/match_single_binding.fixed
index 201301cc9..7c29bb08e 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.fixed
+++ b/src/tools/clippy/tests/ui/match_single_binding.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_single_binding)]
#![allow(
unused,
diff --git a/src/tools/clippy/tests/ui/match_single_binding.rs b/src/tools/clippy/tests/ui/match_single_binding.rs
index 8b047b19c..c068d5e17 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.rs
+++ b/src/tools/clippy/tests/ui/match_single_binding.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_single_binding)]
#![allow(
unused,
diff --git a/src/tools/clippy/tests/ui/match_single_binding2.fixed b/src/tools/clippy/tests/ui/match_single_binding2.fixed
index e3cf56a42..adfb4ba91 100644
--- a/src/tools/clippy/tests/ui/match_single_binding2.fixed
+++ b/src/tools/clippy/tests/ui/match_single_binding2.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_single_binding)]
#![allow(unused_variables)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/match_single_binding2.rs b/src/tools/clippy/tests/ui/match_single_binding2.rs
index 5a4bb8441..b5cfe3654 100644
--- a/src/tools/clippy/tests/ui/match_single_binding2.rs
+++ b/src/tools/clippy/tests/ui/match_single_binding2.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_single_binding)]
#![allow(unused_variables)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/match_str_case_mismatch.fixed b/src/tools/clippy/tests/ui/match_str_case_mismatch.fixed
index e436bcf49..cd53b1f06 100644
--- a/src/tools/clippy/tests/ui/match_str_case_mismatch.fixed
+++ b/src/tools/clippy/tests/ui/match_str_case_mismatch.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_str_case_mismatch)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/match_str_case_mismatch.rs b/src/tools/clippy/tests/ui/match_str_case_mismatch.rs
index 92e2a000a..688530566 100644
--- a/src/tools/clippy/tests/ui/match_str_case_mismatch.rs
+++ b/src/tools/clippy/tests/ui/match_str_case_mismatch.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_str_case_mismatch)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
index 9fd3739b6..d2e6fef07 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_wildcard_for_single_variants)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
index 9a5c849e6..cff0c8960 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::match_wildcard_for_single_variants)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/mem_forget.rs b/src/tools/clippy/tests/ui/mem_forget.rs
index e5b35c098..edb9d87d0 100644
--- a/src/tools/clippy/tests/ui/mem_forget.rs
+++ b/src/tools/clippy/tests/ui/mem_forget.rs
@@ -5,7 +5,7 @@ use std::mem as memstuff;
use std::mem::forget as forgetSomething;
#[warn(clippy::mem_forget)]
-#[allow(clippy::forget_copy)]
+#[allow(forgetting_copy_types)]
fn main() {
let five: i32 = 5;
forgetSomething(five);
diff --git a/src/tools/clippy/tests/ui/mem_replace.fixed b/src/tools/clippy/tests/ui/mem_replace.fixed
index 7fd340173..d37e97b0a 100644
--- a/src/tools/clippy/tests/ui/mem_replace.fixed
+++ b/src/tools/clippy/tests/ui/mem_replace.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(
diff --git a/src/tools/clippy/tests/ui/mem_replace.rs b/src/tools/clippy/tests/ui/mem_replace.rs
index fa2903add..34e37f3db 100644
--- a/src/tools/clippy/tests/ui/mem_replace.rs
+++ b/src/tools/clippy/tests/ui/mem_replace.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(
diff --git a/src/tools/clippy/tests/ui/mem_replace_macro.rs b/src/tools/clippy/tests/ui/mem_replace_macro.rs
index 3932e7d00..132873858 100644
--- a/src/tools/clippy/tests/ui/mem_replace_macro.rs
+++ b/src/tools/clippy/tests/ui/mem_replace_macro.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![warn(clippy::mem_replace_with_default)]
extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs
index 1519e4da9..e0e2cac30 100644
--- a/src/tools/clippy/tests/ui/methods.rs
+++ b/src/tools/clippy/tests/ui/methods.rs
@@ -1,4 +1,4 @@
-// aux-build:option_helpers.rs
+//@aux-build:option_helpers.rs
#![warn(clippy::all, clippy::pedantic)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/methods_fixable.fixed b/src/tools/clippy/tests/ui/methods_fixable.fixed
index ee7c1b0da..dcbed5a4d 100644
--- a/src/tools/clippy/tests/ui/methods_fixable.fixed
+++ b/src/tools/clippy/tests/ui/methods_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::filter_next)]
diff --git a/src/tools/clippy/tests/ui/methods_fixable.rs b/src/tools/clippy/tests/ui/methods_fixable.rs
index 6d0f1b7bd..3a976d235 100644
--- a/src/tools/clippy/tests/ui/methods_fixable.rs
+++ b/src/tools/clippy/tests/ui/methods_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::filter_next)]
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed b/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed
index f219a570e..f58e9a429 100644
--- a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed
+++ b/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::mismatched_target_os)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs b/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs
index 8a8ae756a..e00224f5c 100644
--- a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs
+++ b/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::mismatched_target_os)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed b/src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed
index 7d9d406d9..330587a3c 100644
--- a/src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed
+++ b/src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::mismatched_target_os)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_unix.rs b/src/tools/clippy/tests/ui/mismatched_target_os_unix.rs
index c1177f1ee..5a90019a2 100644
--- a/src/tools/clippy/tests/ui/mismatched_target_os_unix.rs
+++ b/src/tools/clippy/tests/ui/mismatched_target_os_unix.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::mismatched_target_os)]
#![allow(unused)]
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 e6f88c6e6..5db73a7b8 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
@@ -2,8 +2,8 @@
//! compilation error.
//! The .stderr output of this test should be empty. Otherwise it's a bug somewhere.
-// aux-build:helper.rs
-// aux-build:../../auxiliary/proc_macros.rs
+//@aux-build:helper.rs
+//@aux-build:../../auxiliary/proc_macros.rs
#![warn(clippy::missing_const_for_fn)]
#![feature(start)]
diff --git a/src/tools/clippy/tests/ui/missing_doc.rs b/src/tools/clippy/tests/ui/missing_doc.rs
index 575204894..bf587e774 100644
--- a/src/tools/clippy/tests/ui/missing_doc.rs
+++ b/src/tools/clippy/tests/ui/missing_doc.rs
@@ -1,5 +1,5 @@
-// needs-asm-support
-// aux-build: proc_macros.rs
+//@needs-asm-support
+//@aux-build: proc_macros.rs
#![warn(clippy::missing_docs_in_private_items)]
// When denying at the crate level, be sure to not get random warnings from the
diff --git a/src/tools/clippy/tests/ui/missing_doc_impl.rs b/src/tools/clippy/tests/ui/missing_doc_impl.rs
index e2d49b090..520ddbe16 100644
--- a/src/tools/clippy/tests/ui/missing_doc_impl.rs
+++ b/src/tools/clippy/tests/ui/missing_doc_impl.rs
@@ -1,4 +1,4 @@
-// aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs
#![warn(clippy::missing_docs_in_private_items)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/missing_spin_loop.fixed b/src/tools/clippy/tests/ui/missing_spin_loop.fixed
index aa89e04d2..a15298dc3 100644
--- a/src/tools/clippy/tests/ui/missing_spin_loop.fixed
+++ b/src/tools/clippy/tests/ui/missing_spin_loop.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::missing_spin_loop)]
#![allow(clippy::bool_comparison)]
#![allow(unused_braces)]
diff --git a/src/tools/clippy/tests/ui/missing_spin_loop.rs b/src/tools/clippy/tests/ui/missing_spin_loop.rs
index 88745e477..be74581ec 100644
--- a/src/tools/clippy/tests/ui/missing_spin_loop.rs
+++ b/src/tools/clippy/tests/ui/missing_spin_loop.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::missing_spin_loop)]
#![allow(clippy::bool_comparison)]
#![allow(unused_braces)]
diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed
index bb4b47955..960e5c05f 100644
--- a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed
+++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::missing_spin_loop)]
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs
index a19bc72ba..e532ca62d 100644
--- a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs
+++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::missing_spin_loop)]
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed b/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
index 9a47d7c56..62cfeafdc 100644
--- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
+++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build: proc_macros.rs
+//@run-rustfix
+//@aux-build: proc_macros.rs
#![allow(
dead_code,
diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs b/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
index 04261cba5..f83b7c3db 100644
--- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
+++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build: proc_macros.rs
+//@run-rustfix
+//@aux-build: proc_macros.rs
#![allow(
dead_code,
diff --git a/src/tools/clippy/tests/ui/module_name_repetitions.rs b/src/tools/clippy/tests/ui/module_name_repetitions.rs
index ebaa77cc2..fb2c76123 100644
--- a/src/tools/clippy/tests/ui/module_name_repetitions.rs
+++ b/src/tools/clippy/tests/ui/module_name_repetitions.rs
@@ -1,4 +1,4 @@
-// compile-flags: --test
+//@compile-flags: --test
#![warn(clippy::module_name_repetitions)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
index 9082f1675..4ef6f0ca9 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -1,8 +1,8 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![allow(unused)]
#![allow(deref_nullptr)]
#![allow(clippy::unnecessary_operation)]
-#![allow(clippy::drop_copy)]
+#![allow(dropping_copy_types)]
#![warn(clippy::multiple_unsafe_ops_per_block)]
extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.fixed b/src/tools/clippy/tests/ui/must_use_candidates.fixed
index bbbb3cf62..0c275504d 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.fixed
+++ b/src/tools/clippy/tests/ui/must_use_candidates.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(never_type)]
#![allow(unused_mut, unused_tuple_struct_fields, clippy::redundant_allocation)]
#![warn(clippy::must_use_candidate)]
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.rs b/src/tools/clippy/tests/ui/must_use_candidates.rs
index 94d3c83bd..d1c926773 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.rs
+++ b/src/tools/clippy/tests/ui/must_use_candidates.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(never_type)]
#![allow(unused_mut, unused_tuple_struct_fields, clippy::redundant_allocation)]
#![warn(clippy::must_use_candidate)]
diff --git a/src/tools/clippy/tests/ui/must_use_unit.fixed b/src/tools/clippy/tests/ui/must_use_unit.fixed
index b7d375ff8..4f7cf4e56 100644
--- a/src/tools/clippy/tests/ui/must_use_unit.fixed
+++ b/src/tools/clippy/tests/ui/must_use_unit.fixed
@@ -1,5 +1,5 @@
-//run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::must_use_unit)]
#![allow(clippy::unused_unit)]
diff --git a/src/tools/clippy/tests/ui/must_use_unit.rs b/src/tools/clippy/tests/ui/must_use_unit.rs
index 74d6b4ca8..3a814ce16 100644
--- a/src/tools/clippy/tests/ui/must_use_unit.rs
+++ b/src/tools/clippy/tests/ui/must_use_unit.rs
@@ -1,5 +1,5 @@
-//run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::must_use_unit)]
#![allow(clippy::unused_unit)]
diff --git a/src/tools/clippy/tests/ui/mut_mut.rs b/src/tools/clippy/tests/ui/mut_mut.rs
index 06bb08544..d838098de 100644
--- a/src/tools/clippy/tests/ui/mut_mut.rs
+++ b/src/tools/clippy/tests/ui/mut_mut.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![warn(clippy::mut_mut)]
#![allow(unused)]
#![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)]
diff --git a/src/tools/clippy/tests/ui/mut_mutex_lock.fixed b/src/tools/clippy/tests/ui/mut_mutex_lock.fixed
index ecad10a82..433817a4e 100644
--- a/src/tools/clippy/tests/ui/mut_mutex_lock.fixed
+++ b/src/tools/clippy/tests/ui/mut_mutex_lock.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, unused_mut)]
#![warn(clippy::mut_mutex_lock)]
diff --git a/src/tools/clippy/tests/ui/mut_mutex_lock.rs b/src/tools/clippy/tests/ui/mut_mutex_lock.rs
index f2b1d6fbf..567a0b59e 100644
--- a/src/tools/clippy/tests/ui/mut_mutex_lock.rs
+++ b/src/tools/clippy/tests/ui/mut_mutex_lock.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, unused_mut)]
#![warn(clippy::mut_mutex_lock)]
diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type.fixed b/src/tools/clippy/tests/ui/needless_arbitrary_self_type.fixed
index 9da21eb6b..d7eb1a047 100644
--- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type.fixed
+++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_arbitrary_self_type)]
#![allow(unused_mut, clippy::needless_lifetimes)]
diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type.rs b/src/tools/clippy/tests/ui/needless_arbitrary_self_type.rs
index 17aeaaf97..85a2a957f 100644
--- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type.rs
+++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_arbitrary_self_type)]
#![allow(unused_mut, clippy::needless_lifetimes)]
diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
index 02b43cce2..00871f9f4 100644
--- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
+++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macro_attr.rs
+//@aux-build:proc_macro_attr.rs
#![warn(clippy::needless_arbitrary_self_type)]
diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr
index b2edbfe43..c7df5936d 100644
--- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr
@@ -2,7 +2,7 @@ error: the type of the `self` parameter does not need to be arbitrary
--> $DIR/needless_arbitrary_self_type_unfixable.rs:42:31
|
LL | fn call_with_mut_self(self: &mut Self) {}
- | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'_ mut self`
+ | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self`
|
= note: `-D clippy::needless-arbitrary-self-type` implied by `-D warnings`
diff --git a/src/tools/clippy/tests/ui/needless_bitwise_bool.fixed b/src/tools/clippy/tests/ui/needless_bitwise_bool.fixed
index 5e1ea663a..7543ab72c 100644
--- a/src/tools/clippy/tests/ui/needless_bitwise_bool.fixed
+++ b/src/tools/clippy/tests/ui/needless_bitwise_bool.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_bitwise_bool)]
diff --git a/src/tools/clippy/tests/ui/needless_bitwise_bool.rs b/src/tools/clippy/tests/ui/needless_bitwise_bool.rs
index f3075fba0..2cea701dc 100644
--- a/src/tools/clippy/tests/ui/needless_bitwise_bool.rs
+++ b/src/tools/clippy/tests/ui/needless_bitwise_bool.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_bitwise_bool)]
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
index 89dc13fd5..bf1911881 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_bool)]
#![allow(
@@ -63,6 +63,13 @@ fn main() {
needless_bool2(x);
needless_bool3(x);
needless_bool_condition();
+
+ if a == b {
+ true
+ } else {
+ // Do not lint as this comment might be important
+ false
+ };
}
fn bool_ret3(x: bool) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.rs b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
index c11d9472e..a6c465d4f 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_bool)]
#![allow(
@@ -99,6 +99,13 @@ fn main() {
needless_bool2(x);
needless_bool3(x);
needless_bool_condition();
+
+ if a == b {
+ true
+ } else {
+ // Do not lint as this comment might be important
+ false
+ };
}
fn bool_ret3(x: bool) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
index d2c48376f..fa906374f 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
@@ -91,7 +91,7 @@ LL | | };
| |_____^ help: you can reduce it to: `a < b`
error: this if-then-else expression returns a bool literal
- --> $DIR/fixable.rs:105:5
+ --> $DIR/fixable.rs:112:5
|
LL | / if x {
LL | | return true;
@@ -101,7 +101,7 @@ LL | | };
| |_____^ help: you can reduce it to: `return x`
error: this if-then-else expression returns a bool literal
- --> $DIR/fixable.rs:113:5
+ --> $DIR/fixable.rs:120:5
|
LL | / if x {
LL | | return false;
@@ -111,7 +111,7 @@ LL | | };
| |_____^ help: you can reduce it to: `return !x`
error: this if-then-else expression returns a bool literal
- --> $DIR/fixable.rs:121:5
+ --> $DIR/fixable.rs:128:5
|
LL | / if x && y {
LL | | return true;
@@ -121,7 +121,7 @@ LL | | };
| |_____^ help: you can reduce it to: `return x && y`
error: this if-then-else expression returns a bool literal
- --> $DIR/fixable.rs:129:5
+ --> $DIR/fixable.rs:136:5
|
LL | / if x && y {
LL | | return false;
@@ -131,7 +131,7 @@ LL | | };
| |_____^ help: you can reduce it to: `return !(x && y)`
error: equality checks against true are unnecessary
- --> $DIR/fixable.rs:137:8
+ --> $DIR/fixable.rs:144:8
|
LL | if x == true {};
| ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -139,25 +139,25 @@ LL | if x == true {};
= note: `-D clippy::bool-comparison` implied by `-D warnings`
error: equality checks against false can be replaced by a negation
- --> $DIR/fixable.rs:141:8
+ --> $DIR/fixable.rs:148:8
|
LL | if x == false {};
| ^^^^^^^^^^ help: try simplifying it as shown: `!x`
error: equality checks against true are unnecessary
- --> $DIR/fixable.rs:151:8
+ --> $DIR/fixable.rs:158:8
|
LL | if x == true {};
| ^^^^^^^^^ help: try simplifying it as shown: `x`
error: equality checks against false can be replaced by a negation
- --> $DIR/fixable.rs:152:8
+ --> $DIR/fixable.rs:159:8
|
LL | if x == false {};
| ^^^^^^^^^^ help: try simplifying it as shown: `!x`
error: this if-then-else expression returns a bool literal
- --> $DIR/fixable.rs:161:12
+ --> $DIR/fixable.rs:168:12
|
LL | } else if returns_bool() {
| ____________^
@@ -168,7 +168,7 @@ LL | | };
| |_____^ help: you can reduce it to: `{ !returns_bool() }`
error: this if-then-else expression returns a bool literal
- --> $DIR/fixable.rs:174:5
+ --> $DIR/fixable.rs:181:5
|
LL | / if unsafe { no(4) } & 1 != 0 {
LL | | true
@@ -178,13 +178,13 @@ LL | | };
| |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
error: this if-then-else expression returns a bool literal
- --> $DIR/fixable.rs:179:30
+ --> $DIR/fixable.rs:186:30
|
LL | let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0`
error: this if-then-else expression returns a bool literal
- --> $DIR/fixable.rs:182:9
+ --> $DIR/fixable.rs:189:9
|
LL | if unsafe { no(4) } & 1 != 0 { true } else { false }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
diff --git a/src/tools/clippy/tests/ui/needless_bool_assign.fixed b/src/tools/clippy/tests/ui/needless_bool_assign.fixed
new file mode 100644
index 000000000..3ed31d4d7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_bool_assign.fixed
@@ -0,0 +1,33 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::needless_bool_assign)]
+
+fn random() -> bool {
+ true
+}
+
+fn main() {
+ struct Data {
+ field: bool,
+ };
+ let mut a = Data { field: false };
+ a.field = random() && random();
+ a.field = !(random() && random());
+ // Do not lint…
+ if random() {
+ a.field = false;
+ } else {
+ // …to avoid losing this comment
+ a.field = true
+ }
+ // This one also triggers lint `clippy::if_same_then_else`
+ // which does not suggest a rewrite.
+ random(); a.field = true;
+ let mut b = false;
+ if random() {
+ a.field = false;
+ } else {
+ b = true;
+ }
+}
diff --git a/src/tools/clippy/tests/ui/needless_bool_assign.rs b/src/tools/clippy/tests/ui/needless_bool_assign.rs
new file mode 100644
index 000000000..efaeb67fa
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_bool_assign.rs
@@ -0,0 +1,45 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::needless_bool_assign)]
+
+fn random() -> bool {
+ true
+}
+
+fn main() {
+ struct Data {
+ field: bool,
+ };
+ let mut a = Data { field: false };
+ if random() && random() {
+ a.field = true;
+ } else {
+ a.field = false
+ }
+ if random() && random() {
+ a.field = false;
+ } else {
+ a.field = true
+ }
+ // Do not lint…
+ if random() {
+ a.field = false;
+ } else {
+ // …to avoid losing this comment
+ a.field = true
+ }
+ // This one also triggers lint `clippy::if_same_then_else`
+ // which does not suggest a rewrite.
+ if random() {
+ a.field = true;
+ } else {
+ a.field = true;
+ }
+ let mut b = false;
+ if random() {
+ a.field = false;
+ } else {
+ b = true;
+ }
+}
diff --git a/src/tools/clippy/tests/ui/needless_bool_assign.stderr b/src/tools/clippy/tests/ui/needless_bool_assign.stderr
new file mode 100644
index 000000000..601bbed54
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_bool_assign.stderr
@@ -0,0 +1,53 @@
+error: this if-then-else expression assigns a bool literal
+ --> $DIR/needless_bool_assign.rs:15:5
+ |
+LL | / if random() && random() {
+LL | | a.field = true;
+LL | | } else {
+LL | | a.field = false
+LL | | }
+ | |_____^ help: you can reduce it to: `a.field = random() && random();`
+ |
+ = note: `-D clippy::needless-bool-assign` implied by `-D warnings`
+
+error: this if-then-else expression assigns a bool literal
+ --> $DIR/needless_bool_assign.rs:20:5
+ |
+LL | / if random() && random() {
+LL | | a.field = false;
+LL | | } else {
+LL | | a.field = true
+LL | | }
+ | |_____^ help: you can reduce it to: `a.field = !(random() && random());`
+
+error: this if-then-else expression assigns a bool literal
+ --> $DIR/needless_bool_assign.rs:34:5
+ |
+LL | / if random() {
+LL | | a.field = true;
+LL | | } else {
+LL | | a.field = true;
+LL | | }
+ | |_____^ help: you can reduce it to: `random(); a.field = true;`
+
+error: this `if` has identical blocks
+ --> $DIR/needless_bool_assign.rs:34:17
+ |
+LL | if random() {
+ | _________________^
+LL | | a.field = true;
+LL | | } else {
+ | |_____^
+ |
+note: same as this
+ --> $DIR/needless_bool_assign.rs:36:12
+ |
+LL | } else {
+ | ____________^
+LL | | a.field = true;
+LL | | }
+ | |_____^
+ = note: `#[deny(clippy::if_same_then_else)]` on by default
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed
index 4cb7f6b68..425e6eb62 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrow.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![allow(
unused,
diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs
index 9a01190ed..3f7fa4a9d 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![allow(
unused,
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
index 0c47ceb7b..6663520da 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_borrowed_reference)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
index f883bb0c8..6c8efd2ce 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_borrowed_reference)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed
index 2659ad384..b7e80af50 100644
--- a/src/tools/clippy/tests/ui/needless_collect.fixed
+++ b/src/tools/clippy/tests/ui/needless_collect.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::suspicious_map, clippy::iter_count)]
@@ -62,4 +62,16 @@ fn main() {
let _ = sample.iter().next().is_none();
let _ = sample.iter().any(|x| x == &0);
+
+ #[allow(clippy::double_parens)]
+ {
+ Vec::<u8>::new().extend((0..10));
+ foo((0..10));
+ bar((0..10).collect::<Vec<_>>(), (0..10));
+ baz((0..10), (), ('a'..='z'))
+ }
}
+
+fn foo(_: impl IntoIterator<Item = usize>) {}
+fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
+fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs
index 535ec8298..680b6fa5b 100644
--- a/src/tools/clippy/tests/ui/needless_collect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::suspicious_map, clippy::iter_count)]
@@ -62,4 +62,16 @@ fn main() {
let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
+
+ #[allow(clippy::double_parens)]
+ {
+ Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
+ foo((0..10).collect::<Vec<_>>());
+ bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
+ baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
+ }
}
+
+fn foo(_: impl IntoIterator<Item = usize>) {}
+fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
+fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.stderr b/src/tools/clippy/tests/ui/needless_collect.stderr
index 584d2a1d8..ad22a7b05 100644
--- a/src/tools/clippy/tests/ui/needless_collect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect.stderr
@@ -90,5 +90,29 @@ error: avoid using `collect()` when not needed
LL | let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`
-error: aborting due to 15 previous errors
+error: avoid using `collect()` when not needed
+ --> $DIR/needless_collect.rs:68:40
+ |
+LL | Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
+ | ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+ --> $DIR/needless_collect.rs:69:20
+ |
+LL | foo((0..10).collect::<Vec<_>>());
+ | ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+ --> $DIR/needless_collect.rs:70:49
+ |
+LL | bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
+ | ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+ --> $DIR/needless_collect.rs:71:37
+ |
+LL | baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
+ | ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: aborting due to 19 previous errors
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
index 09e671b88..92572942b 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_for_each)]
#![allow(unused)]
#![allow(
@@ -110,7 +110,7 @@ fn should_not_lint() {
}),
}
- // `for_each` is in a let bingind.
+ // `for_each` is in a let binding.
let _ = v.iter().for_each(|elem| {
acc += elem;
});
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
index abb4045b9..95acbdff8 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_for_each)]
#![allow(unused)]
#![allow(
@@ -110,7 +110,7 @@ fn should_not_lint() {
}),
}
- // `for_each` is in a let bingind.
+ // `for_each` is in a let binding.
let _ = v.iter().for_each(|elem| {
acc += elem;
});
diff --git a/src/tools/clippy/tests/ui/needless_late_init.fixed b/src/tools/clippy/tests/ui/needless_late_init.fixed
index 86d899bb4..92f7b3f77 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.fixed
+++ b/src/tools/clippy/tests/ui/needless_late_init.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![feature(let_chains)]
#![allow(unused)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/needless_late_init.rs b/src/tools/clippy/tests/ui/needless_late_init.rs
index 969afb38e..be378c42f 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.rs
+++ b/src/tools/clippy/tests/ui/needless_late_init.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![feature(let_chains)]
#![allow(unused)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.fixed b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
index e6ead69d1..7b99042f7 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::needless_lifetimes)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index 06eb43050..6fcf1efc2 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::needless_lifetimes)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/needless_match.fixed b/src/tools/clippy/tests/ui/needless_match.fixed
index 7e4740679..d8a0400a4 100644
--- a/src/tools/clippy/tests/ui/needless_match.fixed
+++ b/src/tools/clippy/tests/ui/needless_match.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_match)]
#![allow(clippy::manual_map)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/needless_match.rs b/src/tools/clippy/tests/ui/needless_match.rs
index 809c694bf..3de9bd6d7 100644
--- a/src/tools/clippy/tests/ui/needless_match.rs
+++ b/src/tools/clippy/tests/ui/needless_match.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_match)]
#![allow(clippy::manual_map)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
index acd22c6bb..70015fccf 100644
--- a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::needless_option_as_deref)]
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.rs b/src/tools/clippy/tests/ui/needless_option_as_deref.rs
index 61eda5052..e2e35360c 100644
--- a/src/tools/clippy/tests/ui/needless_option_as_deref.rs
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::needless_option_as_deref)]
diff --git a/src/tools/clippy/tests/ui/needless_option_take.fixed b/src/tools/clippy/tests/ui/needless_option_take.fixed
index 29691e816..bfc6d20d5 100644
--- a/src/tools/clippy/tests/ui/needless_option_take.fixed
+++ b/src/tools/clippy/tests/ui/needless_option_take.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
fn main() {
println!("Testing non erroneous option_take_on_temporary");
diff --git a/src/tools/clippy/tests/ui/needless_option_take.rs b/src/tools/clippy/tests/ui/needless_option_take.rs
index 9f4109eb4..697eeab42 100644
--- a/src/tools/clippy/tests/ui/needless_option_take.rs
+++ b/src/tools/clippy/tests/ui/needless_option_take.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
fn main() {
println!("Testing non erroneous option_take_on_temporary");
diff --git a/src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed b/src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed
index f11330a89..9b98f6ea7 100644
--- a/src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed
+++ b/src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// edition:2018
+//@run-rustfix
+//@edition:2018
#![warn(clippy::needless_parens_on_range_literals)]
#![allow(clippy::almost_complete_range)]
diff --git a/src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs b/src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs
index 671c0009e..088e7b2b9 100644
--- a/src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs
+++ b/src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// edition:2018
+//@run-rustfix
+//@edition:2018
#![warn(clippy::needless_parens_on_range_literals)]
#![allow(clippy::almost_complete_range)]
diff --git a/src/tools/clippy/tests/ui/needless_question_mark.fixed b/src/tools/clippy/tests/ui/needless_question_mark.fixed
index 7eaca5719..679b73d40 100644
--- a/src/tools/clippy/tests/ui/needless_question_mark.fixed
+++ b/src/tools/clippy/tests/ui/needless_question_mark.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_question_mark)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/needless_question_mark.rs b/src/tools/clippy/tests/ui/needless_question_mark.rs
index 960bc7b78..a993d3ec3 100644
--- a/src/tools/clippy/tests/ui/needless_question_mark.rs
+++ b/src/tools/clippy/tests/ui/needless_question_mark.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::needless_question_mark)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 57c08996c..d49ae5d86 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![feature(yeet_expr)]
@@ -231,8 +231,9 @@ fn needless_return_macro() -> String {
}
fn issue_9361() -> i32 {
- #[allow(clippy::integer_arithmetic)]
- return 1 + 2;
+ let n = 1;
+ #[allow(clippy::arithmetic_side_effects)]
+ return n + n;
}
fn issue8336(x: i32) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index 7c1feefbe..367638261 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lint_reasons)]
#![feature(yeet_expr)]
@@ -239,8 +239,9 @@ fn needless_return_macro() -> String {
}
fn issue_9361() -> i32 {
- #[allow(clippy::integer_arithmetic)]
- return 1 + 2;
+ let n = 1;
+ #[allow(clippy::arithmetic_side_effects)]
+ return n + n;
}
fn issue8336(x: i32) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 87d0cd3e1..05f6038cd 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -328,7 +328,7 @@ LL | return format!("Hello {}", "world!");
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:249:9
+ --> $DIR/needless_return.rs:250:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -336,7 +336,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:251:9
+ --> $DIR/needless_return.rs:252:9
|
LL | return false;
| ^^^^^^^^^^^^
@@ -344,7 +344,7 @@ LL | return false;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:258:13
+ --> $DIR/needless_return.rs:259:13
|
LL | return 10;
| ^^^^^^^^^
@@ -352,7 +352,7 @@ LL | return 10;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:261:13
+ --> $DIR/needless_return.rs:262:13
|
LL | return 100;
| ^^^^^^^^^^
@@ -360,7 +360,7 @@ LL | return 100;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:269:9
+ --> $DIR/needless_return.rs:270:9
|
LL | return 0;
| ^^^^^^^^
@@ -368,7 +368,7 @@ LL | return 0;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:276:13
+ --> $DIR/needless_return.rs:277:13
|
LL | return *(x as *const isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -376,7 +376,7 @@ LL | return *(x as *const isize);
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:278:13
+ --> $DIR/needless_return.rs:279:13
|
LL | return !*(x as *const isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -384,7 +384,7 @@ LL | return !*(x as *const isize);
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:285:20
+ --> $DIR/needless_return.rs:286:20
|
LL | let _ = 42;
| ____________________^
@@ -395,7 +395,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:292:20
+ --> $DIR/needless_return.rs:293:20
|
LL | let _ = 42; return;
| ^^^^^^^
@@ -403,7 +403,7 @@ LL | let _ = 42; return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:304:9
+ --> $DIR/needless_return.rs:305:9
|
LL | return Ok(format!("ok!"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -411,7 +411,7 @@ LL | return Ok(format!("ok!"));
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:306:9
+ --> $DIR/needless_return.rs:307:9
|
LL | return Err(format!("err!"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -419,7 +419,7 @@ LL | return Err(format!("err!"));
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:312:9
+ --> $DIR/needless_return.rs:313:9
|
LL | return if true { 1 } else { 2 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -427,7 +427,7 @@ LL | return if true { 1 } else { 2 };
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:316:9
+ --> $DIR/needless_return.rs:317:9
|
LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_splitn.fixed b/src/tools/clippy/tests/ui/needless_splitn.fixed
index 5496031fe..30a038312 100644
--- a/src/tools/clippy/tests/ui/needless_splitn.fixed
+++ b/src/tools/clippy/tests/ui/needless_splitn.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// edition:2018
+//@run-rustfix
+//@edition:2018
#![warn(clippy::needless_splitn)]
#![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::manual_split_once)]
diff --git a/src/tools/clippy/tests/ui/needless_splitn.rs b/src/tools/clippy/tests/ui/needless_splitn.rs
index 35c2465ba..1b0b9a598 100644
--- a/src/tools/clippy/tests/ui/needless_splitn.rs
+++ b/src/tools/clippy/tests/ui/needless_splitn.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// edition:2018
+//@run-rustfix
+//@edition:2018
#![warn(clippy::needless_splitn)]
#![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::manual_split_once)]
diff --git a/src/tools/clippy/tests/ui/neg_multiply.fixed b/src/tools/clippy/tests/ui/neg_multiply.fixed
index 58ab9e856..e07e7c88d 100644
--- a/src/tools/clippy/tests/ui/neg_multiply.fixed
+++ b/src/tools/clippy/tests/ui/neg_multiply.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::neg_multiply)]
#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::precedence)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/neg_multiply.rs b/src/tools/clippy/tests/ui/neg_multiply.rs
index 581290dc7..2887af7b4 100644
--- a/src/tools/clippy/tests/ui/neg_multiply.rs
+++ b/src/tools/clippy/tests/ui/neg_multiply.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::neg_multiply)]
#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::precedence)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
index b32e72111..818119f7b 100644
--- a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
+++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
@@ -25,7 +25,7 @@ fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lin
0
}
-// Must not run on functions that explicitly opt in to Rust ABI with `extern "Rust"`
+// Must not run on functions that explicitly opt in to using the Rust ABI with `extern "Rust"`
#[no_mangle]
#[rustfmt::skip]
extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.fixed b/src/tools/clippy/tests/ui/non_minimal_cfg.fixed
new file mode 100644
index 000000000..430caafb3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.fixed
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![allow(unused)]
+
+#[cfg(windows)]
+fn hermit() {}
+
+#[cfg(windows)]
+fn wasi() {}
+
+#[cfg(all(unix, not(windows)))]
+fn the_end() {}
+
+#[cfg(any())]
+fn any() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.rs b/src/tools/clippy/tests/ui/non_minimal_cfg.rs
new file mode 100644
index 000000000..a38ce1c21
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.rs
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![allow(unused)]
+
+#[cfg(all(windows))]
+fn hermit() {}
+
+#[cfg(any(windows))]
+fn wasi() {}
+
+#[cfg(all(any(unix), all(not(windows))))]
+fn the_end() {}
+
+#[cfg(any())]
+fn any() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg.stderr
new file mode 100644
index 000000000..cdfd728aa
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.stderr
@@ -0,0 +1,28 @@
+error: unneeded sub `cfg` when there is only one condition
+ --> $DIR/non_minimal_cfg.rs:5:7
+ |
+LL | #[cfg(all(windows))]
+ | ^^^^^^^^^^^^ help: try: `windows`
+ |
+ = note: `-D clippy::non-minimal-cfg` implied by `-D warnings`
+
+error: unneeded sub `cfg` when there is only one condition
+ --> $DIR/non_minimal_cfg.rs:8:7
+ |
+LL | #[cfg(any(windows))]
+ | ^^^^^^^^^^^^ help: try: `windows`
+
+error: unneeded sub `cfg` when there is only one condition
+ --> $DIR/non_minimal_cfg.rs:11:11
+ |
+LL | #[cfg(all(any(unix), all(not(windows))))]
+ | ^^^^^^^^^ help: try: `unix`
+
+error: unneeded sub `cfg` when there is only one condition
+ --> $DIR/non_minimal_cfg.rs:11:22
+ |
+LL | #[cfg(all(any(unix), all(not(windows))))]
+ | ^^^^^^^^^^^^^^^^^ help: try: `not(windows)`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.rs b/src/tools/clippy/tests/ui/non_minimal_cfg2.rs
new file mode 100644
index 000000000..a4c6abce3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.rs
@@ -0,0 +1,6 @@
+#![allow(unused)]
+
+#[cfg(all())]
+fn all() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr
new file mode 100644
index 000000000..2a9a36fbc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr
@@ -0,0 +1,10 @@
+error: unneeded sub `cfg` when there is no condition
+ --> $DIR/non_minimal_cfg2.rs:3:7
+ |
+LL | #[cfg(all())]
+ | ^^^^^
+ |
+ = note: `-D clippy::non-minimal-cfg` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
index a9b2dcfb0..89d127528 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
@@ -1,5 +1,5 @@
-// ignore-windows
-// run-rustfix
+//@ignore-windows
+//@run-rustfix
#![warn(clippy::non_octal_unix_permissions)]
use std::fs::{DirBuilder, File, OpenOptions, Permissions};
use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt, PermissionsExt};
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
index 7d2922f49..1b3a322d7 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
@@ -1,5 +1,5 @@
-// ignore-windows
-// run-rustfix
+//@ignore-windows
+//@run-rustfix
#![warn(clippy::non_octal_unix_permissions)]
use std::fs::{DirBuilder, File, OpenOptions, Permissions};
use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt, PermissionsExt};
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
index aad44089d..05802a2c8 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::diverging_sub_expression)]
#![warn(clippy::nonminimal_bool)]
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
index b9074da84..cd5b576fa 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::diverging_sub_expression)]
#![warn(clippy::nonminimal_bool)]
diff --git a/src/tools/clippy/tests/ui/numbered_fields.fixed b/src/tools/clippy/tests/ui/numbered_fields.fixed
index 68c987eb4..a52845e53 100644
--- a/src/tools/clippy/tests/ui/numbered_fields.fixed
+++ b/src/tools/clippy/tests/ui/numbered_fields.fixed
@@ -1,4 +1,4 @@
-//run-rustfix
+//@run-rustfix
#![warn(clippy::init_numbered_fields)]
#![allow(unused_tuple_struct_fields)]
diff --git a/src/tools/clippy/tests/ui/numbered_fields.rs b/src/tools/clippy/tests/ui/numbered_fields.rs
index 2ef4fb4de..ca93f7dce 100644
--- a/src/tools/clippy/tests/ui/numbered_fields.rs
+++ b/src/tools/clippy/tests/ui/numbered_fields.rs
@@ -1,4 +1,4 @@
-//run-rustfix
+//@run-rustfix
#![warn(clippy::init_numbered_fields)]
#![allow(unused_tuple_struct_fields)]
diff --git a/src/tools/clippy/tests/ui/obfuscated_if_else.fixed b/src/tools/clippy/tests/ui/obfuscated_if_else.fixed
index 62d932c2c..9e4f97253 100644
--- a/src/tools/clippy/tests/ui/obfuscated_if_else.fixed
+++ b/src/tools/clippy/tests/ui/obfuscated_if_else.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::obfuscated_if_else)]
diff --git a/src/tools/clippy/tests/ui/obfuscated_if_else.rs b/src/tools/clippy/tests/ui/obfuscated_if_else.rs
index 273be9092..c2351d64c 100644
--- a/src/tools/clippy/tests/ui/obfuscated_if_else.rs
+++ b/src/tools/clippy/tests/ui/obfuscated_if_else.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::obfuscated_if_else)]
diff --git a/src/tools/clippy/tests/ui/octal_escapes.rs b/src/tools/clippy/tests/ui/octal_escapes.rs
index 53145ef0f..61ea96604 100644
--- a/src/tools/clippy/tests/ui/octal_escapes.rs
+++ b/src/tools/clippy/tests/ui/octal_escapes.rs
@@ -17,4 +17,5 @@ fn main() {
let _good3 = "\0\0";
let _good4 = "X\0\0X";
let _good5 = "锈\0锈";
+ let _good6 = "\0\\01";
}
diff --git a/src/tools/clippy/tests/ui/octal_escapes.stderr b/src/tools/clippy/tests/ui/octal_escapes.stderr
index 295dc1798..aa362e963 100644
--- a/src/tools/clippy/tests/ui/octal_escapes.stderr
+++ b/src/tools/clippy/tests/ui/octal_escapes.stderr
@@ -64,6 +64,22 @@ LL | let _bad4 = "/x001234567";
| ~~~~~~~~~~~~~
error: octal-looking escape in string literal
+ --> $DIR/octal_escapes.rs:9:17
+ |
+LL | let _bad5 = "/0/03";
+ | ^^^^^^^
+ |
+ = help: octal escapes are not supported, `/0` is always a null character
+help: if an octal escape was intended, use the hexadecimal representation instead
+ |
+LL | let _bad5 = "/0/x03";
+ | ~~~~~~~~
+help: if the null character is intended, disambiguate using
+ |
+LL | let _bad5 = "/0/x003";
+ | ~~~~~~~~~
+
+error: octal-looking escape in string literal
--> $DIR/octal_escapes.rs:10:17
|
LL | let _bad6 = "Text-/055/077-MoreText";
@@ -127,5 +143,5 @@ help: if the null character is intended, disambiguate using
LL | let _bad9 = "锈/x0011锈";
| ~~~~~~~~~~~~
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.fixed b/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
index d124d133f..e1c0fa3f7 100644
--- a/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
+++ b/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::redundant_clone)]
#![warn(clippy::option_as_ref_deref)]
diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.rs b/src/tools/clippy/tests/ui/option_as_ref_deref.rs
index 86e354c67..6f4917fd1 100644
--- a/src/tools/clippy/tests/ui/option_as_ref_deref.rs
+++ b/src/tools/clippy/tests/ui/option_as_ref_deref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::redundant_clone)]
#![warn(clippy::option_as_ref_deref)]
diff --git a/src/tools/clippy/tests/ui/option_env_unwrap.rs b/src/tools/clippy/tests/ui/option_env_unwrap.rs
index 9a56cf40d..ee1fe3f1f 100644
--- a/src/tools/clippy/tests/ui/option_env_unwrap.rs
+++ b/src/tools/clippy/tests/ui/option_env_unwrap.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![warn(clippy::option_env_unwrap)]
#![allow(clippy::map_flatten)]
diff --git a/src/tools/clippy/tests/ui/option_filter_map.fixed b/src/tools/clippy/tests/ui/option_filter_map.fixed
index b20f73f31..93c250cfa 100644
--- a/src/tools/clippy/tests/ui/option_filter_map.fixed
+++ b/src/tools/clippy/tests/ui/option_filter_map.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::option_filter_map)]
#![allow(clippy::map_flatten)]
diff --git a/src/tools/clippy/tests/ui/option_filter_map.rs b/src/tools/clippy/tests/ui/option_filter_map.rs
index 7abaaa0fb..2c5f03250 100644
--- a/src/tools/clippy/tests/ui/option_filter_map.rs
+++ b/src/tools/clippy/tests/ui/option_filter_map.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::option_filter_map)]
#![allow(clippy::map_flatten)]
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 0456005dc..2b8ce5477 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::option_if_let_else)]
#![allow(
unused_tuple_struct_fields,
@@ -25,7 +25,7 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> {
fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
let _ = string.map_or(0, |s| s.len());
let _ = num.as_ref().map_or(&0, |s| s);
- let _ = num.as_mut().map_or(&mut 0, |s| {
+ let _ = num.as_mut().map_or(&0, |s| {
*s += 1;
s
});
@@ -34,7 +34,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
s += 1;
s
});
- let _ = num.as_mut().map_or(&mut 0, |s| {
+ let _ = num.as_mut().map_or(&0, |s| {
*s += 1;
s
});
@@ -92,12 +92,21 @@ fn pattern_to_vec(pattern: &str) -> Vec<String> {
.collect::<Vec<_>>()
}
+// #10335
+fn test_result_impure_else(variable: Result<u32, &str>) {
+ variable.map_or_else(|_| {
+ println!("Err");
+ }, |binding| {
+ println!("Ok {binding}");
+ })
+}
+
enum DummyEnum {
One(u8),
Two,
}
-// should not warn since there is a compled complex subpat
+// should not warn since there is a complex subpat
// see #7991
fn complex_subpat() -> DummyEnum {
let x = Some(DummyEnum::One(1));
@@ -113,6 +122,7 @@ fn main() {
unop_bad(&None, None);
let _ = longer_body(None);
test_map_or_else(None);
+ test_result_impure_else(Ok(42));
let _ = negative_tests(None);
let _ = impure_else(None);
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 23b148752..cfbec8cb2 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::option_if_let_else)]
#![allow(
unused_tuple_struct_fields,
@@ -33,7 +33,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
*s += 1;
s
} else {
- &mut 0
+ &0
};
let _ = if let Some(ref s) = num { s } else { &0 };
let _ = if let Some(mut s) = num {
@@ -46,7 +46,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
*s += 1;
s
} else {
- &mut 0
+ &0
};
}
@@ -115,12 +115,21 @@ fn pattern_to_vec(pattern: &str) -> Vec<String> {
.collect::<Vec<_>>()
}
+// #10335
+fn test_result_impure_else(variable: Result<u32, &str>) {
+ if let Ok(binding) = variable {
+ println!("Ok {binding}");
+ } else {
+ println!("Err");
+ }
+}
+
enum DummyEnum {
One(u8),
Two,
}
-// should not warn since there is a compled complex subpat
+// should not warn since there is a complex subpat
// see #7991
fn complex_subpat() -> DummyEnum {
let x = Some(DummyEnum::One(1));
@@ -136,6 +145,7 @@ fn main() {
unop_bad(&None, None);
let _ = longer_body(None);
test_map_or_else(None);
+ test_result_impure_else(Ok(42));
let _ = negative_tests(None);
let _ = impure_else(None);
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index a5dbf6e1f..91d52fc79 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -30,13 +30,13 @@ LL | let _ = if let Some(s) = &mut num {
LL | | *s += 1;
LL | | s
LL | | } else {
-LL | | &mut 0
+LL | | &0
LL | | };
| |_____^
|
help: try
|
-LL ~ let _ = num.as_mut().map_or(&mut 0, |s| {
+LL ~ let _ = num.as_mut().map_or(&0, |s| {
LL + *s += 1;
LL + s
LL ~ });
@@ -76,13 +76,13 @@ LL | let _ = if let Some(ref mut s) = num {
LL | | *s += 1;
LL | | s
LL | | } else {
-LL | | &mut 0
+LL | | &0
LL | | };
| |_____^
|
help: try
|
-LL ~ let _ = num.as_mut().map_or(&mut 0, |s| {
+LL ~ let _ = num.as_mut().map_or(&0, |s| {
LL + *s += 1;
LL + s
LL ~ });
@@ -152,14 +152,33 @@ LL | | vec![s.to_string()]
LL | | }
| |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`
+error: use Option::map_or_else instead of an if let/else
+ --> $DIR/option_if_let_else.rs:120:5
+ |
+LL | / if let Ok(binding) = variable {
+LL | | println!("Ok {binding}");
+LL | | } else {
+LL | | println!("Err");
+LL | | }
+ | |_____^
+ |
+help: try
+ |
+LL ~ variable.map_or_else(|_| {
+LL + println!("Err");
+LL + }, |binding| {
+LL + println!("Ok {binding}");
+LL + })
+ |
+
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:133:13
+ --> $DIR/option_if_let_else.rs:142:13
|
LL | let _ = if let Some(x) = optional { x + 2 } else { 5 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:142:13
+ --> $DIR/option_if_let_else.rs:152:13
|
LL | let _ = if let Some(x) = Some(0) {
| _____________^
@@ -181,13 +200,13 @@ LL ~ });
|
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:170:13
+ --> $DIR/option_if_let_else.rs:180:13
|
LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:174:13
+ --> $DIR/option_if_let_else.rs:184:13
|
LL | let _ = if let Some(x) = Some(0) {
| _____________^
@@ -207,7 +226,7 @@ LL ~ });
|
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:213:13
+ --> $DIR/option_if_let_else.rs:223:13
|
LL | let _ = match s {
| _____________^
@@ -217,7 +236,7 @@ LL | | };
| |_____^ help: try: `s.map_or(1, |string| string.len())`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:217:13
+ --> $DIR/option_if_let_else.rs:227:13
|
LL | let _ = match Some(10) {
| _____________^
@@ -227,7 +246,7 @@ LL | | };
| |_____^ help: try: `Some(10).map_or(5, |a| a + 1)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:223:13
+ --> $DIR/option_if_let_else.rs:233:13
|
LL | let _ = match res {
| _____________^
@@ -237,7 +256,7 @@ LL | | };
| |_____^ help: try: `res.map_or(1, |a| a + 1)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:227:13
+ --> $DIR/option_if_let_else.rs:237:13
|
LL | let _ = match res {
| _____________^
@@ -247,10 +266,10 @@ LL | | };
| |_____^ help: try: `res.map_or(1, |a| a + 1)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:231:13
+ --> $DIR/option_if_let_else.rs:241:13
|
LL | let _ = if let Ok(a) = res { a + 1 } else { 5 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
-error: aborting due to 20 previous errors
+error: aborting due to 21 previous errors
diff --git a/src/tools/clippy/tests/ui/option_map_or_none.fixed b/src/tools/clippy/tests/ui/option_map_or_none.fixed
index 04bfac773..501757647 100644
--- a/src/tools/clippy/tests/ui/option_map_or_none.fixed
+++ b/src/tools/clippy/tests/ui/option_map_or_none.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::bind_instead_of_map)]
diff --git a/src/tools/clippy/tests/ui/option_map_or_none.rs b/src/tools/clippy/tests/ui/option_map_or_none.rs
index bb84f8a48..4d8704e73 100644
--- a/src/tools/clippy/tests/ui/option_map_or_none.rs
+++ b/src/tools/clippy/tests/ui/option_map_or_none.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::bind_instead_of_map)]
diff --git a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed
index 00264dcce..8f64451ed 100644
--- a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed
+++ b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::option_map_unit_fn)]
#![allow(unused)]
#![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs
index f3363ebce..2bf7a8e0f 100644
--- a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs
+++ b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::option_map_unit_fn)]
#![allow(unused)]
#![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index be9a65506..f723a55f7 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::or_fun_call)]
#![allow(dead_code)]
#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/or_fun_call.rs b/src/tools/clippy/tests/ui/or_fun_call.rs
index 628c97046..61ef6e27f 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.rs
+++ b/src/tools/clippy/tests/ui/or_fun_call.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::or_fun_call)]
#![allow(dead_code)]
#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/or_then_unwrap.fixed b/src/tools/clippy/tests/ui/or_then_unwrap.fixed
index 844cc4b7a..40badac44 100644
--- a/src/tools/clippy/tests/ui/or_then_unwrap.fixed
+++ b/src/tools/clippy/tests/ui/or_then_unwrap.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::or_then_unwrap)]
#![allow(clippy::map_identity, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/or_then_unwrap.rs b/src/tools/clippy/tests/ui/or_then_unwrap.rs
index 1528ef9be..76c9942fe 100644
--- a/src/tools/clippy/tests/ui/or_then_unwrap.rs
+++ b/src/tools/clippy/tests/ui/or_then_unwrap.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::or_then_unwrap)]
#![allow(clippy::map_identity, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.fixed b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
index 4644ea8f5..2df87a26d 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.fixed
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
@@ -1,5 +1,6 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::partialeq_to_none)]
+#![allow(clippy::eq_op)]
struct Foobar;
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.rs b/src/tools/clippy/tests/ui/partialeq_to_none.rs
index 61011b3a8..df6233b9a 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.rs
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.rs
@@ -1,5 +1,6 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::partialeq_to_none)]
+#![allow(clippy::eq_op)]
struct Foobar;
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.stderr b/src/tools/clippy/tests/ui/partialeq_to_none.stderr
index d06ab7aee..4f84862a2 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.stderr
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.stderr
@@ -1,5 +1,5 @@
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:14:8
+ --> $DIR/partialeq_to_none.rs:15:8
|
LL | if f != None { "yay" } else { "nay" }
| ^^^^^^^^^ help: use `Option::is_some()` instead: `f.is_some()`
@@ -7,55 +7,55 @@ LL | if f != None { "yay" } else { "nay" }
= note: `-D clippy::partialeq-to-none` implied by `-D warnings`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:44:13
+ --> $DIR/partialeq_to_none.rs:45:13
|
LL | let _ = x == None;
| ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:45:13
+ --> $DIR/partialeq_to_none.rs:46:13
|
LL | let _ = x != None;
| ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:46:13
+ --> $DIR/partialeq_to_none.rs:47:13
|
LL | let _ = None == x;
| ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:47:13
+ --> $DIR/partialeq_to_none.rs:48:13
|
LL | let _ = None != x;
| ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:49:8
+ --> $DIR/partialeq_to_none.rs:50:8
|
LL | if foobar() == None {}
| ^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `foobar().is_none()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:51:8
+ --> $DIR/partialeq_to_none.rs:52:8
|
LL | if bar().ok() != None {}
| ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `bar().ok().is_some()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:53:13
+ --> $DIR/partialeq_to_none.rs:54:13
|
LL | let _ = Some(1 + 2) != None;
| ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `Some(1 + 2).is_some()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:55:13
+ --> $DIR/partialeq_to_none.rs:56:13
|
LL | let _ = { Some(0) } == None;
| ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `{ Some(0) }.is_none()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:57:13
+ --> $DIR/partialeq_to_none.rs:58:13
|
LL | let _ = {
| _____________^
@@ -77,31 +77,31 @@ LL ~ }.is_some();
|
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:67:13
+ --> $DIR/partialeq_to_none.rs:68:13
|
LL | let _ = optref() == &&None;
| ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:68:13
+ --> $DIR/partialeq_to_none.rs:69:13
|
LL | let _ = &&None != optref();
| ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:69:13
+ --> $DIR/partialeq_to_none.rs:70:13
|
LL | let _ = **optref() == None;
| ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:70:13
+ --> $DIR/partialeq_to_none.rs:71:13
|
LL | let _ = &None != *optref();
| ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()`
error: binary comparison to literal `Option::None`
- --> $DIR/partialeq_to_none.rs:73:13
+ --> $DIR/partialeq_to_none.rs:74:13
|
LL | let _ = None != *x;
| ^^^^^^^^^^ help: use `Option::is_some()` instead: `(*x).is_some()`
diff --git a/src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed b/src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed
index ef8856830..393fc6e1c 100644
--- a/src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed
+++ b/src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
use std::path::PathBuf;
#[warn(clippy::all, clippy::path_buf_push_overwrite)]
diff --git a/src/tools/clippy/tests/ui/path_buf_push_overwrite.rs b/src/tools/clippy/tests/ui/path_buf_push_overwrite.rs
index 6e2d483f4..18de6e064 100644
--- a/src/tools/clippy/tests/ui/path_buf_push_overwrite.rs
+++ b/src/tools/clippy/tests/ui/path_buf_push_overwrite.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
use std::path::PathBuf;
#[warn(clippy::all, clippy::path_buf_push_overwrite)]
diff --git a/src/tools/clippy/tests/ui/patterns.fixed b/src/tools/clippy/tests/ui/patterns.fixed
index cd6901432..a1da47d84 100644
--- a/src/tools/clippy/tests/ui/patterns.fixed
+++ b/src/tools/clippy/tests/ui/patterns.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![allow(unused)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/patterns.rs b/src/tools/clippy/tests/ui/patterns.rs
index 9128da420..399066b81 100644
--- a/src/tools/clippy/tests/ui/patterns.rs
+++ b/src/tools/clippy/tests/ui/patterns.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![allow(unused)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/precedence.fixed b/src/tools/clippy/tests/ui/precedence.fixed
index 163bd044c..af4d5636b 100644
--- a/src/tools/clippy/tests/ui/precedence.fixed
+++ b/src/tools/clippy/tests/ui/precedence.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::precedence)]
#![allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)]
#![allow(clippy::identity_op)]
diff --git a/src/tools/clippy/tests/ui/precedence.rs b/src/tools/clippy/tests/ui/precedence.rs
index 8c849e320..e23ae9127 100644
--- a/src/tools/clippy/tests/ui/precedence.rs
+++ b/src/tools/clippy/tests/ui/precedence.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::precedence)]
#![allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)]
#![allow(clippy::identity_op)]
diff --git a/src/tools/clippy/tests/ui/print_stdout_build_script.rs b/src/tools/clippy/tests/ui/print_stdout_build_script.rs
index 997ebef8a..91448cb0f 100644
--- a/src/tools/clippy/tests/ui/print_stdout_build_script.rs
+++ b/src/tools/clippy/tests/ui/print_stdout_build_script.rs
@@ -1,4 +1,4 @@
-// compile-flags: --crate-name=build_script_build
+//@compile-flags: --crate-name=build_script_build
#![warn(clippy::print_stdout)]
diff --git a/src/tools/clippy/tests/ui/print_with_newline.rs b/src/tools/clippy/tests/ui/print_with_newline.rs
index b8c29d207..ff79ca75f 100644
--- a/src/tools/clippy/tests/ui/print_with_newline.rs
+++ b/src/tools/clippy/tests/ui/print_with_newline.rs
@@ -1,5 +1,5 @@
// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934
-// // run-rustfix
+//
#![allow(clippy::print_literal)]
#![warn(clippy::print_with_newline)]
diff --git a/src/tools/clippy/tests/ui/println_empty_string.fixed b/src/tools/clippy/tests/ui/println_empty_string.fixed
index 976068092..abf951ae2 100644
--- a/src/tools/clippy/tests/ui/println_empty_string.fixed
+++ b/src/tools/clippy/tests/ui/println_empty_string.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::match_single_binding)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/println_empty_string.rs b/src/tools/clippy/tests/ui/println_empty_string.rs
index 80fdb3e6e..fd86e2543 100644
--- a/src/tools/clippy/tests/ui/println_empty_string.rs
+++ b/src/tools/clippy/tests/ui/println_empty_string.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::match_single_binding)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
index ee7b998a0..2c2567d67 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::ptr_as_ptr)]
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.rs b/src/tools/clippy/tests/ui/ptr_as_ptr.rs
index c88329ce4..6000e5c08 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.rs
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::ptr_as_ptr)]
diff --git a/src/tools/clippy/tests/ui/ptr_eq.fixed b/src/tools/clippy/tests/ui/ptr_eq.fixed
index 209081e6e..d5fa273d4 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.fixed
+++ b/src/tools/clippy/tests/ui/ptr_eq.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::ptr_eq)]
macro_rules! mac {
diff --git a/src/tools/clippy/tests/ui/ptr_eq.rs b/src/tools/clippy/tests/ui/ptr_eq.rs
index 691628708..e033366a4 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.rs
+++ b/src/tools/clippy/tests/ui/ptr_eq.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::ptr_eq)]
macro_rules! mac {
diff --git a/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed b/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
index c57e2990f..f69bc1318 100644
--- a/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
+++ b/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::unnecessary_cast)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs b/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
index 3de7997ac..eae36c277 100644
--- a/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::unnecessary_cast)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 5c49d46da..7f1660f31 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unreachable_code)]
#![allow(dead_code)]
#![allow(clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index d057df6a9..a90eae50e 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unreachable_code)]
#![allow(dead_code)]
#![allow(clippy::unnecessary_wraps)]
diff --git a/src/tools/clippy/tests/ui/range_contains.fixed b/src/tools/clippy/tests/ui/range_contains.fixed
index 4923731fe..0a92ee7c8 100644
--- a/src/tools/clippy/tests/ui/range_contains.fixed
+++ b/src/tools/clippy/tests/ui/range_contains.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_range_contains)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/range_contains.rs b/src/tools/clippy/tests/ui/range_contains.rs
index d623ccb5d..7a83be609 100644
--- a/src/tools/clippy/tests/ui/range_contains.rs
+++ b/src/tools/clippy/tests/ui/range_contains.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::manual_range_contains)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/range_plus_minus_one.fixed b/src/tools/clippy/tests/ui/range_plus_minus_one.fixed
index a16a3e54d..79c133cb5 100644
--- a/src/tools/clippy/tests/ui/range_plus_minus_one.fixed
+++ b/src/tools/clippy/tests/ui/range_plus_minus_one.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_parens)]
#![allow(clippy::iter_with_drain)]
diff --git a/src/tools/clippy/tests/ui/range_plus_minus_one.rs b/src/tools/clippy/tests/ui/range_plus_minus_one.rs
index bd6cb4d21..689a6b7a1 100644
--- a/src/tools/clippy/tests/ui/range_plus_minus_one.rs
+++ b/src/tools/clippy/tests/ui/range_plus_minus_one.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_parens)]
#![allow(clippy::iter_with_drain)]
diff --git a/src/tools/clippy/tests/ui/rc_buffer.fixed b/src/tools/clippy/tests/ui/rc_buffer.fixed
index 8910c01b1..4cba292c1 100644
--- a/src/tools/clippy/tests/ui/rc_buffer.fixed
+++ b/src/tools/clippy/tests/ui/rc_buffer.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::rc_buffer)]
#![allow(dead_code, unused_imports)]
diff --git a/src/tools/clippy/tests/ui/rc_buffer.rs b/src/tools/clippy/tests/ui/rc_buffer.rs
index 1e63a4326..d8a9aa278 100644
--- a/src/tools/clippy/tests/ui/rc_buffer.rs
+++ b/src/tools/clippy/tests/ui/rc_buffer.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::rc_buffer)]
#![allow(dead_code, unused_imports)]
diff --git a/src/tools/clippy/tests/ui/rc_buffer_arc.fixed b/src/tools/clippy/tests/ui/rc_buffer_arc.fixed
index 13dd6f5fc..ac51ac9e4 100644
--- a/src/tools/clippy/tests/ui/rc_buffer_arc.fixed
+++ b/src/tools/clippy/tests/ui/rc_buffer_arc.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::rc_buffer)]
#![allow(dead_code, unused_imports)]
diff --git a/src/tools/clippy/tests/ui/rc_buffer_arc.rs b/src/tools/clippy/tests/ui/rc_buffer_arc.rs
index 1a521bfeb..21dc27bc5 100644
--- a/src/tools/clippy/tests/ui/rc_buffer_arc.rs
+++ b/src/tools/clippy/tests/ui/rc_buffer_arc.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::rc_buffer)]
#![allow(dead_code, unused_imports)]
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed b/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed
index 6db02718c..edb7715f4 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed
+++ b/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
#![allow(clippy::disallowed_names, unused_variables, dead_code)]
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs b/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs
index c15806f30..c59422dd9 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs
+++ b/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
#![allow(clippy::disallowed_names, unused_variables, dead_code)]
diff --git a/src/tools/clippy/tests/ui/redundant_async_block.fixed b/src/tools/clippy/tests/ui/redundant_async_block.fixed
index ad96993c4..328958491 100644
--- a/src/tools/clippy/tests/ui/redundant_async_block.fixed
+++ b/src/tools/clippy/tests/ui/redundant_async_block.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::manual_async_fn)]
#![warn(clippy::redundant_async_block)]
diff --git a/src/tools/clippy/tests/ui/redundant_async_block.rs b/src/tools/clippy/tests/ui/redundant_async_block.rs
index 7ae235583..cd189b315 100644
--- a/src/tools/clippy/tests/ui/redundant_async_block.rs
+++ b/src/tools/clippy/tests/ui/redundant_async_block.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::manual_async_fn)]
#![warn(clippy::redundant_async_block)]
diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed
index 00b427450..cb9583aa6 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.fixed
+++ b/src/tools/clippy/tests/ui/redundant_clone.fixed
@@ -1,6 +1,7 @@
-// run-rustfix
+//@run-rustfix
// rustfix-only-machine-applicable
#![feature(lint_reasons)]
+#![warn(clippy::redundant_clone)]
#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)]
use std::ffi::OsString;
diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs
index f899127db..e5aeacbb5 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.rs
+++ b/src/tools/clippy/tests/ui/redundant_clone.rs
@@ -1,6 +1,7 @@
-// run-rustfix
+//@run-rustfix
// rustfix-only-machine-applicable
#![feature(lint_reasons)]
+#![warn(clippy::redundant_clone)]
#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)]
use std::ffi::OsString;
diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr
index 782590034..bb5c602d6 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.stderr
+++ b/src/tools/clippy/tests/ui/redundant_clone.stderr
@@ -1,180 +1,180 @@
error: redundant clone
- --> $DIR/redundant_clone.rs:10:42
+ --> $DIR/redundant_clone.rs:11:42
|
LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
| ^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:10:14
+ --> $DIR/redundant_clone.rs:11:14
|
LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::redundant-clone` implied by `-D warnings`
error: redundant clone
- --> $DIR/redundant_clone.rs:13:15
+ --> $DIR/redundant_clone.rs:14:15
|
LL | let _s = s.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:13:14
+ --> $DIR/redundant_clone.rs:14:14
|
LL | let _s = s.clone();
| ^
error: redundant clone
- --> $DIR/redundant_clone.rs:16:15
+ --> $DIR/redundant_clone.rs:17:15
|
LL | let _s = s.to_string();
| ^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:16:14
+ --> $DIR/redundant_clone.rs:17:14
|
LL | let _s = s.to_string();
| ^
error: redundant clone
- --> $DIR/redundant_clone.rs:19:15
+ --> $DIR/redundant_clone.rs:20:15
|
LL | let _s = s.to_owned();
| ^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:19:14
+ --> $DIR/redundant_clone.rs:20:14
|
LL | let _s = s.to_owned();
| ^
error: redundant clone
- --> $DIR/redundant_clone.rs:21:42
+ --> $DIR/redundant_clone.rs:22:42
|
LL | let _s = Path::new("/a/b/").join("c").to_owned();
| ^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:21:14
+ --> $DIR/redundant_clone.rs:22:14
|
LL | let _s = Path::new("/a/b/").join("c").to_owned();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: redundant clone
- --> $DIR/redundant_clone.rs:23:42
+ --> $DIR/redundant_clone.rs:24:42
|
LL | let _s = Path::new("/a/b/").join("c").to_path_buf();
| ^^^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:23:14
+ --> $DIR/redundant_clone.rs:24:14
|
LL | let _s = Path::new("/a/b/").join("c").to_path_buf();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: redundant clone
- --> $DIR/redundant_clone.rs:25:29
+ --> $DIR/redundant_clone.rs:26:29
|
LL | let _s = OsString::new().to_owned();
| ^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:25:14
+ --> $DIR/redundant_clone.rs:26:14
|
LL | let _s = OsString::new().to_owned();
| ^^^^^^^^^^^^^^^
error: redundant clone
- --> $DIR/redundant_clone.rs:27:29
+ --> $DIR/redundant_clone.rs:28:29
|
LL | let _s = OsString::new().to_os_string();
| ^^^^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:27:14
+ --> $DIR/redundant_clone.rs:28:14
|
LL | let _s = OsString::new().to_os_string();
| ^^^^^^^^^^^^^^^
error: redundant clone
- --> $DIR/redundant_clone.rs:38:19
+ --> $DIR/redundant_clone.rs:39:19
|
LL | let _t = tup.0.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:38:14
+ --> $DIR/redundant_clone.rs:39:14
|
LL | let _t = tup.0.clone();
| ^^^^^
error: redundant clone
- --> $DIR/redundant_clone.rs:70:25
+ --> $DIR/redundant_clone.rs:71:25
|
LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) }
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:70:24
+ --> $DIR/redundant_clone.rs:71:24
|
LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) }
| ^
error: redundant clone
- --> $DIR/redundant_clone.rs:127:15
+ --> $DIR/redundant_clone.rs:128:15
|
LL | let _s = s.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:127:14
+ --> $DIR/redundant_clone.rs:128:14
|
LL | let _s = s.clone();
| ^
error: redundant clone
- --> $DIR/redundant_clone.rs:128:15
+ --> $DIR/redundant_clone.rs:129:15
|
LL | let _t = t.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:128:14
+ --> $DIR/redundant_clone.rs:129:14
|
LL | let _t = t.clone();
| ^
error: redundant clone
- --> $DIR/redundant_clone.rs:138:19
+ --> $DIR/redundant_clone.rs:139:19
|
LL | let _f = f.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:138:18
+ --> $DIR/redundant_clone.rs:139:18
|
LL | let _f = f.clone();
| ^
error: redundant clone
- --> $DIR/redundant_clone.rs:150:14
+ --> $DIR/redundant_clone.rs:151:14
|
LL | let y = x.clone().join("matthias");
| ^^^^^^^^ help: remove this
|
note: cloned value is neither consumed nor mutated
- --> $DIR/redundant_clone.rs:150:13
+ --> $DIR/redundant_clone.rs:151:13
|
LL | let y = x.clone().join("matthias");
| ^^^^^^^^^
error: redundant clone
- --> $DIR/redundant_clone.rs:204:11
+ --> $DIR/redundant_clone.rs:205:11
|
LL | foo(&x.clone(), move || {
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
- --> $DIR/redundant_clone.rs:204:10
+ --> $DIR/redundant_clone.rs:205:10
|
LL | foo(&x.clone(), move || {
| ^
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
index b987fd2ce..61aed2733 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(async_closure)]
#![warn(clippy::redundant_closure_call)]
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
index 633a2979d..56b286635 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(async_closure)]
#![warn(clippy::redundant_closure_call)]
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.fixed b/src/tools/clippy/tests/ui/redundant_field_names.fixed
index 276266a2d..d2a65399d 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.fixed
+++ b/src/tools/clippy/tests/ui/redundant_field_names.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::redundant_field_names)]
#![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)]
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.rs b/src/tools/clippy/tests/ui/redundant_field_names.rs
index f674141c1..605ffd21e 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.rs
+++ b/src/tools/clippy/tests/ui/redundant_field_names.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::redundant_field_names)]
#![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)]
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed
index ce3229f17..bebdf8971 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
// Issue #5746
#![warn(clippy::redundant_pattern_matching)]
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs
index 29b8543cf..8fb6ed5f7 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
// Issue #5746
#![warn(clippy::redundant_pattern_matching)]
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
index 21bae9095..a9faf12cd 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all, clippy::redundant_pattern_matching)]
#![allow(unused_must_use)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
index 4dd917167..574671d03 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all, clippy::redundant_pattern_matching)]
#![allow(unused_must_use)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
index a89845c1d..accdf1da9 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
@@ -46,6 +46,7 @@ fn main() {
let _ = if opt.is_some() { true } else { false };
issue6067();
+ issue10726();
let _ = if gen_opt().is_some() {
1
@@ -54,6 +55,8 @@ fn main() {
} else {
3
};
+
+ if gen_opt().is_some() {}
}
fn gen_opt() -> Option<()> {
@@ -86,3 +89,21 @@ fn issue7921() {
if (&None::<()>).is_none() {}
if (&None::<()>).is_none() {}
}
+
+fn issue10726() {
+ let x = Some(42);
+
+ x.is_some();
+
+ x.is_none();
+
+ x.is_none();
+
+ x.is_some();
+
+ // Don't lint
+ match x {
+ Some(21) => true,
+ _ => false,
+ };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
index d6f444034..ec684bdf7 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
@@ -55,6 +55,7 @@ fn main() {
let _ = if let Some(_) = opt { true } else { false };
issue6067();
+ issue10726();
let _ = if let Some(_) = gen_opt() {
1
@@ -63,6 +64,8 @@ fn main() {
} else {
3
};
+
+ if let Some(..) = gen_opt() {}
}
fn gen_opt() -> Option<()> {
@@ -101,3 +104,33 @@ fn issue7921() {
if let None = *(&None::<()>) {}
if let None = *&None::<()> {}
}
+
+fn issue10726() {
+ let x = Some(42);
+
+ match x {
+ Some(_) => true,
+ _ => false,
+ };
+
+ match x {
+ None => true,
+ _ => false,
+ };
+
+ match x {
+ Some(_) => false,
+ _ => true,
+ };
+
+ match x {
+ None => false,
+ _ => true,
+ };
+
+ // Don't lint
+ match x {
+ Some(21) => true,
+ _ => false,
+ };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
index 27ff812ba..a69eb3905 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
@@ -77,43 +77,49 @@ LL | let _ = if let Some(_) = opt { true } else { false };
| -------^^^^^^^------ help: try this: `if opt.is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:59:20
+ --> $DIR/redundant_pattern_matching_option.rs:60:20
|
LL | let _ = if let Some(_) = gen_opt() {
| -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:61:19
+ --> $DIR/redundant_pattern_matching_option.rs:62:19
|
LL | } else if let None = gen_opt() {
| -------^^^^------------ help: try this: `if gen_opt().is_none()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:80:12
+ --> $DIR/redundant_pattern_matching_option.rs:68:12
+ |
+LL | if let Some(..) = gen_opt() {}
+ | -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()`
+
+error: redundant pattern matching, consider using `is_some()`
+ --> $DIR/redundant_pattern_matching_option.rs:83:12
|
LL | if let Some(_) = Some(42) {}
| -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:82:12
+ --> $DIR/redundant_pattern_matching_option.rs:85:12
|
LL | if let None = None::<()> {}
| -------^^^^------------- help: try this: `if None::<()>.is_none()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:84:15
+ --> $DIR/redundant_pattern_matching_option.rs:87:15
|
LL | while let Some(_) = Some(42) {}
| ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:86:15
+ --> $DIR/redundant_pattern_matching_option.rs:89:15
|
LL | while let None = None::<()> {}
| ----------^^^^------------- help: try this: `while None::<()>.is_none()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:88:5
+ --> $DIR/redundant_pattern_matching_option.rs:91:5
|
LL | / match Some(42) {
LL | | Some(_) => true,
@@ -122,7 +128,7 @@ LL | | };
| |_____^ help: try this: `Some(42).is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:93:5
+ --> $DIR/redundant_pattern_matching_option.rs:96:5
|
LL | / match None::<()> {
LL | | Some(_) => false,
@@ -131,16 +137,52 @@ LL | | };
| |_____^ help: try this: `None::<()>.is_none()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:101:12
+ --> $DIR/redundant_pattern_matching_option.rs:104:12
|
LL | if let None = *(&None::<()>) {}
| -------^^^^----------------- help: try this: `if (&None::<()>).is_none()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:102:12
+ --> $DIR/redundant_pattern_matching_option.rs:105:12
|
LL | if let None = *&None::<()> {}
| -------^^^^--------------- help: try this: `if (&None::<()>).is_none()`
-error: aborting due to 21 previous errors
+error: redundant pattern matching, consider using `is_some()`
+ --> $DIR/redundant_pattern_matching_option.rs:111:5
+ |
+LL | / match x {
+LL | | Some(_) => true,
+LL | | _ => false,
+LL | | };
+ | |_____^ help: try this: `x.is_some()`
+
+error: redundant pattern matching, consider using `is_none()`
+ --> $DIR/redundant_pattern_matching_option.rs:116:5
+ |
+LL | / match x {
+LL | | None => true,
+LL | | _ => false,
+LL | | };
+ | |_____^ help: try this: `x.is_none()`
+
+error: redundant pattern matching, consider using `is_none()`
+ --> $DIR/redundant_pattern_matching_option.rs:121:5
+ |
+LL | / match x {
+LL | | Some(_) => false,
+LL | | _ => true,
+LL | | };
+ | |_____^ help: try this: `x.is_none()`
+
+error: redundant pattern matching, consider using `is_some()`
+ --> $DIR/redundant_pattern_matching_option.rs:126:5
+ |
+LL | / match x {
+LL | | None => false,
+LL | | _ => true,
+LL | | };
+ | |_____^ help: try this: `x.is_some()`
+
+error: aborting due to 26 previous errors
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
index 3645f2c4b..bf3e69220 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
index 866c71b7c..892a21d9d 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
index 42348df44..e4032ae44 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
#![allow(deprecated, unused_must_use)]
@@ -43,6 +43,7 @@ fn main() {
issue5504();
issue6067();
issue6065();
+ issue10726();
let _ = if gen_res().is_ok() {
1
@@ -107,3 +108,28 @@ const fn issue6067() {
Err::<i32, i32>(42).is_err();
}
+
+fn issue10726() {
+ // This is optional, but it makes the examples easier
+ let x: Result<i32, i32> = Ok(42);
+
+ x.is_ok();
+
+ x.is_err();
+
+ x.is_err();
+
+ x.is_ok();
+
+ // Don't lint
+ match x {
+ Err(16) => false,
+ _ => true,
+ };
+
+ // Don't lint
+ match x {
+ Ok(16) => false,
+ _ => true,
+ };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
index 5949cb227..39eb10df8 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
#![allow(deprecated, unused_must_use)]
@@ -55,6 +55,7 @@ fn main() {
issue5504();
issue6067();
issue6065();
+ issue10726();
let _ = if let Ok(_) = gen_res() {
1
@@ -125,3 +126,40 @@ const fn issue6067() {
Err(_) => true,
};
}
+
+fn issue10726() {
+ // This is optional, but it makes the examples easier
+ let x: Result<i32, i32> = Ok(42);
+
+ match x {
+ Ok(_) => true,
+ _ => false,
+ };
+
+ match x {
+ Ok(_) => false,
+ _ => true,
+ };
+
+ match x {
+ Err(_) => true,
+ _ => false,
+ };
+
+ match x {
+ Err(_) => false,
+ _ => true,
+ };
+
+ // Don't lint
+ match x {
+ Err(16) => false,
+ _ => true,
+ };
+
+ // Don't lint
+ match x {
+ Ok(16) => false,
+ _ => true,
+ };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
index d6a46babb..5893ae4dc 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
@@ -73,67 +73,67 @@ LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
| -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:59:20
+ --> $DIR/redundant_pattern_matching_result.rs:60:20
|
LL | let _ = if let Ok(_) = gen_res() {
| -------^^^^^------------ help: try this: `if gen_res().is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:61:19
+ --> $DIR/redundant_pattern_matching_result.rs:62:19
|
LL | } else if let Err(_) = gen_res() {
| -------^^^^^^------------ help: try this: `if gen_res().is_err()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:84:19
+ --> $DIR/redundant_pattern_matching_result.rs:85:19
|
LL | while let Some(_) = r#try!(result_opt()) {}
| ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:85:16
+ --> $DIR/redundant_pattern_matching_result.rs:86:16
|
LL | if let Some(_) = r#try!(result_opt()) {}
| -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:91:12
+ --> $DIR/redundant_pattern_matching_result.rs:92:12
|
LL | if let Some(_) = m!() {}
| -------^^^^^^^------- help: try this: `if m!().is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:92:15
+ --> $DIR/redundant_pattern_matching_result.rs:93:15
|
LL | while let Some(_) = m!() {}
| ----------^^^^^^^------- help: try this: `while m!().is_some()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:110:12
+ --> $DIR/redundant_pattern_matching_result.rs:111:12
|
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:112:12
+ --> $DIR/redundant_pattern_matching_result.rs:113:12
|
LL | if let Err(_) = Err::<i32, i32>(42) {}
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:114:15
+ --> $DIR/redundant_pattern_matching_result.rs:115:15
|
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:116:15
+ --> $DIR/redundant_pattern_matching_result.rs:117:15
|
LL | while let Err(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:118:5
+ --> $DIR/redundant_pattern_matching_result.rs:119:5
|
LL | / match Ok::<i32, i32>(42) {
LL | | Ok(_) => true,
@@ -142,7 +142,7 @@ LL | | };
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:123:5
+ --> $DIR/redundant_pattern_matching_result.rs:124:5
|
LL | / match Err::<i32, i32>(42) {
LL | | Ok(_) => false,
@@ -150,5 +150,41 @@ LL | | Err(_) => true,
LL | | };
| |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
-error: aborting due to 22 previous errors
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_result.rs:134:5
+ |
+LL | / match x {
+LL | | Ok(_) => true,
+LL | | _ => false,
+LL | | };
+ | |_____^ help: try this: `x.is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:139:5
+ |
+LL | / match x {
+LL | | Ok(_) => false,
+LL | | _ => true,
+LL | | };
+ | |_____^ help: try this: `x.is_err()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_result.rs:144:5
+ |
+LL | / match x {
+LL | | Err(_) => true,
+LL | | _ => false,
+LL | | };
+ | |_____^ help: try this: `x.is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_result.rs:149:5
+ |
+LL | / match x {
+LL | | Err(_) => false,
+LL | | _ => true,
+LL | | };
+ | |_____^ help: try this: `x.is_ok()`
+
+error: aborting due to 26 previous errors
diff --git a/src/tools/clippy/tests/ui/redundant_pub_crate.fixed b/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
index 106947de6..f65c0fdd3 100644
--- a/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::redundant_pub_crate)]
diff --git a/src/tools/clippy/tests/ui/redundant_pub_crate.rs b/src/tools/clippy/tests/ui/redundant_pub_crate.rs
index f96cfd318..fb07fed98 100644
--- a/src/tools/clippy/tests/ui/redundant_pub_crate.rs
+++ b/src/tools/clippy/tests/ui/redundant_pub_crate.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
#![warn(clippy::redundant_pub_crate)]
diff --git a/src/tools/clippy/tests/ui/redundant_slicing.fixed b/src/tools/clippy/tests/ui/redundant_slicing.fixed
index 8dd8d3092..56ddca719 100644
--- a/src/tools/clippy/tests/ui/redundant_slicing.fixed
+++ b/src/tools/clippy/tests/ui/redundant_slicing.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::deref_by_slicing)]
#![warn(clippy::redundant_slicing)]
diff --git a/src/tools/clippy/tests/ui/redundant_slicing.rs b/src/tools/clippy/tests/ui/redundant_slicing.rs
index 51c16dd8d..d67b6665e 100644
--- a/src/tools/clippy/tests/ui/redundant_slicing.rs
+++ b/src/tools/clippy/tests/ui/redundant_slicing.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused, clippy::deref_by_slicing)]
#![warn(clippy::redundant_slicing)]
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
index bca777a89..2651735d1 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
index afe764481..728665289 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/ref_patterns.rs b/src/tools/clippy/tests/ui/ref_patterns.rs
new file mode 100644
index 000000000..c51e0bc76
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_patterns.rs
@@ -0,0 +1,19 @@
+#![allow(unused)]
+#![warn(clippy::ref_patterns)]
+
+fn use_in_pattern() {
+ let opt = Some(5);
+ match opt {
+ None => {},
+ Some(ref opt) => {},
+ }
+}
+
+fn use_in_binding() {
+ let x = 5;
+ let ref y = x;
+}
+
+fn use_in_parameter(ref x: i32) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/ref_patterns.stderr b/src/tools/clippy/tests/ui/ref_patterns.stderr
new file mode 100644
index 000000000..aa0077826
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_patterns.stderr
@@ -0,0 +1,27 @@
+error: usage of ref pattern
+ --> $DIR/ref_patterns.rs:8:14
+ |
+LL | Some(ref opt) => {},
+ | ^^^^^^^
+ |
+ = help: consider using `&` for clarity instead
+ = note: `-D clippy::ref-patterns` implied by `-D warnings`
+
+error: usage of ref pattern
+ --> $DIR/ref_patterns.rs:14:9
+ |
+LL | let ref y = x;
+ | ^^^^^
+ |
+ = help: consider using `&` for clarity instead
+
+error: usage of ref pattern
+ --> $DIR/ref_patterns.rs:17:21
+ |
+LL | fn use_in_parameter(ref x: i32) {}
+ | ^^^^^
+ |
+ = help: consider using `&` for clarity instead
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs
index ab8ac97a0..a5f79b139 100644
--- a/src/tools/clippy/tests/ui/regex.rs
+++ b/src/tools/clippy/tests/ui/regex.rs
@@ -34,8 +34,10 @@ fn syntax_error() {
let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]);
let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]);
+ // These following three cases are considering valid since regex-1.8.0
let raw_string_error = Regex::new(r"[...\/...]");
let raw_string_error = Regex::new(r#"[...\/...]"#);
+ let _ = Regex::new(r"(?<hi>hi)").unwrap();
let escaped_string_span = Regex::new("\\b\\c");
diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr
index c2440f39e..6b8a772e7 100644
--- a/src/tools/clippy/tests/ui/regex.stderr
+++ b/src/tools/clippy/tests/ui/regex.stderr
@@ -82,23 +82,11 @@ error: regex parse error:
LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
| ^^^^^^^^^^^^^
-error: regex syntax error: unrecognized escape sequence
- --> $DIR/regex.rs:37:45
- |
-LL | let raw_string_error = Regex::new(r"[...//...]");
- | ^^
-
-error: regex syntax error: unrecognized escape sequence
- --> $DIR/regex.rs:38:46
- |
-LL | let raw_string_error = Regex::new(r#"[...//...]"#);
- | ^^
-
error: regex parse error:
/b/c
^^
error: unrecognized escape sequence
- --> $DIR/regex.rs:40:42
+ --> $DIR/regex.rs:42:42
|
LL | let escaped_string_span = Regex::new("/b/c");
| ^^^^^^^^
@@ -106,13 +94,13 @@ LL | let escaped_string_span = Regex::new("/b/c");
= help: consider using a raw string literal: `r".."`
error: regex syntax error: duplicate flag
- --> $DIR/regex.rs:42:34
+ --> $DIR/regex.rs:44:34
|
LL | let aux_span = Regex::new("(?ixi)");
| ^ ^
error: trivial regex
- --> $DIR/regex.rs:46:33
+ --> $DIR/regex.rs:48:33
|
LL | let trivial_eq = Regex::new("^foobar$");
| ^^^^^^^^^^
@@ -120,7 +108,7 @@ LL | let trivial_eq = Regex::new("^foobar$");
= help: consider using `==` on `str`s
error: trivial regex
- --> $DIR/regex.rs:48:48
+ --> $DIR/regex.rs:50:48
|
LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
| ^^^^^^^^^^
@@ -128,7 +116,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
= help: consider using `==` on `str`s
error: trivial regex
- --> $DIR/regex.rs:50:42
+ --> $DIR/regex.rs:52:42
|
LL | let trivial_starts_with = Regex::new("^foobar");
| ^^^^^^^^^
@@ -136,7 +124,7 @@ LL | let trivial_starts_with = Regex::new("^foobar");
= help: consider using `str::starts_with`
error: trivial regex
- --> $DIR/regex.rs:52:40
+ --> $DIR/regex.rs:54:40
|
LL | let trivial_ends_with = Regex::new("foobar$");
| ^^^^^^^^^
@@ -144,7 +132,7 @@ LL | let trivial_ends_with = Regex::new("foobar$");
= help: consider using `str::ends_with`
error: trivial regex
- --> $DIR/regex.rs:54:39
+ --> $DIR/regex.rs:56:39
|
LL | let trivial_contains = Regex::new("foobar");
| ^^^^^^^^
@@ -152,7 +140,7 @@ LL | let trivial_contains = Regex::new("foobar");
= help: consider using `str::contains`
error: trivial regex
- --> $DIR/regex.rs:56:39
+ --> $DIR/regex.rs:58:39
|
LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
| ^^^^^^^^^^^^^^^^
@@ -160,7 +148,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
= help: consider using `str::contains`
error: trivial regex
- --> $DIR/regex.rs:58:40
+ --> $DIR/regex.rs:60:40
|
LL | let trivial_backslash = Regex::new("a/.b");
| ^^^^^^^
@@ -168,7 +156,7 @@ LL | let trivial_backslash = Regex::new("a/.b");
= help: consider using `str::contains`
error: trivial regex
- --> $DIR/regex.rs:61:36
+ --> $DIR/regex.rs:63:36
|
LL | let trivial_empty = Regex::new("");
| ^^
@@ -176,7 +164,7 @@ LL | let trivial_empty = Regex::new("");
= help: the regex is unlikely to be useful as it is
error: trivial regex
- --> $DIR/regex.rs:63:36
+ --> $DIR/regex.rs:65:36
|
LL | let trivial_empty = Regex::new("^");
| ^^^
@@ -184,7 +172,7 @@ LL | let trivial_empty = Regex::new("^");
= help: the regex is unlikely to be useful as it is
error: trivial regex
- --> $DIR/regex.rs:65:36
+ --> $DIR/regex.rs:67:36
|
LL | let trivial_empty = Regex::new("^$");
| ^^^^
@@ -192,12 +180,12 @@ LL | let trivial_empty = Regex::new("^$");
= help: consider using `str::is_empty`
error: trivial regex
- --> $DIR/regex.rs:67:44
+ --> $DIR/regex.rs:69:44
|
LL | let binary_trivial_empty = BRegex::new("^$");
| ^^^^
|
= help: consider using `str::is_empty`
-error: aborting due to 25 previous errors
+error: aborting due to 23 previous errors
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 5076f6133..dfe45dec8 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -2,7 +2,7 @@
// Use that command to update this file and do not edit by hand.
// Manual edits will be overwritten.
-// run-rustfix
+//@run-rustfix
#![allow(clippy::almost_complete_range)]
#![allow(clippy::disallowed_names)]
@@ -16,6 +16,7 @@
#![allow(clippy::mixed_read_write_in_expression)]
#![allow(clippy::useless_conversion)]
#![allow(clippy::match_result_ok)]
+#![allow(clippy::arithmetic_side_effects)]
#![allow(clippy::overly_complex_bool_expr)]
#![allow(clippy::new_without_default)]
#![allow(clippy::bind_instead_of_map)]
@@ -27,8 +28,13 @@
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::recursive_format_impl)]
#![allow(clippy::invisible_characters)]
+#![allow(suspicious_double_ref_op)]
#![allow(drop_bounds)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
#![allow(for_loops_over_fallibles)]
+#![allow(forgetting_copy_types)]
+#![allow(forgetting_references)]
#![allow(array_into_iter)]
#![allow(invalid_atomic_ordering)]
#![allow(invalid_value)]
@@ -36,6 +42,7 @@
#![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)]
#![allow(named_arguments_used_positionally)]
+#![allow(suspicious_double_ref_op)]
#![allow(temporary_cstring_as_ptr)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
@@ -52,6 +59,7 @@
#![warn(clippy::mixed_read_write_in_expression)]
#![warn(clippy::useless_conversion)]
#![warn(clippy::match_result_ok)]
+#![warn(clippy::arithmetic_side_effects)]
#![warn(clippy::overly_complex_bool_expr)]
#![warn(clippy::new_without_default)]
#![warn(clippy::bind_instead_of_map)]
@@ -67,10 +75,15 @@
#![warn(clippy::module_name_repetitions)]
#![warn(clippy::recursive_format_impl)]
#![warn(clippy::invisible_characters)]
+#![warn(suspicious_double_ref_op)]
#![warn(drop_bounds)]
+#![warn(dropping_copy_types)]
+#![warn(dropping_references)]
#![warn(for_loops_over_fallibles)]
#![warn(for_loops_over_fallibles)]
#![warn(for_loops_over_fallibles)]
+#![warn(forgetting_copy_types)]
+#![warn(forgetting_references)]
#![warn(array_into_iter)]
#![warn(invalid_atomic_ordering)]
#![warn(invalid_value)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 64bc1ca71..ce8eca5a3 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -2,7 +2,7 @@
// Use that command to update this file and do not edit by hand.
// Manual edits will be overwritten.
-// run-rustfix
+//@run-rustfix
#![allow(clippy::almost_complete_range)]
#![allow(clippy::disallowed_names)]
@@ -16,6 +16,7 @@
#![allow(clippy::mixed_read_write_in_expression)]
#![allow(clippy::useless_conversion)]
#![allow(clippy::match_result_ok)]
+#![allow(clippy::arithmetic_side_effects)]
#![allow(clippy::overly_complex_bool_expr)]
#![allow(clippy::new_without_default)]
#![allow(clippy::bind_instead_of_map)]
@@ -27,8 +28,13 @@
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::recursive_format_impl)]
#![allow(clippy::invisible_characters)]
+#![allow(suspicious_double_ref_op)]
#![allow(drop_bounds)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
#![allow(for_loops_over_fallibles)]
+#![allow(forgetting_copy_types)]
+#![allow(forgetting_references)]
#![allow(array_into_iter)]
#![allow(invalid_atomic_ordering)]
#![allow(invalid_value)]
@@ -36,6 +42,7 @@
#![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)]
#![allow(named_arguments_used_positionally)]
+#![allow(suspicious_double_ref_op)]
#![allow(temporary_cstring_as_ptr)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
@@ -52,6 +59,7 @@
#![warn(clippy::eval_order_dependence)]
#![warn(clippy::identity_conversion)]
#![warn(clippy::if_let_some_result)]
+#![warn(clippy::integer_arithmetic)]
#![warn(clippy::logic_bug)]
#![warn(clippy::new_without_default_derive)]
#![warn(clippy::option_and_then_some)]
@@ -67,10 +75,15 @@
#![warn(clippy::stutter)]
#![warn(clippy::to_string_in_display)]
#![warn(clippy::zero_width_space)]
+#![warn(clippy::clone_double_ref)]
#![warn(clippy::drop_bounds)]
+#![warn(clippy::drop_copy)]
+#![warn(clippy::drop_ref)]
#![warn(clippy::for_loop_over_option)]
#![warn(clippy::for_loop_over_result)]
#![warn(clippy::for_loops_over_fallibles)]
+#![warn(clippy::forget_copy)]
+#![warn(clippy::forget_ref)]
#![warn(clippy::into_iter_on_array)]
#![warn(clippy::invalid_atomic_ordering)]
#![warn(clippy::invalid_ref)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 27a026329..3fca60aa2 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
- --> $DIR/rename.rs:42:9
+ --> $DIR/rename.rs:49:9
|
LL | #![warn(clippy::almost_complete_letter_range)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,250 +7,286 @@ LL | #![warn(clippy::almost_complete_letter_range)]
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
- --> $DIR/rename.rs:43:9
+ --> $DIR/rename.rs:50:9
|
LL | #![warn(clippy::blacklisted_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
- --> $DIR/rename.rs:44:9
+ --> $DIR/rename.rs:51:9
|
LL | #![warn(clippy::block_in_if_condition_expr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
- --> $DIR/rename.rs:45:9
+ --> $DIR/rename.rs:52:9
|
LL | #![warn(clippy::block_in_if_condition_stmt)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
- --> $DIR/rename.rs:46:9
+ --> $DIR/rename.rs:53:9
|
LL | #![warn(clippy::box_vec)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
- --> $DIR/rename.rs:47:9
+ --> $DIR/rename.rs:54:9
|
LL | #![warn(clippy::const_static_lifetime)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
- --> $DIR/rename.rs:48:9
+ --> $DIR/rename.rs:55:9
|
LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
- --> $DIR/rename.rs:49:9
+ --> $DIR/rename.rs:56:9
|
LL | #![warn(clippy::derive_hash_xor_eq)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
- --> $DIR/rename.rs:50:9
+ --> $DIR/rename.rs:57:9
|
LL | #![warn(clippy::disallowed_method)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
- --> $DIR/rename.rs:51:9
+ --> $DIR/rename.rs:58:9
|
LL | #![warn(clippy::disallowed_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
- --> $DIR/rename.rs:52:9
+ --> $DIR/rename.rs:59:9
|
LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
- --> $DIR/rename.rs:53:9
+ --> $DIR/rename.rs:60:9
|
LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
- --> $DIR/rename.rs:54:9
+ --> $DIR/rename.rs:61:9
|
LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
+error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
+ --> $DIR/rename.rs:62:9
+ |
+LL | #![warn(clippy::integer_arithmetic)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
+
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
- --> $DIR/rename.rs:55:9
+ --> $DIR/rename.rs:63:9
|
LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
- --> $DIR/rename.rs:56:9
+ --> $DIR/rename.rs:64:9
|
LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
- --> $DIR/rename.rs:57:9
+ --> $DIR/rename.rs:65:9
|
LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
- --> $DIR/rename.rs:58:9
+ --> $DIR/rename.rs:66:9
|
LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:59:9
+ --> $DIR/rename.rs:67:9
|
LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:60:9
+ --> $DIR/rename.rs:68:9
|
LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> $DIR/rename.rs:61:9
+ --> $DIR/rename.rs:69:9
|
LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
- --> $DIR/rename.rs:62:9
+ --> $DIR/rename.rs:70:9
|
LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
- --> $DIR/rename.rs:63:9
+ --> $DIR/rename.rs:71:9
|
LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:64:9
+ --> $DIR/rename.rs:72:9
|
LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> $DIR/rename.rs:65:9
+ --> $DIR/rename.rs:73:9
|
LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
- --> $DIR/rename.rs:66:9
+ --> $DIR/rename.rs:74:9
|
LL | #![warn(clippy::single_char_push_str)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
- --> $DIR/rename.rs:67:9
+ --> $DIR/rename.rs:75:9
|
LL | #![warn(clippy::stutter)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
- --> $DIR/rename.rs:68:9
+ --> $DIR/rename.rs:76:9
|
LL | #![warn(clippy::to_string_in_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
- --> $DIR/rename.rs:69:9
+ --> $DIR/rename.rs:77:9
|
LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
+error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
+ --> $DIR/rename.rs:78:9
+ |
+LL | #![warn(clippy::clone_double_ref)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
+
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
- --> $DIR/rename.rs:70:9
+ --> $DIR/rename.rs:79:9
|
LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
+error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
+ --> $DIR/rename.rs:80:9
+ |
+LL | #![warn(clippy::drop_copy)]
+ | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
+
+error: lint `clippy::drop_ref` has been renamed to `dropping_references`
+ --> $DIR/rename.rs:81:9
+ |
+LL | #![warn(clippy::drop_ref)]
+ | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
+
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:71:9
+ --> $DIR/rename.rs:82:9
|
LL | #![warn(clippy::for_loop_over_option)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:72:9
+ --> $DIR/rename.rs:83:9
|
LL | #![warn(clippy::for_loop_over_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:73:9
+ --> $DIR/rename.rs:84:9
|
LL | #![warn(clippy::for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
+error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
+ --> $DIR/rename.rs:85:9
+ |
+LL | #![warn(clippy::forget_copy)]
+ | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
+
+error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
+ --> $DIR/rename.rs:86:9
+ |
+LL | #![warn(clippy::forget_ref)]
+ | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
+
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
- --> $DIR/rename.rs:74:9
+ --> $DIR/rename.rs:87:9
|
LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
- --> $DIR/rename.rs:75:9
+ --> $DIR/rename.rs:88:9
|
LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
- --> $DIR/rename.rs:76:9
+ --> $DIR/rename.rs:89:9
|
LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
- --> $DIR/rename.rs:77:9
+ --> $DIR/rename.rs:90:9
|
LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
- --> $DIR/rename.rs:78:9
+ --> $DIR/rename.rs:91:9
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
- --> $DIR/rename.rs:79:9
+ --> $DIR/rename.rs:92:9
|
LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
- --> $DIR/rename.rs:80:9
+ --> $DIR/rename.rs:93:9
|
LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
- --> $DIR/rename.rs:81:9
+ --> $DIR/rename.rs:94:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
- --> $DIR/rename.rs:82:9
+ --> $DIR/rename.rs:95:9
|
LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels`
- --> $DIR/rename.rs:83:9
+ --> $DIR/rename.rs:96:9
|
LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
-error: aborting due to 42 previous errors
+error: aborting due to 48 previous errors
diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed b/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed
index cb91b841d..0334c1e1a 100644
--- a/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed
+++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[clippy::cognitive_complexity = "1"]
fn main() {}
diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.rs b/src/tools/clippy/tests/ui/renamed_builtin_attr.rs
index b3ce27580..d350370c2 100644
--- a/src/tools/clippy/tests/ui/renamed_builtin_attr.rs
+++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[clippy::cyclomatic_complexity = "1"]
fn main() {}
diff --git a/src/tools/clippy/tests/ui/repeat_once.fixed b/src/tools/clippy/tests/ui/repeat_once.fixed
index dc197e503..c517bfcc6 100644
--- a/src/tools/clippy/tests/ui/repeat_once.fixed
+++ b/src/tools/clippy/tests/ui/repeat_once.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::repeat_once)]
#[allow(unused, clippy::redundant_clone)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/repeat_once.rs b/src/tools/clippy/tests/ui/repeat_once.rs
index 0ec512711..9a30b4741 100644
--- a/src/tools/clippy/tests/ui/repeat_once.rs
+++ b/src/tools/clippy/tests/ui/repeat_once.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::repeat_once)]
#[allow(unused, clippy::redundant_clone)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/result_map_or_into_option.fixed b/src/tools/clippy/tests/ui/result_map_or_into_option.fixed
index 331531b51..119ff2591 100644
--- a/src/tools/clippy/tests/ui/result_map_or_into_option.fixed
+++ b/src/tools/clippy/tests/ui/result_map_or_into_option.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::result_map_or_into_option)]
diff --git a/src/tools/clippy/tests/ui/result_map_or_into_option.rs b/src/tools/clippy/tests/ui/result_map_or_into_option.rs
index 3058480e2..eeeef830a 100644
--- a/src/tools/clippy/tests/ui/result_map_or_into_option.rs
+++ b/src/tools/clippy/tests/ui/result_map_or_into_option.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::result_map_or_into_option)]
diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed
index d8b56237e..0583d2927 100644
--- a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed
+++ b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::result_map_unit_fn)]
#![allow(unused)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs
index 44f50d211..7ad3bdd04 100644
--- a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs
+++ b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::result_map_unit_fn)]
#![allow(unused)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed
index c67edb36c..30dfc9776 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::reversed_empty_ranges)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs
index 0a4fef5bf..1837249ea 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::reversed_empty_ranges)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed
index 78401e463..a74569599 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::reversed_empty_ranges)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs
index f9e0f7fcd..42f9957df 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::reversed_empty_ranges)]
#![allow(clippy::uninlined_format_args)]
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 e6198a1bc..aea1507cc 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
@@ -1,5 +1,5 @@
#![feature(adt_const_params)]
-#![warn(clippy::same_functions_in_if_condition)]
+#![deny(clippy::same_functions_in_if_condition)]
// ifs_same_cond warning is different from `ifs_same_cond`.
// clippy::if_same_then_else, clippy::comparison_chain -- all empty blocks
#![allow(incomplete_features)]
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 f352ade15..aade3b1fa 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
@@ -9,7 +9,11 @@ note: same as this
|
LL | if function() {
| ^^^^^^^^^^
- = note: `-D clippy::same-functions-in-if-condition` implied by `-D warnings`
+note: the lint level is defined here
+ --> $DIR/same_functions_in_if_condition.rs:2:9
+ |
+LL | #![deny(clippy::same_functions_in_if_condition)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this `if` has the same function call as a previous `if`
--> $DIR/same_functions_in_if_condition.rs:42:15
diff --git a/src/tools/clippy/tests/ui/same_name_method.rs b/src/tools/clippy/tests/ui/same_name_method.rs
index daef95a42..f31a7e33c 100644
--- a/src/tools/clippy/tests/ui/same_name_method.rs
+++ b/src/tools/clippy/tests/ui/same_name_method.rs
@@ -62,7 +62,7 @@ mod should_lint {
impl T1 for S {}
}
- mod multiply_conflicit_trait {
+ mod multiple_conflicting_traits {
use crate::{T1, T2};
struct S;
diff --git a/src/tools/clippy/tests/ui/search_is_some.rs b/src/tools/clippy/tests/ui/search_is_some.rs
index 72f335153..670599b0d 100644
--- a/src/tools/clippy/tests/ui/search_is_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some.rs
@@ -1,4 +1,4 @@
-// aux-build:option_helpers.rs
+//@aux-build:option_helpers.rs
#![warn(clippy::search_is_some)]
#![allow(dead_code)]
extern crate option_helpers;
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
index 5190c5304..9386618c1 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, clippy::explicit_auto_deref)]
#![warn(clippy::search_is_some)]
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
index 310d87333..6b2537a96 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, clippy::explicit_auto_deref)]
#![warn(clippy::search_is_some)]
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
index 385a9986a..e9116fc59 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, clippy::explicit_auto_deref)]
#![warn(clippy::search_is_some)]
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
index 67e190ee3..b15283994 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, clippy::explicit_auto_deref)]
#![warn(clippy::search_is_some)]
diff --git a/src/tools/clippy/tests/ui/seek_from_current.fixed b/src/tools/clippy/tests/ui/seek_from_current.fixed
index 1309c91b8..34c33baf6 100644
--- a/src/tools/clippy/tests/ui/seek_from_current.fixed
+++ b/src/tools/clippy/tests/ui/seek_from_current.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::seek_from_current)]
use std::fs::File;
diff --git a/src/tools/clippy/tests/ui/seek_from_current.rs b/src/tools/clippy/tests/ui/seek_from_current.rs
index 5d9b1424c..22bcff1bc 100644
--- a/src/tools/clippy/tests/ui/seek_from_current.rs
+++ b/src/tools/clippy/tests/ui/seek_from_current.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::seek_from_current)]
use std::fs::File;
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
index dc24d447c..d8a6e6985 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::seek_to_start_instead_of_rewind)]
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
index 4adde2c40..fc6a6433c 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::seek_to_start_instead_of_rewind)]
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.fixed b/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
index 42e97e1ca..ee359f60c 100644
--- a/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
+++ b/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
unused,
clippy::unused_unit,
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.rs b/src/tools/clippy/tests/ui/semicolon_inside_block.rs
index f40848f70..e8516f79b 100644
--- a/src/tools/clippy/tests/ui/semicolon_inside_block.rs
+++ b/src/tools/clippy/tests/ui/semicolon_inside_block.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
unused,
clippy::unused_unit,
diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.fixed b/src/tools/clippy/tests/ui/semicolon_outside_block.fixed
index 091eaa751..034c7f8c7 100644
--- a/src/tools/clippy/tests/ui/semicolon_outside_block.fixed
+++ b/src/tools/clippy/tests/ui/semicolon_outside_block.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
unused,
clippy::unused_unit,
diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.rs b/src/tools/clippy/tests/ui/semicolon_outside_block.rs
index 7ce46431f..4dc956d8a 100644
--- a/src/tools/clippy/tests/ui/semicolon_outside_block.rs
+++ b/src/tools/clippy/tests/ui/semicolon_outside_block.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
unused,
clippy::unused_unit,
diff --git a/src/tools/clippy/tests/ui/shadow.rs b/src/tools/clippy/tests/ui/shadow.rs
index 1fa9fc749..2c0fc3e3f 100644
--- a/src/tools/clippy/tests/ui/shadow.rs
+++ b/src/tools/clippy/tests/ui/shadow.rs
@@ -1,6 +1,19 @@
+//@aux-build:proc_macro_derive.rs
+
#![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)]
#![allow(clippy::let_unit_value)]
+extern crate proc_macro_derive;
+
+#[derive(proc_macro_derive::ShadowDerive)]
+pub struct Nothing;
+
+macro_rules! reuse {
+ ($v:ident) => {
+ let $v = $v + 1;
+ };
+}
+
fn shadow_same() {
let x = 1;
let x = x;
@@ -26,6 +39,12 @@ fn shadow_reuse() -> Option<()> {
None
}
+fn shadow_reuse_macro() {
+ let x = 1;
+ // this should not warn
+ reuse!(x);
+}
+
fn shadow_unrelated() {
let x = 1;
let x = 2;
diff --git a/src/tools/clippy/tests/ui/shadow.stderr b/src/tools/clippy/tests/ui/shadow.stderr
index c3d7bc2a5..8321f6df2 100644
--- a/src/tools/clippy/tests/ui/shadow.stderr
+++ b/src/tools/clippy/tests/ui/shadow.stderr
@@ -1,278 +1,278 @@
error: `x` is shadowed by itself in `x`
- --> $DIR/shadow.rs:6:9
+ --> $DIR/shadow.rs:19:9
|
LL | let x = x;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:5:9
+ --> $DIR/shadow.rs:18:9
|
LL | let x = 1;
| ^
= note: `-D clippy::shadow-same` implied by `-D warnings`
error: `mut x` is shadowed by itself in `&x`
- --> $DIR/shadow.rs:7:13
+ --> $DIR/shadow.rs:20:13
|
LL | let mut x = &x;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:6:9
+ --> $DIR/shadow.rs:19:9
|
LL | let x = x;
| ^
error: `x` is shadowed by itself in `&mut x`
- --> $DIR/shadow.rs:8:9
+ --> $DIR/shadow.rs:21:9
|
LL | let x = &mut x;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:7:9
+ --> $DIR/shadow.rs:20:9
|
LL | let mut x = &x;
| ^^^^^
error: `x` is shadowed by itself in `*x`
- --> $DIR/shadow.rs:9:9
+ --> $DIR/shadow.rs:22:9
|
LL | let x = *x;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:8:9
+ --> $DIR/shadow.rs:21:9
|
LL | let x = &mut x;
| ^
error: `x` is shadowed
- --> $DIR/shadow.rs:14:9
+ --> $DIR/shadow.rs:27:9
|
LL | let x = x.0;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:13:9
+ --> $DIR/shadow.rs:26:9
|
LL | let x = ([[0]], ());
| ^
= note: `-D clippy::shadow-reuse` implied by `-D warnings`
error: `x` is shadowed
- --> $DIR/shadow.rs:15:9
+ --> $DIR/shadow.rs:28:9
|
LL | let x = x[0];
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:14:9
+ --> $DIR/shadow.rs:27:9
|
LL | let x = x.0;
| ^
error: `x` is shadowed
- --> $DIR/shadow.rs:16:10
+ --> $DIR/shadow.rs:29:10
|
LL | let [x] = x;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:15:9
+ --> $DIR/shadow.rs:28:9
|
LL | let x = x[0];
| ^
error: `x` is shadowed
- --> $DIR/shadow.rs:17:9
+ --> $DIR/shadow.rs:30:9
|
LL | let x = Some(x);
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:16:10
+ --> $DIR/shadow.rs:29:10
|
LL | let [x] = x;
| ^
error: `x` is shadowed
- --> $DIR/shadow.rs:18:9
+ --> $DIR/shadow.rs:31:9
|
LL | let x = foo(x);
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:17:9
+ --> $DIR/shadow.rs:30:9
|
LL | let x = Some(x);
| ^
error: `x` is shadowed
- --> $DIR/shadow.rs:19:9
+ --> $DIR/shadow.rs:32:9
|
LL | let x = || x;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:18:9
+ --> $DIR/shadow.rs:31:9
|
LL | let x = foo(x);
| ^
error: `x` is shadowed
- --> $DIR/shadow.rs:20:9
+ --> $DIR/shadow.rs:33:9
|
LL | let x = Some(1).map(|_| x)?;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:19:9
+ --> $DIR/shadow.rs:32:9
|
LL | let x = || x;
| ^
error: `y` is shadowed
- --> $DIR/shadow.rs:22:9
+ --> $DIR/shadow.rs:35:9
|
LL | let y = match y {
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:21:9
+ --> $DIR/shadow.rs:34:9
|
LL | let y = 1;
| ^
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:31:9
+ --> $DIR/shadow.rs:50:9
|
LL | let x = 2;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:30:9
+ --> $DIR/shadow.rs:49:9
|
LL | let x = 1;
| ^
= note: `-D clippy::shadow-unrelated` implied by `-D warnings`
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:36:13
+ --> $DIR/shadow.rs:55:13
|
LL | let x = 1;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:35:10
+ --> $DIR/shadow.rs:54:10
|
LL | fn f(x: u32) {
| ^
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:41:14
+ --> $DIR/shadow.rs:60:14
|
LL | Some(x) => {
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:38:9
+ --> $DIR/shadow.rs:57:9
|
LL | let x = 1;
| ^
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:42:17
+ --> $DIR/shadow.rs:61:17
|
LL | let x = 1;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:41:14
+ --> $DIR/shadow.rs:60:14
|
LL | Some(x) => {
| ^
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:46:17
+ --> $DIR/shadow.rs:65:17
|
LL | if let Some(x) = Some(1) {}
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:38:9
+ --> $DIR/shadow.rs:57:9
|
LL | let x = 1;
| ^
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:47:20
+ --> $DIR/shadow.rs:66:20
|
LL | while let Some(x) = Some(1) {}
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:38:9
+ --> $DIR/shadow.rs:57:9
|
LL | let x = 1;
| ^
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:48:15
+ --> $DIR/shadow.rs:67:15
|
LL | let _ = |[x]: [u32; 1]| {
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:38:9
+ --> $DIR/shadow.rs:57:9
|
LL | let x = 1;
| ^
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:49:13
+ --> $DIR/shadow.rs:68:13
|
LL | let x = 1;
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:48:15
+ --> $DIR/shadow.rs:67:15
|
LL | let _ = |[x]: [u32; 1]| {
| ^
error: `y` is shadowed
- --> $DIR/shadow.rs:52:17
+ --> $DIR/shadow.rs:71:17
|
LL | if let Some(y) = y {}
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:51:9
+ --> $DIR/shadow.rs:70:9
|
LL | let y = Some(1);
| ^
error: `_b` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:88:9
+ --> $DIR/shadow.rs:107:9
|
LL | let _b = _a;
| ^^
|
note: previous binding is here
- --> $DIR/shadow.rs:87:28
+ --> $DIR/shadow.rs:106:28
|
LL | pub async fn foo2(_a: i32, _b: i64) {
| ^^
error: `x` shadows a previous, unrelated binding
- --> $DIR/shadow.rs:94:21
+ --> $DIR/shadow.rs:113:21
|
LL | if let Some(x) = Some(1) { x } else { 1 }
| ^
|
note: previous binding is here
- --> $DIR/shadow.rs:93:13
+ --> $DIR/shadow.rs:112:13
|
LL | let x = 1;
| ^
diff --git a/src/tools/clippy/tests/ui/short_circuit_statement.fixed b/src/tools/clippy/tests/ui/short_circuit_statement.fixed
index dd22ecab0..1737d5014 100644
--- a/src/tools/clippy/tests/ui/short_circuit_statement.fixed
+++ b/src/tools/clippy/tests/ui/short_circuit_statement.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::short_circuit_statement)]
#![allow(clippy::nonminimal_bool)]
diff --git a/src/tools/clippy/tests/ui/short_circuit_statement.rs b/src/tools/clippy/tests/ui/short_circuit_statement.rs
index 73a55bf1f..ab93aa1ca 100644
--- a/src/tools/clippy/tests/ui/short_circuit_statement.rs
+++ b/src/tools/clippy/tests/ui/short_circuit_statement.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::short_circuit_statement)]
#![allow(clippy::nonminimal_bool)]
diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
index c65df9ece..8c48b21f1 100644
--- a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
@@ -1,5 +1,5 @@
// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934
-// // run-rustfix
+//
#![warn(clippy::significant_drop_in_scrutinee)]
#![allow(dead_code, unused_assignments)]
#![allow(clippy::match_single_binding, clippy::single_match, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
index da998c610..ee7f2b063 100644
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::significant_drop_tightening)]
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.rs b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
index 83823f95f..9c139deb9 100644
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.rs
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::significant_drop_tightening)]
diff --git a/src/tools/clippy/tests/ui/single_char_add_str.fixed b/src/tools/clippy/tests/ui/single_char_add_str.fixed
index 63a6d37a9..cbcf1ab21 100644
--- a/src/tools/clippy/tests/ui/single_char_add_str.fixed
+++ b/src/tools/clippy/tests/ui/single_char_add_str.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::single_char_add_str)]
macro_rules! get_string {
diff --git a/src/tools/clippy/tests/ui/single_char_add_str.rs b/src/tools/clippy/tests/ui/single_char_add_str.rs
index a799ea7d8..a1f005cc8 100644
--- a/src/tools/clippy/tests/ui/single_char_add_str.rs
+++ b/src/tools/clippy/tests/ui/single_char_add_str.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::single_char_add_str)]
macro_rules! get_string {
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.fixed b/src/tools/clippy/tests/ui/single_char_pattern.fixed
index 68e267267..dba898720 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.fixed
+++ b/src/tools/clippy/tests/ui/single_char_pattern.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_must_use)]
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.rs b/src/tools/clippy/tests/ui/single_char_pattern.rs
index 186202d78..6a145a14b 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.rs
+++ b/src/tools/clippy/tests/ui/single_char_pattern.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_must_use)]
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.fixed b/src/tools/clippy/tests/ui/single_component_path_imports.fixed
index 8c96c4715..d4d2cbbe5 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.fixed
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.rs b/src/tools/clippy/tests/ui/single_component_path_imports.rs
index 8434bf7ea..80d72115f 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.rs
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
diff --git a/src/tools/clippy/tests/ui/single_element_loop.fixed b/src/tools/clippy/tests/ui/single_element_loop.fixed
index a0dcc0172..1697a0cf2 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.fixed
+++ b/src/tools/clippy/tests/ui/single_element_loop.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
// Tests from for_loop.rs that don't have suggestions
#[warn(clippy::single_element_loop)]
diff --git a/src/tools/clippy/tests/ui/single_element_loop.rs b/src/tools/clippy/tests/ui/single_element_loop.rs
index bc014035c..860424f42 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.rs
+++ b/src/tools/clippy/tests/ui/single_element_loop.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
// Tests from for_loop.rs that don't have suggestions
#[warn(clippy::single_element_loop)]
diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs
index 3c86f41f3..c8ac768b6 100644
--- a/src/tools/clippy/tests/ui/single_match_else.rs
+++ b/src/tools/clippy/tests/ui/single_match_else.rs
@@ -1,4 +1,4 @@
-// aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs
#![warn(clippy::single_match_else)]
#![allow(clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/skip_while_next.rs b/src/tools/clippy/tests/ui/skip_while_next.rs
index a551c19d9..62574e2c8 100644
--- a/src/tools/clippy/tests/ui/skip_while_next.rs
+++ b/src/tools/clippy/tests/ui/skip_while_next.rs
@@ -1,4 +1,4 @@
-// aux-build:option_helpers.rs
+//@aux-build:option_helpers.rs
#![warn(clippy::skip_while_next)]
#![allow(clippy::disallowed_names)]
diff --git a/src/tools/clippy/tests/ui/stable_sort_primitive.fixed b/src/tools/clippy/tests/ui/stable_sort_primitive.fixed
index f5f18169d..1370dd2df 100644
--- a/src/tools/clippy/tests/ui/stable_sort_primitive.fixed
+++ b/src/tools/clippy/tests/ui/stable_sort_primitive.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::stable_sort_primitive)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/stable_sort_primitive.rs b/src/tools/clippy/tests/ui/stable_sort_primitive.rs
index 8149c5638..cd344dd12 100644
--- a/src/tools/clippy/tests/ui/stable_sort_primitive.rs
+++ b/src/tools/clippy/tests/ui/stable_sort_primitive.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::stable_sort_primitive)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/starts_ends_with.fixed b/src/tools/clippy/tests/ui/starts_ends_with.fixed
index 983fac7af..29d56f852 100644
--- a/src/tools/clippy/tests/ui/starts_ends_with.fixed
+++ b/src/tools/clippy/tests/ui/starts_ends_with.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, unused_must_use)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui/starts_ends_with.rs b/src/tools/clippy/tests/ui/starts_ends_with.rs
index e3335dd2e..56bbe2574 100644
--- a/src/tools/clippy/tests/ui/starts_ends_with.rs
+++ b/src/tools/clippy/tests/ui/starts_ends_with.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, unused_must_use)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui/string_add.rs b/src/tools/clippy/tests/ui/string_add.rs
index 20edbe31f..de78dfe4d 100644
--- a/src/tools/clippy/tests/ui/string_add.rs
+++ b/src/tools/clippy/tests/ui/string_add.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
extern crate proc_macros;
use proc_macros::external;
diff --git a/src/tools/clippy/tests/ui/string_add_assign.fixed b/src/tools/clippy/tests/ui/string_add_assign.fixed
index b687f43b2..616c6daaf 100644
--- a/src/tools/clippy/tests/ui/string_add_assign.fixed
+++ b/src/tools/clippy/tests/ui/string_add_assign.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[allow(clippy::string_add, unused)]
#[warn(clippy::string_add_assign)]
diff --git a/src/tools/clippy/tests/ui/string_add_assign.rs b/src/tools/clippy/tests/ui/string_add_assign.rs
index e5dbde108..e1f885975 100644
--- a/src/tools/clippy/tests/ui/string_add_assign.rs
+++ b/src/tools/clippy/tests/ui/string_add_assign.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[allow(clippy::string_add, unused)]
#[warn(clippy::string_add_assign)]
diff --git a/src/tools/clippy/tests/ui/string_extend.fixed b/src/tools/clippy/tests/ui/string_extend.fixed
index d200d7310..65c9abff3 100644
--- a/src/tools/clippy/tests/ui/string_extend.fixed
+++ b/src/tools/clippy/tests/ui/string_extend.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[derive(Copy, Clone)]
struct HasChars;
diff --git a/src/tools/clippy/tests/ui/string_extend.rs b/src/tools/clippy/tests/ui/string_extend.rs
index 0dd96a3b2..5f72ffe2f 100644
--- a/src/tools/clippy/tests/ui/string_extend.rs
+++ b/src/tools/clippy/tests/ui/string_extend.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#[derive(Copy, Clone)]
struct HasChars;
diff --git a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.fixed b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.fixed
index 6e665cdd5..9b315ae2b 100644
--- a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.fixed
+++ b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::string_from_utf8_as_bytes)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.rs b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.rs
index 670d206d3..043dd2350 100644
--- a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.rs
+++ b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::string_from_utf8_as_bytes)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
index 506187fc1..3fc11b8b0 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
@@ -1,8 +1,18 @@
-// run-rustfix
+//@run-rustfix
+//@aux-build:macro_rules.rs
#![allow(dead_code, unused_variables)]
#![warn(clippy::string_lit_as_bytes)]
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! b {
+ ($b:literal) => {
+ const B: &[u8] = b"warning";
+ };
+}
+
fn str_lit_as_bytes() {
let bs = b"hello there";
@@ -11,6 +21,10 @@ fn str_lit_as_bytes() {
let bs = b"lit to string".to_vec();
let bs = b"lit to owned".to_vec();
+ b!("warning");
+
+ string_lit_as_bytes!("no warning");
+
// no warning, because these cannot be written as byte string literals:
let ubs = "☃".as_bytes();
let ubs = "hello there! this is a very long string".as_bytes();
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
index 2c339f1dd..7d54acf63 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
@@ -1,8 +1,18 @@
-// run-rustfix
+//@run-rustfix
+//@aux-build:macro_rules.rs
#![allow(dead_code, unused_variables)]
#![warn(clippy::string_lit_as_bytes)]
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! b {
+ ($b:literal) => {
+ const B: &[u8] = $b.as_bytes();
+ };
+}
+
fn str_lit_as_bytes() {
let bs = "hello there".as_bytes();
@@ -11,6 +21,10 @@ fn str_lit_as_bytes() {
let bs = "lit to string".to_string().into_bytes();
let bs = "lit to owned".to_owned().into_bytes();
+ b!("warning");
+
+ string_lit_as_bytes!("no warning");
+
// no warning, because these cannot be written as byte string literals:
let ubs = "☃".as_bytes();
let ubs = "hello there! this is a very long string".as_bytes();
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr b/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr
index f47d6161c..61b4e210e 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr
@@ -1,5 +1,5 @@
error: calling `as_bytes()` on a string literal
- --> $DIR/string_lit_as_bytes.rs:7:14
+ --> $DIR/string_lit_as_bytes.rs:17:14
|
LL | let bs = "hello there".as_bytes();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"`
@@ -7,34 +7,45 @@ LL | let bs = "hello there".as_bytes();
= note: `-D clippy::string-lit-as-bytes` implied by `-D warnings`
error: calling `as_bytes()` on a string literal
- --> $DIR/string_lit_as_bytes.rs:9:14
+ --> $DIR/string_lit_as_bytes.rs:19:14
|
LL | let bs = r###"raw string with 3# plus " ""###.as_bytes();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with 3# plus " ""###`
error: calling `into_bytes()` on a string literal
- --> $DIR/string_lit_as_bytes.rs:11:14
+ --> $DIR/string_lit_as_bytes.rs:21:14
|
LL | let bs = "lit to string".to_string().into_bytes();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to string".to_vec()`
error: calling `into_bytes()` on a string literal
- --> $DIR/string_lit_as_bytes.rs:12:14
+ --> $DIR/string_lit_as_bytes.rs:22:14
|
LL | let bs = "lit to owned".to_owned().into_bytes();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to owned".to_vec()`
+error: calling `as_bytes()` on a string literal
+ --> $DIR/string_lit_as_bytes.rs:12:26
+ |
+LL | const B: &[u8] = $b.as_bytes();
+ | ^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"warning"`
+...
+LL | b!("warning");
+ | ------------- in this macro invocation
+ |
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
error: calling `as_bytes()` on `include_str!(..)`
- --> $DIR/string_lit_as_bytes.rs:25:22
+ --> $DIR/string_lit_as_bytes.rs:39:22
|
LL | let includestr = include_str!("string_lit_as_bytes.rs").as_bytes();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("string_lit_as_bytes.rs")`
error: calling `as_bytes()` on a string literal
- --> $DIR/string_lit_as_bytes.rs:27:13
+ --> $DIR/string_lit_as_bytes.rs:41:13
|
LL | let _ = "string with newline/t/n".as_bytes();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"string with newline/t/n"`
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed b/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed
index 947a59bcc..ef207e28c 100644
--- a/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed
+++ b/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::strlen_on_c_strings)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.rs b/src/tools/clippy/tests/ui/strlen_on_c_strings.rs
index 1237f1ab0..03ec5f79d 100644
--- a/src/tools/clippy/tests/ui/strlen_on_c_strings.rs
+++ b/src/tools/clippy/tests/ui/strlen_on_c_strings.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::strlen_on_c_strings)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed b/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed
index b404df94d..bffda1cc4 100644
--- a/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::suspicious_doc_comments)]
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments.rs b/src/tools/clippy/tests/ui/suspicious_doc_comments.rs
index 46eff51e2..cdd972ee3 100644
--- a/src/tools/clippy/tests/ui/suspicious_doc_comments.rs
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::suspicious_doc_comments)]
diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
index 21753e5dc..e0153cdd8 100644
--- a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
+++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macro_suspicious_else_formatting.rs
+//@aux-build:proc_macro_suspicious_else_formatting.rs
#![warn(clippy::suspicious_else_formatting)]
#![allow(clippy::if_same_then_else, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed b/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed
index ede8a39fe..0e37701ec 100644
--- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed
+++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::suspicious_operation_groupings)]
#![allow(dead_code, unused_parens, clippy::eq_op)]
diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
index 26ce97bb3..dd4f3b71c 100644
--- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::suspicious_operation_groupings)]
#![allow(dead_code, unused_parens, clippy::eq_op)]
diff --git a/src/tools/clippy/tests/ui/swap.fixed b/src/tools/clippy/tests/ui/swap.fixed
index 9703674d1..fd3569cf3 100644
--- a/src/tools/clippy/tests/ui/swap.fixed
+++ b/src/tools/clippy/tests/ui/swap.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build: macro_rules.rs
+//@run-rustfix
+//@aux-build: macro_rules.rs
#![warn(clippy::all)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/swap.rs b/src/tools/clippy/tests/ui/swap.rs
index a0228065e..34fbce052 100644
--- a/src/tools/clippy/tests/ui/swap.rs
+++ b/src/tools/clippy/tests/ui/swap.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build: macro_rules.rs
+//@run-rustfix
+//@aux-build: macro_rules.rs
#![warn(clippy::all)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/swap_ptr_to_ref.fixed b/src/tools/clippy/tests/ui/swap_ptr_to_ref.fixed
index 596b6ee91..3bede3017 100644
--- a/src/tools/clippy/tests/ui/swap_ptr_to_ref.fixed
+++ b/src/tools/clippy/tests/ui/swap_ptr_to_ref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::swap_ptr_to_ref)]
diff --git a/src/tools/clippy/tests/ui/swap_ptr_to_ref.rs b/src/tools/clippy/tests/ui/swap_ptr_to_ref.rs
index 282f57121..726b09d37 100644
--- a/src/tools/clippy/tests/ui/swap_ptr_to_ref.rs
+++ b/src/tools/clippy/tests/ui/swap_ptr_to_ref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::swap_ptr_to_ref)]
diff --git a/src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed b/src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed
index 4bc4bc86c..21020182c 100644
--- a/src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed
+++ b/src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::tabs_in_doc_comments)]
#[allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/tabs_in_doc_comments.rs b/src/tools/clippy/tests/ui/tabs_in_doc_comments.rs
index 9db3416e6..df704267d 100644
--- a/src/tools/clippy/tests/ui/tabs_in_doc_comments.rs
+++ b/src/tools/clippy/tests/ui/tabs_in_doc_comments.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::tabs_in_doc_comments)]
#[allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/tests_outside_test_module.rs b/src/tools/clippy/tests/ui/tests_outside_test_module.rs
index 1982b1d01..21fdfdf90 100644
--- a/src/tools/clippy/tests/ui/tests_outside_test_module.rs
+++ b/src/tools/clippy/tests/ui/tests_outside_test_module.rs
@@ -1,4 +1,4 @@
-// compile-flags: --test
+//@compile-flags: --test
#![allow(unused)]
#![warn(clippy::tests_outside_test_module)]
diff --git a/src/tools/clippy/tests/ui/to_digit_is_some.fixed b/src/tools/clippy/tests/ui/to_digit_is_some.fixed
index 3c5e96427..dc9be66d4 100644
--- a/src/tools/clippy/tests/ui/to_digit_is_some.fixed
+++ b/src/tools/clippy/tests/ui/to_digit_is_some.fixed
@@ -1,4 +1,4 @@
-//run-rustfix
+//@run-rustfix
#![warn(clippy::to_digit_is_some)]
diff --git a/src/tools/clippy/tests/ui/to_digit_is_some.rs b/src/tools/clippy/tests/ui/to_digit_is_some.rs
index 4f247c06c..d2a09ac30 100644
--- a/src/tools/clippy/tests/ui/to_digit_is_some.rs
+++ b/src/tools/clippy/tests/ui/to_digit_is_some.rs
@@ -1,4 +1,4 @@
-//run-rustfix
+//@run-rustfix
#![warn(clippy::to_digit_is_some)]
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed b/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
index 174c858a4..ea30c1fda 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::toplevel_ref_arg)]
#![allow(clippy::uninlined_format_args, unused)]
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg.rs b/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
index 4b81a0611..7a3d33e5b 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![warn(clippy::toplevel_ref_arg)]
#![allow(clippy::uninlined_format_args, unused)]
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs b/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs
index 2047593e7..8aaf47b1b 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![warn(clippy::toplevel_ref_arg)]
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/track-diagnostics.rs b/src/tools/clippy/tests/ui/track-diagnostics.rs
index fa9221ed0..6ab0bce77 100644
--- a/src/tools/clippy/tests/ui/track-diagnostics.rs
+++ b/src/tools/clippy/tests/ui/track-diagnostics.rs
@@ -1,9 +1,8 @@
-// compile-flags: -Z track-diagnostics
-// error-pattern: created at
+//@compile-flags: -Z track-diagnostics
// Normalize the emitted location so this doesn't need
// updating everytime someone adds or removes a line.
-// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
+//@normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:CC"
struct A;
struct B;
diff --git a/src/tools/clippy/tests/ui/trailing_empty_array.rs b/src/tools/clippy/tests/ui/trailing_empty_array.rs
index 8e3749eef..928475b5f 100644
--- a/src/tools/clippy/tests/ui/trailing_empty_array.rs
+++ b/src/tools/clippy/tests/ui/trailing_empty_array.rs
@@ -144,7 +144,7 @@ struct ReprCAlign {
// NOTE: because of https://doc.rust-lang.org/stable/reference/type-layout.html#primitive-representation-of-enums-with-fields and I'm not sure when in the compilation pipeline that would happen
#[repr(C)]
-enum DontLintAnonymousStructsFromDesuraging {
+enum DontLintAnonymousStructsFromDesugaring {
A(u32),
B(f32, [u64; 0]),
C { x: u32, y: [u64; 0] },
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
index 4ce5d4217..fdac0e4cb 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
@@ -1,7 +1,9 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::trait_duplication_in_bounds)]
#![allow(unused)]
+use std::any::Any;
+
fn bad_foo<T: Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
unimplemented!();
}
@@ -109,4 +111,12 @@ fn qualified_path<T: std::clone::Clone + foo::Clone>(arg0: T) {
unimplemented!();
}
+fn good_trait_object(arg0: &(dyn Any + Send)) {
+ unimplemented!();
+}
+
+fn bad_trait_object(arg0: &(dyn Any + Send)) {
+ unimplemented!();
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
index 7f2e96a22..a0300da55 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
@@ -1,7 +1,9 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::trait_duplication_in_bounds)]
#![allow(unused)]
+use std::any::Any;
+
fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
unimplemented!();
}
@@ -109,4 +111,12 @@ fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
unimplemented!();
}
+fn good_trait_object(arg0: &(dyn Any + Send)) {
+ unimplemented!();
+}
+
+fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
+ unimplemented!();
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
index af800ba78..539b6114c 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
@@ -1,5 +1,5 @@
error: these bounds contain repeated elements
- --> $DIR/trait_duplication_in_bounds.rs:5:15
+ --> $DIR/trait_duplication_in_bounds.rs:7:15
|
LL | fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
@@ -11,46 +11,52 @@ LL | #![deny(clippy::trait_duplication_in_bounds)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: these where clauses contain repeated elements
- --> $DIR/trait_duplication_in_bounds.rs:11:8
+ --> $DIR/trait_duplication_in_bounds.rs:13:8
|
LL | T: Clone + Clone + Clone + Copy,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
error: these bounds contain repeated elements
- --> $DIR/trait_duplication_in_bounds.rs:39:26
+ --> $DIR/trait_duplication_in_bounds.rs:41:26
|
LL | trait BadSelfTraitBound: Clone + Clone + Clone {
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
error: these where clauses contain repeated elements
- --> $DIR/trait_duplication_in_bounds.rs:46:15
+ --> $DIR/trait_duplication_in_bounds.rs:48:15
|
LL | Self: Clone + Clone + Clone;
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
error: these bounds contain repeated elements
- --> $DIR/trait_duplication_in_bounds.rs:60:24
+ --> $DIR/trait_duplication_in_bounds.rs:62:24
|
LL | trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
error: these where clauses contain repeated elements
- --> $DIR/trait_duplication_in_bounds.rs:67:12
+ --> $DIR/trait_duplication_in_bounds.rs:69:12
|
LL | T: Clone + Clone + Clone + Copy,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
error: these bounds contain repeated elements
- --> $DIR/trait_duplication_in_bounds.rs:100:19
+ --> $DIR/trait_duplication_in_bounds.rs:102:19
|
LL | fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u64> + GenericTrait<u32>`
error: these bounds contain repeated elements
- --> $DIR/trait_duplication_in_bounds.rs:108:22
+ --> $DIR/trait_duplication_in_bounds.rs:110:22
|
LL | fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::clone::Clone + foo::Clone`
-error: aborting due to 8 previous errors
+error: this trait bound is already specified in trait declaration
+ --> $DIR/trait_duplication_in_bounds.rs:118:33
+ |
+LL | fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
+ | ^^^^^^^^^^^^^^^^^ help: try: `Any + Send`
+
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/transmute_32bit.rs b/src/tools/clippy/tests/ui/transmute_32bit.rs
index ffe22b12f..8e1316ca3 100644
--- a/src/tools/clippy/tests/ui/transmute_32bit.rs
+++ b/src/tools/clippy/tests/ui/transmute_32bit.rs
@@ -1,4 +1,4 @@
-// ignore-64bit
+//@ignore-64bit
#[warn(clippy::wrong_transmute)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/transmute_32bit.stderr b/src/tools/clippy/tests/ui/transmute_32bit.stderr
index 040519564..75ddca60d 100644
--- a/src/tools/clippy/tests/ui/transmute_32bit.stderr
+++ b/src/tools/clippy/tests/ui/transmute_32bit.stderr
@@ -1,28 +1,39 @@
-error: transmute from a `f32` to a pointer
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_32bit.rs:6:31
|
LL | let _: *const usize = std::mem::transmute(6.0f32);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::wrong-transmute` implied by `-D warnings`
+ = note: source type: `f32` (32 bits)
+ = note: target type: `*const usize` (64 bits)
-error: transmute from a `f32` to a pointer
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_32bit.rs:8:29
|
LL | let _: *mut usize = std::mem::transmute(6.0f32);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `f32` (32 bits)
+ = note: target type: `*mut usize` (64 bits)
-error: transmute from a `char` to a pointer
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_32bit.rs:10:31
|
LL | let _: *const usize = std::mem::transmute('x');
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `char` (32 bits)
+ = note: target type: `*const usize` (64 bits)
-error: transmute from a `char` to a pointer
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_32bit.rs:12:29
|
LL | let _: *mut usize = std::mem::transmute('x');
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `char` (32 bits)
+ = note: target type: `*mut usize` (64 bits)
error: aborting due to 4 previous errors
+For more information about this error, try `rustc --explain E0512`.
diff --git a/src/tools/clippy/tests/ui/transmute_64bit.rs b/src/tools/clippy/tests/ui/transmute_64bit.rs
index 00dc0b2c3..ceecf9b27 100644
--- a/src/tools/clippy/tests/ui/transmute_64bit.rs
+++ b/src/tools/clippy/tests/ui/transmute_64bit.rs
@@ -1,4 +1,4 @@
-// ignore-32bit
+//@ignore-32bit
#[warn(clippy::wrong_transmute)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
index 074dae5fb..575dadde9 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::transmute_ptr_to_ref)]
#![allow(clippy::match_single_binding)]
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
index 2edc122cf..4238ff804 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::transmute_ptr_to_ref)]
#![allow(clippy::match_single_binding)]
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index cc84ba25b..05aa86c47 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::transmutes_expressible_as_ptr_casts)]
// These two warnings currently cover the cases transmutes_expressible_as_ptr_casts
// would otherwise be responsible for
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
index aa65ab4dd..29fa6914c 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::transmutes_expressible_as_ptr_casts)]
// These two warnings currently cover the cases transmutes_expressible_as_ptr_casts
// would otherwise be responsible for
diff --git a/src/tools/clippy/tests/ui/trim_split_whitespace.fixed b/src/tools/clippy/tests/ui/trim_split_whitespace.fixed
index e4d352f73..7909b319d 100644
--- a/src/tools/clippy/tests/ui/trim_split_whitespace.fixed
+++ b/src/tools/clippy/tests/ui/trim_split_whitespace.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::trim_split_whitespace)]
#![allow(clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/trim_split_whitespace.rs b/src/tools/clippy/tests/ui/trim_split_whitespace.rs
index f98451a98..0cf58979f 100644
--- a/src/tools/clippy/tests/ui/trim_split_whitespace.rs
+++ b/src/tools/clippy/tests/ui/trim_split_whitespace.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::trim_split_whitespace)]
#![allow(clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
index c0af011d3..486155831 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
@@ -1,5 +1,5 @@
-// normalize-stderr-test "\(\d+ byte\)" -> "(N byte)"
-// normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)"
+//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
+//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
#![deny(clippy::trivially_copy_pass_by_ref)]
#![allow(
clippy::disallowed_names,
diff --git a/src/tools/clippy/tests/ui/try_err.fixed b/src/tools/clippy/tests/ui/try_err.fixed
index dc497b169..dc773ad4b 100644
--- a/src/tools/clippy/tests/ui/try_err.fixed
+++ b/src/tools/clippy/tests/ui/try_err.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![deny(clippy::try_err)]
#![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
diff --git a/src/tools/clippy/tests/ui/try_err.rs b/src/tools/clippy/tests/ui/try_err.rs
index 86aeb75cd..7a7433a7e 100644
--- a/src/tools/clippy/tests/ui/try_err.rs
+++ b/src/tools/clippy/tests/ui/try_err.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macros.rs
+//@run-rustfix
+//@aux-build:proc_macros.rs
#![deny(clippy::try_err)]
#![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
diff --git a/src/tools/clippy/tests/ui/types.fixed b/src/tools/clippy/tests/ui/types.fixed
index 417da42ed..4a2616a7a 100644
--- a/src/tools/clippy/tests/ui/types.fixed
+++ b/src/tools/clippy/tests/ui/types.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, unused_variables)]
#![warn(clippy::cast_lossless)]
diff --git a/src/tools/clippy/tests/ui/types.rs b/src/tools/clippy/tests/ui/types.rs
index b16e9e538..5e0917907 100644
--- a/src/tools/clippy/tests/ui/types.rs
+++ b/src/tools/clippy/tests/ui/types.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code, unused_variables)]
#![warn(clippy::cast_lossless)]
diff --git a/src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed
index a0e49a8be..757d15921 100644
--- a/src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed
+++ b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unchecked_duration_subtraction)]
use std::time::{Duration, Instant};
diff --git a/src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs
index a14a7ea57..da7faab67 100644
--- a/src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs
+++ b/src/tools/clippy/tests/ui/unchecked_duration_subtraction.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unchecked_duration_subtraction)]
use std::time::{Duration, Instant};
diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
index c05eb447b..229d15085 100644
--- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macro_unsafe.rs
+//@aux-build:proc_macro_unsafe.rs
#![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)]
#![allow(clippy::let_unit_value, clippy::missing_safety_doc)]
diff --git a/src/tools/clippy/tests/ui/unicode.fixed b/src/tools/clippy/tests/ui/unicode.fixed
index 94b472345..910968afa 100644
--- a/src/tools/clippy/tests/ui/unicode.fixed
+++ b/src/tools/clippy/tests/ui/unicode.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// compile-flags: --test
+//@run-rustfix
+//@compile-flags: --test
#![allow(dead_code)]
#[warn(clippy::invisible_characters)]
diff --git a/src/tools/clippy/tests/ui/unicode.rs b/src/tools/clippy/tests/ui/unicode.rs
index 6ad0b255b..bc4b84d34 100644
--- a/src/tools/clippy/tests/ui/unicode.rs
+++ b/src/tools/clippy/tests/ui/unicode.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// compile-flags: --test
+//@run-rustfix
+//@compile-flags: --test
#![allow(dead_code)]
#[warn(clippy::invisible_characters)]
diff --git a/src/tools/clippy/tests/ui/uninit.rs b/src/tools/clippy/tests/ui/uninit.rs
index c996de894..2d567630e 100644
--- a/src/tools/clippy/tests/ui/uninit.rs
+++ b/src/tools/clippy/tests/ui/uninit.rs
@@ -17,10 +17,10 @@ fn main() {
// This is OK, because `MaybeUninit` allows uninitialized data.
let _: MaybeUninit<usize> = unsafe { MaybeUninit::uninit().assume_init() };
- // This is OK, because all constitutent types are uninit-compatible.
+ // This is OK, because all constituent types are uninit-compatible.
let _: (MaybeUninit<usize>, MaybeUninit<bool>) = unsafe { MaybeUninit::uninit().assume_init() };
- // This is OK, because all constitutent types are uninit-compatible.
+ // This is OK, because all constituent types are uninit-compatible.
let _: (MaybeUninit<usize>, [MaybeUninit<bool>; 2]) = unsafe { MaybeUninit::uninit().assume_init() };
// This is OK, because our own MaybeUninit is just as fine as the one from core.
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.fixed b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
index 3122081a4..e25d123dd 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
@@ -1,5 +1,5 @@
-// aux-build:proc_macros.rs
-// run-rustfix
+//@aux-build:proc_macros.rs
+//@run-rustfix
#![warn(clippy::uninlined_format_args)]
#![allow(named_arguments_used_positionally, unused)]
#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.rs b/src/tools/clippy/tests/ui/uninlined_format_args.rs
index b153ef256..6793ec244 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.rs
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.rs
@@ -1,5 +1,5 @@
-// aux-build:proc_macros.rs
-// run-rustfix
+//@aux-build:proc_macros.rs
+//@run-rustfix
#![warn(clippy::uninlined_format_args)]
#![allow(named_arguments_used_positionally, unused)]
#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
index 52b5343c3..559050b3d 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
@@ -1,7 +1,7 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
#![warn(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
index ee72065e2..3a753b49c 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
@@ -1,7 +1,7 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
#![warn(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs b/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
index b4a0a0f49..83fbb9afd 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
@@ -1,7 +1,7 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
#![warn(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/unit_arg.rs b/src/tools/clippy/tests/ui/unit_arg.rs
index 674ae4f1d..d082063c8 100644
--- a/src/tools/clippy/tests/ui/unit_arg.rs
+++ b/src/tools/clippy/tests/ui/unit_arg.rs
@@ -1,4 +1,4 @@
-// aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs
#![warn(clippy::unit_arg)]
#![allow(unused_must_use, unused_variables)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed
index 5787471a3..8c065115a 100644
--- a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed
+++ b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unit_arg)]
#![allow(unused_must_use, unused_variables)]
#![allow(clippy::no_effect, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs
index 6a42c2ccf..af166b56f 100644
--- a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs
+++ b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unit_arg)]
#![allow(unused_must_use, unused_variables)]
#![allow(clippy::no_effect, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed b/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
index 4249ff8a9..49c0e4dc7 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::pedantic)]
// Should suggest lowercase
@@ -10,7 +10,7 @@
#[warn(clippy::unnecessary_cast)]
#[warn(clippy::useless_transmute)]
// Shouldn't suggest rustc lint name(`dead_code`)
-#[warn(clippy::drop_copy)]
+#[warn(clippy::eq_op)]
// Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
#[warn(clippy::unused_self)]
// Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.rs b/src/tools/clippy/tests/ui/unknown_clippy_lints.rs
index 5db345f54..b60042923 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.rs
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::pedantic)]
// Should suggest lowercase
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
index 421bf5ffa..584c42893 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
@@ -34,7 +34,7 @@ error: unknown lint: `clippy::dead_cod`
--> $DIR/unknown_clippy_lints.rs:13:8
|
LL | #[warn(clippy::dead_cod)]
- | ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::drop_copy`
+ | ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::eq_op`
error: unknown lint: `clippy::unused_colle`
--> $DIR/unknown_clippy_lints.rs:15:8
diff --git a/src/tools/clippy/tests/ui/unnecessary_box_returns.rs b/src/tools/clippy/tests/ui/unnecessary_box_returns.rs
index fe60d9297..ce7cc2e97 100644
--- a/src/tools/clippy/tests/ui/unnecessary_box_returns.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_box_returns.rs
@@ -54,6 +54,16 @@ fn string() -> String {
String::from("Hello, world")
}
+struct Huge([u8; 500]);
+struct HasHuge(Box<Huge>);
+
+impl HasHuge {
+ // don't lint: The size of `Huge` is very large
+ fn into_huge(self) -> Box<Huge> {
+ self.0
+ }
+}
+
fn main() {
// don't lint: this is a closure
let a = || -> Box<usize> { Box::new(5) };
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
index 2f7e2997e..bcc231ea7 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unnecessary_cast)]
#![allow(
unused_must_use,
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs
index 54dd46ba5..282b2f128 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unnecessary_cast)]
#![allow(
unused_must_use,
diff --git a/src/tools/clippy/tests/ui/unnecessary_clone.rs b/src/tools/clippy/tests/ui/unnecessary_clone.rs
index 8b1629b19..7ceed3c75 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clone.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_clone.rs
@@ -42,14 +42,6 @@ fn clone_on_copy_generic<T: Copy>(t: T) {
Some(t).clone();
}
-fn clone_on_double_ref() {
- let x = vec![1];
- let y = &&x;
- let z: &Vec<_> = y.clone();
-
- println!("{:p} {:p}", *y, z);
-}
-
mod many_derefs {
struct A;
struct B;
@@ -84,11 +76,6 @@ mod many_derefs {
let _: E = a.clone();
let _: E = *****a;
}
-
- fn check(mut encoded: &[u8]) {
- let _ = &mut encoded.clone();
- let _ = &encoded.clone();
- }
}
mod issue2076 {
diff --git a/src/tools/clippy/tests/ui/unnecessary_clone.stderr b/src/tools/clippy/tests/ui/unnecessary_clone.stderr
index 6022d9fa4..5686ab6b4 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clone.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_clone.stderr
@@ -44,63 +44,17 @@ error: using `clone` on type `Option<T>` which implements the `Copy` trait
LL | Some(t).clone();
| ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
-error: using `clone` on a double-reference; this will copy the reference of type `&Vec<i32>` instead of cloning the inner type
- --> $DIR/unnecessary_clone.rs:48:22
- |
-LL | let z: &Vec<_> = y.clone();
- | ^^^^^^^^^
- |
- = note: `#[deny(clippy::clone_double_ref)]` on by default
-help: try dereferencing it
- |
-LL | let z: &Vec<_> = &(*y).clone();
- | ~~~~~~~~~~~~~
-help: or try being explicit if you are sure, that you want to clone a reference
- |
-LL | let z: &Vec<_> = <&Vec<i32>>::clone(y);
- | ~~~~~~~~~~~~~~~~~~~~~
-
error: using `clone` on type `E` which implements the `Copy` trait
- --> $DIR/unnecessary_clone.rs:84:20
+ --> $DIR/unnecessary_clone.rs:76:20
|
LL | let _: E = a.clone();
| ^^^^^^^^^ help: try dereferencing it: `*****a`
-error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type
- --> $DIR/unnecessary_clone.rs:89:22
- |
-LL | let _ = &mut encoded.clone();
- | ^^^^^^^^^^^^^^^
- |
-help: try dereferencing it
- |
-LL | let _ = &mut &(*encoded).clone();
- | ~~~~~~~~~~~~~~~~~~~
-help: or try being explicit if you are sure, that you want to clone a reference
- |
-LL | let _ = &mut <&[u8]>::clone(encoded);
- | ~~~~~~~~~~~~~~~~~~~~~~~
-
-error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type
- --> $DIR/unnecessary_clone.rs:90:18
- |
-LL | let _ = &encoded.clone();
- | ^^^^^^^^^^^^^^^
- |
-help: try dereferencing it
- |
-LL | let _ = &&(*encoded).clone();
- | ~~~~~~~~~~~~~~~~~~~
-help: or try being explicit if you are sure, that you want to clone a reference
- |
-LL | let _ = &<&[u8]>::clone(encoded);
- | ~~~~~~~~~~~~~~~~~~~~~~~
-
error: using `.clone()` on a ref-counted pointer
- --> $DIR/unnecessary_clone.rs:108:14
+ --> $DIR/unnecessary_clone.rs:95:14
|
LL | Some(try_opt!(Some(rc)).clone())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Rc::<u8>::clone(&try_opt!(Some(rc)))`
-error: aborting due to 12 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.fixed b/src/tools/clippy/tests/ui/unnecessary_fold.fixed
index 52300a3b6..2bed14973 100644
--- a/src/tools/clippy/tests/ui/unnecessary_fold.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_fold.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.rs b/src/tools/clippy/tests/ui/unnecessary_fold.rs
index 4028d80c0..a3cec8ea3 100644
--- a/src/tools/clippy/tests/ui/unnecessary_fold.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_fold.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
index e01e9f07b..a0f8dd1a2 100644
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_assignments)]
#![warn(clippy::unnecessary_to_owned)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
index 6ef2966c8..98f2dfe75 100644
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_assignments)]
#![warn(clippy::unnecessary_to_owned)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_join.fixed b/src/tools/clippy/tests/ui/unnecessary_join.fixed
index 347953960..e102df625 100644
--- a/src/tools/clippy/tests/ui/unnecessary_join.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_join.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unnecessary_join)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_join.rs b/src/tools/clippy/tests/ui/unnecessary_join.rs
index 344918cd2..b87c15bc1 100644
--- a/src/tools/clippy/tests/ui/unnecessary_join.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_join.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unnecessary_join)]
#![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
index 3b93800f8..c3728886e 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build: proc_macros.rs
+//@run-rustfix
+//@aux-build: proc_macros.rs
#![warn(clippy::unnecessary_lazy_evaluations)]
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
index 2851c0c51..76e50fa5b 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build: proc_macros.rs
+//@run-rustfix
+//@aux-build: proc_macros.rs
#![warn(clippy::unnecessary_lazy_evaluations)]
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.fixed b/src/tools/clippy/tests/ui/unnecessary_operation.fixed
index b046694f8..fbd2d3459 100644
--- a/src/tools/clippy/tests/ui/unnecessary_operation.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_operation.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
clippy::deref_addrof,
diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.rs b/src/tools/clippy/tests/ui/unnecessary_operation.rs
index 9ed9679e9..b45298a6d 100644
--- a/src/tools/clippy/tests/ui/unnecessary_operation.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_operation.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(
clippy::deref_addrof,
diff --git a/src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.fixed b/src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.fixed
index 40052c410..af12fd1d6 100644
--- a/src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unnecessary_owned_empty_strings)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.rs b/src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.rs
index 2304dff51..a460b21af 100644
--- a/src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_owned_empty_strings.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unnecessary_owned_empty_strings)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_self_imports.fixed b/src/tools/clippy/tests/ui/unnecessary_self_imports.fixed
index 1185eaa1d..7fc978d3e 100644
--- a/src/tools/clippy/tests/ui/unnecessary_self_imports.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_self_imports.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unnecessary_self_imports)]
#![allow(unused_imports, dead_code)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_self_imports.rs b/src/tools/clippy/tests/ui/unnecessary_self_imports.rs
index 56bfbc094..02424bc12 100644
--- a/src/tools/clippy/tests/ui/unnecessary_self_imports.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_self_imports.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unnecessary_self_imports)]
#![allow(unused_imports, dead_code)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed
index 21e2da474..165cabd82 100644
--- a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::stable_sort_primitive)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs
index 3365bf6e1..8a2158d5a 100644
--- a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::stable_sort_primitive)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
index b47129e4a..bdf746cf2 100644
--- a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::unnecessary_struct_initialization)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
index 63b11c626..7271e2f95 100644
--- a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused)]
#![warn(clippy::unnecessary_struct_initialization)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
index 345f6d604..08733906b 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
@@ -1,7 +1,7 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::needless_borrow, clippy::ptr_arg)]
-#![warn(clippy::unnecessary_to_owned)]
+#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
use std::borrow::Cow;
use std::ffi::{CStr, CString, OsStr, OsString};
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
index 7eb53df39..e3589ea0d 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
@@ -1,7 +1,7 @@
-// run-rustfix
+//@run-rustfix
#![allow(clippy::needless_borrow, clippy::ptr_arg)]
-#![warn(clippy::unnecessary_to_owned)]
+#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
use std::borrow::Cow;
use std::ffi::{CStr, CString, OsStr, OsString};
diff --git a/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs b/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs
index 431093ab3..373b18470 100644
--- a/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs
#![allow(clippy::let_unit_value)]
#![warn(clippy::unnecessary_safety_doc)]
diff --git a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed
index 12c3461c9..16c2de760 100644
--- a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed
+++ b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(stmt_expr_attributes)]
#![deny(clippy::unneeded_wildcard_pattern)]
diff --git a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs
index 4ac01d5d2..9d9eae1d9 100644
--- a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs
+++ b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(stmt_expr_attributes)]
#![deny(clippy::unneeded_wildcard_pattern)]
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
index 0a8e7b34d..8ec35ba4e 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(box_patterns)]
#![warn(clippy::unnested_or_patterns)]
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.rs b/src/tools/clippy/tests/ui/unnested_or_patterns.rs
index 2c454adfe..efdb91b24 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.rs
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(box_patterns)]
#![warn(clippy::unnested_or_patterns)]
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
index d3539d798..de40e9367 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(box_patterns)]
#![warn(clippy::unnested_or_patterns)]
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.rs b/src/tools/clippy/tests/ui/unnested_or_patterns2.rs
index 9cea5cdea..87f66d26c 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns2.rs
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(box_patterns)]
#![warn(clippy::unnested_or_patterns)]
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.fixed b/src/tools/clippy/tests/ui/unreadable_literal.fixed
index 13e5feb19..f5e87648a 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.fixed
+++ b/src/tools/clippy/tests/ui/unreadable_literal.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unreadable_literal)]
#![allow(unused_tuple_struct_fields)]
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.rs b/src/tools/clippy/tests/ui/unreadable_literal.rs
index 82f04e7ce..426bdf7d7 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.rs
+++ b/src/tools/clippy/tests/ui/unreadable_literal.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unreadable_literal)]
#![allow(unused_tuple_struct_fields)]
diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed b/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
index f0c2ba7cc..b6241612d 100644
--- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
+++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macro_derive.rs
+//@run-rustfix
+//@aux-build:proc_macro_derive.rs
#![warn(clippy::unseparated_literal_suffix)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs b/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
index f44880b41..ae583f4bd 100644
--- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
+++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macro_derive.rs
+//@run-rustfix
+//@aux-build:proc_macro_derive.rs
#![warn(clippy::unseparated_literal_suffix)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unused_rounding.fixed b/src/tools/clippy/tests/ui/unused_rounding.fixed
index f6f734c05..f02b55502 100644
--- a/src/tools/clippy/tests/ui/unused_rounding.fixed
+++ b/src/tools/clippy/tests/ui/unused_rounding.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unused_rounding)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/unused_rounding.rs b/src/tools/clippy/tests/ui/unused_rounding.rs
index a0267d814..c7bd4906d 100644
--- a/src/tools/clippy/tests/ui/unused_rounding.rs
+++ b/src/tools/clippy/tests/ui/unused_rounding.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unused_rounding)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/unused_unit.fixed b/src/tools/clippy/tests/ui/unused_unit.fixed
index 3dd640b86..7b8f7847d 100644
--- a/src/tools/clippy/tests/ui/unused_unit.fixed
+++ b/src/tools/clippy/tests/ui/unused_unit.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
// The output for humans should just highlight the whole span without showing
// the suggested replacement, but we also want to test that suggested
diff --git a/src/tools/clippy/tests/ui/unused_unit.rs b/src/tools/clippy/tests/ui/unused_unit.rs
index bddecf06f..fdde1ecad 100644
--- a/src/tools/clippy/tests/ui/unused_unit.rs
+++ b/src/tools/clippy/tests/ui/unused_unit.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
// The output for humans should just highlight the whole span without showing
// the suggested replacement, but we also want to test that suggested
diff --git a/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed b/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed
index 84f779569..59a0ca3f1 100644
--- a/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed
+++ b/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unwrap_or_else_default)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unwrap_or_else_default.rs b/src/tools/clippy/tests/ui/unwrap_or_else_default.rs
index 1735bd580..97cafa336 100644
--- a/src/tools/clippy/tests/ui/unwrap_or_else_default.rs
+++ b/src/tools/clippy/tests/ui/unwrap_or_else_default.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::unwrap_or_else_default)]
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed
index 3ac621731..89ea14759 100644
--- a/src/tools/clippy/tests/ui/use_self.fixed
+++ b/src/tools/clippy/tests/ui/use_self.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macro_derive.rs
+//@run-rustfix
+//@aux-build:proc_macro_derive.rs
#![warn(clippy::use_self)]
#![allow(dead_code, unreachable_code)]
diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs
index 9dc5d1e3f..49e5bcb7e 100644
--- a/src/tools/clippy/tests/ui/use_self.rs
+++ b/src/tools/clippy/tests/ui/use_self.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macro_derive.rs
+//@run-rustfix
+//@aux-build:proc_macro_derive.rs
#![warn(clippy::use_self)]
#![allow(dead_code, unreachable_code)]
diff --git a/src/tools/clippy/tests/ui/use_self_trait.fixed b/src/tools/clippy/tests/ui/use_self_trait.fixed
index 4e779308d..20138a29f 100644
--- a/src/tools/clippy/tests/ui/use_self_trait.fixed
+++ b/src/tools/clippy/tests/ui/use_self_trait.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::use_self)]
#![allow(dead_code)]
@@ -33,7 +33,7 @@ impl SelfTrait for Bad {
fn nested(_p1: Box<Self>, _p2: (&u8, &Self)) {}
fn vals(_: Self) -> Self {
- Self::default()
+ Self
}
}
@@ -70,7 +70,7 @@ impl SelfTrait for Good {
fn nested(_p1: Box<Self>, _p2: (&u8, &Self)) {}
fn vals(_: Self) -> Self {
- Self::default()
+ Self
}
}
diff --git a/src/tools/clippy/tests/ui/use_self_trait.rs b/src/tools/clippy/tests/ui/use_self_trait.rs
index 325dc73b2..bf697b01a 100644
--- a/src/tools/clippy/tests/ui/use_self_trait.rs
+++ b/src/tools/clippy/tests/ui/use_self_trait.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::use_self)]
#![allow(dead_code)]
@@ -33,7 +33,7 @@ impl SelfTrait for Bad {
fn nested(_p1: Box<Bad>, _p2: (&u8, &Bad)) {}
fn vals(_: Bad) -> Bad {
- Bad::default()
+ Bad
}
}
@@ -70,7 +70,7 @@ impl SelfTrait for Good {
fn nested(_p1: Box<Self>, _p2: (&u8, &Self)) {}
fn vals(_: Self) -> Self {
- Self::default()
+ Self
}
}
diff --git a/src/tools/clippy/tests/ui/use_self_trait.stderr b/src/tools/clippy/tests/ui/use_self_trait.stderr
index 090729b9c..6257f802d 100644
--- a/src/tools/clippy/tests/ui/use_self_trait.stderr
+++ b/src/tools/clippy/tests/ui/use_self_trait.stderr
@@ -63,7 +63,7 @@ LL | fn vals(_: Bad) -> Bad {
error: unnecessary structure name repetition
--> $DIR/use_self_trait.rs:36:9
|
-LL | Bad::default()
+LL | Bad
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs
index 8c29e15b1..c672eff1c 100644
--- a/src/tools/clippy/tests/ui/used_underscore_binding.rs
+++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs
@@ -1,4 +1,4 @@
-// aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs
#![feature(rustc_private)]
#![warn(clippy::all)]
#![warn(clippy::used_underscore_binding)]
diff --git a/src/tools/clippy/tests/ui/useless_asref.fixed b/src/tools/clippy/tests/ui/useless_asref.fixed
index 38e4b9201..490d36ae6 100644
--- a/src/tools/clippy/tests/ui/useless_asref.fixed
+++ b/src/tools/clippy/tests/ui/useless_asref.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::useless_asref)]
#![allow(clippy::explicit_auto_deref, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/useless_asref.rs b/src/tools/clippy/tests/ui/useless_asref.rs
index f1e83f9d3..f2681af92 100644
--- a/src/tools/clippy/tests/ui/useless_asref.rs
+++ b/src/tools/clippy/tests/ui/useless_asref.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::useless_asref)]
#![allow(clippy::explicit_auto_deref, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/useless_attribute.fixed b/src/tools/clippy/tests/ui/useless_attribute.fixed
index 871e4fb5c..de6660c95 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.fixed
+++ b/src/tools/clippy/tests/ui/useless_attribute.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macro_derive.rs
+//@run-rustfix
+//@aux-build:proc_macro_derive.rs
#![allow(unused)]
#![warn(clippy::useless_attribute)]
diff --git a/src/tools/clippy/tests/ui/useless_attribute.rs b/src/tools/clippy/tests/ui/useless_attribute.rs
index cb50736ba..8de4331e8 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.rs
+++ b/src/tools/clippy/tests/ui/useless_attribute.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:proc_macro_derive.rs
+//@run-rustfix
+//@aux-build:proc_macro_derive.rs
#![allow(unused)]
#![warn(clippy::useless_attribute)]
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index 94b206d8e..c16caa38f 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::useless_conversion)]
#![allow(clippy::unnecessary_wraps)]
@@ -33,6 +33,11 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
Ok(())
}
+fn dont_lint_on_type_alias() {
+ type A = i32;
+ _ = A::from(0i32);
+}
+
fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
let text = "foo\r\nbar\n\nbaz\n";
let lines = text.lines();
@@ -106,6 +111,7 @@ fn main() {
test_questionmark().unwrap();
test_issue_3913().unwrap();
+ dont_lint_on_type_alias();
dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
lint_into_iter_on_expr_implementing_iterator();
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index c7ae92794..c75a2bce4 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![deny(clippy::useless_conversion)]
#![allow(clippy::unnecessary_wraps)]
@@ -33,6 +33,11 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
Ok(())
}
+fn dont_lint_on_type_alias() {
+ type A = i32;
+ _ = A::from(0i32);
+}
+
fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
let text = "foo\r\nbar\n\nbaz\n";
let lines = text.lines();
@@ -106,6 +111,7 @@ fn main() {
test_questionmark().unwrap();
test_issue_3913().unwrap();
+ dont_lint_on_type_alias();
dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
lint_into_iter_on_expr_implementing_iterator();
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index be067c684..4dca3aac5 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -23,97 +23,97 @@ LL | let _: i32 = 0i32.into();
| ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
error: useless conversion to the same type: `std::str::Lines<'_>`
- --> $DIR/useless_conversion.rs:45:22
+ --> $DIR/useless_conversion.rs:50:22
|
LL | if Some("ok") == lines.into_iter().next() {}
| ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines`
error: useless conversion to the same type: `std::str::Lines<'_>`
- --> $DIR/useless_conversion.rs:50:21
+ --> $DIR/useless_conversion.rs:55:21
|
LL | let mut lines = text.lines().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
error: useless conversion to the same type: `std::str::Lines<'_>`
- --> $DIR/useless_conversion.rs:56:22
+ --> $DIR/useless_conversion.rs:61:22
|
LL | if Some("ok") == text.lines().into_iter().next() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
error: useless conversion to the same type: `std::ops::Range<i32>`
- --> $DIR/useless_conversion.rs:62:13
+ --> $DIR/useless_conversion.rs:67:13
|
LL | let _ = NUMBERS.into_iter().next();
| ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
error: useless conversion to the same type: `std::ops::Range<i32>`
- --> $DIR/useless_conversion.rs:67:17
+ --> $DIR/useless_conversion.rs:72:17
|
LL | let mut n = NUMBERS.into_iter();
| ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:128:21
+ --> $DIR/useless_conversion.rs:134:21
|
LL | let _: String = "foo".to_string().into();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:129:21
+ --> $DIR/useless_conversion.rs:135:21
|
LL | let _: String = From::from("foo".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:130:13
+ --> $DIR/useless_conversion.rs:136:13
|
LL | let _ = String::from("foo".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:131:13
+ --> $DIR/useless_conversion.rs:137:13
|
LL | let _ = String::from(format!("A: {:04}", 123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
error: useless conversion to the same type: `std::str::Lines<'_>`
- --> $DIR/useless_conversion.rs:132:13
+ --> $DIR/useless_conversion.rs:138:13
|
LL | let _ = "".lines().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
error: useless conversion to the same type: `std::vec::IntoIter<i32>`
- --> $DIR/useless_conversion.rs:133:13
+ --> $DIR/useless_conversion.rs:139:13
|
LL | let _ = vec![1, 2, 3].into_iter().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:134:21
+ --> $DIR/useless_conversion.rs:140:21
|
LL | let _: String = format!("Hello {}", "world").into();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
error: useless conversion to the same type: `i32`
- --> $DIR/useless_conversion.rs:139:13
+ --> $DIR/useless_conversion.rs:145:13
|
LL | let _ = i32::from(a + b) * 3;
| ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)`
error: useless conversion to the same type: `Foo<'a'>`
- --> $DIR/useless_conversion.rs:145:23
+ --> $DIR/useless_conversion.rs:151:23
|
LL | let _: Foo<'a'> = s2.into();
| ^^^^^^^^^ help: consider removing `.into()`: `s2`
error: useless conversion to the same type: `Foo<'a'>`
- --> $DIR/useless_conversion.rs:147:13
+ --> $DIR/useless_conversion.rs:153:13
|
LL | let _ = Foo::<'a'>::from(s3);
| ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3`
error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>`
- --> $DIR/useless_conversion.rs:149:13
+ --> $DIR/useless_conversion.rs:155:13
|
LL | let _ = vec![s4, s4, s4].into_iter().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
diff --git a/src/tools/clippy/tests/ui/vec.fixed b/src/tools/clippy/tests/ui/vec.fixed
index 2518d8049..d77a4dd8e 100644
--- a/src/tools/clippy/tests/ui/vec.fixed
+++ b/src/tools/clippy/tests/ui/vec.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::useless_vec)]
#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/vec.rs b/src/tools/clippy/tests/ui/vec.rs
index e1492e2f3..dfed3a29a 100644
--- a/src/tools/clippy/tests/ui/vec.rs
+++ b/src/tools/clippy/tests/ui/vec.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::useless_vec)]
#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/vec_box_sized.fixed b/src/tools/clippy/tests/ui/vec_box_sized.fixed
index a40d91fdb..0d0f710b5 100644
--- a/src/tools/clippy/tests/ui/vec_box_sized.fixed
+++ b/src/tools/clippy/tests/ui/vec_box_sized.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/vec_box_sized.rs b/src/tools/clippy/tests/ui/vec_box_sized.rs
index 843bbb64e..fd3a7543e 100644
--- a/src/tools/clippy/tests/ui/vec_box_sized.rs
+++ b/src/tools/clippy/tests/ui/vec_box_sized.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
index 5afa0a89f..c2f216a89 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::while_let_on_iterator)]
#![allow(dead_code, unreachable_code, unused_mut)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.rs b/src/tools/clippy/tests/ui/while_let_on_iterator.rs
index 3de586c9d..971bd5f0c 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.rs
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![warn(clippy::while_let_on_iterator)]
#![allow(dead_code, unreachable_code, unused_mut)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
index 293bf75a7..ccb40acfb 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:non-exhaustive-enum.rs
+//@run-rustfix
+//@aux-build:non-exhaustive-enum.rs
#![deny(clippy::wildcard_enum_match_arm)]
#![allow(dead_code, unreachable_code, unused_variables)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
index decd86165..3ce00b021 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
@@ -1,5 +1,5 @@
-// run-rustfix
-// aux-build:non-exhaustive-enum.rs
+//@run-rustfix
+//@aux-build:non-exhaustive-enum.rs
#![deny(clippy::wildcard_enum_match_arm)]
#![allow(dead_code, unreachable_code, unused_variables)]
#![allow(
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed
index 0baec6f0b..bd845361f 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed
@@ -1,6 +1,6 @@
-// edition:2015
-// run-rustfix
-// aux-build:wildcard_imports_helper.rs
+//@edition:2015
+//@run-rustfix
+//@aux-build:wildcard_imports_helper.rs
// the 2015 edition here is needed because edition 2018 changed the module system
// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs
index db591d56a..fb51f7bdf 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.rs
+++ b/src/tools/clippy/tests/ui/wildcard_imports.rs
@@ -1,6 +1,6 @@
-// edition:2015
-// run-rustfix
-// aux-build:wildcard_imports_helper.rs
+//@edition:2015
+//@run-rustfix
+//@aux-build:wildcard_imports_helper.rs
// the 2015 edition here is needed because edition 2018 changed the module system
// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed
index 6d534a10e..3aea013fb 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed
@@ -1,8 +1,8 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
-// aux-build:wildcard_imports_helper.rs
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
+//@aux-build:wildcard_imports_helper.rs
#![warn(clippy::wildcard_imports)]
#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed
index 6d534a10e..3aea013fb 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed
@@ -1,8 +1,8 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
-// aux-build:wildcard_imports_helper.rs
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
+//@aux-build:wildcard_imports_helper.rs
#![warn(clippy::wildcard_imports)]
#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs
index b5ed58e68..40c2d0752 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs
@@ -1,8 +1,8 @@
-// revisions: edition2018 edition2021
-//[edition2018] edition:2018
-//[edition2021] edition:2021
-// run-rustfix
-// aux-build:wildcard_imports_helper.rs
+//@revisions: edition2018 edition2021
+//@[edition2018] edition:2018
+//@[edition2021] edition:2021
+//@run-rustfix
+//@aux-build:wildcard_imports_helper.rs
#![warn(clippy::wildcard_imports)]
#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr
deleted file mode 100644
index 92f6d3153..000000000
--- a/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr
+++ /dev/null
@@ -1,132 +0,0 @@
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:9:5
- |
-LL | use crate::fn_mod::*;
- | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
- |
- = note: `-D clippy::wildcard-imports` implied by `-D warnings`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:10:5
- |
-LL | use crate::mod_mod::*;
- | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:11:5
- |
-LL | use crate::multi_fn_mod::*;
- | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:12:5
- |
-LL | use crate::struct_mod::*;
- | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:15:5
- |
-LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:17:5
- |
-LL | use wildcard_imports_helper::*;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:87:13
- |
-LL | use crate::fn_mod::*;
- | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:93:75
- |
-LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
- | ^ help: try: `inner_extern_foo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:94:13
- |
-LL | use wildcard_imports_helper::*;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:105:20
- |
-LL | use self::{inner::*, inner2::*};
- | ^^^^^^^^ help: try: `inner::inner_foo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:105:30
- |
-LL | use self::{inner::*, inner2::*};
- | ^^^^^^^^^ help: try: `inner2::inner_bar`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:112:13
- |
-LL | use wildcard_imports_helper::*;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:141:9
- |
-LL | use crate::in_fn_test::*;
- | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:150:9
- |
-LL | use crate:: in_fn_test:: * ;
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:151:9
- |
-LL | use crate:: fn_mod::
- | _________^
-LL | | *;
- | |_________^ help: try: `crate:: fn_mod::foo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:162:13
- |
-LL | use super::*;
- | ^^^^^^^^ help: try: `super::foofoo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:197:17
- |
-LL | use super::*;
- | ^^^^^^^^ help: try: `super::insidefoo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:205:13
- |
-LL | use crate::super_imports::*;
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:214:17
- |
-LL | use super::super::*;
- | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:223:13
- |
-LL | use super::super::super_imports::*;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
-
-error: usage of wildcard import
- --> $DIR/wildcard_imports_2021.rs:231:13
- |
-LL | use super::*;
- | ^^^^^^^^ help: try: `super::foofoo`
-
-error: aborting due to 21 previous errors
-
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs b/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs
new file mode 100644
index 000000000..203c4e15b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs
@@ -0,0 +1,19 @@
+//@compile-flags: --test
+
+#![warn(clippy::wildcard_imports)]
+#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
+
+// Test for #10580, the lint should ignore it because of the crate's cfg test flag.
+
+fn foofoo() {}
+
+mod outer {
+ mod inner {
+ use super::super::*;
+ fn barbar() {
+ let _ = foofoo();
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/write_with_newline.rs b/src/tools/clippy/tests/ui/write_with_newline.rs
index b79364c87..35bd9e7f3 100644
--- a/src/tools/clippy/tests/ui/write_with_newline.rs
+++ b/src/tools/clippy/tests/ui/write_with_newline.rs
@@ -1,5 +1,5 @@
// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934
-// // run-rustfix
+//
#![allow(clippy::write_literal)]
#![warn(clippy::write_with_newline)]
@@ -54,7 +54,7 @@ fn main() {
// Don't warn on CRLF (#4208)
write!(v, "\r\n");
write!(v, "foo\r\n");
- write!(v, "\\r\n"); //~ ERROR
+ write!(v, "\\r\n");
write!(v, "foo\rbar\n");
// Ignore expanded format strings
diff --git a/src/tools/clippy/tests/ui/write_with_newline.stderr b/src/tools/clippy/tests/ui/write_with_newline.stderr
index 2baaea166..9035275b2 100644
--- a/src/tools/clippy/tests/ui/write_with_newline.stderr
+++ b/src/tools/clippy/tests/ui/write_with_newline.stderr
@@ -106,13 +106,13 @@ LL ~ v
error: using `write!()` with a format string that ends in a single newline
--> $DIR/write_with_newline.rs:57:5
|
-LL | write!(v, "/r/n"); //~ ERROR
+LL | write!(v, "/r/n");
| ^^^^^^^^^^^^^^^^^^
|
help: use `writeln!` instead
|
-LL - write!(v, "/r/n"); //~ ERROR
-LL + writeln!(v, "/r"); //~ ERROR
+LL - write!(v, "/r/n");
+LL + writeln!(v, "/r");
|
error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/writeln_empty_string.fixed b/src/tools/clippy/tests/ui/writeln_empty_string.fixed
index e7d94acd1..45dedd9ea 100644
--- a/src/tools/clippy/tests/ui/writeln_empty_string.fixed
+++ b/src/tools/clippy/tests/ui/writeln_empty_string.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_must_use)]
#![warn(clippy::writeln_empty_string)]
diff --git a/src/tools/clippy/tests/ui/writeln_empty_string.rs b/src/tools/clippy/tests/ui/writeln_empty_string.rs
index 662c62f02..3b9f51a15 100644
--- a/src/tools/clippy/tests/ui/writeln_empty_string.rs
+++ b/src/tools/clippy/tests/ui/writeln_empty_string.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![allow(unused_must_use)]
#![warn(clippy::writeln_empty_string)]
diff --git a/src/tools/clippy/tests/ui/zero_ptr.fixed b/src/tools/clippy/tests/ui/zero_ptr.fixed
index 489aa4121..bed38ecaf 100644
--- a/src/tools/clippy/tests/ui/zero_ptr.fixed
+++ b/src/tools/clippy/tests/ui/zero_ptr.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
pub fn foo(_const: *const f32, _mut: *mut i64) {}
fn main() {
diff --git a/src/tools/clippy/tests/ui/zero_ptr.rs b/src/tools/clippy/tests/ui/zero_ptr.rs
index c3b55ef9e..b7b778915 100644
--- a/src/tools/clippy/tests/ui/zero_ptr.rs
+++ b/src/tools/clippy/tests/ui/zero_ptr.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
pub fn foo(_const: *const f32, _mut: *mut i64) {}
fn main() {
diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed b/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed
index 8906c7769..7afd80cca 100644
--- a/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed
+++ b/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.rs b/src/tools/clippy/tests/ui/zero_ptr_no_std.rs
index 379c1b18d..05a0587d2 100644
--- a/src/tools/clippy/tests/ui/zero_ptr_no_std.rs
+++ b/src/tools/clippy/tests/ui/zero_ptr_no_std.rs
@@ -1,4 +1,4 @@
-// run-rustfix
+//@run-rustfix
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 3f8f6a7b9..c40b71f6c 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -17,9 +17,9 @@ contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIB
[assign.owners]
"/.github" = ["@flip1995"]
+"/book" = ["@flip1995"]
"/util/gh-pages" = ["@xFrednet"]
"*" = [
- "@flip1995",
"@Manishearth",
"@llogiq",
"@giraffate",
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 85fd6523c..d2f258320 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -3,6 +3,9 @@ name = "compiletest"
version = "0.0.0"
edition = "2021"
+[lib]
+doctest = false
+
[dependencies]
colored = "2"
diff = "0.1.10"
@@ -20,6 +23,7 @@ once_cell = "1.16.0"
walkdir = "2"
glob = "0.3.0"
lazycell = "1.3.0"
+anyhow = "1"
[target.'cfg(unix)'.dependencies]
libc = "0.2"
@@ -28,7 +32,7 @@ libc = "0.2"
miow = "0.5"
[target.'cfg(windows)'.dependencies.windows]
-version = "0.46.0"
+version = "0.48.0"
features = [
"Win32_Foundation",
"Win32_System_Diagnostics_Debug",
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index d2f494942..f796c8987 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -69,6 +69,12 @@ string_enum! {
}
}
+impl Default for Mode {
+ fn default() -> Self {
+ Mode::Ui
+ }
+}
+
impl Mode {
pub fn disambiguator(self) -> &'static str {
// Pretty-printing tests could run concurrently, and if they do,
@@ -125,7 +131,7 @@ pub enum PanicStrategy {
}
/// Configuration for compiletest
-#[derive(Debug, Clone)]
+#[derive(Debug, Default, Clone)]
pub struct Config {
/// `true` to overwrite stderr/stdout files instead of complaining about changes in output.
pub bless: bool,
@@ -303,6 +309,9 @@ pub struct Config {
/// The current Rust channel
pub channel: String,
+ /// Whether adding git commit information such as the commit hash has been enabled for building
+ pub git_hash: bool,
+
/// The default Rust edition
pub edition: Option<String>,
@@ -419,19 +428,12 @@ pub struct TargetCfgs {
impl TargetCfgs {
fn new(config: &Config) -> TargetCfgs {
- let targets: HashMap<String, TargetCfg> = if config.stage_id.starts_with("stage0-") {
- // #[cfg(bootstrap)]
- // Needed only for one cycle, remove during the bootstrap bump.
- Self::collect_all_slow(config)
- } else {
- serde_json::from_str(&rustc_output(
- config,
- &["--print=all-target-specs-json", "-Zunstable-options"],
- ))
- .unwrap()
- };
-
- let mut current = None;
+ let targets: HashMap<String, TargetCfg> = serde_json::from_str(&rustc_output(
+ config,
+ &["--print=all-target-specs-json", "-Zunstable-options"],
+ ))
+ .unwrap();
+
let mut all_targets = HashSet::new();
let mut all_archs = HashSet::new();
let mut all_oses = HashSet::new();
@@ -452,14 +454,11 @@ impl TargetCfgs {
}
all_pointer_widths.insert(format!("{}bit", cfg.pointer_width));
- if target == config.target {
- current = Some(cfg);
- }
all_targets.insert(target.into());
}
Self {
- current: current.expect("current target not found"),
+ current: Self::get_current_target_config(config),
all_targets,
all_archs,
all_oses,
@@ -471,23 +470,87 @@ impl TargetCfgs {
}
}
- // #[cfg(bootstrap)]
- // Needed only for one cycle, remove during the bootstrap bump.
- fn collect_all_slow(config: &Config) -> HashMap<String, TargetCfg> {
- let mut result = HashMap::new();
- for target in rustc_output(config, &["--print=target-list"]).trim().lines() {
- let json = rustc_output(
- config,
- &["--print=target-spec-json", "-Zunstable-options", "--target", target],
- );
- match serde_json::from_str(&json) {
- Ok(res) => {
- result.insert(target.into(), res);
+ fn get_current_target_config(config: &Config) -> TargetCfg {
+ let mut arch = None;
+ let mut os = None;
+ let mut env = None;
+ let mut abi = None;
+ let mut families = Vec::new();
+ let mut pointer_width = None;
+ let mut endian = None;
+ let mut panic = None;
+
+ for config in
+ rustc_output(config, &["--print=cfg", "--target", &config.target]).trim().lines()
+ {
+ let (name, value) = config
+ .split_once("=\"")
+ .map(|(name, value)| {
+ (
+ name,
+ Some(
+ value
+ .strip_suffix("\"")
+ .expect("key-value pair should be properly quoted"),
+ ),
+ )
+ })
+ .unwrap_or_else(|| (config, None));
+
+ match name {
+ "target_arch" => {
+ arch = Some(value.expect("target_arch should be a key-value pair").to_string());
+ }
+ "target_os" => {
+ os = Some(value.expect("target_os sould be a key-value pair").to_string());
}
- Err(err) => panic!("failed to parse target spec for {target}: {err}"),
+ "target_env" => {
+ env = Some(value.expect("target_env should be a key-value pair").to_string());
+ }
+ "target_abi" => {
+ abi = Some(value.expect("target_abi should be a key-value pair").to_string());
+ }
+ "target_family" => {
+ families
+ .push(value.expect("target_family should be a key-value pair").to_string());
+ }
+ "target_pointer_width" => {
+ pointer_width = Some(
+ value
+ .expect("target_pointer_width should be a key-value pair")
+ .parse::<u32>()
+ .expect("target_pointer_width should be a valid u32"),
+ );
+ }
+ "target_endian" => {
+ endian = Some(match value.expect("target_endian should be a key-value pair") {
+ "big" => Endian::Big,
+ "little" => Endian::Little,
+ _ => panic!("target_endian should be either 'big' or 'little'"),
+ });
+ }
+ "panic" => {
+ panic = Some(match value.expect("panic should be a key-value pair") {
+ "abort" => PanicStrategy::Abort,
+ "unwind" => PanicStrategy::Unwind,
+ _ => panic!("panic should be either 'abort' or 'unwind'"),
+ });
+ }
+ _ => (),
}
}
- result
+
+ TargetCfg {
+ arch: arch.expect("target configuration should specify target_arch"),
+ os: os.expect("target configuration should specify target_os"),
+ env: env.expect("target configuration should specify target_env"),
+ abi: abi.expect("target configuration should specify target_abi"),
+ families,
+ pointer_width: pointer_width
+ .expect("target configuration should specify target_pointer_width"),
+ endian: endian.expect("target configuration should specify target_endian"),
+ panic: panic.expect("target configuration should specify panic"),
+ }
}
}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index bc65ec932..8cc935e54 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -12,13 +12,24 @@ use tracing::*;
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
use crate::header::cfg::parse_cfg_name_directive;
use crate::header::cfg::MatchOutcome;
-use crate::util;
+use crate::header::needs::CachedNeedsConditions;
use crate::{extract_cdb_version, extract_gdb_version};
mod cfg;
+mod needs;
#[cfg(test)]
mod tests;
+pub struct HeadersCache {
+ needs: CachedNeedsConditions,
+}
+
+impl HeadersCache {
+ pub fn load(config: &Config) -> Self {
+ Self { needs: CachedNeedsConditions::load(config) }
+ }
+}
+
/// Properties which must be known very early, before actually running
/// the test.
#[derive(Default)]
@@ -36,7 +47,7 @@ impl EarlyProps {
pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
let mut props = EarlyProps::default();
- iter_header(testfile, rdr, &mut |_, ln| {
+ iter_header(testfile, rdr, &mut |_, ln, _| {
config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| {
r.trim().to_string()
});
@@ -94,6 +105,9 @@ pub struct TestProps {
pub dont_check_compiler_stdout: bool,
// For UI tests, allows compiler to generate arbitrary output to stderr
pub dont_check_compiler_stderr: bool,
+ // When checking the output of stdout or stderr check
+ // that the lines of expected output are a subset of the actual output.
+ pub compare_output_lines_by_subset: bool,
// Don't force a --crate-type=dylib flag on the command line
//
// Set this for example if you have an auxiliary test file that contains
@@ -202,6 +216,7 @@ mod directives {
pub const KNOWN_BUG: &'static str = "known-bug";
pub const MIR_UNIT_TEST: &'static str = "unit-test";
pub const REMAP_SRC_BASE: &'static str = "remap-src-base";
+ pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset";
// This isn't a real directive, just one that is probably mistyped often
pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
}
@@ -227,6 +242,7 @@ impl TestProps {
check_run_results: false,
dont_check_compiler_stdout: false,
dont_check_compiler_stderr: false,
+ compare_output_lines_by_subset: false,
no_prefer_dynamic: false,
pretty_expanded: false,
pretty_mode: "normal".to_string(),
@@ -293,7 +309,7 @@ impl TestProps {
if !testfile.is_dir() {
let file = File::open(testfile).unwrap();
- iter_header(testfile, file, &mut |revision, ln| {
+ iter_header(testfile, file, &mut |revision, ln, _| {
if revision.is_some() && revision != cfg {
return;
}
@@ -467,6 +483,11 @@ impl TestProps {
s.trim().to_string()
});
config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
+ config.set_name_directive(
+ ln,
+ COMPARE_OUTPUT_LINES_BY_SUBSET,
+ &mut self.compare_output_lines_by_subset,
+ );
});
}
@@ -593,7 +614,7 @@ pub fn line_directive<'line>(
}
}
-fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str)) {
+fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str, usize)) {
if testfile.is_dir() {
return;
}
@@ -602,8 +623,10 @@ fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>
let mut rdr = BufReader::new(rdr);
let mut ln = String::new();
+ let mut line_number = 0;
loop {
+ line_number += 1;
ln.clear();
if rdr.read_line(&mut ln).unwrap() == 0 {
break;
@@ -616,7 +639,7 @@ fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>
if ln.starts_with("fn") || ln.starts_with("mod") {
return;
} else if let Some((lncfg, ln)) = line_directive(comment, ln) {
- it(lncfg, ln);
+ it(lncfg, ln, line_number);
}
}
}
@@ -676,21 +699,6 @@ impl Config {
}
}
- fn parse_needs_matching_clang(&self, line: &str) -> bool {
- self.parse_name_directive(line, "needs-matching-clang")
- }
-
- fn parse_needs_profiler_support(&self, line: &str) -> bool {
- self.parse_name_directive(line, "needs-profiler-support")
- }
-
- fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool {
- // returns whether this line contains this prefix or not. For prefix
- // "ignore", returns true if line says "ignore-x86_64", "ignore-arch",
- // "ignore-android" etc.
- line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-')
- }
-
fn parse_name_directive(&self, line: &str, directive: &str) -> bool {
// Ensure the directive is a whole word. Do not match "ignore-x86" when
// the line says "ignore-x86_64".
@@ -878,155 +886,58 @@ where
pub fn make_test_description<R: Read>(
config: &Config,
+ cache: &HeadersCache,
name: test::TestName,
path: &Path,
src: R,
cfg: Option<&str>,
+ poisoned: &mut bool,
) -> test::TestDesc {
let mut ignore = false;
let mut ignore_message = None;
let mut should_fail = false;
- let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
- let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some();
- let has_asm_support = config.has_asm_support();
- let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_cfi = util::CFI_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_kcfi = util::KCFI_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_kasan = util::KASAN_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_memtag = util::MEMTAG_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_shadow_call_stack = util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(&&*config.target);
- let has_xray = util::XRAY_SUPPORTED_TARGETS.contains(&&*config.target);
-
- // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find
- // whether `rust-lld` is present in the compiler under test.
- //
- // The --compile-lib-path is the path to host shared libraries, but depends on the OS. For
- // example:
- // - on linux, it can be <sysroot>/lib
- // - on windows, it can be <sysroot>/bin
- //
- // However, `rust-lld` is only located under the lib path, so we look for it there.
- let has_rust_lld = config
- .compile_lib_path
- .parent()
- .expect("couldn't traverse to the parent of the specified --compile-lib-path")
- .join("lib")
- .join("rustlib")
- .join(&config.target)
- .join("bin")
- .join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
- .exists();
-
- fn is_on_path(file: &'static str) -> impl Fn() -> bool {
- move || env::split_paths(&env::var_os("PATH").unwrap()).any(|dir| dir.join(file).is_file())
- }
-
- // On Windows, dlltool.exe is used for all architectures.
- #[cfg(windows)]
- let (has_i686_dlltool, has_x86_64_dlltool) =
- (is_on_path("dlltool.exe"), is_on_path("dlltool.exe"));
- // For non-Windows, there are architecture specific dlltool binaries.
- #[cfg(not(windows))]
- let (has_i686_dlltool, has_x86_64_dlltool) =
- (is_on_path("i686-w64-mingw32-dlltool"), is_on_path("x86_64-w64-mingw32-dlltool"));
-
- iter_header(path, src, &mut |revision, ln| {
+ iter_header(path, src, &mut |revision, ln, line_number| {
if revision.is_some() && revision != cfg {
return;
}
- macro_rules! reason {
+
+ macro_rules! decision {
($e:expr) => {
- ignore |= match $e {
- true => {
- ignore_message = Some(stringify!($e));
- true
+ match $e {
+ IgnoreDecision::Ignore { reason } => {
+ ignore = true;
+ // The ignore reason must be a &'static str, so we have to leak memory to
+ // create it. This is fine, as the header is parsed only at the start of
+ // compiletest so it won't grow indefinitely.
+ ignore_message = Some(&*Box::leak(Box::<str>::from(reason)));
}
- false => ignore,
- }
- };
- }
-
- {
- let parsed = parse_cfg_name_directive(config, ln, "ignore");
- ignore = match parsed.outcome {
- MatchOutcome::Match => {
- let reason = parsed.pretty_reason.unwrap();
- // The ignore reason must be a &'static str, so we have to leak memory to
- // create it. This is fine, as the header is parsed only at the start of
- // compiletest so it won't grow indefinitely.
- ignore_message = Some(Box::leak(Box::<str>::from(match parsed.comment {
- Some(comment) => format!("ignored {reason} ({comment})"),
- None => format!("ignored {reason}"),
- })) as &str);
- true
+ IgnoreDecision::Error { message } => {
+ eprintln!("error: {}:{line_number}: {message}", path.display());
+ *poisoned = true;
+ return;
+ }
+ IgnoreDecision::Continue => {}
}
- MatchOutcome::NoMatch => ignore,
- MatchOutcome::External => ignore,
- MatchOutcome::Invalid => panic!("invalid line in {}: {ln}", path.display()),
};
}
- if config.has_cfg_prefix(ln, "only") {
- let parsed = parse_cfg_name_directive(config, ln, "only");
- ignore = match parsed.outcome {
- MatchOutcome::Match => ignore,
- MatchOutcome::NoMatch => {
- let reason = parsed.pretty_reason.unwrap();
- // The ignore reason must be a &'static str, so we have to leak memory to
- // create it. This is fine, as the header is parsed only at the start of
- // compiletest so it won't grow indefinitely.
- ignore_message = Some(Box::leak(Box::<str>::from(match parsed.comment {
- Some(comment) => format!("only executed {reason} ({comment})"),
- None => format!("only executed {reason}"),
- })) as &str);
- true
- }
- MatchOutcome::External => ignore,
- MatchOutcome::Invalid => panic!("invalid line in {}: {ln}", path.display()),
- };
+ decision!(cfg::handle_ignore(config, ln));
+ decision!(cfg::handle_only(config, ln));
+ decision!(needs::handle_needs(&cache.needs, config, ln));
+ decision!(ignore_llvm(config, ln));
+ decision!(ignore_cdb(config, ln));
+ decision!(ignore_gdb(config, ln));
+ decision!(ignore_lldb(config, ln));
+
+ if config.target == "wasm32-unknown-unknown" {
+ if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) {
+ decision!(IgnoreDecision::Ignore {
+ reason: "ignored when checking the run results on WASM".into(),
+ });
+ }
}
- reason!(ignore_llvm(config, ln));
- reason!(
- config.run_clang_based_tests_with.is_none() && config.parse_needs_matching_clang(ln)
- );
- reason!(!has_asm_support && config.parse_name_directive(ln, "needs-asm-support"));
- reason!(!rustc_has_profiler_support && config.parse_needs_profiler_support(ln));
- reason!(!config.run_enabled() && config.parse_name_directive(ln, "needs-run-enabled"));
- reason!(
- !rustc_has_sanitizer_support
- && config.parse_name_directive(ln, "needs-sanitizer-support")
- );
- reason!(!has_asan && config.parse_name_directive(ln, "needs-sanitizer-address"));
- reason!(!has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi"));
- reason!(!has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi"));
- reason!(!has_kasan && config.parse_name_directive(ln, "needs-sanitizer-kasan"));
- reason!(!has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak"));
- reason!(!has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory"));
- reason!(!has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread"));
- reason!(!has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress"));
- reason!(!has_memtag && config.parse_name_directive(ln, "needs-sanitizer-memtag"));
- reason!(
- !has_shadow_call_stack
- && config.parse_name_directive(ln, "needs-sanitizer-shadow-call-stack")
- );
- reason!(!config.can_unwind() && config.parse_name_directive(ln, "needs-unwind"));
- reason!(!has_xray && config.parse_name_directive(ln, "needs-xray"));
- reason!(
- config.target == "wasm32-unknown-unknown"
- && config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS)
- );
- reason!(config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln));
- reason!(config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln));
- reason!(config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln));
- reason!(!has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld"));
- reason!(config.parse_name_directive(ln, "needs-i686-dlltool") && !has_i686_dlltool());
- reason!(config.parse_name_directive(ln, "needs-x86_64-dlltool") && !has_x86_64_dlltool());
should_fail |= config.parse_name_directive(ln, "should-fail");
});
@@ -1043,15 +954,10 @@ pub fn make_test_description<R: Read>(
name,
ignore,
ignore_message,
- #[cfg(not(bootstrap))]
source_file: "",
- #[cfg(not(bootstrap))]
start_line: 0,
- #[cfg(not(bootstrap))]
start_col: 0,
- #[cfg(not(bootstrap))]
end_line: 0,
- #[cfg(not(bootstrap))]
end_col: 0,
should_panic,
compile_fail: false,
@@ -1060,22 +966,34 @@ pub fn make_test_description<R: Read>(
}
}
-fn ignore_cdb(config: &Config, line: &str) -> bool {
+fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision {
+ if config.debugger != Some(Debugger::Cdb) {
+ return IgnoreDecision::Continue;
+ }
+
if let Some(actual_version) = config.cdb_version {
- if let Some(min_version) = line.strip_prefix("min-cdb-version:").map(str::trim) {
- let min_version = extract_cdb_version(min_version).unwrap_or_else(|| {
- panic!("couldn't parse version range: {:?}", min_version);
+ if let Some(rest) = line.strip_prefix("min-cdb-version:").map(str::trim) {
+ let min_version = extract_cdb_version(rest).unwrap_or_else(|| {
+ panic!("couldn't parse version range: {:?}", rest);
});
// Ignore if actual version is smaller than the minimum
// required version
- return actual_version < min_version;
+ if actual_version < min_version {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the CDB version is lower than {rest}"),
+ };
+ }
}
}
- false
+ IgnoreDecision::Continue
}
-fn ignore_gdb(config: &Config, line: &str) -> bool {
+fn ignore_gdb(config: &Config, line: &str) -> IgnoreDecision {
+ if config.debugger != Some(Debugger::Gdb) {
+ return IgnoreDecision::Continue;
+ }
+
if let Some(actual_version) = config.gdb_version {
if let Some(rest) = line.strip_prefix("min-gdb-version:").map(str::trim) {
let (start_ver, end_ver) = extract_version_range(rest, extract_gdb_version)
@@ -1088,7 +1006,11 @@ fn ignore_gdb(config: &Config, line: &str) -> bool {
}
// Ignore if actual version is smaller than the minimum
// required version
- return actual_version < start_ver;
+ if actual_version < start_ver {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the GDB version is lower than {rest}"),
+ };
+ }
} else if let Some(rest) = line.strip_prefix("ignore-gdb-version:").map(str::trim) {
let (min_version, max_version) = extract_version_range(rest, extract_gdb_version)
.unwrap_or_else(|| {
@@ -1099,32 +1021,47 @@ fn ignore_gdb(config: &Config, line: &str) -> bool {
panic!("Malformed GDB version range: max < min")
}
- return actual_version >= min_version && actual_version <= max_version;
+ if actual_version >= min_version && actual_version <= max_version {
+ if min_version == max_version {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the GDB version is {rest}"),
+ };
+ } else {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the GDB version is between {rest}"),
+ };
+ }
+ }
}
}
- false
+ IgnoreDecision::Continue
}
-fn ignore_lldb(config: &Config, line: &str) -> bool {
+fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
+ if config.debugger != Some(Debugger::Lldb) {
+ return IgnoreDecision::Continue;
+ }
+
if let Some(actual_version) = config.lldb_version {
- if let Some(min_version) = line.strip_prefix("min-lldb-version:").map(str::trim) {
- let min_version = min_version.parse().unwrap_or_else(|e| {
- panic!("Unexpected format of LLDB version string: {}\n{:?}", min_version, e);
+ if let Some(rest) = line.strip_prefix("min-lldb-version:").map(str::trim) {
+ let min_version = rest.parse().unwrap_or_else(|e| {
+ panic!("Unexpected format of LLDB version string: {}\n{:?}", rest, e);
});
// Ignore if actual version is smaller the minimum required
// version
- actual_version < min_version
- } else {
- line.starts_with("rust-lldb") && !config.lldb_native_rust
+ if actual_version < min_version {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the LLDB version is {rest}"),
+ };
+ }
}
- } else {
- false
}
+ IgnoreDecision::Continue
}
-fn ignore_llvm(config: &Config, line: &str) -> bool {
+fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
if config.system_llvm && line.starts_with("no-system-llvm") {
- return true;
+ return IgnoreDecision::Ignore { reason: "ignored when the system LLVM is used".into() };
}
if let Some(needed_components) =
config.parse_name_value_directive(line, "needs-llvm-components")
@@ -1137,7 +1074,9 @@ fn ignore_llvm(config: &Config, line: &str) -> bool {
if env::var_os("COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS").is_some() {
panic!("missing LLVM component: {}", missing_component);
}
- return true;
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the {missing_component} LLVM component is missing"),
+ };
}
}
if let Some(actual_version) = config.llvm_version {
@@ -1145,12 +1084,20 @@ fn ignore_llvm(config: &Config, line: &str) -> bool {
let min_version = extract_llvm_version(rest).unwrap();
// Ignore if actual version is smaller the minimum required
// version
- actual_version < min_version
+ if actual_version < min_version {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the LLVM version is older than {rest}"),
+ };
+ }
} else if let Some(rest) = line.strip_prefix("min-system-llvm-version:").map(str::trim) {
let min_version = extract_llvm_version(rest).unwrap();
// Ignore if using system LLVM and actual version
// is smaller the minimum required version
- config.system_llvm && actual_version < min_version
+ if config.system_llvm && actual_version < min_version {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the system LLVM version is older than {rest}"),
+ };
+ }
} else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) {
// Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
let (v_min, v_max) =
@@ -1161,11 +1108,24 @@ fn ignore_llvm(config: &Config, line: &str) -> bool {
panic!("Malformed LLVM version range: max < min")
}
// Ignore if version lies inside of range.
- actual_version >= v_min && actual_version <= v_max
- } else {
- false
+ if actual_version >= v_min && actual_version <= v_max {
+ if v_min == v_max {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the LLVM version is {rest}"),
+ };
+ } else {
+ return IgnoreDecision::Ignore {
+ reason: format!("ignored when the LLVM version is between {rest}"),
+ };
+ }
+ }
}
- } else {
- false
}
+ IgnoreDecision::Continue
+}
+
+enum IgnoreDecision {
+ Ignore { reason: String },
+ Continue,
+ Error { message: String },
}
diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs
index aa36fd708..86a749b93 100644
--- a/src/tools/compiletest/src/header/cfg.rs
+++ b/src/tools/compiletest/src/header/cfg.rs
@@ -1,8 +1,43 @@
use crate::common::{CompareMode, Config, Debugger};
+use crate::header::IgnoreDecision;
use std::collections::HashSet;
const EXTRA_ARCHS: &[&str] = &["spirv"];
+pub(super) fn handle_ignore(config: &Config, line: &str) -> IgnoreDecision {
+ let parsed = parse_cfg_name_directive(config, line, "ignore");
+ match parsed.outcome {
+ MatchOutcome::NoMatch => IgnoreDecision::Continue,
+ MatchOutcome::Match => IgnoreDecision::Ignore {
+ reason: match parsed.comment {
+ Some(comment) => format!("ignored {} ({comment})", parsed.pretty_reason.unwrap()),
+ None => format!("ignored {}", parsed.pretty_reason.unwrap()),
+ },
+ },
+ MatchOutcome::Invalid => IgnoreDecision::Error { message: format!("invalid line: {line}") },
+ MatchOutcome::External => IgnoreDecision::Continue,
+ MatchOutcome::NotADirective => IgnoreDecision::Continue,
+ }
+}
+
+pub(super) fn handle_only(config: &Config, line: &str) -> IgnoreDecision {
+ let parsed = parse_cfg_name_directive(config, line, "only");
+ match parsed.outcome {
+ MatchOutcome::Match => IgnoreDecision::Continue,
+ MatchOutcome::NoMatch => IgnoreDecision::Ignore {
+ reason: match parsed.comment {
+ Some(comment) => {
+ format!("only executed {} ({comment})", parsed.pretty_reason.unwrap())
+ }
+ None => format!("only executed {}", parsed.pretty_reason.unwrap()),
+ },
+ },
+ MatchOutcome::Invalid => IgnoreDecision::Error { message: format!("invalid line: {line}") },
+ MatchOutcome::External => IgnoreDecision::Continue,
+ MatchOutcome::NotADirective => IgnoreDecision::Continue,
+ }
+}
+
/// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
/// or `normalize-stderr-32bit`.
pub(super) fn parse_cfg_name_directive<'a>(
@@ -11,10 +46,10 @@ pub(super) fn parse_cfg_name_directive<'a>(
prefix: &str,
) -> ParsedNameDirective<'a> {
if !line.as_bytes().starts_with(prefix.as_bytes()) {
- return ParsedNameDirective::invalid();
+ return ParsedNameDirective::not_a_directive();
}
if line.as_bytes().get(prefix.len()) != Some(&b'-') {
- return ParsedNameDirective::invalid();
+ return ParsedNameDirective::not_a_directive();
}
let line = &line[prefix.len() + 1..];
@@ -24,7 +59,7 @@ pub(super) fn parse_cfg_name_directive<'a>(
// Some of the matchers might be "" depending on what the target information is. To avoid
// problems we outright reject empty directives.
if name == "" {
- return ParsedNameDirective::invalid();
+ return ParsedNameDirective::not_a_directive();
}
let mut outcome = MatchOutcome::Invalid;
@@ -222,8 +257,13 @@ pub(super) struct ParsedNameDirective<'a> {
}
impl ParsedNameDirective<'_> {
- fn invalid() -> Self {
- Self { name: None, pretty_reason: None, comment: None, outcome: MatchOutcome::NoMatch }
+ fn not_a_directive() -> Self {
+ Self {
+ name: None,
+ pretty_reason: None,
+ comment: None,
+ outcome: MatchOutcome::NotADirective,
+ }
}
}
@@ -237,6 +277,8 @@ pub(super) enum MatchOutcome {
Invalid,
/// The directive is handled by other parts of our tooling.
External,
+ /// The line is not actually a directive.
+ NotADirective,
}
trait CustomContains {
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
new file mode 100644
index 000000000..4a57c6140
--- /dev/null
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -0,0 +1,267 @@
+use crate::common::{Config, Debugger};
+use crate::header::IgnoreDecision;
+use crate::util;
+
+pub(super) fn handle_needs(
+ cache: &CachedNeedsConditions,
+ config: &Config,
+ ln: &str,
+) -> IgnoreDecision {
+ // Note thet we intentionally still put the needs- prefix here to make the file show up when
+ // grepping for a directive name, even though we could technically strip that.
+ let needs = &[
+ Need {
+ name: "needs-asm-support",
+ condition: config.has_asm_support(),
+ ignore_reason: "ignored on targets without inline assembly support",
+ },
+ Need {
+ name: "needs-sanitizer-support",
+ condition: cache.sanitizer_support,
+ ignore_reason: "ignored on targets without sanitizers support",
+ },
+ Need {
+ name: "needs-sanitizer-address",
+ condition: cache.sanitizer_address,
+ ignore_reason: "ignored on targets without address sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-cfi",
+ condition: cache.sanitizer_cfi,
+ ignore_reason: "ignored on targets without CFI sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-kcfi",
+ condition: cache.sanitizer_kcfi,
+ ignore_reason: "ignored on targets without kernel CFI sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-kasan",
+ condition: cache.sanitizer_kasan,
+ ignore_reason: "ignored on targets without kernel address sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-leak",
+ condition: cache.sanitizer_leak,
+ ignore_reason: "ignored on targets without leak sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-memory",
+ condition: cache.sanitizer_memory,
+ ignore_reason: "ignored on targets without memory sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-thread",
+ condition: cache.sanitizer_thread,
+ ignore_reason: "ignored on targets without thread sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-hwaddress",
+ condition: cache.sanitizer_hwaddress,
+ ignore_reason: "ignored on targets without hardware-assisted address sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-memtag",
+ condition: cache.sanitizer_memtag,
+ ignore_reason: "ignored on targets without memory tagging sanitizer",
+ },
+ Need {
+ name: "needs-sanitizer-shadow-call-stack",
+ condition: cache.sanitizer_shadow_call_stack,
+ ignore_reason: "ignored on targets without shadow call stacks",
+ },
+ Need {
+ name: "needs-run-enabled",
+ condition: config.run_enabled(),
+ ignore_reason: "ignored when running the resulting test binaries is disabled",
+ },
+ Need {
+ name: "needs-unwind",
+ condition: config.can_unwind(),
+ ignore_reason: "ignored on targets without unwinding support",
+ },
+ Need {
+ name: "needs-profiler-support",
+ condition: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(),
+ ignore_reason: "ignored when profiler support is disabled",
+ },
+ Need {
+ name: "needs-matching-clang",
+ condition: config.run_clang_based_tests_with.is_some(),
+ ignore_reason: "ignored when the used clang does not match the built LLVM",
+ },
+ Need {
+ name: "needs-xray",
+ condition: cache.xray,
+ ignore_reason: "ignored on targets without xray tracing",
+ },
+ Need {
+ name: "needs-rust-lld",
+ condition: cache.rust_lld,
+ ignore_reason: "ignored on targets without Rust's LLD",
+ },
+ Need {
+ name: "needs-rust-lldb",
+ condition: config.debugger != Some(Debugger::Lldb) || config.lldb_native_rust,
+ ignore_reason: "ignored on targets without Rust's LLDB",
+ },
+ Need {
+ name: "needs-i686-dlltool",
+ condition: cache.i686_dlltool,
+ ignore_reason: "ignored when dlltool for i686 is not present",
+ },
+ Need {
+ name: "needs-x86_64-dlltool",
+ condition: cache.x86_64_dlltool,
+ ignore_reason: "ignored when dlltool for x86_64 is not present",
+ },
+ Need {
+ name: "needs-dlltool",
+ condition: cache.dlltool,
+ ignore_reason: "ignored when dlltool for the current architecture is not present",
+ },
+ Need {
+ name: "needs-git-hash",
+ condition: config.git_hash,
+ ignore_reason: "ignored when git hashes have been omitted for building",
+ },
+ ];
+
+ let (name, comment) = match ln.split_once([':', ' ']) {
+ Some((name, comment)) => (name, Some(comment)),
+ None => (ln, None),
+ };
+
+ if !name.starts_with("needs-") {
+ return IgnoreDecision::Continue;
+ }
+
+ // Handled elsewhere.
+ if name == "needs-llvm-components" {
+ return IgnoreDecision::Continue;
+ }
+
+ let mut found_valid = false;
+ for need in needs {
+ if need.name == name {
+ if need.condition {
+ found_valid = true;
+ break;
+ } else {
+ return IgnoreDecision::Ignore {
+ reason: if let Some(comment) = comment {
+ format!("{} ({comment})", need.ignore_reason)
+ } else {
+ need.ignore_reason.into()
+ },
+ };
+ }
+ }
+ }
+
+ if found_valid {
+ IgnoreDecision::Continue
+ } else {
+ IgnoreDecision::Error { message: format!("invalid needs directive: {name}") }
+ }
+}
+
+struct Need {
+ name: &'static str,
+ condition: bool,
+ ignore_reason: &'static str,
+}
+
+pub(super) struct CachedNeedsConditions {
+ sanitizer_support: bool,
+ sanitizer_address: bool,
+ sanitizer_cfi: bool,
+ sanitizer_kcfi: bool,
+ sanitizer_kasan: bool,
+ sanitizer_leak: bool,
+ sanitizer_memory: bool,
+ sanitizer_thread: bool,
+ sanitizer_hwaddress: bool,
+ sanitizer_memtag: bool,
+ sanitizer_shadow_call_stack: bool,
+ xray: bool,
+ rust_lld: bool,
+ i686_dlltool: bool,
+ x86_64_dlltool: bool,
+ dlltool: bool,
+}
+
+impl CachedNeedsConditions {
+ pub(super) fn load(config: &Config) -> Self {
+ let path = std::env::var_os("PATH").expect("missing PATH environment variable");
+ let path = std::env::split_paths(&path).collect::<Vec<_>>();
+
+ // On Windows, dlltool.exe is used for all architectures.
+ #[cfg(windows)]
+ let dlltool = path.iter().any(|dir| dir.join("dlltool.exe").is_file());
+
+ // For non-Windows, there are architecture specific dlltool binaries.
+ #[cfg(not(windows))]
+ let i686_dlltool = path.iter().any(|dir| dir.join("i686-w64-mingw32-dlltool").is_file());
+ #[cfg(not(windows))]
+ let x86_64_dlltool =
+ path.iter().any(|dir| dir.join("x86_64-w64-mingw32-dlltool").is_file());
+
+ let target = &&*config.target;
+ Self {
+ sanitizer_support: std::env::var_os("RUSTC_SANITIZER_SUPPORT").is_some(),
+ sanitizer_address: util::ASAN_SUPPORTED_TARGETS.contains(target),
+ sanitizer_cfi: util::CFI_SUPPORTED_TARGETS.contains(target),
+ sanitizer_kcfi: util::KCFI_SUPPORTED_TARGETS.contains(target),
+ sanitizer_kasan: util::KASAN_SUPPORTED_TARGETS.contains(target),
+ sanitizer_leak: util::LSAN_SUPPORTED_TARGETS.contains(target),
+ sanitizer_memory: util::MSAN_SUPPORTED_TARGETS.contains(target),
+ sanitizer_thread: util::TSAN_SUPPORTED_TARGETS.contains(target),
+ sanitizer_hwaddress: util::HWASAN_SUPPORTED_TARGETS.contains(target),
+ sanitizer_memtag: util::MEMTAG_SUPPORTED_TARGETS.contains(target),
+ sanitizer_shadow_call_stack: util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(target),
+ xray: util::XRAY_SUPPORTED_TARGETS.contains(target),
+
+ // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find
+ // whether `rust-lld` is present in the compiler under test.
+ //
+ // The --compile-lib-path is the path to host shared libraries, but depends on the OS. For
+ // example:
+ // - on linux, it can be <sysroot>/lib
+ // - on windows, it can be <sysroot>/bin
+ //
+ // However, `rust-lld` is only located under the lib path, so we look for it there.
+ rust_lld: config
+ .compile_lib_path
+ .parent()
+ .expect("couldn't traverse to the parent of the specified --compile-lib-path")
+ .join("lib")
+ .join("rustlib")
+ .join(target)
+ .join("bin")
+ .join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
+ .exists(),
+
+ #[cfg(windows)]
+ i686_dlltool: dlltool,
+ #[cfg(windows)]
+ x86_64_dlltool: dlltool,
+ #[cfg(windows)]
+ dlltool,
+
+ // For non-Windows, there are architecture specific dlltool binaries.
+ #[cfg(not(windows))]
+ i686_dlltool,
+ #[cfg(not(windows))]
+ x86_64_dlltool,
+ #[cfg(not(windows))]
+ dlltool: if config.matches_arch("x86") {
+ i686_dlltool
+ } else if config.matches_arch("x86_64") {
+ x86_64_dlltool
+ } else {
+ false
+ },
+ }
+ }
+}
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index acd588d7f..362fba116 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -1,7 +1,25 @@
+use std::io::Read;
use std::path::Path;
use crate::common::{Config, Debugger};
-use crate::header::{make_test_description, parse_normalization_string, EarlyProps};
+use crate::header::{parse_normalization_string, EarlyProps, HeadersCache};
+
+fn make_test_description<R: Read>(
+ config: &Config,
+ name: test::TestName,
+ path: &Path,
+ src: R,
+ cfg: Option<&str>,
+) -> test::TestDesc {
+ let cache = HeadersCache::load(config);
+ let mut poisoned = false;
+ let test =
+ crate::header::make_test_description(config, &cache, name, path, src, cfg, &mut poisoned);
+ if poisoned {
+ panic!("poisoned!");
+ }
+ test
+}
#[test]
fn test_parse_normalization_string() {
@@ -234,6 +252,16 @@ fn debugger() {
}
#[test]
+fn git_hash() {
+ let mut config = config();
+ config.git_hash = false;
+ assert!(check_ignore(&config, "// needs-git-hash"));
+
+ config.git_hash = true;
+ assert!(!check_ignore(&config, "// needs-git-hash"));
+}
+
+#[test]
fn sanitizers() {
let mut config = config();
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
new file mode 100644
index 000000000..fc48d0159
--- /dev/null
+++ b/src/tools/compiletest/src/lib.rs
@@ -0,0 +1,1136 @@
+#![crate_name = "compiletest"]
+// The `test` crate is the only unstable feature
+// allowed here, just to share similar code.
+#![feature(test)]
+
+extern crate test;
+
+#[cfg(test)]
+mod tests;
+
+pub mod common;
+pub mod compute_diff;
+pub mod errors;
+pub mod header;
+mod json;
+mod raise_fd_limit;
+mod read2;
+pub mod runtest;
+pub mod util;
+
+use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
+use crate::common::{Config, Debugger, Mode, PassMode, TestPaths};
+use crate::util::logv;
+use build_helper::git::{get_git_modified_files, get_git_untracked_files};
+use core::panic;
+use getopts::Options;
+use lazycell::AtomicLazyCell;
+use std::collections::BTreeSet;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{self, ErrorKind};
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+use std::time::SystemTime;
+use std::{env, vec};
+use test::ColorConfig;
+use tracing::*;
+use walkdir::WalkDir;
+
+use self::header::{make_test_description, EarlyProps};
+use crate::header::HeadersCache;
+use std::sync::Arc;
+
+pub fn parse_config(args: Vec<String>) -> Config {
+ let mut opts = Options::new();
+ opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
+ .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
+ .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
+ .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
+ .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH")
+ .reqopt("", "python", "path to python to use for doc tests", "PATH")
+ .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH")
+ .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH")
+ .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
+ .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
+ .optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH")
+ .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
+ .reqopt("", "src-base", "directory to scan for test files", "PATH")
+ .reqopt("", "build-base", "directory to deposit test outputs", "PATH")
+ .reqopt("", "sysroot-base", "directory containing the compiler sysroot", "PATH")
+ .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET")
+ .reqopt(
+ "",
+ "mode",
+ "which sort of compile tests to run",
+ "run-pass-valgrind | pretty | debug-info | codegen | rustdoc \
+ | rustdoc-json | codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
+ )
+ .reqopt(
+ "",
+ "suite",
+ "which suite of compile tests to run. used for nicer error reporting.",
+ "SUITE",
+ )
+ .optopt(
+ "",
+ "pass",
+ "force {check,build,run}-pass tests to this mode.",
+ "check | build | run",
+ )
+ .optopt("", "run", "whether to execute run-* tests", "auto | always | never")
+ .optflag("", "ignored", "run tests marked as ignored")
+ .optmulti("", "skip", "skip tests matching SUBSTRING. Can be passed multiple times", "SUBSTRING")
+ .optflag("", "exact", "filters match exactly")
+ .optopt(
+ "",
+ "runtool",
+ "supervisor program to run tests under \
+ (eg. emulator, valgrind)",
+ "PROGRAM",
+ )
+ .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS")
+ .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS")
+ .optflag("", "optimize-tests", "run tests with optimizations enabled")
+ .optflag("", "verbose", "run tests verbosely, showing all output")
+ .optflag(
+ "",
+ "bless",
+ "overwrite stderr/stdout files instead of complaining about a mismatch",
+ )
+ .optflag("", "quiet", "print one character per test instead of one line")
+ .optopt("", "color", "coloring: auto, always, never", "WHEN")
+ .optflag("", "json", "emit json output instead of plaintext output")
+ .optopt("", "logfile", "file to log test execution to", "FILE")
+ .optopt("", "target", "the target to build for", "TARGET")
+ .optopt("", "host", "the host to build for", "HOST")
+ .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
+ .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
+ .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING")
+ .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING")
+ .optflag("", "system-llvm", "is LLVM the system LLVM")
+ .optopt("", "android-cross-path", "Android NDK standalone path", "PATH")
+ .optopt("", "adb-path", "path to the android debugger", "PATH")
+ .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH")
+ .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH")
+ .reqopt("", "cc", "path to a C compiler", "PATH")
+ .reqopt("", "cxx", "path to a C++ compiler", "PATH")
+ .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
+ .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS")
+ .optopt("", "ar", "path to an archiver", "PATH")
+ .optopt("", "target-linker", "path to a linker for the target", "PATH")
+ .optopt("", "host-linker", "path to a linker for the host", "PATH")
+ .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
+ .optopt("", "llvm-bin-dir", "Path to LLVM's `bin` directory", "PATH")
+ .optopt("", "nodejs", "the name of nodejs", "PATH")
+ .optopt("", "npm", "the name of npm", "PATH")
+ .optopt("", "remote-test-client", "path to the remote test client", "PATH")
+ .optopt(
+ "",
+ "compare-mode",
+ "mode describing what file the actual ui output will be compared to",
+ "COMPARE MODE",
+ )
+ .optflag(
+ "",
+ "rustfix-coverage",
+ "enable this to generate a Rustfix coverage file, which is saved in \
+ `./<build_base>/rustfix_missing_coverage.txt`",
+ )
+ .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
+ .optflag("", "only-modified", "only run tests that result been modified")
+ .optflag("", "nocapture", "")
+ .optflag("h", "help", "show this message")
+ .reqopt("", "channel", "current Rust channel", "CHANNEL")
+ .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
+ .optopt("", "edition", "default Rust edition", "EDITION");
+
+ let (argv0, args_) = args.split_first().unwrap();
+ if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
+ let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
+ println!("{}", opts.usage(&message));
+ println!();
+ panic!()
+ }
+
+ let matches = &match opts.parse(args_) {
+ Ok(m) => m,
+ Err(f) => panic!("{:?}", f),
+ };
+
+ if matches.opt_present("h") || matches.opt_present("help") {
+ let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
+ println!("{}", opts.usage(&message));
+ println!();
+ panic!()
+ }
+
+ fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
+ match m.opt_str(nm) {
+ Some(s) => PathBuf::from(&s),
+ None => panic!("no option (=path) found for {}", nm),
+ }
+ }
+
+ fn make_absolute(path: PathBuf) -> PathBuf {
+ if path.is_relative() { env::current_dir().unwrap().join(path) } else { path }
+ }
+
+ let target = opt_str2(matches.opt_str("target"));
+ let android_cross_path = opt_path(matches, "android-cross-path");
+ let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target);
+ let (gdb, gdb_version, gdb_native_rust) =
+ analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path);
+ let (lldb_version, lldb_native_rust) = matches
+ .opt_str("lldb-version")
+ .as_deref()
+ .and_then(extract_lldb_version)
+ .map(|(v, b)| (Some(v), b))
+ .unwrap_or((None, false));
+ let color = match matches.opt_str("color").as_deref() {
+ Some("auto") | None => ColorConfig::AutoColor,
+ Some("always") => ColorConfig::AlwaysColor,
+ Some("never") => ColorConfig::NeverColor,
+ Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
+ };
+ let llvm_version =
+ matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
+ || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
+ );
+
+ let src_base = opt_path(matches, "src-base");
+ let run_ignored = matches.opt_present("ignored");
+ let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
+ let has_tidy = if mode == Mode::Rustdoc {
+ Command::new("tidy")
+ .arg("--version")
+ .stdout(Stdio::null())
+ .status()
+ .map_or(false, |status| status.success())
+ } else {
+ // Avoid spawning an external command when we know tidy won't be used.
+ false
+ };
+ Config {
+ bless: matches.opt_present("bless"),
+ compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
+ run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
+ rustc_path: opt_path(matches, "rustc-path"),
+ rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
+ rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from),
+ python: matches.opt_str("python").unwrap(),
+ jsondocck_path: matches.opt_str("jsondocck-path"),
+ jsondoclint_path: matches.opt_str("jsondoclint-path"),
+ valgrind_path: matches.opt_str("valgrind-path"),
+ force_valgrind: matches.opt_present("force-valgrind"),
+ run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
+ llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
+ llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
+ src_base,
+ build_base: opt_path(matches, "build-base"),
+ sysroot_base: opt_path(matches, "sysroot-base"),
+ stage_id: matches.opt_str("stage-id").unwrap(),
+ mode,
+ suite: matches.opt_str("suite").unwrap(),
+ debugger: None,
+ run_ignored,
+ filters: matches.free.clone(),
+ skip: matches.opt_strs("skip"),
+ filter_exact: matches.opt_present("exact"),
+ force_pass_mode: matches.opt_str("pass").map(|mode| {
+ mode.parse::<PassMode>()
+ .unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
+ }),
+ run: matches.opt_str("run").and_then(|mode| match mode.as_str() {
+ "auto" => None,
+ "always" => Some(true),
+ "never" => Some(false),
+ _ => panic!("unknown `--run` option `{}` given", mode),
+ }),
+ logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
+ runtool: matches.opt_str("runtool"),
+ host_rustcflags: matches.opt_strs("host-rustcflags"),
+ target_rustcflags: matches.opt_strs("target-rustcflags"),
+ optimize_tests: matches.opt_present("optimize-tests"),
+ target,
+ host: opt_str2(matches.opt_str("host")),
+ cdb,
+ cdb_version,
+ gdb,
+ gdb_version,
+ gdb_native_rust,
+ lldb_version,
+ lldb_native_rust,
+ llvm_version,
+ system_llvm: matches.opt_present("system-llvm"),
+ android_cross_path,
+ adb_path: opt_str2(matches.opt_str("adb-path")),
+ adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
+ adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
+ && "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
+ && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
+ lldb_python_dir: matches.opt_str("lldb-python-dir"),
+ verbose: matches.opt_present("verbose"),
+ format: match (matches.opt_present("quiet"), matches.opt_present("json")) {
+ (true, true) => panic!("--quiet and --json are incompatible"),
+ (true, false) => test::OutputFormat::Terse,
+ (false, true) => test::OutputFormat::Json,
+ (false, false) => test::OutputFormat::Pretty,
+ },
+ only_modified: matches.opt_present("only-modified"),
+ color,
+ remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
+ compare_mode: matches
+ .opt_str("compare-mode")
+ .map(|s| s.parse().expect("invalid --compare-mode provided")),
+ rustfix_coverage: matches.opt_present("rustfix-coverage"),
+ has_tidy,
+ channel: matches.opt_str("channel").unwrap(),
+ git_hash: matches.opt_present("git-hash"),
+ edition: matches.opt_str("edition"),
+
+ cc: matches.opt_str("cc").unwrap(),
+ cxx: matches.opt_str("cxx").unwrap(),
+ cflags: matches.opt_str("cflags").unwrap(),
+ cxxflags: matches.opt_str("cxxflags").unwrap(),
+ ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
+ target_linker: matches.opt_str("target-linker"),
+ host_linker: matches.opt_str("host-linker"),
+ llvm_components: matches.opt_str("llvm-components").unwrap(),
+ nodejs: matches.opt_str("nodejs"),
+ npm: matches.opt_str("npm"),
+
+ force_rerun: matches.opt_present("force-rerun"),
+
+ target_cfgs: AtomicLazyCell::new(),
+
+ nocapture: matches.opt_present("nocapture"),
+ }
+}
+
+pub fn log_config(config: &Config) {
+ let c = config;
+ logv(c, "configuration:".to_string());
+ logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
+ logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
+ logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
+ logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
+ logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path));
+ logv(c, format!("src_base: {:?}", config.src_base.display()));
+ logv(c, format!("build_base: {:?}", config.build_base.display()));
+ logv(c, format!("stage_id: {}", config.stage_id));
+ logv(c, format!("mode: {}", config.mode));
+ logv(c, format!("run_ignored: {}", config.run_ignored));
+ logv(c, format!("filters: {:?}", config.filters));
+ logv(c, format!("skip: {:?}", config.skip));
+ logv(c, format!("filter_exact: {}", config.filter_exact));
+ logv(
+ c,
+ format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
+ );
+ logv(c, format!("runtool: {}", opt_str(&config.runtool)));
+ logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
+ logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
+ logv(c, format!("target: {}", config.target));
+ logv(c, format!("host: {}", config.host));
+ logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
+ logv(c, format!("adb_path: {:?}", config.adb_path));
+ logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
+ logv(c, format!("adb_device_status: {}", config.adb_device_status));
+ logv(c, format!("ar: {}", config.ar));
+ logv(c, format!("target-linker: {:?}", config.target_linker));
+ logv(c, format!("host-linker: {:?}", config.host_linker));
+ logv(c, format!("verbose: {}", config.verbose));
+ logv(c, format!("format: {:?}", config.format));
+ logv(c, "\n".to_string());
+}
+
+pub fn opt_str(maybestr: &Option<String>) -> &str {
+ match *maybestr {
+ None => "(none)",
+ Some(ref s) => s,
+ }
+}
+
+pub fn opt_str2(maybestr: Option<String>) -> String {
+ match maybestr {
+ None => "(none)".to_owned(),
+ Some(s) => s,
+ }
+}
+
+pub fn run_tests(config: Arc<Config>) {
+ // If we want to collect rustfix coverage information,
+ // we first make sure that the coverage file does not exist.
+ // It will be created later on.
+ if config.rustfix_coverage {
+ let mut coverage_file_path = config.build_base.clone();
+ coverage_file_path.push("rustfix_missing_coverage.txt");
+ if coverage_file_path.exists() {
+ if let Err(e) = fs::remove_file(&coverage_file_path) {
+ panic!("Could not delete {} due to {}", coverage_file_path.display(), e)
+ }
+ }
+ }
+
+ // sadly osx needs some file descriptor limits raised for running tests in
+ // parallel (especially when we have lots and lots of child processes).
+ // For context, see #8904
+ unsafe {
+ raise_fd_limit::raise_fd_limit();
+ }
+ // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
+ // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
+ env::set_var("__COMPAT_LAYER", "RunAsInvoker");
+
+ // Let tests know which target they're running as
+ env::set_var("TARGET", &config.target);
+
+ let opts = test_opts(&config);
+
+ let mut configs = Vec::new();
+ if let Mode::DebugInfo = config.mode {
+ // Debugging emscripten code doesn't make sense today
+ if !config.target.contains("emscripten") {
+ configs.extend(configure_cdb(&config));
+ configs.extend(configure_gdb(&config));
+ configs.extend(configure_lldb(&config));
+ }
+ } else {
+ configs.push(config.clone());
+ };
+
+ let mut tests = Vec::new();
+ for c in configs {
+ let mut found_paths = BTreeSet::new();
+ make_tests(c, &mut tests, &mut found_paths);
+ check_overlapping_tests(&found_paths);
+ }
+
+ tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
+
+ let res = test::run_tests_console(&opts, tests);
+ match res {
+ Ok(true) => {}
+ Ok(false) => {
+ // We want to report that the tests failed, but we also want to give
+ // some indication of just what tests we were running. Especially on
+ // CI, where there can be cross-compiled tests for a lot of
+ // architectures, without this critical information it can be quite
+ // easy to miss which tests failed, and as such fail to reproduce
+ // the failure locally.
+
+ println!(
+ "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
+ config.suite,
+ config
+ .compare_mode
+ .as_ref()
+ .map(|c| format!(" compare_mode={:?}", c))
+ .unwrap_or_default(),
+ config.mode,
+ config.host,
+ config.target
+ );
+
+ std::process::exit(1);
+ }
+ Err(e) => {
+ // We don't know if tests passed or not, but if there was an error
+ // during testing we don't want to just succeed (we may not have
+ // tested something), so fail.
+ //
+ // This should realistically "never" happen, so don't try to make
+ // this a pretty error message.
+ panic!("I/O failure during tests: {:?}", e);
+ }
+ }
+}
+
+fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
+ config.cdb.as_ref()?;
+
+ Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() }))
+}
+
+fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
+ config.gdb_version?;
+
+ if config.matches_env("msvc") {
+ return None;
+ }
+
+ if config.remote_test_client.is_some() && !config.target.contains("android") {
+ println!(
+ "WARNING: debuginfo tests are not available when \
+ testing with remote"
+ );
+ return None;
+ }
+
+ if config.target.contains("android") {
+ println!(
+ "{} debug-info test uses tcp 5039 port.\
+ please reserve it",
+ config.target
+ );
+
+ // android debug-info test uses remote debugger so, we test 1 thread
+ // at once as they're all sharing the same TCP port to communicate
+ // over.
+ //
+ // we should figure out how to lift this restriction! (run them all
+ // on different ports allocated dynamically).
+ env::set_var("RUST_TEST_THREADS", "1");
+ }
+
+ Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
+}
+
+fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
+ config.lldb_python_dir.as_ref()?;
+
+ if let Some(350) = config.lldb_version {
+ println!(
+ "WARNING: The used version of LLDB (350) has a \
+ known issue that breaks debuginfo tests. See \
+ issue #32520 for more information. Skipping all \
+ LLDB-based tests!",
+ );
+ return None;
+ }
+
+ Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
+}
+
+pub fn test_opts(config: &Config) -> test::TestOpts {
+ if env::var("RUST_TEST_NOCAPTURE").is_ok() {
+ eprintln!(
+ "WARNING: RUST_TEST_NOCAPTURE is no longer used. \
+ Use the `--nocapture` flag instead."
+ );
+ }
+
+ test::TestOpts {
+ exclude_should_panic: false,
+ filters: config.filters.clone(),
+ filter_exact: config.filter_exact,
+ run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
+ format: config.format,
+ logfile: config.logfile.clone(),
+ run_tests: true,
+ bench_benchmarks: true,
+ nocapture: config.nocapture,
+ color: config.color,
+ shuffle: false,
+ shuffle_seed: None,
+ test_threads: None,
+ skip: config.skip.clone(),
+ list: false,
+ options: test::Options::new(),
+ time_options: None,
+ force_run_in_process: false,
+ fail_fast: std::env::var_os("RUSTC_TEST_FAIL_FAST").is_some(),
+ }
+}
+
+pub fn make_tests(
+ config: Arc<Config>,
+ tests: &mut Vec<test::TestDescAndFn>,
+ found_paths: &mut BTreeSet<PathBuf>,
+) {
+ debug!("making tests from {:?}", config.src_base.display());
+ let inputs = common_inputs_stamp(&config);
+ let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
+ panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
+ });
+
+ let cache = HeadersCache::load(&config);
+ let mut poisoned = false;
+ collect_tests_from_dir(
+ config.clone(),
+ &cache,
+ &config.src_base,
+ &PathBuf::new(),
+ &inputs,
+ tests,
+ found_paths,
+ &modified_tests,
+ &mut poisoned,
+ )
+ .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
+
+ if poisoned {
+ eprintln!();
+ panic!("there are errors in tests");
+ }
+}
+
+/// Returns a stamp constructed from input files common to all test cases.
+fn common_inputs_stamp(config: &Config) -> Stamp {
+ let rust_src_dir = config.find_rust_src_root().expect("Could not find Rust source root");
+
+ let mut stamp = Stamp::from_path(&config.rustc_path);
+
+ // Relevant pretty printer files
+ let pretty_printer_files = [
+ "src/etc/rust_types.py",
+ "src/etc/gdb_load_rust_pretty_printers.py",
+ "src/etc/gdb_lookup.py",
+ "src/etc/gdb_providers.py",
+ "src/etc/lldb_batchmode.py",
+ "src/etc/lldb_lookup.py",
+ "src/etc/lldb_providers.py",
+ ];
+ for file in &pretty_printer_files {
+ let path = rust_src_dir.join(file);
+ stamp.add_path(&path);
+ }
+
+ stamp.add_dir(&rust_src_dir.join("src/etc/natvis"));
+
+ stamp.add_dir(&config.run_lib_path);
+
+ if let Some(ref rustdoc_path) = config.rustdoc_path {
+ stamp.add_path(&rustdoc_path);
+ stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py"));
+ }
+
+ // Compiletest itself.
+ stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/"));
+
+ stamp
+}
+
+fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
+ if !config.only_modified {
+ return Ok(vec![]);
+ }
+ let files =
+ get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]);
+ // Add new test cases to the list, it will be convenient in daily development.
+ let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]);
+
+ let all_paths = [&files[..], &untracked_files[..]].concat();
+ let full_paths = {
+ let mut full_paths: Vec<PathBuf> = all_paths
+ .into_iter()
+ .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
+ .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
+ .collect();
+ full_paths.dedup();
+ full_paths.sort_unstable();
+ full_paths
+ };
+ Ok(full_paths)
+}
+
+fn collect_tests_from_dir(
+ config: Arc<Config>,
+ cache: &HeadersCache,
+ dir: &Path,
+ relative_dir_path: &Path,
+ inputs: &Stamp,
+ tests: &mut Vec<test::TestDescAndFn>,
+ found_paths: &mut BTreeSet<PathBuf>,
+ modified_tests: &Vec<PathBuf>,
+ poisoned: &mut bool,
+) -> io::Result<()> {
+ // Ignore directories that contain a file named `compiletest-ignore-dir`.
+ if dir.join("compiletest-ignore-dir").exists() {
+ return Ok(());
+ }
+
+ if config.mode == Mode::RunMake && dir.join("Makefile").exists() {
+ let paths = TestPaths {
+ file: dir.to_path_buf(),
+ relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
+ };
+ tests.extend(make_test(config, cache, &paths, inputs, poisoned));
+ return Ok(());
+ }
+
+ // If we find a test foo/bar.rs, we have to build the
+ // output directory `$build/foo` so we can write
+ // `$build/foo/bar` into it. We do this *now* in this
+ // sequential loop because otherwise, if we do it in the
+ // tests themselves, they race for the privilege of
+ // creating the directories and sometimes fail randomly.
+ let build_dir = output_relative_path(&config, relative_dir_path);
+ fs::create_dir_all(&build_dir).unwrap();
+
+ // Add each `.rs` file as a test, and recurse further on any
+ // subdirectories we find, except for `aux` directories.
+ for file in fs::read_dir(dir)? {
+ let file = file?;
+ let file_path = file.path();
+ let file_name = file.file_name();
+ if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
+ debug!("found test file: {:?}", file_path.display());
+ let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
+ found_paths.insert(rel_test_path);
+ let paths =
+ TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
+
+ tests.extend(make_test(config.clone(), cache, &paths, inputs, poisoned))
+ } else if file_path.is_dir() {
+ let relative_file_path = relative_dir_path.join(file.file_name());
+ if &file_name != "auxiliary" {
+ debug!("found directory: {:?}", file_path.display());
+ collect_tests_from_dir(
+ config.clone(),
+ cache,
+ &file_path,
+ &relative_file_path,
+ inputs,
+ tests,
+ found_paths,
+ modified_tests,
+ poisoned,
+ )?;
+ }
+ } else {
+ debug!("found other file/directory: {:?}", file_path.display());
+ }
+ }
+ Ok(())
+}
+
+/// Returns true if `file_name` looks like a proper test file name.
+pub fn is_test(file_name: &OsString) -> bool {
+ let file_name = file_name.to_str().unwrap();
+
+ if !file_name.ends_with(".rs") {
+ return false;
+ }
+
+ // `.`, `#`, and `~` are common temp-file prefixes.
+ let invalid_prefixes = &[".", "#", "~"];
+ !invalid_prefixes.iter().any(|p| file_name.starts_with(p))
+}
+
+fn make_test(
+ config: Arc<Config>,
+ cache: &HeadersCache,
+ testpaths: &TestPaths,
+ inputs: &Stamp,
+ poisoned: &mut bool,
+) -> Vec<test::TestDescAndFn> {
+ let test_path = if config.mode == Mode::RunMake {
+ // Parse directives in the Makefile
+ testpaths.file.join("Makefile")
+ } else {
+ PathBuf::from(&testpaths.file)
+ };
+ let early_props = EarlyProps::from_file(&config, &test_path);
+
+ // Incremental tests are special, they inherently cannot be run in parallel.
+ // `runtest::run` will be responsible for iterating over revisions.
+ let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental {
+ vec![None]
+ } else {
+ early_props.revisions.iter().map(Some).collect()
+ };
+
+ revisions
+ .into_iter()
+ .map(|revision| {
+ let src_file =
+ std::fs::File::open(&test_path).expect("open test file to parse ignores");
+ let cfg = revision.map(|v| &**v);
+ let test_name = crate::make_test_name(&config, testpaths, revision);
+ let mut desc = make_test_description(
+ &config, cache, test_name, &test_path, src_file, cfg, poisoned,
+ );
+ // Ignore tests that already run and are up to date with respect to inputs.
+ if !config.force_rerun {
+ desc.ignore |= is_up_to_date(
+ &config,
+ testpaths,
+ &early_props,
+ revision.map(|s| s.as_str()),
+ inputs,
+ );
+ }
+ test::TestDescAndFn {
+ desc,
+ testfn: make_test_closure(config.clone(), testpaths, revision),
+ }
+ })
+ .collect()
+}
+
+fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
+ output_base_dir(config, testpaths, revision).join("stamp")
+}
+
+fn files_related_to_test(
+ config: &Config,
+ testpaths: &TestPaths,
+ props: &EarlyProps,
+ revision: Option<&str>,
+) -> Vec<PathBuf> {
+ let mut related = vec![];
+
+ if testpaths.file.is_dir() {
+ // run-make tests use their individual directory
+ for entry in WalkDir::new(&testpaths.file) {
+ let path = entry.unwrap().into_path();
+ if path.is_file() {
+ related.push(path);
+ }
+ }
+ } else {
+ related.push(testpaths.file.clone());
+ }
+
+ for aux in &props.aux {
+ let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux);
+ related.push(path);
+ }
+
+ // UI test files.
+ for extension in UI_EXTENSIONS {
+ let path = expected_output_path(testpaths, revision, &config.compare_mode, extension);
+ related.push(path);
+ }
+
+ related
+}
+
+fn is_up_to_date(
+ config: &Config,
+ testpaths: &TestPaths,
+ props: &EarlyProps,
+ revision: Option<&str>,
+ inputs: &Stamp,
+) -> bool {
+ let stamp_name = stamp(config, testpaths, revision);
+ // Check hash.
+ let contents = match fs::read_to_string(&stamp_name) {
+ Ok(f) => f,
+ Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"),
+ Err(_) => return false,
+ };
+ let expected_hash = runtest::compute_stamp_hash(config);
+ if contents != expected_hash {
+ return false;
+ }
+
+ // Check timestamps.
+ let mut inputs = inputs.clone();
+ for path in files_related_to_test(config, testpaths, props, revision) {
+ inputs.add_path(&path);
+ }
+
+ inputs < Stamp::from_path(&stamp_name)
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+struct Stamp {
+ time: SystemTime,
+}
+
+impl Stamp {
+ fn from_path(path: &Path) -> Self {
+ let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH };
+ stamp.add_path(path);
+ stamp
+ }
+
+ fn add_path(&mut self, path: &Path) {
+ let modified = fs::metadata(path)
+ .and_then(|metadata| metadata.modified())
+ .unwrap_or(SystemTime::UNIX_EPOCH);
+ self.time = self.time.max(modified);
+ }
+
+ fn add_dir(&mut self, path: &Path) {
+ for entry in WalkDir::new(path) {
+ let entry = entry.unwrap();
+ if entry.file_type().is_file() {
+ let modified = entry
+ .metadata()
+ .ok()
+ .and_then(|metadata| metadata.modified().ok())
+ .unwrap_or(SystemTime::UNIX_EPOCH);
+ self.time = self.time.max(modified);
+ }
+ }
+ }
+}
+
+fn make_test_name(
+ config: &Config,
+ testpaths: &TestPaths,
+ revision: Option<&String>,
+) -> test::TestName {
+ // Print the name of the file, relative to the repository root.
+ // `src_base` looks like `/path/to/rust/tests/ui`
+ let root_directory = config.src_base.parent().unwrap().parent().unwrap();
+ let path = testpaths.file.strip_prefix(root_directory).unwrap();
+ let debugger = match config.debugger {
+ Some(d) => format!("-{}", d),
+ None => String::new(),
+ };
+ let mode_suffix = match config.compare_mode {
+ Some(ref mode) => format!(" ({})", mode.to_str()),
+ None => String::new(),
+ };
+
+ test::DynTestName(format!(
+ "[{}{}{}] {}{}",
+ config.mode,
+ debugger,
+ mode_suffix,
+ path.display(),
+ revision.map_or("".to_string(), |rev| format!("#{}", rev))
+ ))
+}
+
+fn make_test_closure(
+ config: Arc<Config>,
+ testpaths: &TestPaths,
+ revision: Option<&String>,
+) -> test::TestFn {
+ let config = config.clone();
+ let testpaths = testpaths.clone();
+ let revision = revision.cloned();
+ test::DynTestFn(Box::new(move || {
+ runtest::run(config, &testpaths, revision.as_deref());
+ Ok(())
+ }))
+}
+
+/// Returns `true` if the given target is an Android target for the
+/// purposes of GDB testing.
+fn is_android_gdb_target(target: &str) -> bool {
+ matches!(
+ &target[..],
+ "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android"
+ )
+}
+
+/// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing.
+fn is_pc_windows_msvc_target(target: &str) -> bool {
+ target.ends_with("-pc-windows-msvc")
+}
+
+fn find_cdb(target: &str) -> Option<OsString> {
+ if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
+ return None;
+ }
+
+ let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
+ let cdb_arch = if cfg!(target_arch = "x86") {
+ "x86"
+ } else if cfg!(target_arch = "x86_64") {
+ "x64"
+ } else if cfg!(target_arch = "aarch64") {
+ "arm64"
+ } else if cfg!(target_arch = "arm") {
+ "arm"
+ } else {
+ return None; // No compatible CDB.exe in the Windows 10 SDK
+ };
+
+ let mut path = PathBuf::new();
+ path.push(pf86);
+ path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too?
+ path.push(cdb_arch);
+ path.push(r"cdb.exe");
+
+ if !path.exists() {
+ return None;
+ }
+
+ Some(path.into_os_string())
+}
+
+/// Returns Path to CDB
+fn analyze_cdb(cdb: Option<String>, target: &str) -> (Option<OsString>, Option<[u16; 4]>) {
+ let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target));
+
+ let mut version = None;
+ if let Some(cdb) = cdb.as_ref() {
+ if let Ok(output) = Command::new(cdb).arg("/version").output() {
+ if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
+ version = extract_cdb_version(&first_line);
+ }
+ }
+ }
+
+ (cdb, version)
+}
+
+fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> {
+ // Example full_version_line: "cdb version 10.0.18362.1"
+ let version = full_version_line.rsplit(' ').next()?;
+ let mut components = version.split('.');
+ let major: u16 = components.next().unwrap().parse().unwrap();
+ let minor: u16 = components.next().unwrap().parse().unwrap();
+ let patch: u16 = components.next().unwrap_or("0").parse().unwrap();
+ let build: u16 = components.next().unwrap_or("0").parse().unwrap();
+ Some([major, minor, patch, build])
+}
+
+/// Returns (Path to GDB, GDB Version, GDB has Rust Support)
+fn analyze_gdb(
+ gdb: Option<String>,
+ target: &str,
+ android_cross_path: &PathBuf,
+) -> (Option<String>, Option<u32>, bool) {
+ #[cfg(not(windows))]
+ const GDB_FALLBACK: &str = "gdb";
+ #[cfg(windows)]
+ const GDB_FALLBACK: &str = "gdb.exe";
+
+ const MIN_GDB_WITH_RUST: u32 = 7011010;
+
+ let fallback_gdb = || {
+ if is_android_gdb_target(target) {
+ let mut gdb_path = match android_cross_path.to_str() {
+ Some(x) => x.to_owned(),
+ None => panic!("cannot find android cross path"),
+ };
+ gdb_path.push_str("/bin/gdb");
+ gdb_path
+ } else {
+ GDB_FALLBACK.to_owned()
+ }
+ };
+
+ let gdb = match gdb {
+ None => fallback_gdb(),
+ Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb
+ Some(ref s) => s.to_owned(),
+ };
+
+ let mut version_line = None;
+ if let Ok(output) = Command::new(&gdb).arg("--version").output() {
+ if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
+ version_line = Some(first_line.to_string());
+ }
+ }
+
+ let version = match version_line {
+ Some(line) => extract_gdb_version(&line),
+ None => return (None, None, false),
+ };
+
+ let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
+
+ (Some(gdb), version, gdb_native_rust)
+}
+
+fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
+ let full_version_line = full_version_line.trim();
+
+ // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both
+ // of the ? sections being optional
+
+ // We will parse up to 3 digits for each component, ignoring the date
+
+ // We skip text in parentheses. This avoids accidentally parsing
+ // the openSUSE version, which looks like:
+ // GNU gdb (GDB; openSUSE Leap 15.0) 8.1
+ // This particular form is documented in the GNU coding standards:
+ // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion
+
+ let unbracketed_part = full_version_line.split('[').next().unwrap();
+ let mut splits = unbracketed_part.trim_end().rsplit(' ');
+ let version_string = splits.next().unwrap();
+
+ let mut splits = version_string.split('.');
+ let major = splits.next().unwrap();
+ let minor = splits.next().unwrap();
+ let patch = splits.next();
+
+ let major: u32 = major.parse().unwrap();
+ let (minor, patch): (u32, u32) = match minor.find(not_a_digit) {
+ None => {
+ let minor = minor.parse().unwrap();
+ let patch: u32 = match patch {
+ Some(patch) => match patch.find(not_a_digit) {
+ None => patch.parse().unwrap(),
+ Some(idx) if idx > 3 => 0,
+ Some(idx) => patch[..idx].parse().unwrap(),
+ },
+ None => 0,
+ };
+ (minor, patch)
+ }
+ // There is no patch version after minor-date (e.g. "4-2012").
+ Some(idx) => {
+ let minor = minor[..idx].parse().unwrap();
+ (minor, 0)
+ }
+ };
+
+ Some(((major * 1000) + minor) * 1000 + patch)
+}
+
+/// Returns (LLDB version, LLDB is rust-enabled)
+fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
+ // Extract the major LLDB version from the given version string.
+ // LLDB version strings are different for Apple and non-Apple platforms.
+ // The Apple variant looks like this:
+ //
+ // LLDB-179.5 (older versions)
+ // lldb-300.2.51 (new versions)
+ //
+ // We are only interested in the major version number, so this function
+ // will return `Some(179)` and `Some(300)` respectively.
+ //
+ // Upstream versions look like:
+ // lldb version 6.0.1
+ //
+ // There doesn't seem to be a way to correlate the Apple version
+ // with the upstream version, and since the tests were originally
+ // written against Apple versions, we make a fake Apple version by
+ // multiplying the first number by 100. This is a hack, but
+ // normally fine because the only non-Apple version we test is
+ // rust-enabled.
+
+ let full_version_line = full_version_line.trim();
+
+ if let Some(apple_ver) =
+ full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-"))
+ {
+ if let Some(idx) = apple_ver.find(not_a_digit) {
+ let version: u32 = apple_ver[..idx].parse().unwrap();
+ return Some((version, full_version_line.contains("rust-enabled")));
+ }
+ } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") {
+ if let Some(idx) = lldb_ver.find(not_a_digit) {
+ let version: u32 = lldb_ver[..idx].parse().ok()?;
+ return Some((version * 100, full_version_line.contains("rust-enabled")));
+ }
+ }
+ None
+}
+
+fn not_a_digit(c: char) -> bool {
+ !c.is_digit(10)
+}
+
+fn check_overlapping_tests(found_paths: &BTreeSet<PathBuf>) {
+ let mut collisions = Vec::new();
+ for path in found_paths {
+ for ancestor in path.ancestors().skip(1) {
+ if found_paths.contains(ancestor) {
+ collisions.push((path, ancestor.clone()));
+ }
+ }
+ }
+ if !collisions.is_empty() {
+ let collisions: String = collisions
+ .into_iter()
+ .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
+ .collect();
+ panic!(
+ "{collisions}\n\
+ Tests cannot have overlapping names. Make sure they use unique prefixes."
+ );
+ }
+}
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 6a91d25a8..34d48559c 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -1,44 +1,6 @@
-#![crate_name = "compiletest"]
-// The `test` crate is the only unstable feature
-// allowed here, just to share similar code.
-#![feature(test)]
+use std::{env, sync::Arc};
-extern crate test;
-
-use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
-use crate::common::{Config, Debugger, Mode, PassMode, TestPaths};
-use crate::util::logv;
-use build_helper::git::{get_git_modified_files, get_git_untracked_files};
-use core::panic;
-use getopts::Options;
-use lazycell::AtomicLazyCell;
-use std::collections::BTreeSet;
-use std::ffi::OsString;
-use std::fs;
-use std::io::{self, ErrorKind};
-use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
-use std::time::SystemTime;
-use std::{env, vec};
-use test::ColorConfig;
-use tracing::*;
-use walkdir::WalkDir;
-
-use self::header::{make_test_description, EarlyProps};
-use std::sync::Arc;
-
-#[cfg(test)]
-mod tests;
-
-pub mod common;
-pub mod compute_diff;
-pub mod errors;
-pub mod header;
-mod json;
-mod raise_fd_limit;
-mod read2;
-pub mod runtest;
-pub mod util;
+use compiletest::{common::Mode, log_config, parse_config, run_tests};
fn main() {
tracing_subscriber::fmt::init();
@@ -56,1076 +18,3 @@ fn main() {
log_config(&config);
run_tests(config);
}
-
-pub fn parse_config(args: Vec<String>) -> Config {
- let mut opts = Options::new();
- opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
- .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
- .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
- .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
- .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH")
- .reqopt("", "python", "path to python to use for doc tests", "PATH")
- .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH")
- .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH")
- .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
- .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
- .optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH")
- .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
- .reqopt("", "src-base", "directory to scan for test files", "PATH")
- .reqopt("", "build-base", "directory to deposit test outputs", "PATH")
- .reqopt("", "sysroot-base", "directory containing the compiler sysroot", "PATH")
- .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET")
- .reqopt(
- "",
- "mode",
- "which sort of compile tests to run",
- "run-pass-valgrind | pretty | debug-info | codegen | rustdoc \
- | rustdoc-json | codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
- )
- .reqopt(
- "",
- "suite",
- "which suite of compile tests to run. used for nicer error reporting.",
- "SUITE",
- )
- .optopt(
- "",
- "pass",
- "force {check,build,run}-pass tests to this mode.",
- "check | build | run",
- )
- .optopt("", "run", "whether to execute run-* tests", "auto | always | never")
- .optflag("", "ignored", "run tests marked as ignored")
- .optmulti("", "skip", "skip tests matching SUBSTRING. Can be passed multiple times", "SUBSTRING")
- .optflag("", "exact", "filters match exactly")
- .optopt(
- "",
- "runtool",
- "supervisor program to run tests under \
- (eg. emulator, valgrind)",
- "PROGRAM",
- )
- .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS")
- .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS")
- .optflag("", "optimize-tests", "run tests with optimizations enabled")
- .optflag("", "verbose", "run tests verbosely, showing all output")
- .optflag(
- "",
- "bless",
- "overwrite stderr/stdout files instead of complaining about a mismatch",
- )
- .optflag("", "quiet", "print one character per test instead of one line")
- .optopt("", "color", "coloring: auto, always, never", "WHEN")
- .optflag("", "json", "emit json output instead of plaintext output")
- .optopt("", "logfile", "file to log test execution to", "FILE")
- .optopt("", "target", "the target to build for", "TARGET")
- .optopt("", "host", "the host to build for", "HOST")
- .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
- .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
- .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING")
- .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING")
- .optflag("", "system-llvm", "is LLVM the system LLVM")
- .optopt("", "android-cross-path", "Android NDK standalone path", "PATH")
- .optopt("", "adb-path", "path to the android debugger", "PATH")
- .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH")
- .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH")
- .reqopt("", "cc", "path to a C compiler", "PATH")
- .reqopt("", "cxx", "path to a C++ compiler", "PATH")
- .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
- .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS")
- .optopt("", "ar", "path to an archiver", "PATH")
- .optopt("", "target-linker", "path to a linker for the target", "PATH")
- .optopt("", "host-linker", "path to a linker for the host", "PATH")
- .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
- .optopt("", "llvm-bin-dir", "Path to LLVM's `bin` directory", "PATH")
- .optopt("", "nodejs", "the name of nodejs", "PATH")
- .optopt("", "npm", "the name of npm", "PATH")
- .optopt("", "remote-test-client", "path to the remote test client", "PATH")
- .optopt(
- "",
- "compare-mode",
- "mode describing what file the actual ui output will be compared to",
- "COMPARE MODE",
- )
- .optflag(
- "",
- "rustfix-coverage",
- "enable this to generate a Rustfix coverage file, which is saved in \
- `./<build_base>/rustfix_missing_coverage.txt`",
- )
- .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
- .optflag("", "only-modified", "only run tests that result been modified")
- .optflag("", "nocapture", "")
- .optflag("h", "help", "show this message")
- .reqopt("", "channel", "current Rust channel", "CHANNEL")
- .optopt("", "edition", "default Rust edition", "EDITION");
-
- let (argv0, args_) = args.split_first().unwrap();
- if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
- let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
- println!("{}", opts.usage(&message));
- println!();
- panic!()
- }
-
- let matches = &match opts.parse(args_) {
- Ok(m) => m,
- Err(f) => panic!("{:?}", f),
- };
-
- if matches.opt_present("h") || matches.opt_present("help") {
- let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
- println!("{}", opts.usage(&message));
- println!();
- panic!()
- }
-
- fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
- match m.opt_str(nm) {
- Some(s) => PathBuf::from(&s),
- None => panic!("no option (=path) found for {}", nm),
- }
- }
-
- fn make_absolute(path: PathBuf) -> PathBuf {
- if path.is_relative() { env::current_dir().unwrap().join(path) } else { path }
- }
-
- let target = opt_str2(matches.opt_str("target"));
- let android_cross_path = opt_path(matches, "android-cross-path");
- let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target);
- let (gdb, gdb_version, gdb_native_rust) =
- analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path);
- let (lldb_version, lldb_native_rust) = matches
- .opt_str("lldb-version")
- .as_deref()
- .and_then(extract_lldb_version)
- .map(|(v, b)| (Some(v), b))
- .unwrap_or((None, false));
- let color = match matches.opt_str("color").as_deref() {
- Some("auto") | None => ColorConfig::AutoColor,
- Some("always") => ColorConfig::AlwaysColor,
- Some("never") => ColorConfig::NeverColor,
- Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
- };
- let llvm_version =
- matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
- || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
- );
-
- let src_base = opt_path(matches, "src-base");
- let run_ignored = matches.opt_present("ignored");
- let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
- let has_tidy = if mode == Mode::Rustdoc {
- Command::new("tidy")
- .arg("--version")
- .stdout(Stdio::null())
- .status()
- .map_or(false, |status| status.success())
- } else {
- // Avoid spawning an external command when we know tidy won't be used.
- false
- };
- Config {
- bless: matches.opt_present("bless"),
- compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
- run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
- rustc_path: opt_path(matches, "rustc-path"),
- rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
- rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from),
- python: matches.opt_str("python").unwrap(),
- jsondocck_path: matches.opt_str("jsondocck-path"),
- jsondoclint_path: matches.opt_str("jsondoclint-path"),
- valgrind_path: matches.opt_str("valgrind-path"),
- force_valgrind: matches.opt_present("force-valgrind"),
- run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
- llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
- llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
- src_base,
- build_base: opt_path(matches, "build-base"),
- sysroot_base: opt_path(matches, "sysroot-base"),
- stage_id: matches.opt_str("stage-id").unwrap(),
- mode,
- suite: matches.opt_str("suite").unwrap(),
- debugger: None,
- run_ignored,
- filters: matches.free.clone(),
- skip: matches.opt_strs("skip"),
- filter_exact: matches.opt_present("exact"),
- force_pass_mode: matches.opt_str("pass").map(|mode| {
- mode.parse::<PassMode>()
- .unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
- }),
- run: matches.opt_str("run").and_then(|mode| match mode.as_str() {
- "auto" => None,
- "always" => Some(true),
- "never" => Some(false),
- _ => panic!("unknown `--run` option `{}` given", mode),
- }),
- logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
- runtool: matches.opt_str("runtool"),
- host_rustcflags: matches.opt_strs("host-rustcflags"),
- target_rustcflags: matches.opt_strs("target-rustcflags"),
- optimize_tests: matches.opt_present("optimize-tests"),
- target,
- host: opt_str2(matches.opt_str("host")),
- cdb,
- cdb_version,
- gdb,
- gdb_version,
- gdb_native_rust,
- lldb_version,
- lldb_native_rust,
- llvm_version,
- system_llvm: matches.opt_present("system-llvm"),
- android_cross_path,
- adb_path: opt_str2(matches.opt_str("adb-path")),
- adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
- adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
- && "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
- && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
- lldb_python_dir: matches.opt_str("lldb-python-dir"),
- verbose: matches.opt_present("verbose"),
- format: match (matches.opt_present("quiet"), matches.opt_present("json")) {
- (true, true) => panic!("--quiet and --json are incompatible"),
- (true, false) => test::OutputFormat::Terse,
- (false, true) => test::OutputFormat::Json,
- (false, false) => test::OutputFormat::Pretty,
- },
- only_modified: matches.opt_present("only-modified"),
- color,
- remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
- compare_mode: matches
- .opt_str("compare-mode")
- .map(|s| s.parse().expect("invalid --compare-mode provided")),
- rustfix_coverage: matches.opt_present("rustfix-coverage"),
- has_tidy,
- channel: matches.opt_str("channel").unwrap(),
- edition: matches.opt_str("edition"),
-
- cc: matches.opt_str("cc").unwrap(),
- cxx: matches.opt_str("cxx").unwrap(),
- cflags: matches.opt_str("cflags").unwrap(),
- cxxflags: matches.opt_str("cxxflags").unwrap(),
- ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
- target_linker: matches.opt_str("target-linker"),
- host_linker: matches.opt_str("host-linker"),
- llvm_components: matches.opt_str("llvm-components").unwrap(),
- nodejs: matches.opt_str("nodejs"),
- npm: matches.opt_str("npm"),
-
- force_rerun: matches.opt_present("force-rerun"),
-
- target_cfgs: AtomicLazyCell::new(),
-
- nocapture: matches.opt_present("nocapture"),
- }
-}
-
-pub fn log_config(config: &Config) {
- let c = config;
- logv(c, "configuration:".to_string());
- logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
- logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
- logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
- logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
- logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path));
- logv(c, format!("src_base: {:?}", config.src_base.display()));
- logv(c, format!("build_base: {:?}", config.build_base.display()));
- logv(c, format!("stage_id: {}", config.stage_id));
- logv(c, format!("mode: {}", config.mode));
- logv(c, format!("run_ignored: {}", config.run_ignored));
- logv(c, format!("filters: {:?}", config.filters));
- logv(c, format!("skip: {:?}", config.skip));
- logv(c, format!("filter_exact: {}", config.filter_exact));
- logv(
- c,
- format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
- );
- logv(c, format!("runtool: {}", opt_str(&config.runtool)));
- logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
- logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
- logv(c, format!("target: {}", config.target));
- logv(c, format!("host: {}", config.host));
- logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
- logv(c, format!("adb_path: {:?}", config.adb_path));
- logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
- logv(c, format!("adb_device_status: {}", config.adb_device_status));
- logv(c, format!("ar: {}", config.ar));
- logv(c, format!("target-linker: {:?}", config.target_linker));
- logv(c, format!("host-linker: {:?}", config.host_linker));
- logv(c, format!("verbose: {}", config.verbose));
- logv(c, format!("format: {:?}", config.format));
- logv(c, "\n".to_string());
-}
-
-pub fn opt_str(maybestr: &Option<String>) -> &str {
- match *maybestr {
- None => "(none)",
- Some(ref s) => s,
- }
-}
-
-pub fn opt_str2(maybestr: Option<String>) -> String {
- match maybestr {
- None => "(none)".to_owned(),
- Some(s) => s,
- }
-}
-
-pub fn run_tests(config: Arc<Config>) {
- // If we want to collect rustfix coverage information,
- // we first make sure that the coverage file does not exist.
- // It will be created later on.
- if config.rustfix_coverage {
- let mut coverage_file_path = config.build_base.clone();
- coverage_file_path.push("rustfix_missing_coverage.txt");
- if coverage_file_path.exists() {
- if let Err(e) = fs::remove_file(&coverage_file_path) {
- panic!("Could not delete {} due to {}", coverage_file_path.display(), e)
- }
- }
- }
-
- // sadly osx needs some file descriptor limits raised for running tests in
- // parallel (especially when we have lots and lots of child processes).
- // For context, see #8904
- unsafe {
- raise_fd_limit::raise_fd_limit();
- }
- // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
- // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
- env::set_var("__COMPAT_LAYER", "RunAsInvoker");
-
- // Let tests know which target they're running as
- env::set_var("TARGET", &config.target);
-
- let opts = test_opts(&config);
-
- let mut configs = Vec::new();
- if let Mode::DebugInfo = config.mode {
- // Debugging emscripten code doesn't make sense today
- if !config.target.contains("emscripten") {
- configs.extend(configure_cdb(&config));
- configs.extend(configure_gdb(&config));
- configs.extend(configure_lldb(&config));
- }
- } else {
- configs.push(config.clone());
- };
-
- let mut tests = Vec::new();
- for c in configs {
- let mut found_paths = BTreeSet::new();
- make_tests(c, &mut tests, &mut found_paths);
- check_overlapping_tests(&found_paths);
- }
-
- tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
-
- let res = test::run_tests_console(&opts, tests);
- match res {
- Ok(true) => {}
- Ok(false) => {
- // We want to report that the tests failed, but we also want to give
- // some indication of just what tests we were running. Especially on
- // CI, where there can be cross-compiled tests for a lot of
- // architectures, without this critical information it can be quite
- // easy to miss which tests failed, and as such fail to reproduce
- // the failure locally.
-
- println!(
- "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
- config.suite,
- config
- .compare_mode
- .as_ref()
- .map(|c| format!(" compare_mode={:?}", c))
- .unwrap_or_default(),
- config.mode,
- config.host,
- config.target
- );
-
- std::process::exit(1);
- }
- Err(e) => {
- // We don't know if tests passed or not, but if there was an error
- // during testing we don't want to just succeed (we may not have
- // tested something), so fail.
- //
- // This should realistically "never" happen, so don't try to make
- // this a pretty error message.
- panic!("I/O failure during tests: {:?}", e);
- }
- }
-}
-
-fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
- config.cdb.as_ref()?;
-
- Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() }))
-}
-
-fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
- config.gdb_version?;
-
- if config.matches_env("msvc") {
- return None;
- }
-
- if config.remote_test_client.is_some() && !config.target.contains("android") {
- println!(
- "WARNING: debuginfo tests are not available when \
- testing with remote"
- );
- return None;
- }
-
- if config.target.contains("android") {
- println!(
- "{} debug-info test uses tcp 5039 port.\
- please reserve it",
- config.target
- );
-
- // android debug-info test uses remote debugger so, we test 1 thread
- // at once as they're all sharing the same TCP port to communicate
- // over.
- //
- // we should figure out how to lift this restriction! (run them all
- // on different ports allocated dynamically).
- env::set_var("RUST_TEST_THREADS", "1");
- }
-
- Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() }))
-}
-
-fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
- config.lldb_python_dir.as_ref()?;
-
- if let Some(350) = config.lldb_version {
- println!(
- "WARNING: The used version of LLDB (350) has a \
- known issue that breaks debuginfo tests. See \
- issue #32520 for more information. Skipping all \
- LLDB-based tests!",
- );
- return None;
- }
-
- Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
-}
-
-pub fn test_opts(config: &Config) -> test::TestOpts {
- if env::var("RUST_TEST_NOCAPTURE").is_ok() {
- eprintln!(
- "WARNING: RUST_TEST_NOCAPTURE is no longer used. \
- Use the `--nocapture` flag instead."
- );
- }
-
- test::TestOpts {
- exclude_should_panic: false,
- filters: config.filters.clone(),
- filter_exact: config.filter_exact,
- run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
- format: config.format,
- logfile: config.logfile.clone(),
- run_tests: true,
- bench_benchmarks: true,
- nocapture: config.nocapture,
- color: config.color,
- shuffle: false,
- shuffle_seed: None,
- test_threads: None,
- skip: config.skip.clone(),
- list: false,
- options: test::Options::new(),
- time_options: None,
- force_run_in_process: false,
- fail_fast: std::env::var_os("RUSTC_TEST_FAIL_FAST").is_some(),
- }
-}
-
-pub fn make_tests(
- config: Arc<Config>,
- tests: &mut Vec<test::TestDescAndFn>,
- found_paths: &mut BTreeSet<PathBuf>,
-) {
- debug!("making tests from {:?}", config.src_base.display());
- let inputs = common_inputs_stamp(&config);
- let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
- panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
- });
- collect_tests_from_dir(
- config.clone(),
- &config.src_base,
- &PathBuf::new(),
- &inputs,
- tests,
- found_paths,
- &modified_tests,
- )
- .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
-}
-
-/// Returns a stamp constructed from input files common to all test cases.
-fn common_inputs_stamp(config: &Config) -> Stamp {
- let rust_src_dir = config.find_rust_src_root().expect("Could not find Rust source root");
-
- let mut stamp = Stamp::from_path(&config.rustc_path);
-
- // Relevant pretty printer files
- let pretty_printer_files = [
- "src/etc/rust_types.py",
- "src/etc/gdb_load_rust_pretty_printers.py",
- "src/etc/gdb_lookup.py",
- "src/etc/gdb_providers.py",
- "src/etc/lldb_batchmode.py",
- "src/etc/lldb_lookup.py",
- "src/etc/lldb_providers.py",
- ];
- for file in &pretty_printer_files {
- let path = rust_src_dir.join(file);
- stamp.add_path(&path);
- }
-
- stamp.add_dir(&rust_src_dir.join("src/etc/natvis"));
-
- stamp.add_dir(&config.run_lib_path);
-
- if let Some(ref rustdoc_path) = config.rustdoc_path {
- stamp.add_path(&rustdoc_path);
- stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py"));
- }
-
- // Compiletest itself.
- stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/"));
-
- stamp
-}
-
-fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
- if !config.only_modified {
- return Ok(vec![]);
- }
- let files =
- get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]);
- // Add new test cases to the list, it will be convenient in daily development.
- let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]);
-
- let all_paths = [&files[..], &untracked_files[..]].concat();
- let full_paths = {
- let mut full_paths: Vec<PathBuf> = all_paths
- .into_iter()
- .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
- .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
- .collect();
- full_paths.dedup();
- full_paths.sort_unstable();
- full_paths
- };
- Ok(full_paths)
-}
-
-fn collect_tests_from_dir(
- config: Arc<Config>,
- dir: &Path,
- relative_dir_path: &Path,
- inputs: &Stamp,
- tests: &mut Vec<test::TestDescAndFn>,
- found_paths: &mut BTreeSet<PathBuf>,
- modified_tests: &Vec<PathBuf>,
-) -> io::Result<()> {
- // Ignore directories that contain a file named `compiletest-ignore-dir`.
- if dir.join("compiletest-ignore-dir").exists() {
- return Ok(());
- }
-
- if config.mode == Mode::RunMake && dir.join("Makefile").exists() {
- let paths = TestPaths {
- file: dir.to_path_buf(),
- relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
- };
- tests.extend(make_test(config, &paths, inputs));
- return Ok(());
- }
-
- // If we find a test foo/bar.rs, we have to build the
- // output directory `$build/foo` so we can write
- // `$build/foo/bar` into it. We do this *now* in this
- // sequential loop because otherwise, if we do it in the
- // tests themselves, they race for the privilege of
- // creating the directories and sometimes fail randomly.
- let build_dir = output_relative_path(&config, relative_dir_path);
- fs::create_dir_all(&build_dir).unwrap();
-
- // Add each `.rs` file as a test, and recurse further on any
- // subdirectories we find, except for `aux` directories.
- for file in fs::read_dir(dir)? {
- let file = file?;
- let file_path = file.path();
- let file_name = file.file_name();
- if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
- debug!("found test file: {:?}", file_path.display());
- let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
- found_paths.insert(rel_test_path);
- let paths =
- TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
-
- tests.extend(make_test(config.clone(), &paths, inputs))
- } else if file_path.is_dir() {
- let relative_file_path = relative_dir_path.join(file.file_name());
- if &file_name != "auxiliary" {
- debug!("found directory: {:?}", file_path.display());
- collect_tests_from_dir(
- config.clone(),
- &file_path,
- &relative_file_path,
- inputs,
- tests,
- found_paths,
- modified_tests,
- )?;
- }
- } else {
- debug!("found other file/directory: {:?}", file_path.display());
- }
- }
- Ok(())
-}
-
-/// Returns true if `file_name` looks like a proper test file name.
-pub fn is_test(file_name: &OsString) -> bool {
- let file_name = file_name.to_str().unwrap();
-
- if !file_name.ends_with(".rs") {
- return false;
- }
-
- // `.`, `#`, and `~` are common temp-file prefixes.
- let invalid_prefixes = &[".", "#", "~"];
- !invalid_prefixes.iter().any(|p| file_name.starts_with(p))
-}
-
-fn make_test(
- config: Arc<Config>,
- testpaths: &TestPaths,
- inputs: &Stamp,
-) -> Vec<test::TestDescAndFn> {
- let test_path = if config.mode == Mode::RunMake {
- // Parse directives in the Makefile
- testpaths.file.join("Makefile")
- } else {
- PathBuf::from(&testpaths.file)
- };
- let early_props = EarlyProps::from_file(&config, &test_path);
-
- // Incremental tests are special, they inherently cannot be run in parallel.
- // `runtest::run` will be responsible for iterating over revisions.
- let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental {
- vec![None]
- } else {
- early_props.revisions.iter().map(Some).collect()
- };
- revisions
- .into_iter()
- .map(|revision| {
- let src_file =
- std::fs::File::open(&test_path).expect("open test file to parse ignores");
- let cfg = revision.map(|v| &**v);
- let test_name = crate::make_test_name(&config, testpaths, revision);
- let mut desc = make_test_description(&config, test_name, &test_path, src_file, cfg);
- // Ignore tests that already run and are up to date with respect to inputs.
- if !config.force_rerun {
- desc.ignore |= is_up_to_date(
- &config,
- testpaths,
- &early_props,
- revision.map(|s| s.as_str()),
- inputs,
- );
- }
- test::TestDescAndFn {
- desc,
- testfn: make_test_closure(config.clone(), testpaths, revision),
- }
- })
- .collect()
-}
-
-fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
- output_base_dir(config, testpaths, revision).join("stamp")
-}
-
-fn files_related_to_test(
- config: &Config,
- testpaths: &TestPaths,
- props: &EarlyProps,
- revision: Option<&str>,
-) -> Vec<PathBuf> {
- let mut related = vec![];
-
- if testpaths.file.is_dir() {
- // run-make tests use their individual directory
- for entry in WalkDir::new(&testpaths.file) {
- let path = entry.unwrap().into_path();
- if path.is_file() {
- related.push(path);
- }
- }
- } else {
- related.push(testpaths.file.clone());
- }
-
- for aux in &props.aux {
- let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux);
- related.push(path);
- }
-
- // UI test files.
- for extension in UI_EXTENSIONS {
- let path = expected_output_path(testpaths, revision, &config.compare_mode, extension);
- related.push(path);
- }
-
- related
-}
-
-fn is_up_to_date(
- config: &Config,
- testpaths: &TestPaths,
- props: &EarlyProps,
- revision: Option<&str>,
- inputs: &Stamp,
-) -> bool {
- let stamp_name = stamp(config, testpaths, revision);
- // Check hash.
- let contents = match fs::read_to_string(&stamp_name) {
- Ok(f) => f,
- Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"),
- Err(_) => return false,
- };
- let expected_hash = runtest::compute_stamp_hash(config);
- if contents != expected_hash {
- return false;
- }
-
- // Check timestamps.
- let mut inputs = inputs.clone();
- for path in files_related_to_test(config, testpaths, props, revision) {
- inputs.add_path(&path);
- }
-
- inputs < Stamp::from_path(&stamp_name)
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-struct Stamp {
- time: SystemTime,
-}
-
-impl Stamp {
- fn from_path(path: &Path) -> Self {
- let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH };
- stamp.add_path(path);
- stamp
- }
-
- fn add_path(&mut self, path: &Path) {
- let modified = fs::metadata(path)
- .and_then(|metadata| metadata.modified())
- .unwrap_or(SystemTime::UNIX_EPOCH);
- self.time = self.time.max(modified);
- }
-
- fn add_dir(&mut self, path: &Path) {
- for entry in WalkDir::new(path) {
- let entry = entry.unwrap();
- if entry.file_type().is_file() {
- let modified = entry
- .metadata()
- .ok()
- .and_then(|metadata| metadata.modified().ok())
- .unwrap_or(SystemTime::UNIX_EPOCH);
- self.time = self.time.max(modified);
- }
- }
- }
-}
-
-fn make_test_name(
- config: &Config,
- testpaths: &TestPaths,
- revision: Option<&String>,
-) -> test::TestName {
- // Print the name of the file, relative to the repository root.
- // `src_base` looks like `/path/to/rust/tests/ui`
- let root_directory = config.src_base.parent().unwrap().parent().unwrap();
- let path = testpaths.file.strip_prefix(root_directory).unwrap();
- let debugger = match config.debugger {
- Some(d) => format!("-{}", d),
- None => String::new(),
- };
- let mode_suffix = match config.compare_mode {
- Some(ref mode) => format!(" ({})", mode.to_str()),
- None => String::new(),
- };
-
- test::DynTestName(format!(
- "[{}{}{}] {}{}",
- config.mode,
- debugger,
- mode_suffix,
- path.display(),
- revision.map_or("".to_string(), |rev| format!("#{}", rev))
- ))
-}
-
-fn make_test_closure(
- config: Arc<Config>,
- testpaths: &TestPaths,
- revision: Option<&String>,
-) -> test::TestFn {
- let config = config.clone();
- let testpaths = testpaths.clone();
- let revision = revision.cloned();
- test::DynTestFn(Box::new(move || {
- runtest::run(config, &testpaths, revision.as_deref());
- Ok(())
- }))
-}
-
-/// Returns `true` if the given target is an Android target for the
-/// purposes of GDB testing.
-fn is_android_gdb_target(target: &str) -> bool {
- matches!(
- &target[..],
- "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android"
- )
-}
-
-/// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing.
-fn is_pc_windows_msvc_target(target: &str) -> bool {
- target.ends_with("-pc-windows-msvc")
-}
-
-fn find_cdb(target: &str) -> Option<OsString> {
- if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
- return None;
- }
-
- let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
- let cdb_arch = if cfg!(target_arch = "x86") {
- "x86"
- } else if cfg!(target_arch = "x86_64") {
- "x64"
- } else if cfg!(target_arch = "aarch64") {
- "arm64"
- } else if cfg!(target_arch = "arm") {
- "arm"
- } else {
- return None; // No compatible CDB.exe in the Windows 10 SDK
- };
-
- let mut path = PathBuf::new();
- path.push(pf86);
- path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too?
- path.push(cdb_arch);
- path.push(r"cdb.exe");
-
- if !path.exists() {
- return None;
- }
-
- Some(path.into_os_string())
-}
-
-/// Returns Path to CDB
-fn analyze_cdb(cdb: Option<String>, target: &str) -> (Option<OsString>, Option<[u16; 4]>) {
- let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target));
-
- let mut version = None;
- if let Some(cdb) = cdb.as_ref() {
- if let Ok(output) = Command::new(cdb).arg("/version").output() {
- if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
- version = extract_cdb_version(&first_line);
- }
- }
- }
-
- (cdb, version)
-}
-
-fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> {
- // Example full_version_line: "cdb version 10.0.18362.1"
- let version = full_version_line.rsplit(' ').next()?;
- let mut components = version.split('.');
- let major: u16 = components.next().unwrap().parse().unwrap();
- let minor: u16 = components.next().unwrap().parse().unwrap();
- let patch: u16 = components.next().unwrap_or("0").parse().unwrap();
- let build: u16 = components.next().unwrap_or("0").parse().unwrap();
- Some([major, minor, patch, build])
-}
-
-/// Returns (Path to GDB, GDB Version, GDB has Rust Support)
-fn analyze_gdb(
- gdb: Option<String>,
- target: &str,
- android_cross_path: &PathBuf,
-) -> (Option<String>, Option<u32>, bool) {
- #[cfg(not(windows))]
- const GDB_FALLBACK: &str = "gdb";
- #[cfg(windows)]
- const GDB_FALLBACK: &str = "gdb.exe";
-
- const MIN_GDB_WITH_RUST: u32 = 7011010;
-
- let fallback_gdb = || {
- if is_android_gdb_target(target) {
- let mut gdb_path = match android_cross_path.to_str() {
- Some(x) => x.to_owned(),
- None => panic!("cannot find android cross path"),
- };
- gdb_path.push_str("/bin/gdb");
- gdb_path
- } else {
- GDB_FALLBACK.to_owned()
- }
- };
-
- let gdb = match gdb {
- None => fallback_gdb(),
- Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb
- Some(ref s) => s.to_owned(),
- };
-
- let mut version_line = None;
- if let Ok(output) = Command::new(&gdb).arg("--version").output() {
- if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
- version_line = Some(first_line.to_string());
- }
- }
-
- let version = match version_line {
- Some(line) => extract_gdb_version(&line),
- None => return (None, None, false),
- };
-
- let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
-
- (Some(gdb), version, gdb_native_rust)
-}
-
-fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
- let full_version_line = full_version_line.trim();
-
- // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both
- // of the ? sections being optional
-
- // We will parse up to 3 digits for each component, ignoring the date
-
- // We skip text in parentheses. This avoids accidentally parsing
- // the openSUSE version, which looks like:
- // GNU gdb (GDB; openSUSE Leap 15.0) 8.1
- // This particular form is documented in the GNU coding standards:
- // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion
-
- let unbracketed_part = full_version_line.split('[').next().unwrap();
- let mut splits = unbracketed_part.trim_end().rsplit(' ');
- let version_string = splits.next().unwrap();
-
- let mut splits = version_string.split('.');
- let major = splits.next().unwrap();
- let minor = splits.next().unwrap();
- let patch = splits.next();
-
- let major: u32 = major.parse().unwrap();
- let (minor, patch): (u32, u32) = match minor.find(not_a_digit) {
- None => {
- let minor = minor.parse().unwrap();
- let patch: u32 = match patch {
- Some(patch) => match patch.find(not_a_digit) {
- None => patch.parse().unwrap(),
- Some(idx) if idx > 3 => 0,
- Some(idx) => patch[..idx].parse().unwrap(),
- },
- None => 0,
- };
- (minor, patch)
- }
- // There is no patch version after minor-date (e.g. "4-2012").
- Some(idx) => {
- let minor = minor[..idx].parse().unwrap();
- (minor, 0)
- }
- };
-
- Some(((major * 1000) + minor) * 1000 + patch)
-}
-
-/// Returns (LLDB version, LLDB is rust-enabled)
-fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
- // Extract the major LLDB version from the given version string.
- // LLDB version strings are different for Apple and non-Apple platforms.
- // The Apple variant looks like this:
- //
- // LLDB-179.5 (older versions)
- // lldb-300.2.51 (new versions)
- //
- // We are only interested in the major version number, so this function
- // will return `Some(179)` and `Some(300)` respectively.
- //
- // Upstream versions look like:
- // lldb version 6.0.1
- //
- // There doesn't seem to be a way to correlate the Apple version
- // with the upstream version, and since the tests were originally
- // written against Apple versions, we make a fake Apple version by
- // multiplying the first number by 100. This is a hack, but
- // normally fine because the only non-Apple version we test is
- // rust-enabled.
-
- let full_version_line = full_version_line.trim();
-
- if let Some(apple_ver) =
- full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-"))
- {
- if let Some(idx) = apple_ver.find(not_a_digit) {
- let version: u32 = apple_ver[..idx].parse().unwrap();
- return Some((version, full_version_line.contains("rust-enabled")));
- }
- } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") {
- if let Some(idx) = lldb_ver.find(not_a_digit) {
- let version: u32 = lldb_ver[..idx].parse().ok()?;
- return Some((version * 100, full_version_line.contains("rust-enabled")));
- }
- }
- None
-}
-
-fn not_a_digit(c: char) -> bool {
- !c.is_digit(10)
-}
-
-fn check_overlapping_tests(found_paths: &BTreeSet<PathBuf>) {
- let mut collisions = Vec::new();
- for path in found_paths {
- for ancestor in path.ancestors().skip(1) {
- if found_paths.contains(ancestor) {
- collisions.push((path, ancestor.clone()));
- }
- }
- }
- if !collisions.is_empty() {
- let collisions: String = collisions
- .into_iter()
- .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
- .collect();
- panic!(
- "{collisions}\n\
- Tests cannot have overlapping names. Make sure they use unique prefixes."
- );
- }
-}
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 7f0b894f5..5bc4d1642 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -32,6 +32,7 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio};
use std::str;
use std::sync::Arc;
+use anyhow::Context;
use glob::glob;
use once_cell::sync::Lazy;
use tracing::*;
@@ -131,7 +132,11 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
}
let cx = TestCx { config: &config, props: &props, testpaths, revision };
- create_dir_all(&cx.output_base_dir()).unwrap();
+ create_dir_all(&cx.output_base_dir())
+ .with_context(|| {
+ format!("failed to create output base directory {}", cx.output_base_dir().display())
+ })
+ .unwrap();
if props.incremental {
cx.init_incremental_test();
}
@@ -224,6 +229,7 @@ enum Emit {
Metadata,
LlvmIr,
Asm,
+ LinkArgsAsm,
}
impl<'test> TestCx<'test> {
@@ -1384,7 +1390,9 @@ impl<'test> TestCx<'test> {
let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res);
let mut unexpected = Vec::new();
let mut found = vec![false; expected_errors.len()];
- for actual_error in &actual_errors {
+ for mut actual_error in actual_errors {
+ actual_error.msg = self.normalize_output(&actual_error.msg, &[]);
+
let opt_index =
expected_errors.iter().enumerate().position(|(index, expected_error)| {
!found[index]
@@ -1403,7 +1411,8 @@ impl<'test> TestCx<'test> {
None => {
// If the test is a known bug, don't require that the error is annotated
- if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) {
+ if self.is_unexpected_compiler_message(&actual_error, expect_help, expect_note)
+ {
self.error(&format!(
"{}:{}: unexpected {}: '{}'",
file_name,
@@ -1479,7 +1488,16 @@ impl<'test> TestCx<'test> {
}
fn compile_test(&self, will_execute: WillExecute, emit: Emit) -> ProcRes {
- self.compile_test_general(will_execute, emit, self.props.local_pass_mode())
+ self.compile_test_general(will_execute, emit, self.props.local_pass_mode(), Vec::new())
+ }
+
+ fn compile_test_with_passes(
+ &self,
+ will_execute: WillExecute,
+ emit: Emit,
+ passes: Vec<String>,
+ ) -> ProcRes {
+ self.compile_test_general(will_execute, emit, self.props.local_pass_mode(), passes)
}
fn compile_test_general(
@@ -1487,6 +1505,7 @@ impl<'test> TestCx<'test> {
will_execute: WillExecute,
emit: Emit,
local_pm: Option<PassMode>,
+ passes: Vec<String>,
) -> ProcRes {
// Only use `make_exe_name` when the test ends up being executed.
let output_file = match will_execute {
@@ -1523,6 +1542,7 @@ impl<'test> TestCx<'test> {
emit,
allow_unused,
LinkToAux::Yes,
+ passes,
);
self.compose_and_run_compiler(rustc, None)
@@ -1773,6 +1793,7 @@ impl<'test> TestCx<'test> {
Emit::None,
AllowUnused::No,
LinkToAux::No,
+ Vec::new(),
);
for key in &aux_props.unset_rustc_env {
@@ -1904,6 +1925,7 @@ impl<'test> TestCx<'test> {
emit: Emit,
allow_unused: AllowUnused,
link_to_aux: LinkToAux,
+ passes: Vec<String>, // Vec of passes under mir-opt test to be dumped
) -> Command {
let is_aux = input_file.components().map(|c| c.as_os_str()).any(|c| c == "auxiliary");
let is_rustdoc = self.is_rustdoc() && !is_aux;
@@ -1917,6 +1939,12 @@ impl<'test> TestCx<'test> {
// Use a single thread for efficiency and a deterministic error message order
rustc.arg("-Zthreads=1");
+ // Optionally prevent default --sysroot if specified in test compile-flags.
+ if !self.props.compile_flags.iter().any(|flag| flag.starts_with("--sysroot")) {
+ // In stage 0, make sure we use `stage0-sysroot` instead of the bootstrap sysroot.
+ rustc.arg("--sysroot").arg(&self.config.sysroot_base);
+ }
+
// Optionally prevent default --target if specified in test compile-flags.
let custom_target = self.props.compile_flags.iter().any(|x| x.starts_with("--target"));
@@ -1998,9 +2026,18 @@ impl<'test> TestCx<'test> {
rustc.arg("-Cstrip=debuginfo");
}
MirOpt => {
+ // We check passes under test to minimize the mir-opt test dump
+ // if files_for_miropt_test parses the passes, we dump only those passes
+ // otherwise we conservatively pass -Zdump-mir=all
+ let zdump_arg = if !passes.is_empty() {
+ format!("-Zdump-mir={}", passes.join(" | "))
+ } else {
+ "-Zdump-mir=all".to_string()
+ };
+
rustc.args(&[
"-Copt-level=1",
- "-Zdump-mir=all",
+ &zdump_arg,
"-Zvalidate-mir",
"-Zdump-mir-exclude-pass-number",
"-Zmir-pretty-relative-line-numbers=yes",
@@ -2046,6 +2083,9 @@ impl<'test> TestCx<'test> {
Emit::Asm => {
rustc.args(&["--emit", "asm"]);
}
+ Emit::LinkArgsAsm => {
+ rustc.args(&["-Clink-args=--emit=asm"]);
+ }
}
if !is_rustdoc {
@@ -2320,6 +2360,7 @@ impl<'test> TestCx<'test> {
Emit::LlvmIr,
AllowUnused::No,
LinkToAux::Yes,
+ Vec::new(),
);
self.compose_and_run_compiler(rustc, None)
@@ -2339,16 +2380,26 @@ impl<'test> TestCx<'test> {
emit = Emit::Asm;
}
+ Some("bpf-linker") => {
+ emit = Emit::LinkArgsAsm;
+ }
+
Some("ptx-linker") => {
// No extra flags needed.
}
- Some(_) => self.fatal("unknown 'assembly-output' header"),
+ Some(header) => self.fatal(&format!("unknown 'assembly-output' header: {header}")),
None => self.fatal("missing 'assembly-output' header"),
}
- let rustc =
- self.make_compile_args(input_file, output_file, emit, AllowUnused::No, LinkToAux::Yes);
+ let rustc = self.make_compile_args(
+ input_file,
+ output_file,
+ emit,
+ AllowUnused::No,
+ LinkToAux::Yes,
+ Vec::new(),
+ );
(self.compose_and_run_compiler(rustc, None), output_path)
}
@@ -2479,6 +2530,7 @@ impl<'test> TestCx<'test> {
Emit::None,
AllowUnused::Yes,
LinkToAux::Yes,
+ Vec::new(),
);
new_rustdoc.build_all_auxiliary(&mut rustc);
@@ -3255,17 +3307,35 @@ impl<'test> TestCx<'test> {
match output_kind {
TestOutput::Compile => {
if !self.props.dont_check_compiler_stdout {
- errors +=
- self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
+ errors += self.compare_output(
+ stdout_kind,
+ &normalized_stdout,
+ &expected_stdout,
+ self.props.compare_output_lines_by_subset,
+ );
}
if !self.props.dont_check_compiler_stderr {
- errors +=
- self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
+ errors += self.compare_output(
+ stderr_kind,
+ &normalized_stderr,
+ &expected_stderr,
+ self.props.compare_output_lines_by_subset,
+ );
}
}
TestOutput::Run => {
- errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
- errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
+ errors += self.compare_output(
+ stdout_kind,
+ &normalized_stdout,
+ &expected_stdout,
+ self.props.compare_output_lines_by_subset,
+ );
+ errors += self.compare_output(
+ stderr_kind,
+ &normalized_stderr,
+ &expected_stderr,
+ self.props.compare_output_lines_by_subset,
+ );
}
}
errors
@@ -3275,7 +3345,8 @@ impl<'test> TestCx<'test> {
if let Some(FailMode::Build) = self.props.fail_mode {
// Make sure a build-fail test cannot fail due to failing analysis (e.g. typeck).
let pm = Some(PassMode::Check);
- let proc_res = self.compile_test_general(WillExecute::No, Emit::Metadata, pm);
+ let proc_res =
+ self.compile_test_general(WillExecute::No, Emit::Metadata, pm, Vec::new());
self.check_if_test_should_compile(&proc_res, pm);
}
@@ -3349,7 +3420,12 @@ impl<'test> TestCx<'test> {
)
});
- errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
+ errors += self.compare_output(
+ "fixed",
+ &fixed_code,
+ &expected_fixed,
+ self.props.compare_output_lines_by_subset,
+ );
} else if !expected_fixed.is_empty() {
panic!(
"the `// run-rustfix` directive wasn't found but a `*.fixed` \
@@ -3439,6 +3515,7 @@ impl<'test> TestCx<'test> {
emit_metadata,
AllowUnused::No,
LinkToAux::Yes,
+ Vec::new(),
);
let res = self.compose_and_run_compiler(rustc, None);
if !res.status.success() {
@@ -3457,14 +3534,14 @@ impl<'test> TestCx<'test> {
let pm = self.pass_mode();
let should_run = self.should_run(pm);
let emit_metadata = self.should_emit_metadata(pm);
- let proc_res = self.compile_test(should_run, emit_metadata);
+ let passes = self.get_passes();
+ let proc_res = self.compile_test_with_passes(should_run, emit_metadata, passes);
+ self.check_mir_dump();
if !proc_res.status.success() {
self.fatal_proc_rec("compilation failed!", &proc_res);
}
- self.check_mir_dump();
-
if let WillExecute::Yes = should_run {
let proc_res = self.exec_compiled_test();
@@ -3474,6 +3551,26 @@ impl<'test> TestCx<'test> {
}
}
+ fn get_passes(&self) -> Vec<String> {
+ let files = miropt_test_tools::files_for_miropt_test(
+ &self.testpaths.file,
+ self.config.get_pointer_width(),
+ );
+
+ let mut out = Vec::new();
+
+ for miropt_test_tools::MiroptTestFiles {
+ from_file: _,
+ to_file: _,
+ expected_file: _,
+ passes,
+ } in files
+ {
+ out.extend(passes);
+ }
+ out
+ }
+
fn check_mir_dump(&self) {
let test_file_contents = fs::read_to_string(&self.testpaths.file).unwrap();
@@ -3503,8 +3600,9 @@ impl<'test> TestCx<'test> {
&self.testpaths.file,
self.config.get_pointer_width(),
);
-
- for miropt_test_tools::MiroptTestFiles { from_file, to_file, expected_file } in files {
+ for miropt_test_tools::MiroptTestFiles { from_file, to_file, expected_file, passes: _ } in
+ files
+ {
let dumped_string = if let Some(after) = to_file {
self.diff_mir_files(from_file.into(), after.into())
} else {
@@ -3807,11 +3905,38 @@ impl<'test> TestCx<'test> {
}
}
- fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
+ fn compare_output(
+ &self,
+ kind: &str,
+ actual: &str,
+ expected: &str,
+ compare_output_by_lines: bool,
+ ) -> usize {
if actual == expected {
return 0;
}
+ let tmp;
+ let (expected, actual): (&str, &str) = if compare_output_by_lines {
+ let actual_lines: HashSet<_> = actual.lines().collect();
+ let expected_lines: Vec<_> = expected.lines().collect();
+ let mut used = expected_lines.clone();
+ used.retain(|line| actual_lines.contains(line));
+ // check if `expected` contains a subset of the lines of `actual`
+ if used.len() == expected_lines.len() && (expected.is_empty() == actual.is_empty()) {
+ return 0;
+ }
+ if expected_lines.is_empty() {
+ // if we have no lines to check, force a full overwite
+ ("", actual)
+ } else {
+ tmp = (expected_lines.join("\n"), used.join("\n"));
+ (&tmp.0, &tmp.1)
+ }
+ } else {
+ (expected, actual)
+ };
+
if !self.config.bless {
if expected.is_empty() {
println!("normalized {}:\n{}\n", kind, actual);
diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml
new file mode 100644
index 000000000..23e88844b
--- /dev/null
+++ b/src/tools/generate-windows-sys/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "generate-windows-sys"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies.windows-bindgen]
+version = "0.49"
diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs
new file mode 100644
index 000000000..91d981462
--- /dev/null
+++ b/src/tools/generate-windows-sys/src/main.rs
@@ -0,0 +1,37 @@
+use std::fs;
+use std::io::{self, Write};
+use std::path::PathBuf;
+
+/// This is printed to the file before the rest of the contents.
+const PRELUDE: &str = r#"// This file is autogenerated.
+//
+// To add bindings, edit windows_sys.lst then use `./x run generate-windows-sys` to
+// regenerate the bindings.
+//
+// ignore-tidy-filelength
+"#;
+
+fn main() -> io::Result<()> {
+ let mut path: PathBuf =
+ std::env::args_os().nth(1).expect("a path to the rust repository is required").into();
+ path.push("library/std/src/sys/windows/c/windows_sys.lst");
+
+ // Load the list of APIs
+ let buffer = fs::read_to_string(&path)?;
+ let names: Vec<&str> = buffer
+ .lines()
+ .filter_map(|line| {
+ let line = line.trim();
+ if line.is_empty() || line.starts_with("//") { None } else { Some(line) }
+ })
+ .collect();
+
+ // Write the bindings to windows-sys.rs
+ let bindings = windows_bindgen::standalone_std(&names);
+ path.set_extension("rs");
+ let mut f = std::fs::File::create(&path)?;
+ f.write_all(PRELUDE.as_bytes())?;
+ f.write_all(bindings.as_bytes())?;
+
+ Ok(())
+}
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index a1f675a3b..bf8a64acf 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -273,7 +273,9 @@ impl<'a> Validator<'a> {
Type::QualifiedPath { name: _, args, self_type, trait_ } => {
self.check_generic_args(&**args);
self.check_type(&**self_type);
- self.check_path(trait_, PathKind::Trait);
+ if let Some(trait_) = trait_ {
+ self.check_path(trait_, PathKind::Trait);
+ }
}
}
}
diff --git a/src/tools/linkchecker/linkcheck.sh b/src/tools/linkchecker/linkcheck.sh
index 9eeebf444..6c1e668a7 100755
--- a/src/tools/linkchecker/linkcheck.sh
+++ b/src/tools/linkchecker/linkcheck.sh
@@ -16,15 +16,13 @@
#
# --all Check all books. This can help make sure you don't break links
# from other books into your book.
+#
+# --path <book-path>
+# Path to the root directory for the book. Default to the current
+# working directory if omitted.
set -e
-if [ ! -f book.toml ] && [ ! -f src/SUMMARY.md ]
-then
- echo "Run command in root directory of the book."
- exit 1
-fi
-
html_dir="$(rustc +nightly --print sysroot)/share/doc/rust/html"
if [ ! -d "$html_dir" ]
@@ -38,6 +36,8 @@ fi
export MDBOOK_OUTPUT__HTML__INPUT_404=""
book_name=""
+# Default to the current directory
+book_path="."
# Iterative will avoid cleaning up, so you can quickly run it repeatedly.
iterative=0
# If "1", test all books, else only this book.
@@ -52,6 +52,10 @@ do
--all)
all_books=1
;;
+ --path)
+ book_path="${2:-.}"
+ shift
+ ;;
*)
if [ -n "$book_name" ]
then
@@ -70,6 +74,12 @@ then
exit 1
fi
+if [ ! -f "$book_path/book.toml" ] && [ ! -f "$book_path/src/SUMMARY.md" ]
+then
+ echo "Run command in root directory of the book or provide a path to the book"
+ exit 1
+fi
+
if [ ! -d "$html_dir/$book_name" ]
then
echo "book name \"$book_name\" not found in sysroot \"$html_dir\""
@@ -93,11 +103,11 @@ then
fi
echo "Building book \"$book_name\"..."
-mdbook build
+mdbook build "$book_path"
cp -R "$html_dir" linkcheck
rm -rf "linkcheck/$book_name"
-cp -R book "linkcheck/$book_name"
+cp -R "$book_path/book" "linkcheck/$book_name"
if [ "$all_books" = "1" ]
then
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 4170c32f1..c8a370085 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -139,18 +139,18 @@ enum FileEntry {
type Cache = HashMap<String, FileEntry>;
fn small_url_encode(s: &str) -> String {
- s.replace("<", "%3C")
- .replace(">", "%3E")
- .replace(" ", "%20")
- .replace("?", "%3F")
- .replace("'", "%27")
- .replace("&", "%26")
- .replace(",", "%2C")
- .replace(":", "%3A")
- .replace(";", "%3B")
- .replace("[", "%5B")
- .replace("]", "%5D")
- .replace("\"", "%22")
+ s.replace('<', "%3C")
+ .replace('>', "%3E")
+ .replace(' ', "%20")
+ .replace('?', "%3F")
+ .replace('\'', "%27")
+ .replace('&', "%26")
+ .replace(',', "%2C")
+ .replace(':', "%3A")
+ .replace(';', "%3B")
+ .replace('[', "%5B")
+ .replace(']', "%5D")
+ .replace('\"', "%22")
}
impl Checker {
@@ -267,7 +267,6 @@ impl Checker {
FileEntry::OtherFile => return,
FileEntry::Redirect { target } => {
let t = target.clone();
- drop(target);
let (target, redir_entry) = self.load_file(&t, report);
match redir_entry {
FileEntry::Missing => {
@@ -391,7 +390,7 @@ impl Checker {
const ERROR_INVALID_NAME: i32 = 123;
let pretty_path =
- file.strip_prefix(&self.root).unwrap_or(&file).to_str().unwrap().to_string();
+ file.strip_prefix(&self.root).unwrap_or(file).to_str().unwrap().to_string();
let entry =
self.cache.entry(pretty_path.clone()).or_insert_with(|| match fs::metadata(file) {
@@ -470,10 +469,8 @@ fn is_exception(file: &Path, link: &str) -> bool {
// NOTE: This cannot be added to `LINKCHECK_EXCEPTIONS` because the resolved path
// calculated in `check` function is outside `build/<triple>/doc` dir.
// So the `strip_prefix` method just returns the old absolute broken path.
- if file.ends_with("std/primitive.slice.html") {
- if link.ends_with("primitive.slice.html") {
- return true;
- }
+ if file.ends_with("std/primitive.slice.html") && link.ends_with("primitive.slice.html") {
+ return true;
}
false
}
@@ -545,7 +542,7 @@ fn with_attrs_in_source<F: FnMut(&str, usize, &str)>(source: &str, attr: &str, m
fn parse_ids(ids: &mut HashSet<String>, file: &str, source: &str, report: &mut Report) {
if ids.is_empty() {
with_attrs_in_source(source, " id", |fragment, i, _| {
- let frag = fragment.trim_start_matches("#").to_owned();
+ let frag = fragment.trim_start_matches('#').to_owned();
let encoded = small_url_encode(&frag);
if !ids.insert(frag) {
report.errors += 1;
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index 2a923a61b..5be8ef799 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -43,7 +43,7 @@ impl<'a> LintExtractor<'a> {
let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?;
if !output.status.success() {
return Err(format!(
- "failed to collect lint info: {:?}\n--- stderr\n{}--- stdout\n{}\n",
+ "failed to collect lint info: failed to run {cmd:?}: {:?}\n--- stderr\n{}--- stdout\n{}\n",
output.status,
std::str::from_utf8(&output.stderr).unwrap(),
std::str::from_utf8(&output.stdout).unwrap(),
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index 034c6aa07..b7c8b9ed2 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -415,6 +415,9 @@ impl<'a> LintExtractor<'a> {
}
cmd.arg("lint_example.rs");
cmd.current_dir(tempdir.path());
+ if self.verbose {
+ eprintln!("running: {cmd:?}");
+ }
let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?;
let stderr = std::str::from_utf8(&output.stderr).unwrap();
let msgs = stderr
diff --git a/src/tools/miropt-test-tools/src/lib.rs b/src/tools/miropt-test-tools/src/lib.rs
index cfba7d583..f86c3ce0a 100644
--- a/src/tools/miropt-test-tools/src/lib.rs
+++ b/src/tools/miropt-test-tools/src/lib.rs
@@ -4,6 +4,8 @@ pub struct MiroptTestFiles {
pub expected_file: std::path::PathBuf,
pub from_file: String,
pub to_file: Option<String>,
+ /// Vec of passes under test to be dumped
+ pub passes: Vec<String>,
}
pub fn files_for_miropt_test(testfile: &std::path::Path, bit_width: u32) -> Vec<MiroptTestFiles> {
@@ -28,9 +30,11 @@ pub fn files_for_miropt_test(testfile: &std::path::Path, bit_width: u32) -> Vec<
let mut expected_file;
let from_file;
let to_file;
+ let mut passes = Vec::new();
if test_name.ends_with(".diff") {
let trimmed = test_name.trim_end_matches(".diff");
+ passes.push(trimmed.split('.').last().unwrap().to_owned());
let test_against = format!("{}.after.mir", trimmed);
from_file = format!("{}.before.mir", trimmed);
expected_file = format!("{}{}.diff", trimmed, bit_width);
@@ -38,7 +42,14 @@ pub fn files_for_miropt_test(testfile: &std::path::Path, bit_width: u32) -> Vec<
to_file = Some(test_against);
} else if let Some(first_pass) = test_names.next() {
let second_pass = test_names.next().unwrap();
+ if let Some((first_pass_name, _)) = first_pass.split_once('.') {
+ passes.push(first_pass_name.to_owned());
+ }
+ if let Some((second_pass_name, _)) = second_pass.split_once('.') {
+ passes.push(second_pass_name.to_owned());
+ }
assert!(test_names.next().is_none(), "three mir pass names specified for MIR diff");
+
expected_file =
format!("{}{}.{}-{}.diff", test_name, bit_width, first_pass, second_pass);
let second_file = format!("{}.{}.mir", test_name, second_pass);
@@ -51,18 +62,24 @@ pub fn files_for_miropt_test(testfile: &std::path::Path, bit_width: u32) -> Vec<
.next()
.expect("test_name has an invalid extension");
let extension = cap.get(1).unwrap().as_str();
+
expected_file =
format!("{}{}{}", test_name.trim_end_matches(extension), bit_width, extension,);
from_file = test_name.to_string();
assert!(test_names.next().is_none(), "two mir pass names specified for MIR dump");
to_file = None;
+ // the pass name is the third to last string in the test name
+ // this gets pushed into passes
+ passes.push(
+ test_name.split('.').rev().nth(2).expect("invalid test format").to_string(),
+ );
};
if !expected_file.starts_with(&test_crate) {
expected_file = format!("{}.{}", test_crate, expected_file);
}
let expected_file = test_dir.join(expected_file);
- out.push(MiroptTestFiles { expected_file, from_file, to_file });
+ out.push(MiroptTestFiles { expected_file, from_file, to_file, passes });
}
}
diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs
index 0aebfc4aa..5c9c18b9b 100644
--- a/src/tools/replace-version-placeholder/src/main.rs
+++ b/src/tools/replace-version-placeholder/src/main.rs
@@ -8,15 +8,13 @@ fn main() {
let version_path = root_path.join("src").join("version");
let version_str = t!(std::fs::read_to_string(&version_path), version_path);
let version_str = version_str.trim();
- walk::walk(
- &root_path,
+ walk::walk_many(
+ &[&root_path.join("compiler"), &root_path.join("library")],
|path, _is_dir| {
walk::filter_dirs(path)
// We exempt these as they require the placeholder
// for their operation
|| path.ends_with("compiler/rustc_attr/src/builtin.rs")
- || path.ends_with("src/tools/tidy/src/features/version.rs")
- || path.ends_with("src/tools/replace-version-placeholder")
},
&mut |entry, contents| {
if !contents.contains(VERSION_PLACEHOLDER) {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index 4096e0a38..d338bb412 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -379,7 +379,6 @@ language_item_table! {
// FIXME(swatinem): the following lang items are used for async lowering and
// should become obsolete eventually.
ResumeTy, ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
- IdentityFuture, identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
GetContext, get_context, get_context_fn, Target::Fn, GenericRequirement::None;
Context, Context, context, Target::Struct, GenericRequirement::None;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 0b72ca1ee..5fbd1789b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -201,7 +201,7 @@ macro_rules! format_args {
}
fn main() {
- $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(arg1(a, b, c)), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(arg2), $crate::fmt::Display::fmt), ]);
+ $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(arg1(a, b, c)), $crate::fmt::Display::fmt), $crate::fmt::Argument::new(&(arg2), $crate::fmt::Display::fmt), ]);
}
"#]],
);
@@ -229,7 +229,7 @@ macro_rules! format_args {
}
fn main() {
- $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(a::<A, B>()), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(b), $crate::fmt::Display::fmt), ]);
+ $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(a::<A, B>()), $crate::fmt::Display::fmt), $crate::fmt::Argument::new(&(b), $crate::fmt::Display::fmt), ]);
}
"#]],
);
@@ -260,7 +260,7 @@ macro_rules! format_args {
fn main() {
let _ =
/* parse error: expected field name or number */
-$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(a.), $crate::fmt::Display::fmt), ]);
+$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(a.), $crate::fmt::Display::fmt), ]);
}
"#]],
);
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
index 44510f2b7..a9c5e1488 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
@@ -241,8 +241,8 @@ fn format_args_expand(
// We expand `format_args!("", a1, a2)` to
// ```
// $crate::fmt::Arguments::new_v1(&[], &[
- // $crate::fmt::ArgumentV1::new(&arg1,$crate::fmt::Display::fmt),
- // $crate::fmt::ArgumentV1::new(&arg2,$crate::fmt::Display::fmt),
+ // $crate::fmt::Argument::new(&arg1,$crate::fmt::Display::fmt),
+ // $crate::fmt::Argument::new(&arg2,$crate::fmt::Display::fmt),
// ])
// ```,
// which is still not really correct, but close enough for now
@@ -267,7 +267,7 @@ fn format_args_expand(
}
let _format_string = args.remove(0);
let arg_tts = args.into_iter().flat_map(|arg| {
- quote! { #DOLLAR_CRATE::fmt::ArgumentV1::new(&(#arg), #DOLLAR_CRATE::fmt::Display::fmt), }
+ quote! { #DOLLAR_CRATE::fmt::Argument::new(&(#arg), #DOLLAR_CRATE::fmt::Display::fmt), }
}.token_trees);
let expanded = quote! {
#DOLLAR_CRATE::fmt::Arguments::new_v1(&[], &[##arg_tts])
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
index d258a0247..a9cd8e705 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
@@ -20,7 +20,7 @@ use token_stream::TokenStreamBuilder;
mod symbol;
pub use symbol::*;
-use std::ops::Bound;
+use std::ops::{Bound, Range};
use crate::tt;
@@ -298,6 +298,10 @@ impl server::Span for RustAnalyzer {
// FIXME handle span
span
}
+ fn byte_range(&mut self, _span: Self::Span) -> Range<usize> {
+ // FIXME handle span
+ Range { start: 0, end: 0 }
+ }
fn start(&mut self, _span: Self::Span) -> LineColumn {
// FIXME handle span
LineColumn { line: 0, column: 0 }
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
deleted file mode 100644
index e088ffbbe..000000000
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ /dev/null
@@ -1,102 +0,0 @@
-[package]
-name = "rustc-workspace-hack"
-version = "1.0.0"
-license = 'MIT OR Apache-2.0'
-description = """
-Hack for the compiler's own build system
-"""
-edition = "2021"
-
-[lib]
-path = "lib.rs"
-
-# For documentation about what this is and why in the world these dependencies
-# are appearing, see `README.md`.
-
-[target.'cfg(windows)'.dependencies.winapi]
-version = "0.3"
-features = [
- "accctrl",
- "aclapi",
- "basetsd",
- "cfg",
- "consoleapi",
- "errhandlingapi",
- "evntrace",
- "fibersapi",
- "handleapi",
- "in6addr",
- "inaddr",
- "ioapiset",
- "jobapi",
- "jobapi2",
- "knownfolders",
- "libloaderapi",
- "lmcons",
- "memoryapi",
- "minschannel",
- "minwinbase",
- "mstcpip",
- "mswsock",
- "namedpipeapi",
- "ntdef",
- "ntsecapi",
- "ntstatus",
- "objbase",
- "processenv",
- "processthreadsapi",
- "profileapi",
- "psapi",
- "schannel",
- "securitybaseapi",
- "shellapi",
- "shlobj",
- "sspi",
- "synchapi",
- "sysinfoapi",
- "threadpoollegacyapiset",
- "timezoneapi",
- "userenv",
- "winbase",
- "wincon",
- "wincrypt",
- "windef",
- "winioctl",
- "winnt",
- "winreg",
- "winsock2",
- "winuser",
- "ws2def",
- "ws2ipdef",
- "ws2tcpip",
-]
-
-[dependencies]
-bstr = { version = "0.2.17", features = ["default"] }
-clap = { version = "3.1.1", features = ["derive", "clap_derive"]}
-curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
-# Ensure `extra_traits` of libc, which is used transitively by Cargo.
-libc = { version = "0.2", features = ["extra_traits"] }
-# Ensure `js` of getrandom, which is (unfortunately) used transitively by Cargo.
-getrandom = { version = "0.2", features = ["js"] }
-# Ensure default features of libz-sys, which are disabled in some scenarios.
-libz-sys = { version = "1.1.2" }
-# Ensure default features of regex, which are disabled in some scenarios.
-regex = { version = "1.5.6" }
-serde_json = { version = "1.0.31", features = ["raw_value", "unbounded_depth"] }
-syn = { version = "1", features = ['full', 'visit', 'visit-mut'] } # `visit-mut` required by Cargo via `gix`
-url = { version = "2.0", features = ['serde'] }
-# Ensure default features of rand, which are disabled in some scenarios.
-rand = { version = "0.8.5" }
-
-# Ensure features of `hashbrown`, `smallvec`, and `once_cell`,
-# which are used transitively by Cargo (via `gix`).
-hashbrown = { version = "0.12.3", default-features = false, features = ["inline-more"] }
-once_cell = { version = "1.16.0", default-features = false, features = ["unstable"] }
-smallvec = { version = "1.10.0", features = ["write"] }
-
-[target.'cfg(not(windows))'.dependencies]
-openssl = { version = "0.10.35", optional = true }
-
-[features]
-all-static = ['openssl/vendored', 'curl-sys/static-curl', 'curl-sys/force-system-lib-on-osx']
diff --git a/src/tools/rustc-workspace-hack/README.md b/src/tools/rustc-workspace-hack/README.md
deleted file mode 100644
index 3c6147035..000000000
--- a/src/tools/rustc-workspace-hack/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# `rustc-workspace-hack`
-
-This crate is a bit of a hack to make workspaces in rustc work a bit better.
-The rationale for this existence is a bit subtle, but the general idea is that
-we want commands like `./x.py build src/tools/{clippy,cargo}` to share as
-many dependencies as possible.
-
-Each invocation is a different invocation of Cargo, however. Each time Cargo
-runs a build it will re-resolve the dependency graph, notably selecting
-different features sometimes for each build.
-
-For example, let's say there's a very deep dependency like `winapi` in each of
-these builds. For Cargo, `winapi` has 33 features enabled. In Clippy, however,
-`winapi` has 22 features enabled. This means that building Cargo and then the
-Clippy will actually build winapi twice, which in turn will build duplicates
-of everything that depends on `winapi`. This is bad!
-
-The goal of this crate is to solve this problem and ensure that the resolved
-dependency graph for all of these tools is the same in the various subsets of
-each tool, notably enabling the same features of transitive dependencies.
-
-All tools vendored here depend on the `rustc-workspace-hack` crate on crates.io.
-When on crates.io this crate is an empty crate that is just a noop. We override
-it, however, in this workspace to this crate here, which means we can control
-crates in the dependency graph for each of these tools.
diff --git a/src/tools/rustc-workspace-hack/lib.rs b/src/tools/rustc-workspace-hack/lib.rs
deleted file mode 100644
index 44425d9c1..000000000
--- a/src/tools/rustc-workspace-hack/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-// intentionally left blank
diff --git a/src/tools/rustdoc-gui-test/Cargo.toml b/src/tools/rustdoc-gui-test/Cargo.toml
new file mode 100644
index 000000000..f0c5b3671
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "rustdoc-gui-test"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+compiletest = { path = "../compiletest" }
+getopts = "0.2"
+walkdir = "2"
diff --git a/src/tools/rustdoc-gui-test/src/config.rs b/src/tools/rustdoc-gui-test/src/config.rs
new file mode 100644
index 000000000..dc4c56a5e
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/src/config.rs
@@ -0,0 +1,62 @@
+use getopts::Options;
+use std::{env, path::PathBuf};
+
+pub(crate) struct Config {
+ pub(crate) nodejs: PathBuf,
+ pub(crate) npm: PathBuf,
+ pub(crate) rust_src: PathBuf,
+ pub(crate) out_dir: PathBuf,
+ pub(crate) initial_cargo: PathBuf,
+ pub(crate) jobs: String,
+ pub(crate) test_args: Vec<PathBuf>,
+ pub(crate) goml_files: Vec<PathBuf>,
+ pub(crate) rustc: PathBuf,
+ pub(crate) rustdoc: PathBuf,
+ pub(crate) verbose: bool,
+}
+
+impl Config {
+ pub(crate) fn from_args(args: Vec<String>) -> Self {
+ let mut opts = Options::new();
+ opts.reqopt("", "nodejs", "absolute path of nodejs", "PATH")
+ .reqopt("", "npm", "absolute path of npm", "PATH")
+ .reqopt("", "out-dir", "output path of doc compilation", "PATH")
+ .reqopt("", "rust-src", "root source of the rust source", "PATH")
+ .reqopt(
+ "",
+ "initial-cargo",
+ "path to cargo to use for compiling tests/rustdoc-gui/src/*",
+ "PATH",
+ )
+ .reqopt("", "jobs", "jobs arg of browser-ui-test", "JOBS")
+ .optflag("", "verbose", "run tests verbosely, showing all output")
+ .optmulti("", "test-arg", "args for browser-ui-test", "FLAGS")
+ .optmulti("", "goml-file", "goml files for testing with browser-ui-test", "LIST");
+
+ let (argv0, args_) = args.split_first().unwrap();
+ if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
+ let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
+ println!("{}", opts.usage(&message));
+ std::process::exit(1);
+ }
+
+ let matches = &match opts.parse(args_) {
+ Ok(m) => m,
+ Err(f) => panic!("{:?}", f),
+ };
+
+ Self {
+ nodejs: matches.opt_str("nodejs").map(PathBuf::from).expect("nodejs isn't available"),
+ npm: matches.opt_str("npm").map(PathBuf::from).expect("npm isn't available"),
+ rust_src: matches.opt_str("rust-src").map(PathBuf::from).unwrap(),
+ out_dir: matches.opt_str("out-dir").map(PathBuf::from).unwrap(),
+ initial_cargo: matches.opt_str("initial-cargo").map(PathBuf::from).unwrap(),
+ jobs: matches.opt_str("jobs").unwrap(),
+ goml_files: matches.opt_strs("goml-file").iter().map(PathBuf::from).collect(),
+ test_args: matches.opt_strs("test-arg").iter().map(PathBuf::from).collect(),
+ rustc: env::var("RUSTC").map(PathBuf::from).unwrap(),
+ rustdoc: env::var("RUSTDOC").map(PathBuf::from).unwrap(),
+ verbose: matches.opt_present("verbose"),
+ }
+ }
+}
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
new file mode 100644
index 000000000..8dc18dfae
--- /dev/null
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -0,0 +1,162 @@
+use compiletest::header::TestProps;
+use config::Config;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+use std::sync::Arc;
+use std::{env, fs};
+
+mod config;
+
+fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String> {
+ let mut command = Command::new(&npm);
+ command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
+ if global {
+ command.arg("--global");
+ }
+ let lines = command
+ .output()
+ .map(|output| String::from_utf8_lossy(&output.stdout).into_owned())
+ .unwrap_or(String::new());
+ lines
+ .lines()
+ .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
+ .map(|v| v.to_owned())
+}
+
+fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
+ get_browser_ui_test_version_inner(npm, false)
+ .or_else(|| get_browser_ui_test_version_inner(npm, true))
+}
+
+fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
+ match fs::read_to_string(
+ src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
+ ) {
+ Ok(v) => {
+ if v.trim() != installed_version {
+ eprintln!(
+ "⚠️ Installed version of browser-ui-test (`{}`) is different than the \
+ one used in the CI (`{}`)",
+ installed_version, v
+ );
+ eprintln!(
+ "You can install this version using `npm update browser-ui-test` or by using \
+ `npm install browser-ui-test@{}`",
+ v,
+ );
+ }
+ }
+ Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
+ }
+}
+
+fn find_librs<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
+ for entry in walkdir::WalkDir::new(path) {
+ let entry = entry.ok()?;
+ if entry.file_type().is_file() && entry.file_name() == "lib.rs" {
+ return Some(entry.path().to_path_buf());
+ }
+ }
+ None
+}
+
+// FIXME: move `bootstrap::util::try_run` into `build_helper` crate
+// and use that one instead of creating this function.
+fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
+ let status = match cmd.status() {
+ Ok(status) => status,
+ Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cmd, e),
+ };
+ if !status.success() && print_cmd_on_fail {
+ println!(
+ "\n\ncommand did not execute successfully: {:?}\n\
+ expected success, got: {}\n\n",
+ cmd, status
+ );
+ }
+ status.success()
+}
+
+fn main() {
+ let config = Arc::new(Config::from_args(env::args().collect()));
+
+ // The goal here is to check if the necessary packages are installed, and if not, we
+ // panic.
+ match get_browser_ui_test_version(&config.npm) {
+ Some(version) => {
+ // We also check the version currently used in CI and emit a warning if it's not the
+ // same one.
+ compare_browser_ui_test_version(&version, &config.rust_src);
+ }
+ None => {
+ eprintln!(
+ r#"
+error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` dependency is missing.
+
+If you want to install the `browser-ui-test` dependency, run `npm install browser-ui-test`
+"#,
+ );
+
+ panic!("Cannot run rustdoc-gui tests");
+ }
+ }
+
+ let src_path = config.rust_src.join("tests/rustdoc-gui/src");
+ for entry in src_path.read_dir().expect("read_dir call failed") {
+ if let Ok(entry) = entry {
+ let path = entry.path();
+
+ if !path.is_dir() {
+ continue;
+ }
+
+ let mut cargo = Command::new(&config.initial_cargo);
+ cargo
+ .arg("doc")
+ .arg("--target-dir")
+ .arg(&config.out_dir)
+ .env("RUSTC_BOOTSTRAP", "1")
+ .env("RUSTDOC", &config.rustdoc)
+ .env("RUSTC", &config.rustc)
+ .current_dir(path);
+
+ if let Some(librs) = find_librs(entry.path()) {
+ let compiletest_c = compiletest::common::Config {
+ edition: None,
+ mode: compiletest::common::Mode::Rustdoc,
+ ..Default::default()
+ };
+
+ let test_props = TestProps::from_file(&librs, None, &compiletest_c);
+
+ if !test_props.compile_flags.is_empty() {
+ cargo.env("RUSTDOCFLAGS", test_props.compile_flags.join(" "));
+ }
+
+ if let Some(flags) = &test_props.run_flags {
+ cargo.arg(flags);
+ }
+ }
+
+ try_run(&mut cargo, config.verbose);
+ }
+ }
+
+ let mut command = Command::new(&config.nodejs);
+ command
+ .arg(config.rust_src.join("src/tools/rustdoc-gui/tester.js"))
+ .arg("--jobs")
+ .arg(&config.jobs)
+ .arg("--doc-folder")
+ .arg(config.out_dir.join("doc"))
+ .arg("--tests-folder")
+ .arg(config.rust_src.join("tests/rustdoc-gui"));
+
+ for file in &config.goml_files {
+ command.arg("--file").arg(file);
+ }
+
+ command.args(&config.test_args);
+
+ try_run(&mut command, config.verbose);
+}
diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js
index 72baad606..b26480f66 100644
--- a/src/tools/rustdoc-gui/tester.js
+++ b/src/tools/rustdoc-gui/tester.js
@@ -42,7 +42,7 @@ function parseOptions(args) {
"executable_path": null,
"no_sandbox": false,
};
- const correspondances = {
+ const correspondences = {
"--doc-folder": "doc_folder",
"--tests-folder": "tests_folder",
"--debug": "debug",
@@ -73,7 +73,7 @@ function parseOptions(args) {
}
opts["jobs"] = parseInt(arg_value);
} else if (arg !== "--file") {
- opts[correspondances[arg]] = arg_value;
+ opts[correspondences[arg]] = arg_value;
} else {
opts["files"].push(arg_value);
}
@@ -82,9 +82,9 @@ function parseOptions(args) {
process.exit(0);
} else if (arg === "--no-sandbox") {
console.log("`--no-sandbox` is being used. Be very careful!");
- opts[correspondances[arg]] = true;
- } else if (correspondances[arg]) {
- opts[correspondances[arg]] = true;
+ opts[correspondences[arg]] = true;
+ } else if (correspondences[arg]) {
+ opts[correspondences[arg]] = true;
} else {
console.log("Unknown option `" + arg + "`.");
console.log("Use `--help` to see the list of options");
@@ -143,7 +143,7 @@ async function runTests(opts, framework_options, files, results, status_bar, sho
const tests_queue = [];
for (const testPath of files) {
- const callback = runTest(testPath, framework_options)
+ const callback = runTest(testPath, {"options": framework_options})
.then(out => {
const [output, nb_failures] = out;
results[nb_failures === 0 ? "successful" : "failed"].push({
@@ -323,6 +323,7 @@ async function main(argv) {
if (results.failed.length > 0 || results.errored.length > 0) {
process.exit(1);
}
+ process.exit(0);
}
main(process.argv);
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 6b9a9b66a..270704ebf 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -226,6 +226,24 @@ function runSearch(query, expected, doSearch, loadedFile, queryName) {
return error_text;
}
+function runCorrections(query, corrections, getCorrections, loadedFile) {
+ const qc = getCorrections(query, loadedFile.FILTER_CRATE);
+ const error_text = [];
+
+ if (corrections === null) {
+ if (qc !== null) {
+ error_text.push(`==> expected = null, found = ${qc}`);
+ }
+ return error_text;
+ }
+
+ if (qc !== corrections.toLowerCase()) {
+ error_text.push(`==> expected = ${corrections}, found = ${qc}`);
+ }
+
+ return error_text;
+}
+
function checkResult(error_text, loadedFile, displaySuccess) {
if (error_text.length === 0 && loadedFile.should_fail === true) {
console.log("FAILED");
@@ -272,9 +290,10 @@ function runCheck(loadedFile, key, callback) {
return 0;
}
-function runChecks(testFile, doSearch, parseQuery) {
+function runChecks(testFile, doSearch, parseQuery, getCorrections) {
let checkExpected = false;
let checkParsed = false;
+ let checkCorrections = false;
let testFileContent = readFile(testFile) + "exports.QUERY = QUERY;";
if (testFileContent.indexOf("FILTER_CRATE") !== -1) {
@@ -291,9 +310,13 @@ function runChecks(testFile, doSearch, parseQuery) {
testFileContent += "exports.PARSED = PARSED;";
checkParsed = true;
}
- if (!checkParsed && !checkExpected) {
+ if (testFileContent.indexOf("\nconst CORRECTIONS") !== -1) {
+ testFileContent += "exports.CORRECTIONS = CORRECTIONS;";
+ checkCorrections = true;
+ }
+ if (!checkParsed && !checkExpected && !checkCorrections) {
console.log("FAILED");
- console.log("==> At least `PARSED` or `EXPECTED` is needed!");
+ console.log("==> At least `PARSED`, `EXPECTED`, or `CORRECTIONS` is needed!");
return 1;
}
@@ -310,6 +333,11 @@ function runChecks(testFile, doSearch, parseQuery) {
return runParser(query, expected, parseQuery, text);
});
}
+ if (checkCorrections) {
+ res += runCheck(loadedFile, "CORRECTIONS", (query, expected) => {
+ return runCorrections(query, expected, getCorrections, loadedFile);
+ });
+ }
return res;
}
@@ -318,9 +346,10 @@ function runChecks(testFile, doSearch, parseQuery) {
*
* @param {string} doc_folder - Path to a folder generated by running rustdoc
* @param {string} resource_suffix - Version number between filename and .js, e.g. "1.59.0"
- * @returns {Object} - Object containing two keys: `doSearch`, which runs a search
- * with the loaded index and returns a table of results; and `parseQuery`, which is the
- * `parseQuery` function exported from the search module.
+ * @returns {Object} - Object containing keys: `doSearch`, which runs a search
+ * with the loaded index and returns a table of results; `parseQuery`, which is the
+ * `parseQuery` function exported from the search module; and `getCorrections`, which runs
+ * a search but returns type name corrections instead of results.
*/
function loadSearchJS(doc_folder, resource_suffix) {
const searchIndexJs = path.join(doc_folder, "search-index" + resource_suffix + ".js");
@@ -336,6 +365,12 @@ function loadSearchJS(doc_folder, resource_suffix) {
return searchModule.execQuery(searchModule.parseQuery(queryStr), searchWords,
filterCrate, currentCrate);
},
+ getCorrections: function(queryStr, filterCrate, currentCrate) {
+ const parsedQuery = searchModule.parseQuery(queryStr);
+ searchModule.execQuery(parsedQuery, searchWords,
+ filterCrate, currentCrate);
+ return parsedQuery.correction;
+ },
parseQuery: searchModule.parseQuery,
};
}
@@ -417,11 +452,14 @@ function main(argv) {
const doSearch = function(queryStr, filterCrate) {
return parseAndSearch.doSearch(queryStr, filterCrate, opts["crate_name"]);
};
+ const getCorrections = function(queryStr, filterCrate) {
+ return parseAndSearch.getCorrections(queryStr, filterCrate, opts["crate_name"]);
+ };
if (opts["test_file"].length !== 0) {
opts["test_file"].forEach(file => {
process.stdout.write(`Testing ${file} ... `);
- errors += runChecks(file, doSearch, parseAndSearch.parseQuery);
+ errors += runChecks(file, doSearch, parseAndSearch.parseQuery, getCorrections);
});
} else if (opts["test_folder"].length !== 0) {
fs.readdirSync(opts["test_folder"]).forEach(file => {
@@ -430,7 +468,7 @@ function main(argv) {
}
process.stdout.write(`Testing ${file} ... `);
errors += runChecks(path.join(opts["test_folder"], file), doSearch,
- parseAndSearch.parseQuery);
+ parseAndSearch.parseQuery, getCorrections);
});
}
return errors > 0 ? 1 : 0;
diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs
index be64559e8..47846424b 100644
--- a/src/tools/rustfmt/src/bin/main.rs
+++ b/src/tools/rustfmt/src/bin/main.rs
@@ -1,3 +1,5 @@
+#![feature(rustc_private)]
+
use anyhow::{format_err, Result};
use io::Error as IoError;
@@ -19,7 +21,14 @@ use crate::rustfmt::{
FormatReportFormatterBuilder, Input, Session, Verbosity,
};
+const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?labels=bug";
+
+// N.B. these crates are loaded from the sysroot, so they need extern crate.
+extern crate rustc_driver;
+
fn main() {
+ rustc_driver::install_ice_hook(BUG_REPORT_URL, |_| ());
+
env_logger::Builder::from_env("RUSTFMT_LOG").init();
let opts = make_opts();
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index cbe523c6c..0afce7cf6 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -232,7 +232,7 @@ impl ChainItemKind {
let span = mk_sp(nested.span.hi(), field.span.hi());
(kind, span)
}
- ast::ExprKind::Await(ref nested) => {
+ ast::ExprKind::Await(ref nested, _) => {
let span = mk_sp(nested.span.hi(), expr.span.hi());
(ChainItemKind::Await, span)
}
@@ -459,7 +459,7 @@ impl Chain {
ast::ExprKind::MethodCall(ref call) => Some(Self::convert_try(&call.receiver, context)),
ast::ExprKind::Field(ref subexpr, _)
| ast::ExprKind::Try(ref subexpr)
- | ast::ExprKind::Await(ref subexpr) => Some(Self::convert_try(subexpr, context)),
+ | ast::ExprKind::Await(ref subexpr, _) => Some(Self::convert_try(subexpr, context)),
_ => None,
}
}
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index ac96bedf2..5dc628adb 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -218,7 +218,7 @@ 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(_, _) => rewrite_chain(expr, context, shape),
ast::ExprKind::MacCall(ref mac) => {
rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| {
wrap_str(
@@ -399,7 +399,9 @@ pub(crate) fn format_expr(
}
}
ast::ExprKind::Underscore => Some("_".to_owned()),
- ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) => {
+ ast::ExprKind::FormatArgs(..)
+ | ast::ExprKind::IncludedBytes(..)
+ | ast::ExprKind::OffsetOf(..) => {
// These do not occur in the AST because macros aren't expanded.
unreachable!()
}
@@ -1887,7 +1889,7 @@ impl<'ast> RhsAssignKind<'ast> {
ast::ExprKind::Try(..)
| ast::ExprKind::Field(..)
| ast::ExprKind::MethodCall(..)
- | ast::ExprKind::Await(_)
+ | ast::ExprKind::Await(_, _)
)
}
_ => false,
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 01e2fb6e6..f548388ed 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -552,6 +552,12 @@ impl Rewrite for ast::GenericBound {
ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref
.rewrite(context, shape.offset_left(8)?)
.map(|s| format!("~const ?{}", s)),
+ ast::TraitBoundModifier::Negative => poly_trait_ref
+ .rewrite(context, shape.offset_left(1)?)
+ .map(|s| format!("!{}", s)),
+ ast::TraitBoundModifier::MaybeConstNegative => poly_trait_ref
+ .rewrite(context, shape.offset_left(8)?)
+ .map(|s| format!("~const !{}", s)),
};
rewrite.map(|s| if has_paren { format!("({})", s) } else { s })
}
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index a26375ee6..ca1716574 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -499,6 +499,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
| ast::ExprKind::Field(..)
| ast::ExprKind::IncludedBytes(..)
| ast::ExprKind::InlineAsm(..)
+ | ast::ExprKind::OffsetOf(..)
| ast::ExprKind::Let(..)
| ast::ExprKind::Path(..)
| ast::ExprKind::Range(..)
diff --git a/src/tools/rustfmt/tests/source/type-ascription.rs b/src/tools/rustfmt/tests/source/type-ascription.rs
deleted file mode 100644
index 4874094cc..000000000
--- a/src/tools/rustfmt/tests/source/type-ascription.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-
-fn main() {
- let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait<AA, BB, CC>;
-
- let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
-
- let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
-
- x : u32 - 1u32 / 10f32 : u32
-}
diff --git a/src/tools/rustfmt/tests/target/configs/format_macro_bodies/true.rs b/src/tools/rustfmt/tests/target/configs/format_macro_bodies/true.rs
index 9dc2524c3..17ac1498c 100644
--- a/src/tools/rustfmt/tests/target/configs/format_macro_bodies/true.rs
+++ b/src/tools/rustfmt/tests/target/configs/format_macro_bodies/true.rs
@@ -1,10 +1,6 @@
// rustfmt-format_macro_bodies: true
macro_rules! foo {
- ($a: ident : $b: ty) => {
- $a(42): $b;
- };
- ($a: ident $b: ident $c: ident) => {
- $a = $b + $c;
- };
+ ($a: ident : $b: ty) => { $a(42): $b; };
+ ($a: ident $b: ident $c: ident) => { $a=$b+$c; };
}
diff --git a/src/tools/rustfmt/tests/target/configs/format_macro_matchers/false.rs b/src/tools/rustfmt/tests/target/configs/format_macro_matchers/false.rs
index 3966d21be..01ecac987 100644
--- a/src/tools/rustfmt/tests/target/configs/format_macro_matchers/false.rs
+++ b/src/tools/rustfmt/tests/target/configs/format_macro_matchers/false.rs
@@ -1,10 +1,6 @@
// rustfmt-format_macro_matchers: false
macro_rules! foo {
- ($a: ident : $b: ty) => {
- $a(42): $b;
- };
- ($a: ident $b: ident $c: ident) => {
- $a = $b + $c;
- };
+ ($a: ident : $b: ty) => { $a(42): $b; };
+ ($a: ident $b: ident $c: ident) => { $a=$b+$c; };
}
diff --git a/src/tools/rustfmt/tests/target/configs/format_macro_matchers/true.rs b/src/tools/rustfmt/tests/target/configs/format_macro_matchers/true.rs
index e113af96f..fa0442e22 100644
--- a/src/tools/rustfmt/tests/target/configs/format_macro_matchers/true.rs
+++ b/src/tools/rustfmt/tests/target/configs/format_macro_matchers/true.rs
@@ -1,10 +1,6 @@
// rustfmt-format_macro_matchers: true
macro_rules! foo {
- ($a:ident : $b:ty) => {
- $a(42): $b;
- };
- ($a:ident $b:ident $c:ident) => {
- $a = $b + $c;
- };
+ ($a: ident : $b: ty) => { $a(42): $b; };
+ ($a: ident $b: ident $c: ident) => { $a=$b+$c; };
}
diff --git a/src/tools/rustfmt/tests/target/macros.rs b/src/tools/rustfmt/tests/target/macros.rs
index e930b5037..7b4574349 100644
--- a/src/tools/rustfmt/tests/target/macros.rs
+++ b/src/tools/rustfmt/tests/target/macros.rs
@@ -122,7 +122,7 @@ fn main() {
20, 21, 22);
// #1092
- chain!(input, a: take!(max_size), || []);
+ chain!(input, a:take!(max_size), || []);
// #2727
foo!("bar");
@@ -156,17 +156,13 @@ fn issue1178() {
}
fn issue1739() {
- sql_function!(
- add_rss_item,
- add_rss_item_t,
- (
- a: types::Integer,
- b: types::Timestamptz,
- c: types::Text,
- d: types::Text,
- e: types::Text
- )
- );
+ sql_function!(add_rss_item,
+ add_rss_item_t,
+ (a: types::Integer,
+ b: types::Timestamptz,
+ c: types::Text,
+ d: types::Text,
+ e: types::Text));
w.slice_mut(s![
..,
@@ -232,7 +228,7 @@ fn issue_3174() {
"debugMessage": debug.message,
})
} else {
- json!({ "errorKind": format!("{:?}", error.err_kind()) })
+ json!({"errorKind": format!("{:?}", error.err_kind())})
};
}
diff --git a/src/tools/rustfmt/tests/target/negative-bounds.rs b/src/tools/rustfmt/tests/target/negative-bounds.rs
new file mode 100644
index 000000000..4fb35cccf
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/negative-bounds.rs
@@ -0,0 +1,11 @@
+fn negative()
+where
+ i32: !Copy,
+{
+}
+
+fn maybe_const_negative()
+where
+ i32: ~const !Copy,
+{
+}
diff --git a/src/tools/rustfmt/tests/target/type-ascription.rs b/src/tools/rustfmt/tests/target/type-ascription.rs
deleted file mode 100644
index a2f082ba4..000000000
--- a/src/tools/rustfmt/tests/target/type-ascription.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-fn main() {
- let xxxxxxxxxxx =
- yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait<AA, BB, CC>;
-
- let xxxxxxxxxxxxxxx =
- yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
-
- let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww):
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
-
- x: u32 - 1u32 / 10f32: u32
-}
diff --git a/src/tools/rustfmt/tests/target/type.rs b/src/tools/rustfmt/tests/target/type.rs
index 38cf909c2..c789ecb05 100644
--- a/src/tools/rustfmt/tests/target/type.rs
+++ b/src/tools/rustfmt/tests/target/type.rs
@@ -129,7 +129,7 @@ fn issue3117() {
fn issue3139() {
assert_eq!(
to_json_value(&None::<i32>).unwrap(),
- json!({ "test": None::<i32> })
+ json!( { "test": None :: <i32> } )
);
}
diff --git a/src/tools/suggest-tests/src/static_suggestions.rs b/src/tools/suggest-tests/src/static_suggestions.rs
index d8166ead8..a84e78254 100644
--- a/src/tools/suggest-tests/src/static_suggestions.rs
+++ b/src/tools/suggest-tests/src/static_suggestions.rs
@@ -15,7 +15,7 @@ static_suggestions! {
"compiler/*" => [
sug!("check"),
- sug!("test", 1, ["src/test/ui", "src/test/run-make"])
+ sug!("test", 1, ["tests/ui", "tests/run-make"])
],
"src/librustdoc/*" => [
diff --git a/src/tools/suggest-tests/src/tests.rs b/src/tools/suggest-tests/src/tests.rs
index 5bc1a7df7..b4149136f 100644
--- a/src/tools/suggest-tests/src/tests.rs
+++ b/src/tools/suggest-tests/src/tests.rs
@@ -12,7 +12,7 @@ macro_rules! sugg_test {
sugg_test! {
test_error_code_docs: ["compiler/rustc_error_codes/src/error_codes/E0000.md"] =>
- ["check N/A", "test compiler/rustc_error_codes N/A", "test linkchecker 0", "test src/test/ui src/test/run-make 1"],
+ ["check N/A", "test compiler/rustc_error_codes N/A", "test linkchecker 0", "test tests/ui tests/run-make 1"],
test_rustdoc: ["src/librustdoc/src/lib.rs"] => ["test rustdoc 1"],
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index a9eb6c8d0..2e7781109 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -6,58 +6,73 @@ use std::path::Path;
/// These are licenses that are allowed for all crates, including the runtime,
/// rustc, tools, etc.
+#[rustfmt::skip]
const LICENSES: &[&str] = &[
- "MIT/Apache-2.0",
- "MIT / Apache-2.0",
- "Apache-2.0/MIT",
+ // tidy-alphabetical-start
+ "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident
+ "0BSD OR MIT OR Apache-2.0", // adler license
+ "0BSD",
"Apache-2.0 / MIT",
- "MIT OR Apache-2.0",
"Apache-2.0 OR MIT",
"Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license
- "MIT",
+ "Apache-2.0/MIT",
"ISC",
- "Unlicense/MIT",
+ "MIT / Apache-2.0",
+ "MIT OR Apache-2.0 OR Zlib", // tinyvec_macros
+ "MIT OR Apache-2.0",
+ "MIT OR Zlib OR Apache-2.0", // miniz_oxide
+ "MIT",
+ "MIT/Apache-2.0",
+ "Unicode-DFS-2016", // tinystr and icu4x
"Unlicense OR MIT",
- "0BSD OR MIT OR Apache-2.0", // adler license
- "Zlib OR Apache-2.0 OR MIT", // tinyvec
- "MIT OR Apache-2.0 OR Zlib", // tinyvec_macros
- "MIT OR Zlib OR Apache-2.0", // miniz_oxide
- "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident
- "Unicode-DFS-2016", // tinystr and icu4x
+ "Unlicense/MIT",
+ "Zlib OR Apache-2.0 OR MIT", // tinyvec
+ // tidy-alphabetical-end
];
/// These are exceptions to Rust's permissive licensing policy, and
/// should be considered bugs. Exceptions are only allowed in Rust
/// tooling. It is _crucial_ that no exception crates be dependencies
/// of the Rust runtime (std/test).
+#[rustfmt::skip]
const EXCEPTIONS: &[(&str, &str)] = &[
+ // tidy-alphabetical-start
("ar_archive_writer", "Apache-2.0 WITH LLVM-exception"), // rustc
- ("mdbook", "MPL-2.0"), // mdbook
- ("openssl", "Apache-2.0"), // cargo, mdbook
+ ("codespan-reporting", "Apache-2.0"), // cxx via iana-time-zone-haiku via time, only on haiku
("colored", "MPL-2.0"), // rustfmt
+ ("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
+ ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations)
+ ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target. FIXME: this dependency violates the documentation comment above.
+ ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
+ ("mdbook", "MPL-2.0"), // mdbook
("ryu", "Apache-2.0 OR BSL-1.0"), // cargo/... (because of serde)
- ("bytesize", "Apache-2.0"), // cargo
- ("im-rc", "MPL-2.0+"), // cargo
- ("sized-chunks", "MPL-2.0+"), // cargo via im-rc
- ("bitmaps", "MPL-2.0+"), // cargo via im-rc
- ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"), // cargo via pasetors
- ("subtle", "BSD-3-Clause"), // cargo via pasetors
- ("dunce", "CC0-1.0 OR MIT-0"), // cargo via gix (and dev dependency)
- ("imara-diff", "Apache-2.0"), // cargo via gix
- ("sha1_smol", "BSD-3-Clause"), // cargo via gix
- ("unicode-bom", "Apache-2.0"), // cargo via gix
- ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
- ("snap", "BSD-3-Clause"), // rustc
- ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations)
- ("self_cell", "Apache-2.0"), // rustc (fluent translations)
- // FIXME: this dependency violates the documentation comment above:
- ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
- ("similar", "Apache-2.0"), // cargo (dev dependency)
- ("normalize-line-endings", "Apache-2.0"), // cargo (dev dependency)
- ("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
+ ("self_cell", "Apache-2.0"), // rustc (fluent translations)
+ ("snap", "BSD-3-Clause"), // rustc
+ // tidy-alphabetical-end
+];
+
+const EXCEPTIONS_CARGO: &[(&str, &str)] = &[
+ // tidy-alphabetical-start
+ ("bitmaps", "MPL-2.0+"),
+ ("bytesize", "Apache-2.0"),
+ ("dunce", "CC0-1.0 OR MIT-0"),
+ ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"),
+ ("im-rc", "MPL-2.0+"),
+ ("imara-diff", "Apache-2.0"),
+ ("instant", "BSD-3-Clause"),
+ ("normalize-line-endings", "Apache-2.0"),
+ ("openssl", "Apache-2.0"),
+ ("ryu", "Apache-2.0 OR BSL-1.0"),
+ ("sha1_smol", "BSD-3-Clause"),
+ ("similar", "Apache-2.0"),
+ ("sized-chunks", "MPL-2.0+"),
+ ("subtle", "BSD-3-Clause"),
+ ("unicode-bom", "Apache-2.0"),
+ // tidy-alphabetical-end
];
const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
+ // tidy-alphabetical-start
("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
@@ -73,6 +88,7 @@ const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
("regalloc2", "Apache-2.0 WITH LLVM-exception"),
("target-lexicon", "Apache-2.0 WITH LLVM-exception"),
("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"),
+ // tidy-alphabetical-end
];
const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
@@ -88,6 +104,7 @@ const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort",
/// This list is here to provide a speed-bump to adding a new dependency to
/// rustc. Please check with the compiler team before adding an entry.
const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
+ // tidy-alphabetical-start
"addr2line",
"adler",
"ahash",
@@ -100,14 +117,15 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"autocfg",
"bitflags",
"block-buffer",
+ "byteorder", // via ruzstd in object in thorin-dwp
"cc",
"cfg-if",
"chalk-derive",
"chalk-engine",
"chalk-ir",
"chalk-solve",
- "convert_case", // dependency of derive_more
"compiler_builtins",
+ "convert_case", // dependency of derive_more
"cpufeatures",
"crc32fast",
"crossbeam-channel",
@@ -128,6 +146,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"expect-test",
"fallible-iterator", // dependency of `thorin`
"fastrand",
+ "field-offset",
"fixedbitset",
"flate2",
"fluent-bundle",
@@ -156,7 +175,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"lazy_static",
"libc",
"libloading",
- "libz-sys",
"litemap",
"lock_api",
"log",
@@ -177,13 +195,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"perf-event-open-sys",
"petgraph",
"pin-project-lite",
- "pkg-config",
"polonius-engine",
"ppv-lite86",
"proc-macro-hack",
"proc-macro2",
- "pulldown-cmark",
"psm",
+ "pulldown-cmark",
"punycode",
"quote",
"rand",
@@ -201,6 +218,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"rustc-rayon",
"rustc-rayon-core",
"rustc_version",
+ "ruzstd", // via object in thorin-dwp
"ryu",
"scoped-tls",
"scopeguard",
@@ -217,12 +235,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"stable_deref_trait",
"stacker",
"static_assertions",
- "subtle", // dependency of cargo (via pasetors)
"syn",
"synstructure",
"tempfile",
"termcolor",
"termize",
+ "thin-vec",
"thiserror",
"thiserror-impl",
"thorin-dwp",
@@ -230,7 +248,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"tinystr",
"tinyvec",
"tinyvec_macros",
- "thin-vec",
"tracing",
"tracing-attributes",
"tracing-core",
@@ -256,34 +273,40 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"unicode-security",
"unicode-width",
"unicode-xid",
- "vcpkg",
"valuable",
"version_check",
"wasi",
- "windows",
"winapi",
"winapi-i686-pc-windows-gnu",
"winapi-util",
"winapi-x86_64-pc-windows-gnu",
+ "windows",
+ "windows-targets",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
"writeable",
- // this is a false-positive: it's only used by rustfmt, but because it's enabled through a
- // feature, tidy thinks it's used by rustc as well.
- "yansi-term",
+ "yansi-term", // this is a false-positive: it's only used by rustfmt, but because it's enabled through a feature, tidy thinks it's used by rustc as well.
"yoke",
"yoke-derive",
"zerofrom",
"zerofrom-derive",
"zerovec",
"zerovec-derive",
+ // tidy-alphabetical-end
];
const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
+ // tidy-alphabetical-start
"ahash",
"anyhow",
- "arrayvec",
"autocfg",
- "bumpalo",
"bitflags",
+ "bumpalo",
"byteorder",
"cfg-if",
"cranelift-bforest",
@@ -300,7 +323,6 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
"crc32fast",
"fallible-iterator",
"fxhash",
- "getrandom",
"gimli",
"hashbrown",
"indexmap",
@@ -318,26 +340,12 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
"stable_deref_trait",
"target-lexicon",
"version_check",
- "wasi",
"wasmtime-jit-icache-coherence",
"winapi",
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
"windows-sys",
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-];
-
-const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[
- // This crate takes quite a long time to build, so don't allow two versions of them
- // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
- // under control.
- "cargo",
+ // tidy-alphabetical-end
];
/// Dependency checks.
@@ -359,8 +367,16 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
&["rustc_driver", "rustc_codegen_llvm"],
bad,
);
- check_crate_duplicate(&metadata, FORBIDDEN_TO_HAVE_DUPLICATES, bad);
- check_rustfix(&metadata, bad);
+
+ // Check cargo independently as it has it's own workspace.
+ let mut cmd = cargo_metadata::MetadataCommand::new();
+ cmd.cargo_path(cargo)
+ .manifest_path(root.join("src/tools/cargo/Cargo.toml"))
+ .features(cargo_metadata::CargoOpt::AllFeatures);
+ let cargo_metadata = t!(cmd.exec());
+ let runtime_ids = HashSet::new();
+ check_license_exceptions(&cargo_metadata, EXCEPTIONS_CARGO, runtime_ids, bad);
+ check_rustfix(&metadata, &cargo_metadata, bad);
// Check rustc_codegen_cranelift independently as it has it's own workspace.
let mut cmd = cargo_metadata::MetadataCommand::new();
@@ -377,7 +393,6 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
&["rustc_codegen_cranelift"],
bad,
);
- check_crate_duplicate(&metadata, &[], bad);
let mut cmd = cargo_metadata::MetadataCommand::new();
cmd.cargo_path(cargo)
@@ -523,40 +538,6 @@ fn check_permitted_dependencies(
}
}
-/// Prevents multiple versions of some expensive crates.
-fn check_crate_duplicate(
- metadata: &Metadata,
- forbidden_to_have_duplicates: &[&str],
- bad: &mut bool,
-) {
- for &name in forbidden_to_have_duplicates {
- let matches: Vec<_> = metadata.packages.iter().filter(|pkg| pkg.name == name).collect();
- match matches.len() {
- 0 => {
- tidy_error!(
- bad,
- "crate `{}` is missing, update `check_crate_duplicate` \
- if it is no longer used",
- name
- );
- }
- 1 => {}
- _ => {
- tidy_error!(
- bad,
- "crate `{}` is duplicated in `Cargo.lock`, \
- it is too expensive to build multiple times, \
- so make sure only one version appears across all dependencies",
- name
- );
- for pkg in matches {
- println!(" * {}", pkg.id);
- }
- }
- }
- }
-}
-
/// Finds a package with the given name.
fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package {
let mut i = metadata.packages.iter().filter(|p| p.name == name);
@@ -606,19 +587,24 @@ fn deps_of_filtered<'a>(
}
}
-fn direct_deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
+fn direct_deps_of<'a>(
+ metadata: &'a Metadata,
+ pkg_id: &'a PackageId,
+) -> impl Iterator<Item = &'a Package> {
let resolve = metadata.resolve.as_ref().unwrap();
let node = resolve.nodes.iter().find(|n| &n.id == pkg_id).unwrap();
- node.deps.iter().map(|dep| pkg_from_id(metadata, &dep.pkg)).collect()
+ node.deps.iter().map(|dep| pkg_from_id(metadata, &dep.pkg))
}
-fn check_rustfix(metadata: &Metadata, bad: &mut bool) {
- let cargo = pkg_from_name(metadata, "cargo");
- let compiletest = pkg_from_name(metadata, "compiletest");
- let cargo_deps = direct_deps_of(metadata, &cargo.id);
- let compiletest_deps = direct_deps_of(metadata, &compiletest.id);
- let cargo_rustfix = cargo_deps.iter().find(|p| p.name == "rustfix").unwrap();
- let compiletest_rustfix = compiletest_deps.iter().find(|p| p.name == "rustfix").unwrap();
+fn check_rustfix(rust_metadata: &Metadata, cargo_metadata: &Metadata, bad: &mut bool) {
+ let cargo = pkg_from_name(cargo_metadata, "cargo");
+ let cargo_rustfix =
+ direct_deps_of(cargo_metadata, &cargo.id).find(|p| p.name == "rustfix").unwrap();
+
+ let compiletest = pkg_from_name(rust_metadata, "compiletest");
+ let compiletest_rustfix =
+ direct_deps_of(rust_metadata, &compiletest.id).find(|p| p.name == "rustfix").unwrap();
+
if cargo_rustfix.version != compiletest_rustfix.version {
tidy_error!(
bad,
diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs
new file mode 100644
index 000000000..5f8eaebf5
--- /dev/null
+++ b/src/tools/tidy/src/fluent_alphabetical.rs
@@ -0,0 +1,72 @@
+//! Checks that all Flunt files have messages in alphabetical order
+
+use crate::walk::{filter_dirs, walk};
+use std::{fs::OpenOptions, io::Write, path::Path};
+
+use regex::Regex;
+
+lazy_static::lazy_static! {
+ static ref MESSAGE: Regex = Regex::new(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#).unwrap();
+}
+
+fn filter_fluent(path: &Path) -> bool {
+ if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
+}
+
+fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) {
+ let mut matches = MESSAGE.captures_iter(fluent).peekable();
+ while let Some(m) = matches.next() {
+ if let Some(next) = matches.peek() {
+ let name = m.get(1).unwrap();
+ let next = next.get(1).unwrap();
+ if name.as_str() > next.as_str() {
+ tidy_error!(
+ bad,
+ "{filename}: message `{}` appears before `{}`, but is alphabetically later than it
+run tidy with `--bless` to sort the file correctly",
+ name.as_str(),
+ next.as_str()
+ );
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+fn sort_messages(fluent: &str) -> String {
+ let mut chunks = vec![];
+ let mut cur = String::new();
+ for line in fluent.lines() {
+ if MESSAGE.is_match(line) {
+ chunks.push(std::mem::take(&mut cur));
+ }
+ cur += line;
+ cur.push('\n');
+ }
+ chunks.push(cur);
+ chunks.sort();
+ let mut out = chunks.join("");
+ out = out.trim().to_string();
+ out.push('\n');
+ out
+}
+
+pub fn check(path: &Path, bless: bool, bad: &mut bool) {
+ walk(
+ path,
+ |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)),
+ &mut |ent, contents| {
+ if bless {
+ let sorted = sort_messages(contents);
+ if sorted != contents {
+ let mut f =
+ OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap();
+ f.write(sorted.as_bytes()).unwrap();
+ }
+ } else {
+ check_alphabetic(ent.path().to_str().unwrap(), contents, bad);
+ }
+ },
+ );
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 35000320d..e467514a7 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -59,6 +59,7 @@ pub mod edition;
pub mod error_codes;
pub mod extdeps;
pub mod features;
+pub mod fluent_alphabetical;
pub mod mir_opt_tests;
pub mod pal;
pub mod primitive_docs;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index f59406c40..1c4d96c32 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -96,6 +96,7 @@ fn main() {
// Checks that only make sense for the compiler.
check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
+ check!(fluent_alphabetical, &compiler_path, bless);
// Checks that only make sense for the std libs.
check!(pal, &library_path);
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index a2012db90..d0257d716 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -296,6 +296,12 @@ pub fn check(path: &Path, bad: &mut bool) {
if filename.contains("ignore-tidy") {
return;
}
+ // Shell completions are automatically generated
+ if let Some(p) = file.parent() {
+ if p.ends_with(Path::new("src/etc/completions")) {
+ return;
+ }
+ }
// apfloat shouldn't be changed because of license problems
if is_in(file, "compiler", "rustc_apfloat") {
return;
@@ -385,10 +391,12 @@ pub fn check(path: &Path, bad: &mut bool) {
}
if filename != "style.rs" {
if trimmed.contains("TODO") {
- err("TODO is deprecated; use FIXME")
+ err(
+ "TODO is used for tasks that should be done before merging a PR; If you want to leave a message in the codebase use FIXME",
+ )
}
if trimmed.contains("//") && trimmed.contains(" XXX") {
- err("XXX is deprecated; use FIXME")
+ err("Instead of XXX use FIXME")
}
if any_problematic_line {
for s in problematic_consts_strings.iter() {
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 29664c854..be3a5d3aa 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -4,13 +4,39 @@
use ignore::Walk;
use std::collections::HashMap;
+use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
+const ENTRY_LIMIT: usize = 900;
// FIXME: The following limits should be reduced eventually.
-const ENTRY_LIMIT: usize = 885;
-const ROOT_ENTRY_LIMIT: usize = 891;
-const ISSUES_ENTRY_LIMIT: usize = 1977;
+const ISSUES_ENTRY_LIMIT: usize = 1920;
+const ROOT_ENTRY_LIMIT: usize = 896;
+
+const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
+ "rs", // test source files
+ "stderr", // expected stderr file, corresponds to a rs file
+ "stdout", // expected stdout file, corresponds to a rs file
+ "fixed", // expected source file after applying fixes
+ "md", // test directory descriptions
+ "ftl", // translation tests
+];
+
+const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
+ "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint
+ "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs
+ "tests/ui/commandline-argfile-badutf8.args", // passing args via a file
+ "tests/ui/commandline-argfile.args", // passing args via a file
+ "tests/ui/crate-loading/auxiliary/libfoo.rlib", // testing loading a manually created rlib
+ "tests/ui/include-macros/data.bin", // testing including data with the include macros
+ "tests/ui/include-macros/file.txt", // testing including data with the include macros
+ "tests/ui/macros/macro-expanded-include/file.txt", // testing including data with the include macros
+ "tests/ui/macros/not-utf8.bin", // testing including data with the include macros
+ "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include
+ "tests/ui/unused-crate-deps/test.mk", // why would you use make
+ "tests/ui/proc-macro/auxiliary/included-file.txt", // more include
+ "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer
+];
fn check_entries(tests_path: &Path, bad: &mut bool) {
let mut directories: HashMap<PathBuf, usize> = HashMap::new();
@@ -46,9 +72,6 @@ fn check_entries(tests_path: &Path, bad: &mut bool) {
);
}
}
- if ENTRY_LIMIT > max {
- tidy_error!(bad, "`ENTRY_LIMIT` is too high (is {ENTRY_LIMIT}, should be {max})");
- }
if ROOT_ENTRY_LIMIT > max_root {
tidy_error!(
bad,
@@ -69,7 +92,14 @@ pub fn check(path: &Path, bad: &mut bool) {
let paths = [ui.as_path(), ui_fulldeps.as_path()];
crate::walk::walk_no_read(&paths, |_, _| false, &mut |entry| {
let file_path = entry.path();
- if let Some(ext) = file_path.extension() {
+ if let Some(ext) = file_path.extension().and_then(OsStr::to_str) {
+ // files that are neither an expected extension or an exception should not exist
+ // they're probably typos or not meant to exist
+ if !(EXPECTED_TEST_FILE_EXTENSIONS.contains(&ext)
+ || EXTENSION_EXCEPTION_PATHS.iter().any(|path| file_path.ends_with(path)))
+ {
+ tidy_error!(bad, "file {} has unexpected extension {}", file_path.display(), ext);
+ }
if ext == "stderr" || ext == "stdout" {
// Test output filenames have one of the formats:
// ```
diff --git a/src/version b/src/version
index 832e9afb6..68bc7ff2a 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.70.0
+1.71.1