From 023939b627b7dc93b01471f7d41fb8553ddb4ffa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:59:24 +0200 Subject: Merging upstream version 1.73.0+dfsg1. Signed-off-by: Daniel Baumann --- src/bootstrap/Cargo.lock | 8 +- src/bootstrap/Cargo.toml | 2 +- src/bootstrap/bin/main.rs | 8 +- src/bootstrap/bin/rustc.rs | 23 +- src/bootstrap/bin/rustdoc.rs | 8 +- src/bootstrap/bolt.rs | 60 - src/bootstrap/bootstrap.py | 16 +- src/bootstrap/bootstrap_test.py | 19 +- src/bootstrap/build.rs | 2 +- src/bootstrap/builder.rs | 116 +- src/bootstrap/builder/tests.rs | 14 +- src/bootstrap/cache.rs | 4 +- src/bootstrap/cc_detect.rs | 2 +- src/bootstrap/check.rs | 32 +- src/bootstrap/clean.rs | 86 +- src/bootstrap/compile.rs | 180 ++- src/bootstrap/config.rs | 232 ++- src/bootstrap/config/tests.rs | 5 +- src/bootstrap/configure.py | 15 +- src/bootstrap/dist.rs | 163 +- src/bootstrap/doc.rs | 170 +- src/bootstrap/download-ci-llvm-stamp | 2 +- src/bootstrap/download.rs | 86 +- src/bootstrap/flags.rs | 35 +- src/bootstrap/format.rs | 47 +- src/bootstrap/lib.rs | 122 +- src/bootstrap/llvm.rs | 81 +- src/bootstrap/metrics.rs | 105 +- src/bootstrap/mk/Makefile.in | 4 +- src/bootstrap/render_tests.rs | 8 +- src/bootstrap/run.rs | 19 +- src/bootstrap/sanity.rs | 6 +- src/bootstrap/setup.rs | 18 +- src/bootstrap/suggest.rs | 24 +- src/bootstrap/tarball.rs | 4 +- src/bootstrap/test.rs | 367 +++-- src/bootstrap/tool.rs | 40 +- src/bootstrap/toolstate.rs | 45 +- src/bootstrap/util.rs | 42 +- src/ci/docker/README.md | 3 +- src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile | 5 +- src/ci/docker/host-x86_64/armhf-gnu/Dockerfile | 14 +- .../docker/host-x86_64/armhf-gnu/vexpress_config | 617 +++++--- .../disabled/dist-m68k-linux/Dockerfile | 2 + .../disabled/riscv64gc-linux/Dockerfile | 4 + .../docker/host-x86_64/dist-i686-linux/Dockerfile | 6 +- .../host-x86_64/dist-powerpc64le-linux/Dockerfile | 5 +- .../riscv64-unknown-linux-gnu.defconfig | 2 +- .../docker/host-x86_64/dist-various-1/Dockerfile | 11 +- .../docker/host-x86_64/dist-various-2/Dockerfile | 29 +- .../dist-various-2/build-wasi-threads-toolchain.sh | 24 + .../dist-various-2/build-wasi-toolchain.sh | 8 +- .../host-x86_64/dist-x86_64-linux/Dockerfile | 14 +- .../docker/host-x86_64/dist-x86_64-musl/Dockerfile | 10 +- .../host-x86_64/dist-x86_64-netbsd/Dockerfile | 9 +- src/ci/docker/host-x86_64/i686-gnu/Dockerfile | 10 +- .../docker/host-x86_64/mingw-check-tidy/Dockerfile | 6 +- src/ci/docker/host-x86_64/test-various/Dockerfile | 18 +- .../host-x86_64/test-various/uefi_qemu_test/run.py | 7 +- src/ci/docker/host-x86_64/wasm32/Dockerfile | 9 +- .../docker/host-x86_64/x86_64-gnu-debug/Dockerfile | 2 +- .../host-x86_64/x86_64-gnu-llvm-14/Dockerfile | 54 - .../host-x86_64/x86_64-gnu-llvm-14/script.sh | 34 - .../host-x86_64/x86_64-gnu-llvm-15/Dockerfile | 24 +- .../host-x86_64/x86_64-gnu-llvm-15/script.sh | 34 + .../host-x86_64/x86_64-gnu-llvm-16/Dockerfile | 20 +- .../docker/host-x86_64/x86_64-gnu-nopt/Dockerfile | 5 +- src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile | 2 +- src/ci/docker/run.sh | 16 +- src/ci/docker/scripts/cmake.sh | 6 +- src/ci/docker/scripts/fuchsia-test-runner.py | 6 +- src/ci/github-actions/ci.yml | 22 +- src/ci/run.sh | 25 +- src/ci/scripts/install-clang.sh | 5 - src/ci/scripts/setup-environment.sh | 2 +- src/ci/stage-build.py | 1037 ------------- .../using-rust-without-the-standard-library.md | 6 +- src/doc/book/src/ch08-02-strings.md | 2 +- src/doc/book/src/ch10-03-lifetime-syntax.md | 6 +- .../src/rust-2021/default-cargo-resolver.md | 2 +- .../src/rust-2021/reserving-syntax.md | 4 +- src/doc/embedded-book/.github/bors.toml | 4 - src/doc/embedded-book/.github/workflows/ci.yml | 8 +- src/doc/embedded-book/src/start/qemu.md | 2 +- src/doc/embedded-book/src/unsorted/math.md | 1 + src/doc/nomicon/src/atomics.md | 2 +- src/doc/nomicon/src/exception-safety.md | 4 +- src/doc/nomicon/src/ffi.md | 1 + src/doc/nomicon/src/leaking.md | 6 +- src/doc/nomicon/src/vec/vec-final.md | 2 +- src/doc/nomicon/src/vec/vec-zsts.md | 2 +- src/doc/reference/.github/workflows/main.yml | 4 +- src/doc/reference/src/attributes/codegen.md | 24 +- .../reference/src/behavior-considered-undefined.md | 25 +- src/doc/reference/src/destructors.md | 2 +- src/doc/reference/src/expressions.md | 2 +- src/doc/reference/src/expressions/operator-expr.md | 6 +- src/doc/reference/src/items/external-blocks.md | 2 + src/doc/reference/src/trait-bounds.md | 73 + src/doc/reference/src/type-layout.md | 30 +- src/doc/reference/src/types/never.md | 23 +- src/doc/reference/src/types/textual.md | 2 +- src/doc/reference/src/unsafe-keyword.md | 4 +- src/doc/rust-by-example/README.md | 1 + src/doc/rust-by-example/src/error/panic.md | 3 + .../src/flow_control/loop/nested.md | 4 +- src/doc/rust-by-example/src/hello/print/fmt.md | 6 +- src/doc/rustc-dev-guide/README.md | 2 +- src/doc/rustc-dev-guide/src/SUMMARY.md | 9 +- src/doc/rustc-dev-guide/src/about-this-guide.md | 1 - src/doc/rustc-dev-guide/src/appendix/background.md | 2 +- .../rustc-dev-guide/src/backend/updating-llvm.md | 8 +- .../rustc-dev-guide/src/bound-vars-and-params.md | 59 + src/doc/rustc-dev-guide/src/bug-fix-procedure.md | 4 +- .../rustc-dev-guide/src/building/bootstrapping.md | 36 +- .../build-install-distribution-artifacts.md | 14 +- .../src/building/compiler-documenting.md | 12 +- .../src/building/how-to-build-and-run.md | 157 +- src/doc/rustc-dev-guide/src/building/new-target.md | 4 +- .../rustc-dev-guide/src/building/prerequisites.md | 2 +- src/doc/rustc-dev-guide/src/building/suggested.md | 51 +- src/doc/rustc-dev-guide/src/closure.md | 4 +- src/doc/rustc-dev-guide/src/compiler-src.md | 3 - src/doc/rustc-dev-guide/src/constants.md | 2 +- src/doc/rustc-dev-guide/src/contributing.md | 146 +- src/doc/rustc-dev-guide/src/conventions.md | 8 +- .../src/debugging-support-in-rustc.md | 4 +- src/doc/rustc-dev-guide/src/diagnostics.md | 77 + .../src/diagnostics/diagnostic-structs.md | 17 +- .../rustc-dev-guide/src/diagnostics/error-codes.md | 2 +- .../rustc-dev-guide/src/diagnostics/translation.md | 11 +- src/doc/rustc-dev-guide/src/early-late-bound.md | 266 ++-- src/doc/rustc-dev-guide/src/feature-gates.md | 41 +- src/doc/rustc-dev-guide/src/fuzzing.md | 6 +- src/doc/rustc-dev-guide/src/generic_arguments.md | 26 +- src/doc/rustc-dev-guide/src/getting-started.md | 4 +- src/doc/rustc-dev-guide/src/git.md | 34 +- src/doc/rustc-dev-guide/src/identifiers.md | 4 +- .../src/implementing_new_features.md | 88 +- .../src/llvm-coverage-instrumentation.md | 15 +- src/doc/rustc-dev-guide/src/macro-expansion.md | 2 +- src/doc/rustc-dev-guide/src/mir/optimizations.md | 11 +- src/doc/rustc-dev-guide/src/mir/visitor.md | 2 +- src/doc/rustc-dev-guide/src/name-resolution.md | 2 +- .../src/notification-groups/about.md | 2 +- .../src/notification-groups/cleanup-crew.md | 4 +- src/doc/rustc-dev-guide/src/overview.md | 2 +- src/doc/rustc-dev-guide/src/parallel-rustc.md | 2 - src/doc/rustc-dev-guide/src/part-2-intro.md | 2 +- src/doc/rustc-dev-guide/src/part-3-intro.md | 2 +- src/doc/rustc-dev-guide/src/part-4-intro.md | 2 +- src/doc/rustc-dev-guide/src/profiling.md | 10 +- src/doc/rustc-dev-guide/src/profiling/with_perf.md | 4 +- .../rustc-dev-guide/src/profiling/wpa_profiling.md | 4 +- src/doc/rustc-dev-guide/src/query.md | 2 +- .../src/return-position-impl-trait-in-trait.md | 419 +++++ src/doc/rustc-dev-guide/src/rustc-driver.md | 2 +- src/doc/rustc-dev-guide/src/rustdoc-internals.md | 4 +- src/doc/rustc-dev-guide/src/rustdoc.md | 10 +- src/doc/rustc-dev-guide/src/salsa.md | 6 +- src/doc/rustc-dev-guide/src/sanitizers.md | 2 +- src/doc/rustc-dev-guide/src/serialization.md | 4 +- src/doc/rustc-dev-guide/src/solve/normalization.md | 80 + src/doc/rustc-dev-guide/src/solve/trait-solving.md | 6 +- src/doc/rustc-dev-guide/src/stability.md | 8 +- src/doc/rustc-dev-guide/src/stabilization_guide.md | 2 +- src/doc/rustc-dev-guide/src/tests/adding.md | 6 +- src/doc/rustc-dev-guide/src/tests/ci.md | 6 +- src/doc/rustc-dev-guide/src/tests/compiletest.md | 13 +- src/doc/rustc-dev-guide/src/tests/docker.md | 2 +- src/doc/rustc-dev-guide/src/tests/headers.md | 5 +- src/doc/rustc-dev-guide/src/tests/intro.md | 61 +- src/doc/rustc-dev-guide/src/tests/running.md | 55 +- src/doc/rustc-dev-guide/src/tests/ui.md | 8 +- src/doc/rustc-dev-guide/src/walkthrough.md | 2 +- src/doc/rustc/book.toml | 6 + src/doc/rustc/src/SUMMARY.md | 9 + src/doc/rustc/src/codegen-options/index.md | 8 +- src/doc/rustc/src/platform-support.md | 32 +- .../src/platform-support/aarch64-unknown-teeos.md | 100 ++ src/doc/rustc/src/platform-support/android.md | 2 + .../csky-unknown-linux-gnuabiv2.md | 70 + src/doc/rustc/src/platform-support/hermit.md | 75 + .../rustc/src/platform-support/loongarch-linux.md | 2 +- .../rustc/src/platform-support/mips-release-6.md | 181 +++ src/doc/rustc/src/platform-support/netbsd.md | 2 +- src/doc/rustc/src/platform-support/openharmony.md | 33 + .../src/platform-support/sparc-unknown-none-elf.md | 188 +++ .../src/platform-support/unikraft-linux-musl.md | 67 + .../wasm32-wasi-preview1-threads.md | 148 ++ .../src/platform-support/x86_64h-apple-darwin.md | 4 +- src/doc/rustc/src/symbol-mangling/index.md | 52 + src/doc/rustc/src/symbol-mangling/v0.md | 1222 +++++++++++++++ src/doc/rustdoc/src/lints.md | 34 + src/doc/rustdoc/src/unstable-features.md | 1 + src/doc/rustdoc/src/what-is-rustdoc.md | 2 +- src/doc/style-guide/src/README.md | 58 +- src/doc/style-guide/src/SUMMARY.md | 1 + src/doc/style-guide/src/advice.md | 20 +- src/doc/style-guide/src/editions.md | 46 + src/doc/style-guide/src/expressions.md | 353 +++-- src/doc/style-guide/src/items.md | 223 ++- src/doc/style-guide/src/nightly.md | 2 + src/doc/style-guide/src/principles.md | 42 +- src/doc/style-guide/src/statements.md | 73 +- src/doc/style-guide/src/types.md | 43 +- .../src/compiler-flags/no-parallel-llvm.md | 8 + .../src/compiler-flags/path-options.md | 11 + .../src/compiler-flags/profile_sample_use.md | 2 +- .../src/language-features/abi-thiscall.md | 12 - .../src/language-features/asm-experimental-arch.md | 25 + .../src/language-features/intrinsics.md | 1 + .../src/language-features/lang-items.md | 310 +--- .../unstable-book/src/language-features/start.md | 59 + .../src/library-features/default-free-fn.md | 47 - src/etc/completions/x.py.fish | 66 +- src/etc/completions/x.py.ps1 | 64 +- src/etc/completions/x.py.sh | 128 +- src/etc/htmldocck.py | 2 + src/etc/natvis/liballoc.natvis | 13 +- src/etc/rust_analyzer_settings.json | 5 +- src/librustdoc/clean/auto_trait.rs | 20 +- src/librustdoc/clean/blanket_impl.rs | 35 +- src/librustdoc/clean/cfg.rs | 31 +- src/librustdoc/clean/inline.rs | 61 +- src/librustdoc/clean/mod.rs | 464 ++++-- src/librustdoc/clean/render_macro_matchers.rs | 14 +- src/librustdoc/clean/simplify.rs | 39 +- src/librustdoc/clean/types.rs | 117 +- src/librustdoc/clean/types/tests.rs | 2 +- src/librustdoc/clean/utils.rs | 123 +- src/librustdoc/config.rs | 26 +- src/librustdoc/core.rs | 56 +- src/librustdoc/docfs.rs | 6 +- src/librustdoc/doctest.rs | 80 +- src/librustdoc/externalfiles.rs | 12 +- src/librustdoc/formats/cache.rs | 9 +- src/librustdoc/formats/item_type.rs | 3 +- src/librustdoc/formats/renderer.rs | 7 +- src/librustdoc/html/format.rs | 138 +- src/librustdoc/html/highlight.rs | 38 +- src/librustdoc/html/highlight/tests.rs | 2 +- src/librustdoc/html/length_limit.rs | 7 +- src/librustdoc/html/markdown.rs | 145 +- src/librustdoc/html/markdown/tests.rs | 2 +- src/librustdoc/html/render/context.rs | 39 +- src/librustdoc/html/render/mod.rs | 266 ++-- src/librustdoc/html/render/print_item.rs | 114 +- src/librustdoc/html/render/sidebar.rs | 14 +- src/librustdoc/html/render/span_map.rs | 97 +- src/librustdoc/html/render/type_layout.rs | 2 +- src/librustdoc/html/render/write_shared.rs | 29 +- src/librustdoc/html/sources.rs | 7 +- src/librustdoc/html/static/css/noscript.css | 2 +- src/librustdoc/html/static/css/rustdoc.css | 74 +- src/librustdoc/html/static/css/themes/ayu.css | 14 +- src/librustdoc/html/static/css/themes/dark.css | 6 +- src/librustdoc/html/static/css/themes/light.css | 6 +- src/librustdoc/html/static/js/search.js | 29 +- src/librustdoc/html/static/js/source-script.js | 235 --- src/librustdoc/html/static/js/src-script.js | 235 +++ src/librustdoc/html/static/js/storage.js | 2 +- src/librustdoc/html/static_files.rs | 4 +- src/librustdoc/html/templates/STYLE.md | 2 +- src/librustdoc/html/templates/page.html | 16 +- src/librustdoc/html/templates/print_item.html | 2 +- src/librustdoc/html/templates/type_layout.html | 5 + src/librustdoc/json/conversions.rs | 9 +- src/librustdoc/json/mod.rs | 6 +- src/librustdoc/lib.rs | 15 +- src/librustdoc/lint.rs | 12 + src/librustdoc/markdown.rs | 12 +- src/librustdoc/passes/calculate_doc_coverage.rs | 8 +- src/librustdoc/passes/check_doc_test_visibility.rs | 11 +- src/librustdoc/passes/collect_intra_doc_links.rs | 222 ++- src/librustdoc/passes/collect_trait_impls.rs | 4 +- src/librustdoc/passes/lint.rs | 2 + src/librustdoc/passes/lint/bare_urls.rs | 13 +- .../passes/lint/check_code_block_syntax.rs | 19 +- src/librustdoc/passes/lint/html_tags.rs | 14 +- .../passes/lint/redundant_explicit_links.rs | 347 +++++ src/librustdoc/passes/propagate_doc_cfg.rs | 5 +- src/librustdoc/passes/strip_hidden.rs | 3 +- src/librustdoc/passes/strip_priv_imports.rs | 7 +- src/librustdoc/passes/strip_private.rs | 9 +- src/librustdoc/passes/stripper.rs | 19 +- src/librustdoc/scrape_examples.rs | 8 +- src/librustdoc/visit_ast.rs | 85 +- src/librustdoc/visit_lib.rs | 4 +- src/stage0.json | 568 ++++--- src/tools/build-manifest/Cargo.toml | 2 +- src/tools/build-manifest/src/main.rs | 5 + src/tools/build_helper/Cargo.toml | 2 + src/tools/build_helper/src/ci.rs | 54 +- src/tools/build_helper/src/git.rs | 8 +- src/tools/build_helper/src/lib.rs | 1 + src/tools/build_helper/src/metrics.rs | 92 ++ src/tools/build_helper/src/util.rs | 6 +- src/tools/cargo/.cargo/config.toml | 2 +- src/tools/cargo/.github/renovate.json5 | 38 + src/tools/cargo/.github/workflows/main.yml | 96 +- src/tools/cargo/CHANGELOG.md | 108 +- src/tools/cargo/Cargo.lock | 701 +++++---- src/tools/cargo/Cargo.toml | 151 +- src/tools/cargo/benches/benchsuite/Cargo.toml | 4 +- src/tools/cargo/benches/capture/Cargo.toml | 4 +- src/tools/cargo/ci/validate-version-bump.sh | 45 +- src/tools/cargo/crates/cargo-platform/Cargo.toml | 6 +- src/tools/cargo/crates/cargo-test-macro/Cargo.toml | 4 +- .../cargo/crates/cargo-test-support/Cargo.toml | 4 +- .../cargo-test-support/containers/sshd/Dockerfile | 2 +- .../cargo/crates/cargo-test-support/src/compare.rs | 1 + .../crates/cargo-test-support/src/registry.rs | 36 + src/tools/cargo/crates/cargo-util/Cargo.toml | 8 +- src/tools/cargo/crates/cargo-util/src/paths.rs | 20 +- .../cargo/crates/cargo-util/src/process_builder.rs | 4 +- src/tools/cargo/crates/crates-io/Cargo.toml | 8 +- src/tools/cargo/crates/crates-io/lib.rs | 167 +- src/tools/cargo/crates/home/Cargo.toml | 7 +- src/tools/cargo/crates/mdman/Cargo.toml | 4 +- src/tools/cargo/crates/resolver-tests/Cargo.toml | 2 +- src/tools/cargo/crates/semver-check/Cargo.toml | 2 +- src/tools/cargo/crates/semver-check/src/main.rs | 13 +- src/tools/cargo/crates/xtask-build-man/Cargo.toml | 2 +- src/tools/cargo/crates/xtask-bump-check/Cargo.toml | 14 + .../cargo/crates/xtask-bump-check/src/main.rs | 27 + .../cargo/crates/xtask-bump-check/src/xtask.rs | 423 +++++ .../cargo/crates/xtask-stale-label/Cargo.toml | 2 +- .../cargo/crates/xtask-stale-label/src/main.rs | 2 +- .../cargo/crates/xtask-unpublished/Cargo.toml | 12 - .../cargo/crates/xtask-unpublished/src/main.rs | 15 - .../cargo/crates/xtask-unpublished/src/xtask.rs | 200 --- .../cargo-credential-1password/Cargo.toml | 6 +- .../cargo-credential-1password/src/main.rs | 141 +- .../cargo-credential-gnome-secret/Cargo.toml | 13 - .../cargo-credential-gnome-secret/README.md | 7 - .../cargo-credential-gnome-secret/build.rs | 8 - .../cargo-credential-gnome-secret/src/libsecret.rs | 190 --- .../cargo-credential-gnome-secret/src/main.rs | 12 - .../cargo-credential-libsecret/Cargo.toml | 12 + .../cargo-credential-libsecret/README.md | 7 + .../cargo-credential-libsecret/src/lib.rs | 235 +++ .../cargo-credential-macos-keychain/Cargo.toml | 6 +- .../cargo-credential-macos-keychain/src/lib.rs | 81 + .../cargo-credential-macos-keychain/src/main.rs | 58 - .../credential/cargo-credential-wincred/Cargo.toml | 6 +- .../credential/cargo-credential-wincred/src/lib.rs | 125 ++ .../cargo-credential-wincred/src/main.rs | 122 -- .../cargo/credential/cargo-credential/Cargo.toml | 18 +- .../cargo/credential/cargo-credential/README.md | 2 +- .../cargo-credential/examples/file-provider.rs | 90 ++ .../cargo-credential/examples/stdout-redirected.rs | 25 + .../cargo/credential/cargo-credential/src/error.rs | 206 +++ .../cargo/credential/cargo-credential/src/lib.rs | 312 +++- .../credential/cargo-credential/src/secret.rs | 101 ++ .../cargo/credential/cargo-credential/src/stdio.rs | 163 ++ .../credential/cargo-credential/tests/examples.rs | 45 + src/tools/cargo/deny.toml | 1 + src/tools/cargo/publish.py | 6 + src/tools/cargo/src/bin/cargo/cli.rs | 24 +- src/tools/cargo/src/bin/cargo/commands/add.rs | 2 +- src/tools/cargo/src/bin/cargo/commands/bench.rs | 45 +- src/tools/cargo/src/bin/cargo/commands/build.rs | 15 +- src/tools/cargo/src/bin/cargo/commands/check.rs | 12 +- src/tools/cargo/src/bin/cargo/commands/clean.rs | 8 +- src/tools/cargo/src/bin/cargo/commands/doc.rs | 22 +- src/tools/cargo/src/bin/cargo/commands/fetch.rs | 2 +- src/tools/cargo/src/bin/cargo/commands/fix.rs | 52 +- src/tools/cargo/src/bin/cargo/commands/init.rs | 4 +- src/tools/cargo/src/bin/cargo/commands/install.rs | 50 +- .../cargo/src/bin/cargo/commands/locate_project.rs | 6 +- src/tools/cargo/src/bin/cargo/commands/login.rs | 37 +- src/tools/cargo/src/bin/cargo/commands/logout.rs | 2 +- src/tools/cargo/src/bin/cargo/commands/metadata.rs | 6 +- src/tools/cargo/src/bin/cargo/commands/new.rs | 4 +- src/tools/cargo/src/bin/cargo/commands/owner.rs | 4 +- src/tools/cargo/src/bin/cargo/commands/package.rs | 17 +- src/tools/cargo/src/bin/cargo/commands/pkgid.rs | 9 +- src/tools/cargo/src/bin/cargo/commands/publish.rs | 19 +- src/tools/cargo/src/bin/cargo/commands/remove.rs | 108 +- src/tools/cargo/src/bin/cargo/commands/run.rs | 10 +- src/tools/cargo/src/bin/cargo/commands/rustc.rs | 38 +- src/tools/cargo/src/bin/cargo/commands/rustdoc.rs | 12 +- src/tools/cargo/src/bin/cargo/commands/search.rs | 4 +- src/tools/cargo/src/bin/cargo/commands/test.rs | 41 +- src/tools/cargo/src/bin/cargo/commands/tree.rs | 26 +- .../cargo/src/bin/cargo/commands/uninstall.rs | 9 +- src/tools/cargo/src/bin/cargo/commands/update.rs | 21 +- src/tools/cargo/src/bin/cargo/commands/vendor.rs | 4 +- src/tools/cargo/src/bin/cargo/commands/yank.rs | 6 +- src/tools/cargo/src/bin/cargo/main.rs | 15 +- .../core/compiler/build_context/target_info.rs | 12 +- .../core/compiler/context/compilation_files.rs | 4 +- .../cargo/src/cargo/core/compiler/custom_build.rs | 12 +- .../src/cargo/core/compiler/fingerprint/mod.rs | 27 +- .../src/cargo/core/compiler/future_incompat.rs | 2 +- .../cargo/src/cargo/core/compiler/job_queue/mod.rs | 4 +- src/tools/cargo/src/cargo/core/compiler/mod.rs | 4 +- .../src/cargo/core/compiler/output_depinfo.rs | 2 +- src/tools/cargo/src/cargo/core/compiler/rustdoc.rs | 6 +- src/tools/cargo/src/cargo/core/compiler/timings.js | 10 +- src/tools/cargo/src/cargo/core/compiler/timings.rs | 4 +- .../src/cargo/core/compiler/unit_dependencies.rs | 2 +- src/tools/cargo/src/cargo/core/dependency.rs | 2 +- src/tools/cargo/src/cargo/core/package.rs | 8 +- src/tools/cargo/src/cargo/core/registry.rs | 6 +- .../src/cargo/core/resolver/conflict_cache.rs | 2 +- src/tools/cargo/src/cargo/core/resolver/context.rs | 2 +- .../cargo/src/cargo/core/resolver/dep_cache.rs | 2 +- src/tools/cargo/src/cargo/core/resolver/encode.rs | 106 +- .../cargo/src/cargo/core/resolver/features.rs | 14 +- src/tools/cargo/src/cargo/core/resolver/mod.rs | 2 +- src/tools/cargo/src/cargo/core/resolver/resolve.rs | 2 + src/tools/cargo/src/cargo/core/source/source_id.rs | 74 +- src/tools/cargo/src/cargo/core/workspace.rs | 2 +- src/tools/cargo/src/cargo/lib.rs | 2 +- src/tools/cargo/src/cargo/ops/cargo_compile/mod.rs | 4 +- .../cargo/src/cargo/ops/cargo_generate_lockfile.rs | 2 +- src/tools/cargo/src/cargo/ops/cargo_new.rs | 2 +- src/tools/cargo/src/cargo/ops/cargo_package.rs | 105 +- .../cargo/src/cargo/ops/cargo_read_manifest.rs | 2 +- src/tools/cargo/src/cargo/ops/cargo_run.rs | 4 + src/tools/cargo/src/cargo/ops/cargo_test.rs | 33 +- src/tools/cargo/src/cargo/ops/fix.rs | 2 +- src/tools/cargo/src/cargo/ops/registry/login.rs | 144 +- src/tools/cargo/src/cargo/ops/registry/logout.rs | 26 - src/tools/cargo/src/cargo/ops/registry/mod.rs | 18 +- src/tools/cargo/src/cargo/ops/registry/owner.rs | 8 +- src/tools/cargo/src/cargo/ops/registry/publish.rs | 14 +- src/tools/cargo/src/cargo/ops/registry/yank.rs | 8 +- src/tools/cargo/src/cargo/ops/resolve.rs | 2 +- src/tools/cargo/src/cargo/ops/tree/graph.rs | 2 +- src/tools/cargo/src/cargo/sources/config.rs | 2 +- .../cargo/src/cargo/sources/git/known_hosts.rs | 20 +- src/tools/cargo/src/cargo/sources/git/oxide.rs | 2 +- src/tools/cargo/src/cargo/sources/git/source.rs | 7 +- src/tools/cargo/src/cargo/sources/git/utils.rs | 10 +- src/tools/cargo/src/cargo/sources/path.rs | 6 +- .../cargo/src/cargo/sources/registry/download.rs | 9 +- .../src/cargo/sources/registry/http_remote.rs | 44 +- .../cargo/src/cargo/sources/registry/index.rs | 36 +- src/tools/cargo/src/cargo/sources/registry/mod.rs | 9 +- .../cargo/src/cargo/sources/registry/remote.rs | 2 +- src/tools/cargo/src/cargo/util/auth/asymmetric.rs | 155 -- src/tools/cargo/src/cargo/util/auth/mod.rs | 872 +++++------ src/tools/cargo/src/cargo/util/command_prelude.rs | 146 +- src/tools/cargo/src/cargo/util/config/mod.rs | 35 +- src/tools/cargo/src/cargo/util/config/path.rs | 25 +- src/tools/cargo/src/cargo/util/config/target.rs | 2 +- .../cargo/src/cargo/util/credential/adaptor.rs | 68 + src/tools/cargo/src/cargo/util/credential/mod.rs | 8 + .../cargo/src/cargo/util/credential/paseto.rs | 224 +++ .../cargo/src/cargo/util/credential/process.rs | 80 + src/tools/cargo/src/cargo/util/credential/token.rs | 96 ++ .../cargo/src/cargo/util/diagnostic_server.rs | 2 +- src/tools/cargo/src/cargo/util/errors.rs | 17 +- src/tools/cargo/src/cargo/util/job.rs | 2 +- src/tools/cargo/src/cargo/util/mod.rs | 1 + src/tools/cargo/src/cargo/util/network/http.rs | 39 +- src/tools/cargo/src/cargo/util/network/mod.rs | 2 +- src/tools/cargo/src/cargo/util/network/sleep.rs | 2 +- src/tools/cargo/src/cargo/util/restricted_names.rs | 15 +- src/tools/cargo/src/cargo/util/rustc.rs | 2 +- src/tools/cargo/src/cargo/util/toml/embedded.rs | 37 +- src/tools/cargo/src/cargo/util/toml/mod.rs | 10 +- .../cargo/src/cargo/util/toml_mut/dependency.rs | 6 +- .../doc/contrib/src/implementation/debugging.md | 15 +- .../cargo/src/doc/contrib/src/process/release.md | 37 +- src/tools/cargo/src/doc/man/cargo-metadata.md | 44 +- src/tools/cargo/src/doc/man/cargo-test.md | 1 - src/tools/cargo/src/doc/man/cargo-yank.md | 2 +- .../src/doc/man/generated_txt/cargo-metadata.txt | 45 +- .../cargo/src/doc/man/generated_txt/cargo-test.txt | 5 - .../cargo/src/doc/man/generated_txt/cargo-yank.txt | 2 +- .../cargo/src/doc/src/commands/cargo-metadata.md | 44 +- src/tools/cargo/src/doc/src/commands/cargo-test.md | 6 - src/tools/cargo/src/doc/src/commands/cargo-yank.md | 2 +- .../src/doc/src/guide/cargo-toml-vs-cargo-lock.md | 2 +- .../cargo/src/doc/src/reference/build-scripts.md | 53 +- src/tools/cargo/src/doc/src/reference/config.md | 14 + .../src/doc/src/reference/environment-variables.md | 6 +- .../cargo/src/doc/src/reference/external-tools.md | 3 +- src/tools/cargo/src/doc/src/reference/manifest.md | 22 +- .../doc/src/reference/overriding-dependencies.md | 6 +- src/tools/cargo/src/doc/src/reference/profiles.md | 15 +- src/tools/cargo/src/doc/src/reference/resolver.md | 7 +- src/tools/cargo/src/doc/src/reference/semver.md | 858 +++++++++- .../doc/src/reference/specifying-dependencies.md | 2 +- src/tools/cargo/src/doc/src/reference/unstable.md | 328 ++-- .../cargo/src/doc/src/reference/workspaces.md | 23 +- src/tools/cargo/src/etc/_cargo | 12 +- src/tools/cargo/src/etc/cargo.bashcomp.sh | 7 +- src/tools/cargo/src/etc/man/cargo-metadata.1 | 49 +- src/tools/cargo/src/etc/man/cargo-test.1 | 7 - src/tools/cargo/src/etc/man/cargo-yank.1 | 2 +- src/tools/cargo/tests/testsuite/alt_registry.rs | 41 + src/tools/cargo/tests/testsuite/bench.rs | 61 +- src/tools/cargo/tests/testsuite/build_script.rs | 29 + .../cargo/tests/testsuite/build_script_env.rs | 10 +- src/tools/cargo/tests/testsuite/cargo/help/mod.rs | 12 + .../cargo/tests/testsuite/cargo/help/stderr.log | 0 .../cargo/tests/testsuite/cargo/help/stdout.log | 39 + src/tools/cargo/tests/testsuite/cargo/mod.rs | 1 + .../cargo/tests/testsuite/cargo_add/help/mod.rs | 13 + .../tests/testsuite/cargo_add/help/stderr.log | 0 .../tests/testsuite/cargo_add/help/stdout.log | 124 ++ src/tools/cargo/tests/testsuite/cargo_add/mod.rs | 1 + .../cargo/tests/testsuite/cargo_bench/help/mod.rs | 13 + .../tests/testsuite/cargo_bench/help/stderr.log | 0 .../tests/testsuite/cargo_bench/help/stdout.log | 59 + src/tools/cargo/tests/testsuite/cargo_bench/mod.rs | 1 + .../cargo/tests/testsuite/cargo_build/help/mod.rs | 13 + .../tests/testsuite/cargo_build/help/stderr.log | 0 .../tests/testsuite/cargo_build/help/stdout.log | 58 + src/tools/cargo/tests/testsuite/cargo_build/mod.rs | 1 + .../cargo/tests/testsuite/cargo_check/help/mod.rs | 13 + .../tests/testsuite/cargo_check/help/stderr.log | 0 .../tests/testsuite/cargo_check/help/stdout.log | 56 + src/tools/cargo/tests/testsuite/cargo_check/mod.rs | 1 + .../cargo/tests/testsuite/cargo_clean/help/mod.rs | 13 + .../tests/testsuite/cargo_clean/help/stderr.log | 0 .../tests/testsuite/cargo_clean/help/stdout.log | 29 + src/tools/cargo/tests/testsuite/cargo_clean/mod.rs | 1 + src/tools/cargo/tests/testsuite/cargo_config.rs | 520 ------- .../cargo/tests/testsuite/cargo_config/help/mod.rs | 13 + .../tests/testsuite/cargo_config/help/stderr.log | 0 .../tests/testsuite/cargo_config/help/stdout.log | 18 + .../cargo/tests/testsuite/cargo_config/mod.rs | 522 +++++++ .../cargo/tests/testsuite/cargo_doc/help/mod.rs | 13 + .../tests/testsuite/cargo_doc/help/stderr.log | 0 .../tests/testsuite/cargo_doc/help/stdout.log | 53 + src/tools/cargo/tests/testsuite/cargo_doc/mod.rs | 1 + .../cargo/tests/testsuite/cargo_fetch/help/mod.rs | 13 + .../tests/testsuite/cargo_fetch/help/stderr.log | 0 .../tests/testsuite/cargo_fetch/help/stdout.log | 22 + src/tools/cargo/tests/testsuite/cargo_fetch/mod.rs | 1 + .../cargo/tests/testsuite/cargo_fix/help/mod.rs | 13 + .../tests/testsuite/cargo_fix/help/stderr.log | 0 .../tests/testsuite/cargo_fix/help/stdout.log | 60 + src/tools/cargo/tests/testsuite/cargo_fix/mod.rs | 1 + .../testsuite/cargo_generate_lockfile/help/mod.rs | 13 + .../cargo_generate_lockfile/help/stderr.log | 0 .../cargo_generate_lockfile/help/stdout.log | 19 + .../tests/testsuite/cargo_generate_lockfile/mod.rs | 1 + .../tests/testsuite/cargo_git_checkout/help/mod.rs | 13 + .../testsuite/cargo_git_checkout/help/stderr.log | 0 .../testsuite/cargo_git_checkout/help/stdout.log | 1 + .../tests/testsuite/cargo_git_checkout/mod.rs | 1 + .../cargo/tests/testsuite/cargo_help/help/mod.rs | 13 + .../tests/testsuite/cargo_help/help/stderr.log | 0 .../tests/testsuite/cargo_help/help/stdout.log | 18 + src/tools/cargo/tests/testsuite/cargo_help/mod.rs | 1 + .../cargo/tests/testsuite/cargo_init/auto_git/in | 1 + .../tests/testsuite/cargo_init/auto_git/mod.rs | 22 + .../testsuite/cargo_init/auto_git/out/Cargo.toml | 8 + .../testsuite/cargo_init/auto_git/out/src/lib.rs | 14 + .../tests/testsuite/cargo_init/auto_git/stderr.log | 1 + .../tests/testsuite/cargo_init/auto_git/stdout.log | 0 .../bin_already_exists_explicit/in/src/main.rs | 4 + .../cargo_init/bin_already_exists_explicit/mod.rs | 21 + .../bin_already_exists_explicit/out/Cargo.toml | 8 + .../bin_already_exists_explicit/out/src/main.rs | 4 + .../bin_already_exists_explicit/stderr.log | 1 + .../bin_already_exists_explicit/stdout.log | 0 .../bin_already_exists_explicit_nosrc/in/main.rs | 4 + .../bin_already_exists_explicit_nosrc/mod.rs | 22 + .../out/Cargo.toml | 12 + .../bin_already_exists_explicit_nosrc/out/main.rs | 4 + .../bin_already_exists_explicit_nosrc/stderr.log | 1 + .../bin_already_exists_explicit_nosrc/stdout.log | 0 .../bin_already_exists_implicit/in/src/main.rs | 4 + .../cargo_init/bin_already_exists_implicit/mod.rs | 21 + .../bin_already_exists_implicit/out/Cargo.toml | 8 + .../bin_already_exists_implicit/out/src/main.rs | 4 + .../bin_already_exists_implicit/stderr.log | 1 + .../bin_already_exists_implicit/stdout.log | 0 .../in/case.rs | 4 + .../bin_already_exists_implicit_namenosrc/mod.rs | 22 + .../out/Cargo.toml | 12 + .../out/case.rs | 4 + .../stderr.log | 1 + .../stdout.log | 0 .../in/src/case.rs | 4 + .../bin_already_exists_implicit_namesrc/mod.rs | 22 + .../out/Cargo.toml | 12 + .../out/src/case.rs | 4 + .../bin_already_exists_implicit_namesrc/stderr.log | 1 + .../bin_already_exists_implicit_namesrc/stdout.log | 0 .../bin_already_exists_implicit_nosrc/in/main.rs | 4 + .../bin_already_exists_implicit_nosrc/mod.rs | 22 + .../out/Cargo.toml | 12 + .../bin_already_exists_implicit_nosrc/out/main.rs | 4 + .../bin_already_exists_implicit_nosrc/stderr.log | 1 + .../bin_already_exists_implicit_nosrc/stdout.log | 0 .../testsuite/cargo_init/both_lib_and_bin/mod.rs | 19 + .../cargo_init/both_lib_and_bin/stderr.log | 1 + .../cargo_init/both_lib_and_bin/stdout.log | 0 .../in/case.rs | 1 + .../in/lib.rs | 1 + .../mod.rs | 18 + .../stderr.log | 1 + .../stdout.log | 0 .../confused_by_multiple_lib_files/in/lib.rs | 1 + .../confused_by_multiple_lib_files/in/src/lib.rs | 1 + .../confused_by_multiple_lib_files/mod.rs | 22 + .../confused_by_multiple_lib_files/out/lib.rs | 1 + .../confused_by_multiple_lib_files/out/src/lib.rs | 1 + .../confused_by_multiple_lib_files/stderr.log | 1 + .../confused_by_multiple_lib_files/stdout.log | 0 .../in/case.rs | 1 + .../in/lib.rs | 1 + .../creates_binary_when_both_binlib_present/mod.rs | 21 + .../out/Cargo.toml | 16 + .../out/case.rs | 1 + .../out/lib.rs | 1 + .../stderr.log | 1 + .../stdout.log | 0 .../in/case.rs | 1 + .../mod.rs | 21 + .../out/Cargo.toml | 12 + .../out/case.rs | 1 + .../stderr.log | 2 + .../stdout.log | 0 .../in/case.rs | 1 + .../mod.rs | 21 + .../out/Cargo.toml | 12 + .../out/case.rs | 1 + .../stderr.log | 2 + .../stdout.log | 0 .../tests/testsuite/cargo_init/empty_dir/.keep | 0 .../tests/testsuite/cargo_init/empty_dir/mod.rs | 7 + .../testsuite/cargo_init/explicit_bin_with_git/in | 1 + .../cargo_init/explicit_bin_with_git/mod.rs | 21 + .../explicit_bin_with_git/out/Cargo.toml | 8 + .../explicit_bin_with_git/out/src/main.rs | 3 + .../cargo_init/explicit_bin_with_git/stderr.log | 1 + .../cargo_init/explicit_bin_with_git/stdout.log | 0 .../cargo_init/formats_source/in/rustfmt.toml | 1 + .../testsuite/cargo_init/formats_source/mod.rs | 29 + .../cargo_init/formats_source/out/Cargo.toml | 8 + .../cargo_init/formats_source/out/rustfmt.toml | 1 + .../cargo_init/formats_source/out/src/lib.rs | 14 + .../testsuite/cargo_init/formats_source/stderr.log | 1 + .../testsuite/cargo_init/formats_source/stdout.log | 0 .../cargo_init/fossil_autodetect/in/.fossil/.keep | 0 .../testsuite/cargo_init/fossil_autodetect/mod.rs | 22 + .../out/.fossil-settings/clean-glob | 2 + .../out/.fossil-settings/ignore-glob | 2 + .../cargo_init/fossil_autodetect/out/Cargo.toml | 8 + .../cargo_init/fossil_autodetect/out/src/lib.rs | 14 + .../cargo_init/fossil_autodetect/stderr.log | 1 + .../cargo_init/fossil_autodetect/stdout.log | 0 .../testsuite/cargo_init/git_autodetect/mod.rs | 24 + .../cargo_init/git_autodetect/out/Cargo.toml | 8 + .../cargo_init/git_autodetect/out/src/lib.rs | 14 + .../testsuite/cargo_init/git_autodetect/stderr.log | 1 + .../testsuite/cargo_init/git_autodetect/stdout.log | 0 .../mod.rs | 22 + .../out/Cargo.toml | 8 + .../out/src/lib.rs | 14 + .../stderr.log | 1 + .../stdout.log | 0 .../cargo/tests/testsuite/cargo_init/help/mod.rs | 13 + .../tests/testsuite/cargo_init/help/stderr.log | 0 .../tests/testsuite/cargo_init/help/stdout.log | 31 + .../in/rustfmt.toml | 1 + .../ignores_failure_to_format_source/mod.rs | 22 + .../out/Cargo.toml | 8 + .../out/rustfmt.toml | 1 + .../out/src/lib.rs | 14 + .../ignores_failure_to_format_source/stderr.log | 1 + .../ignores_failure_to_format_source/stdout.log | 0 .../cargo_init/inferred_bin_with_git/in/main.rs | 1 + .../cargo_init/inferred_bin_with_git/mod.rs | 21 + .../inferred_bin_with_git/out/Cargo.toml | 12 + .../cargo_init/inferred_bin_with_git/out/main.rs | 1 + .../cargo_init/inferred_bin_with_git/stderr.log | 1 + .../cargo_init/inferred_bin_with_git/stdout.log | 0 .../cargo_init/inferred_lib_with_git/in/lib.rs | 1 + .../cargo_init/inferred_lib_with_git/mod.rs | 21 + .../inferred_lib_with_git/out/Cargo.toml | 12 + .../cargo_init/inferred_lib_with_git/out/lib.rs | 1 + .../cargo_init/inferred_lib_with_git/stderr.log | 1 + .../cargo_init/inferred_lib_with_git/stdout.log | 0 .../inherit_workspace_package_table/in/Cargo.toml | 21 + .../inherit_workspace_package_table/in/README.md | 0 .../in/crates/foo/src/main.rs | 3 + .../inherit_workspace_package_table/in/src/lib.rs | 14 + .../inherit_workspace_package_table/mod.rs | 22 + .../inherit_workspace_package_table/out/Cargo.toml | 21 + .../out/crates/foo/Cargo.toml | 21 + .../out/crates/foo/src/main.rs | 3 + .../inherit_workspace_package_table/out/src/lib.rs | 14 + .../inherit_workspace_package_table/stderr.log | 1 + .../inherit_workspace_package_table/stdout.log | 0 .../testsuite/cargo_init/invalid_dir_name/mod.rs | 21 + .../cargo_init/invalid_dir_name/stderr.log | 8 + .../cargo_init/invalid_dir_name/stdout.log | 0 .../cargo_init/lib_already_exists_nosrc/in/lib.rs | 0 .../cargo_init/lib_already_exists_nosrc/mod.rs | 22 + .../lib_already_exists_nosrc/out/Cargo.toml | 12 + .../cargo_init/lib_already_exists_nosrc/out/lib.rs | 0 .../cargo_init/lib_already_exists_nosrc/stderr.log | 1 + .../cargo_init/lib_already_exists_nosrc/stdout.log | 0 .../lib_already_exists_src/in/src/lib.rs | 1 + .../cargo_init/lib_already_exists_src/mod.rs | 22 + .../lib_already_exists_src/out/Cargo.toml | 8 + .../lib_already_exists_src/out/src/lib.rs | 1 + .../cargo_init/lib_already_exists_src/stderr.log | 1 + .../cargo_init/lib_already_exists_src/stdout.log | 0 .../cargo_init/mercurial_autodetect/mod.rs | 22 + .../cargo_init/mercurial_autodetect/out/Cargo.toml | 8 + .../cargo_init/mercurial_autodetect/out/src/lib.rs | 14 + .../cargo_init/mercurial_autodetect/stderr.log | 1 + .../cargo_init/mercurial_autodetect/stdout.log | 0 src/tools/cargo/tests/testsuite/cargo_init/mod.rs | 44 + .../multibin_project_name_clash/in/case.rs | 1 + .../multibin_project_name_clash/in/main.rs | 1 + .../cargo_init/multibin_project_name_clash/mod.rs | 22 + .../multibin_project_name_clash/out/case.rs | 1 + .../multibin_project_name_clash/out/main.rs | 1 + .../multibin_project_name_clash/stderr.log | 4 + .../multibin_project_name_clash/stdout.log | 0 .../tests/testsuite/cargo_init/no_filename/mod.rs | 16 + .../testsuite/cargo_init/no_filename/stderr.log | 1 + .../testsuite/cargo_init/no_filename/stdout.log | 0 .../cargo_init/path_contains_separator/in/.keep | 0 .../cargo_init/path_contains_separator/mod.rs | 26 + .../path_contains_separator/out/Cargo.toml | 8 + .../path_contains_separator/out/src/main.rs | 3 + .../cargo_init/path_contains_separator/stderr.log | 3 + .../cargo_init/path_contains_separator/stdout.log | 0 .../cargo_init/pijul_autodetect/in/.pijul/.keep | 0 .../testsuite/cargo_init/pijul_autodetect/mod.rs | 22 + .../cargo_init/pijul_autodetect/out/.ignore | 2 + .../cargo_init/pijul_autodetect/out/Cargo.toml | 8 + .../cargo_init/pijul_autodetect/out/src/lib.rs | 14 + .../cargo_init/pijul_autodetect/stderr.log | 1 + .../cargo_init/pijul_autodetect/stdout.log | 0 .../testsuite/cargo_init/reserved_name/mod.rs | 21 + .../testsuite/cargo_init/reserved_name/stderr.log | 8 + .../testsuite/cargo_init/reserved_name/stdout.log | 0 .../cargo/tests/testsuite/cargo_init/simple_bin/in | 1 + .../tests/testsuite/cargo_init/simple_bin/mod.rs | 29 + .../testsuite/cargo_init/simple_bin/out/Cargo.toml | 8 + .../cargo_init/simple_bin/out/src/main.rs | 3 + .../testsuite/cargo_init/simple_bin/stderr.log | 1 + .../testsuite/cargo_init/simple_bin/stdout.log | 0 .../cargo/tests/testsuite/cargo_init/simple_git/in | 1 + .../tests/testsuite/cargo_init/simple_git/mod.rs | 22 + .../testsuite/cargo_init/simple_git/out/Cargo.toml | 8 + .../testsuite/cargo_init/simple_git/out/src/lib.rs | 14 + .../testsuite/cargo_init/simple_git/stderr.log | 1 + .../testsuite/cargo_init/simple_git/stdout.log | 0 .../cargo_init/simple_git_ignore_exists/mod.rs | 28 + .../simple_git_ignore_exists/out/Cargo.toml | 8 + .../simple_git_ignore_exists/out/src/lib.rs | 14 + .../cargo_init/simple_git_ignore_exists/stderr.log | 1 + .../cargo_init/simple_git_ignore_exists/stdout.log | 0 .../cargo/tests/testsuite/cargo_init/simple_hg/in | 1 + .../tests/testsuite/cargo_init/simple_hg/mod.rs | 22 + .../testsuite/cargo_init/simple_hg/out/Cargo.toml | 8 + .../testsuite/cargo_init/simple_hg/out/src/lib.rs | 14 + .../testsuite/cargo_init/simple_hg/stderr.log | 1 + .../testsuite/cargo_init/simple_hg/stdout.log | 0 .../cargo_init/simple_hg_ignore_exists/mod.rs | 22 + .../simple_hg_ignore_exists/out/Cargo.toml | 8 + .../simple_hg_ignore_exists/out/src/lib.rs | 14 + .../cargo_init/simple_hg_ignore_exists/stderr.log | 1 + .../cargo_init/simple_hg_ignore_exists/stdout.log | 0 .../cargo/tests/testsuite/cargo_init/simple_lib/in | 1 + .../tests/testsuite/cargo_init/simple_lib/mod.rs | 29 + .../testsuite/cargo_init/simple_lib/out/Cargo.toml | 8 + .../testsuite/cargo_init/simple_lib/out/src/lib.rs | 14 + .../testsuite/cargo_init/simple_lib/stderr.log | 1 + .../testsuite/cargo_init/simple_lib/stdout.log | 0 .../testsuite/cargo_init/unknown_flags/mod.rs | 15 + .../testsuite/cargo_init/unknown_flags/stderr.log | 7 + .../testsuite/cargo_init/unknown_flags/stdout.log | 0 .../cargo_init/with_argument/in/foo/.keep | 0 .../testsuite/cargo_init/with_argument/mod.rs | 21 + .../cargo_init/with_argument/out/foo/Cargo.toml | 8 + .../cargo_init/with_argument/out/foo/src/main.rs | 3 + .../testsuite/cargo_init/with_argument/stderr.log | 1 + .../testsuite/cargo_init/with_argument/stdout.log | 0 .../tests/testsuite/cargo_install/help/mod.rs | 13 + .../tests/testsuite/cargo_install/help/stderr.log | 0 .../tests/testsuite/cargo_install/help/stdout.log | 56 + .../cargo/tests/testsuite/cargo_install/mod.rs | 1 + .../testsuite/cargo_locate_project/help/mod.rs | 13 + .../testsuite/cargo_locate_project/help/stderr.log | 0 .../testsuite/cargo_locate_project/help/stdout.log | 22 + .../tests/testsuite/cargo_locate_project/mod.rs | 1 + .../cargo/tests/testsuite/cargo_login/help/mod.rs | 13 + .../tests/testsuite/cargo_login/help/stderr.log | 0 .../tests/testsuite/cargo_login/help/stdout.log | 23 + src/tools/cargo/tests/testsuite/cargo_login/mod.rs | 1 + .../cargo/tests/testsuite/cargo_logout/help/mod.rs | 13 + .../tests/testsuite/cargo_logout/help/stderr.log | 0 .../tests/testsuite/cargo_logout/help/stdout.log | 19 + .../cargo/tests/testsuite/cargo_logout/mod.rs | 1 + .../tests/testsuite/cargo_metadata/help/mod.rs | 13 + .../tests/testsuite/cargo_metadata/help/stderr.log | 0 .../tests/testsuite/cargo_metadata/help/stdout.log | 30 + .../cargo/tests/testsuite/cargo_metadata/mod.rs | 1 + .../cargo/tests/testsuite/cargo_new/help/mod.rs | 13 + .../tests/testsuite/cargo_new/help/stderr.log | 0 .../tests/testsuite/cargo_new/help/stdout.log | 31 + src/tools/cargo/tests/testsuite/cargo_new/mod.rs | 1 + .../cargo/tests/testsuite/cargo_owner/help/mod.rs | 13 + .../tests/testsuite/cargo_owner/help/stderr.log | 0 .../tests/testsuite/cargo_owner/help/stdout.log | 27 + src/tools/cargo/tests/testsuite/cargo_owner/mod.rs | 1 + .../tests/testsuite/cargo_package/help/mod.rs | 13 + .../tests/testsuite/cargo_package/help/stderr.log | 0 .../tests/testsuite/cargo_package/help/stdout.log | 39 + .../cargo/tests/testsuite/cargo_package/mod.rs | 1 + .../cargo/tests/testsuite/cargo_pkgid/help/mod.rs | 13 + .../tests/testsuite/cargo_pkgid/help/stderr.log | 0 .../tests/testsuite/cargo_pkgid/help/stdout.log | 25 + src/tools/cargo/tests/testsuite/cargo_pkgid/mod.rs | 1 + .../tests/testsuite/cargo_publish/help/mod.rs | 13 + .../tests/testsuite/cargo_publish/help/stderr.log | 0 .../tests/testsuite/cargo_publish/help/stdout.log | 39 + .../cargo/tests/testsuite/cargo_publish/mod.rs | 1 + .../testsuite/cargo_read_manifest/help/mod.rs | 13 + .../testsuite/cargo_read_manifest/help/stderr.log | 0 .../testsuite/cargo_read_manifest/help/stdout.log | 19 + .../tests/testsuite/cargo_read_manifest/mod.rs | 1 + .../cargo_remove/avoid_empty_tables/stderr.log | 1 - .../tests/testsuite/cargo_remove/build/stderr.log | 1 - .../tests/testsuite/cargo_remove/dev/stderr.log | 1 - .../cargo_remove/gc_keep_used_patch/in/Cargo.toml | 8 + .../gc_keep_used_patch/in/serde/Cargo.toml | 9 + .../gc_keep_used_patch/in/serde/src/lib.rs | 0 .../gc_keep_used_patch/in/serde_derive/Cargo.toml | 8 + .../gc_keep_used_patch/in/serde_derive/src/lib.rs | 0 .../cargo_remove/gc_keep_used_patch/mod.rs | 27 + .../cargo_remove/gc_keep_used_patch/out/Cargo.toml | 8 + .../gc_keep_used_patch/out/serde/Cargo.toml | 6 + .../gc_keep_used_patch/out/serde/src/lib.rs | 0 .../gc_keep_used_patch/out/serde_derive/Cargo.toml | 8 + .../gc_keep_used_patch/out/serde_derive/src/lib.rs | 0 .../cargo_remove/gc_keep_used_patch/stderr.log | 1 + .../cargo_remove/gc_keep_used_patch/stdout.log | 0 .../tests/testsuite/cargo_remove/gc_patch/mod.rs | 9 +- .../testsuite/cargo_remove/gc_patch/out/Cargo.lock | 19 + .../testsuite/cargo_remove/gc_patch/stderr.log | 2 - .../testsuite/cargo_remove/gc_profile/stderr.log | 1 - .../testsuite/cargo_remove/gc_replace/stderr.log | 1 - .../cargo/tests/testsuite/cargo_remove/help/mod.rs | 13 + .../tests/testsuite/cargo_remove/help/stderr.log | 0 .../tests/testsuite/cargo_remove/help/stdout.log | 29 + .../cargo/tests/testsuite/cargo_remove/mod.rs | 2 + .../cargo_remove/multiple_deps/stderr.log | 1 - .../testsuite/cargo_remove/multiple_dev/stderr.log | 1 - .../cargo_remove/optional_dep_feature/stderr.log | 1 - .../cargo_remove/optional_feature/stderr.log | 1 - .../testsuite/cargo_remove/package/stderr.log | 1 - .../testsuite/cargo_remove/remove_basic/stderr.log | 1 - .../tests/testsuite/cargo_remove/target/stderr.log | 1 - .../testsuite/cargo_remove/target_build/stderr.log | 1 - .../testsuite/cargo_remove/target_dev/stderr.log | 1 - .../cargo_remove/update_lock_file/stderr.log | 1 - .../testsuite/cargo_remove/workspace/stderr.log | 1 - .../cargo_remove/workspace_non_virtual/stderr.log | 1 - .../cargo_remove/workspace_preserved/stderr.log | 1 - .../cargo/tests/testsuite/cargo_report/help/mod.rs | 13 + .../tests/testsuite/cargo_report/help/stderr.log | 0 .../tests/testsuite/cargo_report/help/stdout.log | 20 + .../cargo/tests/testsuite/cargo_report/mod.rs | 1 + .../cargo/tests/testsuite/cargo_run/help/mod.rs | 13 + .../tests/testsuite/cargo_run/help/stderr.log | 0 .../tests/testsuite/cargo_run/help/stdout.log | 47 + src/tools/cargo/tests/testsuite/cargo_run/mod.rs | 1 + .../cargo/tests/testsuite/cargo_rustc/help/mod.rs | 13 + .../tests/testsuite/cargo_rustc/help/stderr.log | 0 .../tests/testsuite/cargo_rustc/help/stdout.log | 58 + src/tools/cargo/tests/testsuite/cargo_rustc/mod.rs | 1 + .../tests/testsuite/cargo_rustdoc/help/mod.rs | 13 + .../tests/testsuite/cargo_rustdoc/help/stderr.log | 0 .../tests/testsuite/cargo_rustdoc/help/stdout.log | 56 + .../cargo/tests/testsuite/cargo_rustdoc/mod.rs | 1 + .../cargo/tests/testsuite/cargo_search/help/mod.rs | 13 + .../tests/testsuite/cargo_search/help/stderr.log | 0 .../tests/testsuite/cargo_search/help/stdout.log | 24 + .../cargo/tests/testsuite/cargo_search/mod.rs | 1 + .../cargo/tests/testsuite/cargo_test/help/mod.rs | 13 + .../tests/testsuite/cargo_test/help/stderr.log | 0 .../tests/testsuite/cargo_test/help/stdout.log | 63 + src/tools/cargo/tests/testsuite/cargo_test/mod.rs | 1 + .../cargo/tests/testsuite/cargo_tree/help/mod.rs | 13 + .../tests/testsuite/cargo_tree/help/stderr.log | 0 .../tests/testsuite/cargo_tree/help/stdout.log | 45 + src/tools/cargo/tests/testsuite/cargo_tree/mod.rs | 1 + .../tests/testsuite/cargo_uninstall/help/mod.rs | 13 + .../testsuite/cargo_uninstall/help/stderr.log | 0 .../testsuite/cargo_uninstall/help/stdout.log | 28 + .../cargo/tests/testsuite/cargo_uninstall/mod.rs | 1 + .../cargo/tests/testsuite/cargo_update/help/mod.rs | 13 + .../tests/testsuite/cargo_update/help/stderr.log | 0 .../tests/testsuite/cargo_update/help/stdout.log | 26 + .../cargo/tests/testsuite/cargo_update/mod.rs | 1 + .../cargo/tests/testsuite/cargo_vendor/help/mod.rs | 13 + .../tests/testsuite/cargo_vendor/help/stderr.log | 0 .../tests/testsuite/cargo_vendor/help/stdout.log | 27 + .../cargo/tests/testsuite/cargo_vendor/mod.rs | 1 + .../testsuite/cargo_verify_project/help/mod.rs | 13 + .../testsuite/cargo_verify_project/help/stderr.log | 0 .../testsuite/cargo_verify_project/help/stdout.log | 19 + .../tests/testsuite/cargo_verify_project/mod.rs | 1 + .../tests/testsuite/cargo_version/help/mod.rs | 13 + .../tests/testsuite/cargo_version/help/stderr.log | 0 .../tests/testsuite/cargo_version/help/stdout.log | 18 + .../cargo/tests/testsuite/cargo_version/mod.rs | 1 + .../cargo/tests/testsuite/cargo_yank/help/mod.rs | 13 + .../tests/testsuite/cargo_yank/help/stderr.log | 0 .../tests/testsuite/cargo_yank/help/stdout.log | 26 + src/tools/cargo/tests/testsuite/cargo_yank/mod.rs | 1 + .../cargo/tests/testsuite/credential_process.rs | 640 +++++--- src/tools/cargo/tests/testsuite/freshness.rs | 62 +- src/tools/cargo/tests/testsuite/init/auto_git/in | 1 - .../cargo/tests/testsuite/init/auto_git/mod.rs | 22 - .../tests/testsuite/init/auto_git/out/Cargo.toml | 8 - .../tests/testsuite/init/auto_git/out/src/lib.rs | 14 - .../cargo/tests/testsuite/init/auto_git/stderr.log | 1 - .../cargo/tests/testsuite/init/auto_git/stdout.log | 0 .../bin_already_exists_explicit/in/src/main.rs | 4 - .../init/bin_already_exists_explicit/mod.rs | 21 - .../bin_already_exists_explicit/out/Cargo.toml | 8 - .../bin_already_exists_explicit/out/src/main.rs | 4 - .../init/bin_already_exists_explicit/stderr.log | 1 - .../init/bin_already_exists_explicit/stdout.log | 0 .../bin_already_exists_explicit_nosrc/in/main.rs | 4 - .../init/bin_already_exists_explicit_nosrc/mod.rs | 22 - .../out/Cargo.toml | 12 - .../bin_already_exists_explicit_nosrc/out/main.rs | 4 - .../bin_already_exists_explicit_nosrc/stderr.log | 1 - .../bin_already_exists_explicit_nosrc/stdout.log | 0 .../bin_already_exists_implicit/in/src/main.rs | 4 - .../init/bin_already_exists_implicit/mod.rs | 21 - .../bin_already_exists_implicit/out/Cargo.toml | 8 - .../bin_already_exists_implicit/out/src/main.rs | 4 - .../init/bin_already_exists_implicit/stderr.log | 1 - .../init/bin_already_exists_implicit/stdout.log | 0 .../in/case.rs | 4 - .../bin_already_exists_implicit_namenosrc/mod.rs | 22 - .../out/Cargo.toml | 12 - .../out/case.rs | 4 - .../stderr.log | 1 - .../stdout.log | 0 .../in/src/case.rs | 4 - .../bin_already_exists_implicit_namesrc/mod.rs | 22 - .../out/Cargo.toml | 12 - .../out/src/case.rs | 4 - .../bin_already_exists_implicit_namesrc/stderr.log | 1 - .../bin_already_exists_implicit_namesrc/stdout.log | 0 .../bin_already_exists_implicit_nosrc/in/main.rs | 4 - .../init/bin_already_exists_implicit_nosrc/mod.rs | 22 - .../out/Cargo.toml | 12 - .../bin_already_exists_implicit_nosrc/out/main.rs | 4 - .../bin_already_exists_implicit_nosrc/stderr.log | 1 - .../bin_already_exists_implicit_nosrc/stdout.log | 0 .../tests/testsuite/init/both_lib_and_bin/mod.rs | 19 - .../testsuite/init/both_lib_and_bin/stderr.log | 1 - .../testsuite/init/both_lib_and_bin/stdout.log | 0 .../in/case.rs | 1 - .../in/lib.rs | 1 - .../mod.rs | 18 - .../stderr.log | 1 - .../stdout.log | 0 .../init/confused_by_multiple_lib_files/in/lib.rs | 1 - .../confused_by_multiple_lib_files/in/src/lib.rs | 1 - .../init/confused_by_multiple_lib_files/mod.rs | 22 - .../init/confused_by_multiple_lib_files/out/lib.rs | 1 - .../confused_by_multiple_lib_files/out/src/lib.rs | 1 - .../init/confused_by_multiple_lib_files/stderr.log | 1 - .../init/confused_by_multiple_lib_files/stdout.log | 0 .../in/case.rs | 1 - .../in/lib.rs | 1 - .../creates_binary_when_both_binlib_present/mod.rs | 21 - .../out/Cargo.toml | 16 - .../out/case.rs | 1 - .../out/lib.rs | 1 - .../stderr.log | 1 - .../stdout.log | 0 .../in/case.rs | 1 - .../mod.rs | 21 - .../out/Cargo.toml | 12 - .../out/case.rs | 1 - .../stderr.log | 2 - .../stdout.log | 0 .../in/case.rs | 1 - .../mod.rs | 21 - .../out/Cargo.toml | 12 - .../out/case.rs | 1 - .../stderr.log | 2 - .../stdout.log | 0 .../cargo/tests/testsuite/init/empty_dir/.keep | 0 .../cargo/tests/testsuite/init/empty_dir/mod.rs | 7 - .../tests/testsuite/init/explicit_bin_with_git/in | 1 - .../testsuite/init/explicit_bin_with_git/mod.rs | 21 - .../init/explicit_bin_with_git/out/Cargo.toml | 8 - .../init/explicit_bin_with_git/out/src/main.rs | 3 - .../init/explicit_bin_with_git/stderr.log | 1 - .../init/explicit_bin_with_git/stdout.log | 0 .../testsuite/init/formats_source/in/rustfmt.toml | 1 - .../tests/testsuite/init/formats_source/mod.rs | 29 - .../testsuite/init/formats_source/out/Cargo.toml | 8 - .../testsuite/init/formats_source/out/rustfmt.toml | 1 - .../testsuite/init/formats_source/out/src/lib.rs | 14 - .../tests/testsuite/init/formats_source/stderr.log | 1 - .../tests/testsuite/init/formats_source/stdout.log | 0 .../init/fossil_autodetect/in/.fossil/.keep | 0 .../tests/testsuite/init/fossil_autodetect/mod.rs | 22 - .../out/.fossil-settings/clean-glob | 2 - .../out/.fossil-settings/ignore-glob | 2 - .../init/fossil_autodetect/out/Cargo.toml | 8 - .../init/fossil_autodetect/out/src/lib.rs | 14 - .../testsuite/init/fossil_autodetect/stderr.log | 1 - .../testsuite/init/fossil_autodetect/stdout.log | 0 .../tests/testsuite/init/git_autodetect/mod.rs | 24 - .../testsuite/init/git_autodetect/out/Cargo.toml | 8 - .../testsuite/init/git_autodetect/out/src/lib.rs | 14 - .../tests/testsuite/init/git_autodetect/stderr.log | 1 - .../tests/testsuite/init/git_autodetect/stdout.log | 0 .../mod.rs | 22 - .../out/Cargo.toml | 8 - .../out/src/lib.rs | 14 - .../stderr.log | 1 - .../stdout.log | 0 .../in/rustfmt.toml | 1 - .../init/ignores_failure_to_format_source/mod.rs | 22 - .../out/Cargo.toml | 8 - .../out/rustfmt.toml | 1 - .../out/src/lib.rs | 14 - .../ignores_failure_to_format_source/stderr.log | 1 - .../ignores_failure_to_format_source/stdout.log | 0 .../init/inferred_bin_with_git/in/main.rs | 1 - .../testsuite/init/inferred_bin_with_git/mod.rs | 21 - .../init/inferred_bin_with_git/out/Cargo.toml | 12 - .../init/inferred_bin_with_git/out/main.rs | 1 - .../init/inferred_bin_with_git/stderr.log | 1 - .../init/inferred_bin_with_git/stdout.log | 0 .../testsuite/init/inferred_lib_with_git/in/lib.rs | 1 - .../testsuite/init/inferred_lib_with_git/mod.rs | 21 - .../init/inferred_lib_with_git/out/Cargo.toml | 12 - .../init/inferred_lib_with_git/out/lib.rs | 1 - .../init/inferred_lib_with_git/stderr.log | 1 - .../init/inferred_lib_with_git/stdout.log | 0 .../inherit_workspace_package_table/in/Cargo.toml | 21 - .../inherit_workspace_package_table/in/README.md | 0 .../in/crates/foo/src/main.rs | 3 - .../inherit_workspace_package_table/in/src/lib.rs | 14 - .../init/inherit_workspace_package_table/mod.rs | 22 - .../inherit_workspace_package_table/out/Cargo.toml | 21 - .../out/crates/foo/Cargo.toml | 21 - .../out/crates/foo/src/main.rs | 3 - .../inherit_workspace_package_table/out/src/lib.rs | 14 - .../inherit_workspace_package_table/stderr.log | 1 - .../inherit_workspace_package_table/stdout.log | 0 .../tests/testsuite/init/invalid_dir_name/mod.rs | 21 - .../testsuite/init/invalid_dir_name/stderr.log | 8 - .../testsuite/init/invalid_dir_name/stdout.log | 0 .../init/lib_already_exists_nosrc/in/lib.rs | 0 .../testsuite/init/lib_already_exists_nosrc/mod.rs | 22 - .../init/lib_already_exists_nosrc/out/Cargo.toml | 12 - .../init/lib_already_exists_nosrc/out/lib.rs | 0 .../init/lib_already_exists_nosrc/stderr.log | 1 - .../init/lib_already_exists_nosrc/stdout.log | 0 .../init/lib_already_exists_src/in/src/lib.rs | 1 - .../testsuite/init/lib_already_exists_src/mod.rs | 22 - .../init/lib_already_exists_src/out/Cargo.toml | 8 - .../init/lib_already_exists_src/out/src/lib.rs | 1 - .../init/lib_already_exists_src/stderr.log | 1 - .../init/lib_already_exists_src/stdout.log | 0 .../testsuite/init/mercurial_autodetect/mod.rs | 22 - .../init/mercurial_autodetect/out/Cargo.toml | 8 - .../init/mercurial_autodetect/out/src/lib.rs | 14 - .../testsuite/init/mercurial_autodetect/stderr.log | 1 - .../testsuite/init/mercurial_autodetect/stdout.log | 0 src/tools/cargo/tests/testsuite/init/mod.rs | 43 - .../init/multibin_project_name_clash/in/case.rs | 1 - .../init/multibin_project_name_clash/in/main.rs | 1 - .../init/multibin_project_name_clash/mod.rs | 22 - .../init/multibin_project_name_clash/out/case.rs | 1 - .../init/multibin_project_name_clash/out/main.rs | 1 - .../init/multibin_project_name_clash/stderr.log | 4 - .../init/multibin_project_name_clash/stdout.log | 0 .../cargo/tests/testsuite/init/no_filename/mod.rs | 16 - .../tests/testsuite/init/no_filename/stderr.log | 1 - .../tests/testsuite/init/no_filename/stdout.log | 0 .../init/path_contains_separator/in/.keep | 0 .../testsuite/init/path_contains_separator/mod.rs | 26 - .../init/path_contains_separator/out/Cargo.toml | 8 - .../init/path_contains_separator/out/src/main.rs | 3 - .../init/path_contains_separator/stderr.log | 3 - .../init/path_contains_separator/stdout.log | 0 .../init/pijul_autodetect/in/.pijul/.keep | 0 .../tests/testsuite/init/pijul_autodetect/mod.rs | 22 - .../testsuite/init/pijul_autodetect/out/.ignore | 2 - .../testsuite/init/pijul_autodetect/out/Cargo.toml | 8 - .../testsuite/init/pijul_autodetect/out/src/lib.rs | 14 - .../testsuite/init/pijul_autodetect/stderr.log | 1 - .../testsuite/init/pijul_autodetect/stdout.log | 0 .../tests/testsuite/init/reserved_name/mod.rs | 21 - .../tests/testsuite/init/reserved_name/stderr.log | 8 - .../tests/testsuite/init/reserved_name/stdout.log | 0 src/tools/cargo/tests/testsuite/init/simple_bin/in | 1 - .../cargo/tests/testsuite/init/simple_bin/mod.rs | 29 - .../tests/testsuite/init/simple_bin/out/Cargo.toml | 8 - .../testsuite/init/simple_bin/out/src/main.rs | 3 - .../tests/testsuite/init/simple_bin/stderr.log | 1 - .../tests/testsuite/init/simple_bin/stdout.log | 0 src/tools/cargo/tests/testsuite/init/simple_git/in | 1 - .../cargo/tests/testsuite/init/simple_git/mod.rs | 22 - .../tests/testsuite/init/simple_git/out/Cargo.toml | 8 - .../tests/testsuite/init/simple_git/out/src/lib.rs | 14 - .../tests/testsuite/init/simple_git/stderr.log | 1 - .../tests/testsuite/init/simple_git/stdout.log | 0 .../testsuite/init/simple_git_ignore_exists/mod.rs | 28 - .../init/simple_git_ignore_exists/out/Cargo.toml | 8 - .../init/simple_git_ignore_exists/out/src/lib.rs | 14 - .../init/simple_git_ignore_exists/stderr.log | 1 - .../init/simple_git_ignore_exists/stdout.log | 0 src/tools/cargo/tests/testsuite/init/simple_hg/in | 1 - .../cargo/tests/testsuite/init/simple_hg/mod.rs | 22 - .../tests/testsuite/init/simple_hg/out/Cargo.toml | 8 - .../tests/testsuite/init/simple_hg/out/src/lib.rs | 14 - .../tests/testsuite/init/simple_hg/stderr.log | 1 - .../tests/testsuite/init/simple_hg/stdout.log | 0 .../testsuite/init/simple_hg_ignore_exists/mod.rs | 22 - .../init/simple_hg_ignore_exists/out/Cargo.toml | 8 - .../init/simple_hg_ignore_exists/out/src/lib.rs | 14 - .../init/simple_hg_ignore_exists/stderr.log | 1 - .../init/simple_hg_ignore_exists/stdout.log | 0 src/tools/cargo/tests/testsuite/init/simple_lib/in | 1 - .../cargo/tests/testsuite/init/simple_lib/mod.rs | 29 - .../tests/testsuite/init/simple_lib/out/Cargo.toml | 8 - .../tests/testsuite/init/simple_lib/out/src/lib.rs | 14 - .../tests/testsuite/init/simple_lib/stderr.log | 1 - .../tests/testsuite/init/simple_lib/stdout.log | 0 .../tests/testsuite/init/unknown_flags/mod.rs | 15 - .../tests/testsuite/init/unknown_flags/stderr.log | 7 - .../tests/testsuite/init/unknown_flags/stdout.log | 0 .../testsuite/init/with_argument/in/foo/.keep | 0 .../tests/testsuite/init/with_argument/mod.rs | 21 - .../init/with_argument/out/foo/Cargo.toml | 8 - .../init/with_argument/out/foo/src/main.rs | 3 - .../tests/testsuite/init/with_argument/stderr.log | 1 - .../tests/testsuite/init/with_argument/stdout.log | 0 src/tools/cargo/tests/testsuite/lints.rs | 55 + src/tools/cargo/tests/testsuite/lockfile_compat.rs | 195 +++ src/tools/cargo/tests/testsuite/login.rs | 188 +-- src/tools/cargo/tests/testsuite/main.rs | 36 +- src/tools/cargo/tests/testsuite/owner.rs | 8 +- src/tools/cargo/tests/testsuite/package.rs | 112 ++ src/tools/cargo/tests/testsuite/profile_targets.rs | 8 +- src/tools/cargo/tests/testsuite/publish.rs | 10 +- src/tools/cargo/tests/testsuite/registry.rs | 35 + src/tools/cargo/tests/testsuite/registry_auth.rs | 96 +- src/tools/cargo/tests/testsuite/run.rs | 22 +- src/tools/cargo/tests/testsuite/script.rs | 158 +- src/tools/cargo/tests/testsuite/test.rs | 71 +- src/tools/cargo/tests/testsuite/update.rs | 40 + src/tools/cargo/tests/testsuite/yank.rs | 8 +- src/tools/clippy/.github/workflows/clippy.yml | 2 +- src/tools/clippy/.github/workflows/clippy_bors.yml | 31 +- src/tools/clippy/CHANGELOG.md | 197 ++- src/tools/clippy/Cargo.toml | 13 +- src/tools/clippy/README.md | 2 +- src/tools/clippy/book/src/README.md | 2 +- .../development/infrastructure/changelog_update.md | 22 - src/tools/clippy/book/src/development/speedtest.md | 24 + src/tools/clippy/book/src/lint_configuration.md | 23 +- src/tools/clippy/clippy_dev/src/lib.rs | 2 +- src/tools/clippy/clippy_dev/src/main.rs | 2 +- src/tools/clippy/clippy_dev/src/new_lint.rs | 26 +- src/tools/clippy/clippy_dev/src/setup/intellij.rs | 2 +- src/tools/clippy/clippy_dev/src/setup/vscode.rs | 2 +- src/tools/clippy/clippy_dev/src/update_lints.rs | 5 +- src/tools/clippy/clippy_lints/Cargo.toml | 2 +- .../clippy/clippy_lints/src/absolute_paths.rs | 100 ++ .../clippy/clippy_lints/src/allow_attributes.rs | 3 +- .../clippy_lints/src/arc_with_non_send_sync.rs | 15 +- .../clippy_lints/src/assertions_on_constants.rs | 12 +- .../src/assertions_on_result_states.rs | 6 +- src/tools/clippy/clippy_lints/src/attrs.rs | 6 +- .../clippy_lints/src/blocks_in_if_conditions.rs | 6 +- .../clippy_lints/src/bool_assert_comparison.rs | 14 +- .../clippy/clippy_lints/src/bool_to_int_with_if.rs | 4 +- .../clippy/clippy_lints/src/borrow_deref_ref.rs | 3 +- src/tools/clippy/clippy_lints/src/box_default.rs | 14 +- .../clippy_lints/src/casts/as_ptr_cast_mut.rs | 8 +- .../clippy_lints/src/casts/cast_ptr_alignment.rs | 2 +- .../src/casts/cast_slice_different_sizes.rs | 6 +- .../src/casts/cast_slice_from_raw_parts.rs | 3 +- src/tools/clippy/clippy_lints/src/casts/mod.rs | 8 + .../clippy/clippy_lints/src/casts/ptr_as_ptr.rs | 64 +- .../clippy_lints/src/casts/ptr_cast_constness.rs | 4 +- .../clippy_lints/src/casts/unnecessary_cast.rs | 26 +- src/tools/clippy/clippy_lints/src/copies.rs | 3 +- src/tools/clippy/clippy_lints/src/copy_iterator.rs | 2 +- .../clippy/clippy_lints/src/crate_in_macro_def.rs | 3 +- src/tools/clippy/clippy_lints/src/dbg_macro.rs | 4 +- .../clippy/clippy_lints/src/declared_lints.rs | 23 +- src/tools/clippy/clippy_lints/src/default.rs | 8 +- .../src/default_constructed_unit_structs.rs | 6 +- .../src/default_instead_of_iter_empty.rs | 3 +- .../clippy_lints/src/default_numeric_fallback.rs | 20 +- src/tools/clippy/clippy_lints/src/dereference.rs | 1070 +++++-------- .../clippy/clippy_lints/src/derivable_impls.rs | 26 +- src/tools/clippy/clippy_lints/src/derive.rs | 38 +- .../clippy/clippy_lints/src/disallowed_methods.rs | 2 +- .../clippy/clippy_lints/src/disallowed_names.rs | 3 +- src/tools/clippy/clippy_lints/src/doc.rs | 33 +- .../clippy/clippy_lints/src/drop_forget_ref.rs | 3 +- src/tools/clippy/clippy_lints/src/empty_drop.rs | 3 +- src/tools/clippy/clippy_lints/src/empty_enum.rs | 2 +- .../src/empty_structs_with_brackets.rs | 3 +- src/tools/clippy/clippy_lints/src/endian_bytes.rs | 6 +- src/tools/clippy/clippy_lints/src/entry.rs | 33 +- src/tools/clippy/clippy_lints/src/enum_clike.rs | 2 +- .../clippy/clippy_lints/src/error_impl_error.rs | 87 ++ src/tools/clippy/clippy_lints/src/escape.rs | 3 +- src/tools/clippy/clippy_lints/src/eta_reduction.rs | 337 ++-- .../clippy/clippy_lints/src/excessive_nesting.rs | 11 +- .../clippy/clippy_lints/src/explicit_write.rs | 2 +- .../src/extra_unused_type_parameters.rs | 9 +- .../clippy_lints/src/floating_point_arithmetic.rs | 10 +- src/tools/clippy/clippy_lints/src/fn_null_check.rs | 102 -- src/tools/clippy/clippy_lints/src/format.rs | 4 +- src/tools/clippy/clippy_lints/src/format_args.rs | 10 +- src/tools/clippy/clippy_lints/src/format_impl.rs | 8 +- .../clippy_lints/src/four_forward_slashes.rs | 99 ++ .../clippy/clippy_lints/src/from_over_into.rs | 16 +- .../clippy_lints/src/from_raw_with_void_ptr.rs | 3 +- .../src/functions/impl_trait_in_params.rs | 6 +- .../clippy_lints/src/functions/misnamed_getters.rs | 19 +- .../clippy/clippy_lints/src/functions/must_use.rs | 17 +- .../clippy/clippy_lints/src/functions/result.rs | 6 +- .../clippy_lints/src/functions/too_many_lines.rs | 2 +- .../clippy/clippy_lints/src/future_not_send.rs | 4 +- src/tools/clippy/clippy_lints/src/if_let_mutex.rs | 3 +- .../clippy_lints/src/if_then_some_else_none.rs | 8 +- .../clippy_lints/src/ignored_unit_patterns.rs | 52 + .../clippy/clippy_lints/src/implicit_return.rs | 10 +- .../clippy_lints/src/implicit_saturating_sub.rs | 4 +- .../clippy/clippy_lints/src/incorrect_impls.rs | 213 ++- .../clippy_lints/src/index_refutable_slice.rs | 5 +- .../clippy/clippy_lints/src/indexing_slicing.rs | 2 +- src/tools/clippy/clippy_lints/src/inherent_impl.rs | 5 +- .../clippy/clippy_lints/src/inherent_to_string.rs | 35 +- .../clippy_lints/src/init_numbered_fields.rs | 4 +- .../clippy/clippy_lints/src/instant_subtraction.rs | 3 +- .../clippy_lints/src/items_after_test_module.rs | 5 +- .../src/iter_not_returning_iterator.rs | 9 +- .../clippy/clippy_lints/src/large_const_arrays.rs | 6 +- .../clippy/clippy_lints/src/large_enum_variant.rs | 12 +- src/tools/clippy/clippy_lints/src/large_futures.rs | 3 +- .../clippy/clippy_lints/src/large_include_file.rs | 3 +- .../clippy/clippy_lints/src/large_stack_frames.rs | 6 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 50 +- src/tools/clippy/clippy_lints/src/let_if_seq.rs | 3 +- .../clippy/clippy_lints/src/let_underscore.rs | 6 +- src/tools/clippy/clippy_lints/src/lib.rs | 41 +- src/tools/clippy/clippy_lints/src/lifetimes.rs | 3 +- .../clippy/clippy_lints/src/lines_filter_map_ok.rs | 7 +- .../clippy_lints/src/literal_representation.rs | 4 +- .../clippy_lints/src/loops/explicit_iter_loop.rs | 4 +- .../clippy/clippy_lints/src/loops/manual_find.rs | 14 +- .../clippy_lints/src/loops/manual_flatten.rs | 3 +- .../clippy/clippy_lints/src/loops/manual_memcpy.rs | 4 +- .../src/loops/manual_while_let_some.rs | 9 +- .../clippy_lints/src/loops/missing_spin_loop.rs | 4 +- src/tools/clippy/clippy_lints/src/loops/mod.rs | 2 +- .../clippy_lints/src/loops/mut_range_bound.rs | 3 +- .../clippy_lints/src/loops/needless_range_loop.rs | 4 +- .../clippy/clippy_lints/src/loops/never_loop.rs | 8 +- .../clippy_lints/src/loops/single_element_loop.rs | 3 +- src/tools/clippy/clippy_lints/src/loops/utils.rs | 4 +- .../src/loops/while_immutable_condition.rs | 3 +- .../src/loops/while_let_on_iterator.rs | 16 +- src/tools/clippy/clippy_lints/src/macro_use.rs | 3 +- src/tools/clippy/clippy_lints/src/manual_bits.rs | 2 +- src/tools/clippy/clippy_lints/src/manual_clamp.rs | 14 +- .../clippy_lints/src/manual_float_methods.rs | 175 +++ .../clippy_lints/src/manual_is_ascii_check.rs | 8 +- .../clippy/clippy_lints/src/manual_let_else.rs | 49 +- .../clippy_lints/src/manual_range_patterns.rs | 31 +- .../clippy/clippy_lints/src/manual_rem_euclid.rs | 2 +- .../src/manual_slice_size_calculation.rs | 2 +- src/tools/clippy/clippy_lints/src/manual_strip.rs | 5 +- src/tools/clippy/clippy_lints/src/map_unit_fn.rs | 8 +- .../clippy/clippy_lints/src/match_result_ok.rs | 3 +- .../src/matches/infallible_destructuring_match.rs | 2 +- .../clippy_lints/src/matches/manual_filter.rs | 2 +- .../clippy/clippy_lints/src/matches/manual_map.rs | 2 +- .../clippy_lints/src/matches/manual_utils.rs | 9 +- .../clippy_lints/src/matches/match_as_ref.rs | 10 +- .../clippy_lints/src/matches/match_like_matches.rs | 6 +- .../clippy_lints/src/matches/match_on_vec_items.rs | 6 +- .../clippy_lints/src/matches/match_same_arms.rs | 5 +- .../clippy_lints/src/matches/match_wild_enum.rs | 4 +- src/tools/clippy/clippy_lints/src/matches/mod.rs | 39 +- .../clippy_lints/src/matches/redundant_guards.rs | 196 +++ .../src/matches/redundant_pattern_match.rs | 152 +- .../src/matches/rest_pat_in_fully_bound_struct.rs | 2 +- .../src/matches/significant_drop_in_scrutinee.rs | 3 +- .../clippy_lints/src/matches/single_match.rs | 2 +- .../clippy/clippy_lints/src/matches/try_err.rs | 4 +- .../src/methods/bind_instead_of_map.rs | 7 +- .../clippy/clippy_lints/src/methods/bytecount.rs | 2 +- .../clippy_lints/src/methods/bytes_count_to_len.rs | 2 +- .../case_sensitive_file_extension_comparisons.rs | 8 +- .../clippy/clippy_lints/src/methods/chars_cmp.rs | 3 +- .../src/methods/chars_cmp_with_unwrap.rs | 3 +- .../clippy_lints/src/methods/clone_on_copy.rs | 6 +- .../clippy_lints/src/methods/clone_on_ref_ptr.rs | 2 +- .../src/methods/collapsible_str_replace.rs | 3 +- .../clippy_lints/src/methods/drain_collect.rs | 9 +- .../clippy/clippy_lints/src/methods/err_expect.rs | 5 +- .../clippy_lints/src/methods/expect_fun_call.rs | 8 +- .../clippy/clippy_lints/src/methods/expect_used.rs | 44 - .../clippy_lints/src/methods/extend_with_drain.rs | 2 +- .../clippy/clippy_lints/src/methods/filter_map.rs | 324 +++- .../src/methods/filter_map_bool_then.rs | 53 + .../src/methods/filter_map_identity.rs | 3 +- .../clippy_lints/src/methods/filter_map_next.rs | 2 +- .../clippy/clippy_lints/src/methods/filter_next.rs | 51 +- .../clippy_lints/src/methods/flat_map_identity.rs | 3 +- .../clippy_lints/src/methods/flat_map_option.rs | 5 +- .../clippy_lints/src/methods/format_collect.rs | 33 + .../clippy/clippy_lints/src/methods/get_first.rs | 2 +- .../clippy/clippy_lints/src/methods/get_unwrap.rs | 2 +- .../clippy_lints/src/methods/implicit_clone.rs | 2 +- .../src/methods/inefficient_to_string.rs | 10 +- .../clippy_lints/src/methods/inspect_for_each.rs | 3 +- .../src/methods/is_digit_ascii_radix.rs | 6 +- .../clippy/clippy_lints/src/methods/iter_kv_map.rs | 3 +- .../clippy_lints/src/methods/iter_next_slice.rs | 2 +- .../src/methods/iter_overeager_cloned.rs | 2 +- .../clippy_lints/src/methods/iter_skip_next.rs | 3 +- .../clippy_lints/src/methods/iter_skip_zero.rs | 34 + .../clippy_lints/src/methods/iter_with_drain.rs | 2 +- .../clippy_lints/src/methods/manual_ok_or.rs | 2 +- .../src/methods/manual_saturating_arithmetic.rs | 10 +- .../clippy_lints/src/methods/manual_str_repeat.rs | 2 +- .../clippy_lints/src/methods/manual_try_fold.rs | 18 +- .../clippy/clippy_lints/src/methods/map_clone.rs | 2 +- .../src/methods/map_collect_result_unit.rs | 6 +- .../clippy_lints/src/methods/map_err_ignore.rs | 2 +- .../clippy/clippy_lints/src/methods/map_flatten.rs | 5 +- .../clippy_lints/src/methods/map_identity.rs | 3 +- .../clippy_lints/src/methods/map_unwrap_or.rs | 5 +- src/tools/clippy/clippy_lints/src/methods/mod.rs | 351 ++++- .../clippy_lints/src/methods/mut_mutex_lock.rs | 5 +- .../clippy_lints/src/methods/needless_collect.rs | 19 +- .../src/methods/needless_option_as_deref.rs | 6 +- .../clippy_lints/src/methods/obfuscated_if_else.rs | 3 +- .../clippy/clippy_lints/src/methods/ok_expect.rs | 2 +- .../clippy_lints/src/methods/open_options.rs | 2 +- .../clippy_lints/src/methods/option_map_or_none.rs | 3 +- .../src/methods/option_map_unwrap_or.rs | 9 +- .../clippy/clippy_lints/src/methods/or_fun_call.rs | 124 +- .../clippy_lints/src/methods/or_then_unwrap.rs | 8 +- .../src/methods/path_buf_push_overwrite.rs | 2 +- .../clippy_lints/src/methods/range_zip_with_len.rs | 3 +- .../src/methods/read_line_without_trim.rs | 74 + .../src/methods/readonly_write_lock.rs | 52 + .../clippy_lints/src/methods/seek_from_current.rs | 8 +- .../src/methods/stable_sort_primitive.rs | 2 +- .../clippy/clippy_lints/src/methods/str_splitn.rs | 6 +- .../src/methods/string_extend_chars.rs | 2 +- .../src/methods/string_lit_chars_any.rs | 58 + .../src/methods/suspicious_command_arg_space.rs | 3 +- .../clippy_lints/src/methods/suspicious_splitn.rs | 2 +- .../src/methods/suspicious_to_owned.rs | 3 +- .../clippy_lints/src/methods/type_id_on_box.rs | 62 + .../src/methods/uninit_assumed_init.rs | 3 +- .../src/methods/unnecessary_filter_map.rs | 13 +- .../clippy_lints/src/methods/unnecessary_fold.rs | 3 +- .../src/methods/unnecessary_iter_cloned.rs | 3 +- .../clippy_lints/src/methods/unnecessary_join.rs | 3 +- .../src/methods/unnecessary_literal_unwrap.rs | 24 +- .../src/methods/unnecessary_sort_by.rs | 4 +- .../src/methods/unnecessary_to_owned.rs | 54 +- .../clippy_lints/src/methods/unwrap_expect_used.rs | 83 + .../src/methods/unwrap_or_else_default.rs | 66 - .../clippy/clippy_lints/src/methods/unwrap_used.rs | 53 - .../clippy_lints/src/methods/useless_asref.rs | 2 +- src/tools/clippy/clippy_lints/src/methods/utils.rs | 2 +- .../clippy_lints/src/methods/vec_resize_to_zero.rs | 2 +- .../clippy/clippy_lints/src/min_ident_chars.rs | 21 +- .../clippy_lints/src/missing_assert_message.rs | 12 +- .../src/missing_enforced_import_rename.rs | 7 +- .../clippy_lints/src/missing_fields_in_debug.rs | 20 +- .../clippy/clippy_lints/src/missing_inline.rs | 1 - .../src/mixed_read_write_in_expression.rs | 2 +- src/tools/clippy/clippy_lints/src/module_style.rs | 4 +- .../src/multiple_unsafe_ops_per_block.rs | 12 +- src/tools/clippy/clippy_lints/src/mut_key.rs | 6 +- src/tools/clippy/clippy_lints/src/mut_reference.rs | 9 +- .../clippy_lints/src/mutable_debug_assertion.rs | 8 +- src/tools/clippy/clippy_lints/src/needless_bool.rs | 8 +- .../clippy_lints/src/needless_borrowed_ref.rs | 4 +- src/tools/clippy/clippy_lints/src/needless_else.rs | 6 +- .../clippy/clippy_lints/src/needless_for_each.rs | 11 +- src/tools/clippy/clippy_lints/src/needless_if.rs | 5 +- .../clippy/clippy_lints/src/needless_late_init.rs | 4 +- .../src/needless_parens_on_range_literals.rs | 8 +- .../clippy_lints/src/needless_pass_by_ref_mut.rs | 441 ++++++ .../clippy_lints/src/needless_pass_by_value.rs | 24 +- .../clippy_lints/src/needless_question_mark.rs | 2 +- .../clippy/clippy_lints/src/new_without_default.rs | 6 +- src/tools/clippy/clippy_lints/src/no_effect.rs | 7 +- .../clippy/clippy_lints/src/non_copy_const.rs | 75 +- .../clippy_lints/src/non_expressive_names.rs | 8 +- .../clippy_lints/src/non_send_fields_in_send_ty.rs | 14 +- .../clippy_lints/src/nonstandard_macro_braces.rs | 6 +- .../clippy_lints/src/only_used_in_recursion.rs | 19 +- .../src/operators/arithmetic_side_effects.rs | 36 +- .../src/operators/assign_op_pattern.rs | 3 +- .../clippy/clippy_lints/src/operators/bit_mask.rs | 6 +- .../src/operators/const_comparisons.rs | 207 +++ .../clippy/clippy_lints/src/operators/eq_op.rs | 3 +- .../src/operators/misrefactored_assign_op.rs | 3 +- src/tools/clippy/clippy_lints/src/operators/mod.rs | 43 + .../clippy/clippy_lints/src/operators/op_ref.rs | 4 +- .../clippy/clippy_lints/src/option_env_unwrap.rs | 39 +- .../clippy/clippy_lints/src/option_if_let_else.rs | 7 +- .../clippy/clippy_lints/src/panic_in_result_fn.rs | 10 +- .../clippy/clippy_lints/src/panic_unimplemented.rs | 4 +- .../clippy/clippy_lints/src/partialeq_to_none.rs | 7 +- .../clippy_lints/src/pass_by_ref_or_value.rs | 5 +- src/tools/clippy/clippy_lints/src/ptr.rs | 41 +- .../clippy_lints/src/ptr_offset_with_cast.rs | 4 +- src/tools/clippy/clippy_lints/src/question_mark.rs | 72 +- .../clippy/clippy_lints/src/question_mark_used.rs | 2 +- src/tools/clippy/clippy_lints/src/ranges.rs | 3 +- src/tools/clippy/clippy_lints/src/raw_strings.rs | 14 +- .../clippy_lints/src/rc_clone_in_vec_init.rs | 15 +- .../clippy/clippy_lints/src/read_zero_byte_vec.rs | 10 +- .../clippy_lints/src/redundant_async_block.rs | 13 +- .../clippy_lints/src/redundant_closure_call.rs | 5 +- .../clippy/clippy_lints/src/redundant_locals.rs | 126 ++ .../clippy/clippy_lints/src/redundant_slicing.rs | 7 +- .../clippy_lints/src/redundant_static_lifetimes.rs | 3 +- src/tools/clippy/clippy_lints/src/reference.rs | 2 +- src/tools/clippy/clippy_lints/src/regex.rs | 66 +- src/tools/clippy/clippy_lints/src/renamed_lints.rs | 2 + src/tools/clippy/clippy_lints/src/returns.rs | 90 +- .../clippy_lints/src/self_named_constructors.rs | 2 +- .../clippy/clippy_lints/src/semicolon_block.rs | 10 +- .../src/semicolon_if_nothing_returned.rs | 2 +- src/tools/clippy/clippy_lints/src/shadow.rs | 4 +- .../src/significant_drop_tightening.rs | 65 +- .../clippy/clippy_lints/src/single_call_fn.rs | 4 +- .../src/single_component_path_imports.rs | 7 +- .../clippy_lints/src/single_range_in_vec_init.rs | 10 +- .../clippy_lints/src/size_of_in_element_count.rs | 7 +- src/tools/clippy/clippy_lints/src/size_of_ref.rs | 4 +- .../clippy_lints/src/slow_vector_initialization.rs | 133 +- .../clippy/clippy_lints/src/std_instead_of_core.rs | 6 +- src/tools/clippy/clippy_lints/src/strings.rs | 12 +- .../clippy/clippy_lints/src/strlen_on_c_strings.rs | 2 +- .../clippy_lints/src/suspicious_doc_comments.rs | 3 +- .../src/suspicious_operation_groupings.rs | 2 +- .../clippy_lints/src/suspicious_xor_used_as_pow.rs | 49 +- src/tools/clippy/clippy_lints/src/swap.rs | 8 +- .../clippy_lints/src/temporary_assignment.rs | 2 +- .../clippy_lints/src/tests_outside_test_module.rs | 9 +- .../clippy/clippy_lints/src/to_digit_is_some.rs | 2 +- .../src/transmute/transmute_int_to_non_zero.rs | 6 +- .../src/transmute/transmute_ptr_to_ptr.rs | 2 +- .../src/transmute/transmute_undefined_repr.rs | 9 +- .../transmutes_expressible_as_ptr_casts.rs | 3 +- .../src/transmute/unsound_collection_transmute.rs | 6 +- .../src/transmute/useless_transmute.rs | 2 +- .../clippy/clippy_lints/src/transmute/utils.rs | 3 +- .../clippy_lints/src/tuple_array_conversions.rs | 324 ++-- .../clippy/clippy_lints/src/types/borrowed_box.rs | 5 +- .../clippy_lints/src/types/box_collection.rs | 3 +- .../clippy/clippy_lints/src/types/linked_list.rs | 3 +- src/tools/clippy/clippy_lints/src/types/mod.rs | 2 +- .../clippy/clippy_lints/src/types/option_option.rs | 3 +- .../clippy/clippy_lints/src/types/rc_buffer.rs | 7 +- .../clippy/clippy_lints/src/types/rc_mutex.rs | 3 +- .../clippy_lints/src/types/redundant_allocation.rs | 9 +- src/tools/clippy/clippy_lints/src/types/vec_box.rs | 3 +- .../clippy_lints/src/undocumented_unsafe_blocks.rs | 11 +- src/tools/clippy/clippy_lints/src/uninit_vec.rs | 4 +- .../clippy_lints/src/unit_return_expecting_ord.rs | 8 +- .../clippy_lints/src/unit_types/let_unit_value.rs | 2 +- .../clippy/clippy_lints/src/unit_types/unit_arg.rs | 2 +- .../clippy/clippy_lints/src/unit_types/unit_cmp.rs | 4 +- .../clippy/clippy_lints/src/unnamed_address.rs | 2 +- .../clippy_lints/src/unnecessary_box_returns.rs | 26 +- .../src/unnecessary_owned_empty_strings.rs | 3 +- .../src/unnecessary_struct_initialization.rs | 5 +- .../clippy/clippy_lints/src/unnecessary_wraps.rs | 3 +- .../clippy_lints/src/unnested_or_patterns.rs | 7 +- src/tools/clippy/clippy_lints/src/unused_async.rs | 108 +- .../clippy/clippy_lints/src/unused_io_amount.rs | 2 +- src/tools/clippy/clippy_lints/src/unused_unit.rs | 3 +- src/tools/clippy/clippy_lints/src/unwrap.rs | 4 +- src/tools/clippy/clippy_lints/src/use_self.rs | 21 +- .../clippy/clippy_lints/src/useless_conversion.rs | 15 +- src/tools/clippy/clippy_lints/src/utils/author.rs | 2 +- src/tools/clippy/clippy_lints/src/utils/conf.rs | 12 +- .../src/utils/format_args_collector.rs | 4 +- .../src/utils/internal_lints/if_chain_style.rs | 4 +- .../internal_lints/interning_defined_symbol.rs | 2 +- .../src/utils/internal_lints/invalid_paths.rs | 13 +- .../utils/internal_lints/lint_without_lint_pass.rs | 3 +- .../src/utils/internal_lints/metadata_collector.rs | 19 +- .../src/utils/internal_lints/msrv_attr_impl.rs | 4 +- .../utils/internal_lints/unnecessary_def_path.rs | 4 +- src/tools/clippy/clippy_lints/src/utils/mod.rs | 2 +- src/tools/clippy/clippy_lints/src/vec.rs | 10 +- .../clippy/clippy_lints/src/vec_init_then_push.rs | 4 +- src/tools/clippy/clippy_lints/src/visibility.rs | 6 +- .../clippy/clippy_lints/src/wildcard_imports.rs | 6 +- src/tools/clippy/clippy_lints/src/write.rs | 22 +- .../clippy_lints/src/zero_sized_map_values.rs | 4 +- src/tools/clippy/clippy_test_deps/Cargo.toml | 23 - src/tools/clippy/clippy_test_deps/src/lib.rs | 14 - src/tools/clippy/clippy_utils/Cargo.toml | 2 +- src/tools/clippy/clippy_utils/src/ast_utils.rs | 12 +- src/tools/clippy/clippy_utils/src/attrs.rs | 7 +- .../clippy/clippy_utils/src/check_proc_macro.rs | 24 +- src/tools/clippy/clippy_utils/src/comparisons.rs | 4 +- src/tools/clippy/clippy_utils/src/consts.rs | 32 +- src/tools/clippy/clippy_utils/src/eager_or_lazy.rs | 39 +- src/tools/clippy/clippy_utils/src/higher.rs | 9 +- src/tools/clippy/clippy_utils/src/hir_utils.rs | 32 +- src/tools/clippy/clippy_utils/src/lib.rs | 420 ++++- src/tools/clippy/clippy_utils/src/macros.rs | 20 +- .../clippy_utils/src/mir/possible_borrower.rs | 12 +- .../clippy/clippy_utils/src/mir/possible_origin.rs | 2 +- src/tools/clippy/clippy_utils/src/paths.rs | 16 +- .../clippy_utils/src/qualify_min_const_fn.rs | 66 +- src/tools/clippy/clippy_utils/src/source.rs | 3 +- src/tools/clippy/clippy_utils/src/sugg.rs | 8 +- src/tools/clippy/clippy_utils/src/ty.rs | 282 ++-- .../src/ty/type_certainty/certainty.rs | 122 ++ .../clippy_utils/src/ty/type_certainty/mod.rs | 320 ++++ src/tools/clippy/clippy_utils/src/usage.rs | 55 +- src/tools/clippy/clippy_utils/src/visitors.rs | 16 +- src/tools/clippy/declare_clippy_lint/Cargo.toml | 2 +- src/tools/clippy/lintcheck/src/config.rs | 3 +- src/tools/clippy/lintcheck/src/main.rs | 4 +- src/tools/clippy/lintcheck/src/recursive.rs | 3 +- src/tools/clippy/rust-toolchain | 2 +- src/tools/clippy/rustfmt.toml | 1 + src/tools/clippy/src/driver.rs | 9 +- src/tools/clippy/src/main.rs | 3 +- src/tools/clippy/tests/compile-test.rs | 199 ++- src/tools/clippy/tests/integration.rs | 24 + src/tools/clippy/tests/lint_message_convention.rs | 6 +- .../cargo_common_metadata/fail/src/main.rs | 1 - .../cargo_common_metadata/fail_publish/src/main.rs | 1 - .../fail_publish_true/src/main.rs | 1 - .../cargo_common_metadata/pass/src/main.rs | 1 - .../pass_publish_empty/src/main.rs | 1 - .../pass_publish_false/src/main.rs | 1 - .../tests/ui-cargo/feature_name/fail/src/main.rs | 1 - .../tests/ui-cargo/feature_name/pass/src/main.rs | 1 - .../module_style/fail_mod_remap/src/main.rs | 1 + .../5041_allow_dev_build/src/main.rs | 1 - .../multiple_crate_versions/fail/src/main.rs | 1 - .../multiple_crate_versions/pass/src/main.rs | 1 - .../wildcard_dependencies/fail/src/main.rs | 1 - .../wildcard_dependencies/pass/src/main.rs | 1 - .../tests/ui-internal/custom_ice_message.stderr | 5 +- .../absolute_paths.allow_crates.stderr | 28 + .../absolute_paths.disallow_crates.stderr | 70 + .../tests/ui-toml/absolute_paths/absolute_paths.rs | 97 ++ .../absolute_paths/allow_crates/clippy.toml | 2 + .../ui-toml/absolute_paths/auxiliary/helper.rs | 11 + .../absolute_paths/disallow_crates/clippy.toml | 1 + .../uninlined_format_args.stderr | 2 +- .../excessive_nesting/auxiliary/proc_macros.rs | 11 +- .../tests/ui-toml/expect_used/expect_used.stderr | 4 +- .../tests/ui-toml/toml_trivially_copy/test.rs | 1 + .../tests/ui-toml/toml_trivially_copy/test.stderr | 4 +- .../toml_unknown_key/conf_unknown_key.stderr | 4 + .../tests/ui-toml/unwrap_used/unwrap_used.rs | 4 +- .../tests/ui-toml/unwrap_used/unwrap_used.stderr | 125 +- .../clippy/tests/ui/arc_with_non_send_sync.rs | 30 +- .../clippy/tests/ui/arc_with_non_send_sync.stderr | 6 +- .../clippy/tests/ui/arithmetic_side_effects.rs | 12 + src/tools/clippy/tests/ui/as_conversions.rs | 3 +- src/tools/clippy/tests/ui/as_conversions.stderr | 6 +- .../clippy/tests/ui/auxiliary/macro_use_helper.rs | 3 +- .../clippy/tests/ui/auxiliary/proc_macro_attr.rs | 4 +- src/tools/clippy/tests/ui/auxiliary/proc_macros.rs | 11 +- .../clippy/tests/ui/bind_instead_of_map.stderr | 2 +- .../tests/ui/bind_instead_of_map_multipart.stderr | 10 +- src/tools/clippy/tests/ui/bool_comparison.fixed | 1 + src/tools/clippy/tests/ui/bool_comparison.rs | 1 + src/tools/clippy/tests/ui/bool_comparison.stderr | 44 +- src/tools/clippy/tests/ui/borrow_box.rs | 6 +- src/tools/clippy/tests/ui/borrow_box.stderr | 20 +- .../clippy/tests/ui/comparison_to_empty.fixed | 12 +- src/tools/clippy/tests/ui/comparison_to_empty.rs | 12 +- .../clippy/tests/ui/comparison_to_empty.stderr | 40 +- src/tools/clippy/tests/ui/const_comparisons.rs | 93 ++ src/tools/clippy/tests/ui/const_comparisons.stderr | 228 +++ src/tools/clippy/tests/ui/crashes/ice-6256.rs | 2 +- src/tools/clippy/tests/ui/crashes/ice-7169.stderr | 2 +- src/tools/clippy/tests/ui/crashes/ice-8250.stderr | 2 +- .../clippy/tests/ui/default_trait_access.fixed | 3 +- src/tools/clippy/tests/ui/default_trait_access.rs | 3 +- .../clippy/tests/ui/default_trait_access.stderr | 16 +- src/tools/clippy/tests/ui/deref_addrof.stderr | 20 +- .../tests/ui/deref_addrof_double_trigger.stderr | 6 +- src/tools/clippy/tests/ui/derive.rs | 6 +- src/tools/clippy/tests/ui/derive.stderr | 20 +- .../clippy/tests/ui/derive_ord_xor_partial_ord.rs | 1 + .../tests/ui/derive_ord_xor_partial_ord.stderr | 16 +- src/tools/clippy/tests/ui/entry.stderr | 20 +- src/tools/clippy/tests/ui/entry_btree.stderr | 2 +- src/tools/clippy/tests/ui/entry_with_else.stderr | 14 +- src/tools/clippy/tests/ui/error_impl_error.rs | 90 ++ src/tools/clippy/tests/ui/error_impl_error.stderr | 45 + src/tools/clippy/tests/ui/eta.fixed | 57 +- src/tools/clippy/tests/ui/eta.rs | 57 +- src/tools/clippy/tests/ui/eta.stderr | 8 +- src/tools/clippy/tests/ui/expect.stderr | 6 +- src/tools/clippy/tests/ui/expect_fun_call.stderr | 30 +- .../clippy/tests/ui/explicit_auto_deref.stderr | 78 +- .../clippy/tests/ui/explicit_deref_methods.fixed | 1 + .../clippy/tests/ui/explicit_deref_methods.rs | 1 + .../clippy/tests/ui/explicit_deref_methods.stderr | 48 +- src/tools/clippy/tests/ui/explicit_write.stderr | 26 +- src/tools/clippy/tests/ui/extend_with_drain.stderr | 8 +- .../clippy/tests/ui/filter_map_bool_then.fixed | 58 + src/tools/clippy/tests/ui/filter_map_bool_then.rs | 58 + .../clippy/tests/ui/filter_map_bool_then.stderr | 40 + .../clippy/tests/ui/filter_map_next_fixable.stderr | 4 +- src/tools/clippy/tests/ui/fn_null_check.rs | 22 - src/tools/clippy/tests/ui/fn_null_check.stderr | 43 - src/tools/clippy/tests/ui/format_collect.rs | 31 + src/tools/clippy/tests/ui/format_collect.stderr | 62 + .../clippy/tests/ui/four_forward_slashes.fixed | 48 + src/tools/clippy/tests/ui/four_forward_slashes.rs | 48 + .../clippy/tests/ui/four_forward_slashes.stderr | 68 + .../tests/ui/four_forward_slashes_first_line.fixed | 7 + .../tests/ui/four_forward_slashes_first_line.rs | 7 + .../ui/four_forward_slashes_first_line.stderr | 15 + src/tools/clippy/tests/ui/get_first.fixed | 4 +- src/tools/clippy/tests/ui/get_first.rs | 4 +- src/tools/clippy/tests/ui/get_first.stderr | 6 +- src/tools/clippy/tests/ui/get_unwrap.fixed | 4 +- src/tools/clippy/tests/ui/get_unwrap.rs | 4 +- src/tools/clippy/tests/ui/get_unwrap.stderr | 133 +- src/tools/clippy/tests/ui/if_same_then_else.rs | 41 + src/tools/clippy/tests/ui/if_same_then_else.stderr | 20 +- src/tools/clippy/tests/ui/if_same_then_else2.rs | 2 +- .../clippy/tests/ui/if_same_then_else2.stderr | 21 +- src/tools/clippy/tests/ui/ifs_same_cond.rs | 4 + src/tools/clippy/tests/ui/ifs_same_cond.stderr | 4 +- .../clippy/tests/ui/ignored_unit_patterns.fixed | 17 + src/tools/clippy/tests/ui/ignored_unit_patterns.rs | 17 + .../clippy/tests/ui/ignored_unit_patterns.stderr | 28 + .../ui/incorrect_clone_impl_on_copy_type.stderr | 4 +- .../incorrect_partial_ord_impl_on_ord_type.fixed | 145 ++ .../ui/incorrect_partial_ord_impl_on_ord_type.rs | 149 ++ .../incorrect_partial_ord_impl_on_ord_type.stderr | 31 + ...rect_partial_ord_impl_on_ord_type_fully_qual.rs | 51 + ..._partial_ord_impl_on_ord_type_fully_qual.stderr | 31 + .../tests/ui/infallible_destructuring_match.stderr | 8 +- src/tools/clippy/tests/ui/inherent_to_string.rs | 26 +- .../clippy/tests/ui/inherent_to_string.stderr | 10 +- src/tools/clippy/tests/ui/issue-7447.rs | 5 +- src/tools/clippy/tests/ui/issue-7447.stderr | 4 +- .../clippy/tests/ui/iter_cloned_collect.fixed | 3 +- src/tools/clippy/tests/ui/iter_cloned_collect.rs | 3 +- .../clippy/tests/ui/iter_cloned_collect.stderr | 10 +- .../clippy/tests/ui/iter_overeager_cloned.stderr | 14 +- src/tools/clippy/tests/ui/iter_skip_zero.fixed | 25 + src/tools/clippy/tests/ui/iter_skip_zero.rs | 25 + src/tools/clippy/tests/ui/iter_skip_zero.stderr | 43 + src/tools/clippy/tests/ui/iter_with_drain.stderr | 12 +- src/tools/clippy/tests/ui/let_and_return.rs | 71 +- src/tools/clippy/tests/ui/let_and_return.stderr | 22 +- src/tools/clippy/tests/ui/let_underscore_lock.rs | 3 +- .../clippy/tests/ui/let_underscore_lock.stderr | 8 +- .../clippy/tests/ui/let_underscore_untyped.rs | 3 +- .../clippy/tests/ui/let_underscore_untyped.stderr | 20 +- src/tools/clippy/tests/ui/manual_filter.stderr | 30 +- src/tools/clippy/tests/ui/manual_filter_map.fixed | 24 + src/tools/clippy/tests/ui/manual_filter_map.rs | 28 + src/tools/clippy/tests/ui/manual_filter_map.stderr | 73 +- src/tools/clippy/tests/ui/manual_find_map.stderr | 53 + src/tools/clippy/tests/ui/manual_float_methods.rs | 55 + .../clippy/tests/ui/manual_float_methods.stderr | 80 + src/tools/clippy/tests/ui/manual_let_else.rs | 8 +- src/tools/clippy/tests/ui/manual_let_else.stderr | 2 +- .../tests/ui/manual_let_else_question_mark.fixed | 63 + .../tests/ui/manual_let_else_question_mark.rs | 68 + .../tests/ui/manual_let_else_question_mark.stderr | 55 + src/tools/clippy/tests/ui/manual_map_option.stderr | 42 +- .../clippy/tests/ui/manual_map_option_2.stderr | 10 +- .../clippy/tests/ui/manual_range_patterns.fixed | 4 + src/tools/clippy/tests/ui/manual_range_patterns.rs | 4 + .../clippy/tests/ui/manual_range_patterns.stderr | 16 +- src/tools/clippy/tests/ui/manual_retain.fixed | 7 +- src/tools/clippy/tests/ui/manual_retain.rs | 7 +- src/tools/clippy/tests/ui/manual_retain.stderr | 38 +- src/tools/clippy/tests/ui/manual_split_once.stderr | 28 +- src/tools/clippy/tests/ui/manual_str_repeat.stderr | 20 +- src/tools/clippy/tests/ui/manual_try_fold.rs | 4 +- src/tools/clippy/tests/ui/manual_try_fold.stderr | 8 +- .../clippy/tests/ui/map_collect_result_unit.stderr | 4 +- src/tools/clippy/tests/ui/map_unwrap_or.stderr | 2 +- .../clippy/tests/ui/map_unwrap_or_fixable.stderr | 4 +- src/tools/clippy/tests/ui/match_as_ref.fixed | 4 +- src/tools/clippy/tests/ui/match_as_ref.rs | 4 +- src/tools/clippy/tests/ui/match_as_ref.stderr | 8 +- .../tests/ui/match_expr_like_matches_macro.fixed | 3 +- .../tests/ui/match_expr_like_matches_macro.rs | 3 +- .../tests/ui/match_expr_like_matches_macro.stderr | 56 +- .../clippy/tests/ui/match_on_vec_items.stderr | 16 +- src/tools/clippy/tests/ui/match_ref_pats.stderr | 4 +- src/tools/clippy/tests/ui/match_same_arms2.stderr | 2 +- .../ui/match_wildcard_for_single_variants.stderr | 20 +- src/tools/clippy/tests/ui/methods.rs | 5 +- src/tools/clippy/tests/ui/methods.stderr | 4 +- src/tools/clippy/tests/ui/methods_fixable.stderr | 2 +- src/tools/clippy/tests/ui/methods_unfixable.rs | 10 + src/tools/clippy/tests/ui/methods_unfixable.stderr | 15 + src/tools/clippy/tests/ui/min_ident_chars.rs | 7 +- src/tools/clippy/tests/ui/min_ident_chars.stderr | 58 +- src/tools/clippy/tests/ui/min_max.rs | 4 +- src/tools/clippy/tests/ui/min_max.stderr | 26 +- .../ui/missing_const_for_fn/could_be_const.rs | 1 + .../ui/missing_const_for_fn/could_be_const.stderr | 8 +- src/tools/clippy/tests/ui/missing_doc.rs | 4 +- src/tools/clippy/tests/ui/missing_spin_loop.stderr | 12 +- .../tests/ui/missing_spin_loop_no_std.stderr | 2 +- .../clippy/tests/ui/must_use_candidates.fixed | 7 +- src/tools/clippy/tests/ui/must_use_candidates.rs | 7 +- .../clippy/tests/ui/must_use_candidates.stderr | 10 +- src/tools/clippy/tests/ui/mut_from_ref.rs | 2 +- src/tools/clippy/tests/ui/mut_key.rs | 3 +- src/tools/clippy/tests/ui/mut_key.stderr | 34 +- src/tools/clippy/tests/ui/mut_mut.rs | 7 +- src/tools/clippy/tests/ui/mut_mut.stderr | 18 +- src/tools/clippy/tests/ui/mut_reference.rs | 15 +- src/tools/clippy/tests/ui/mut_reference.stderr | 6 +- .../clippy/tests/ui/needless_borrow_pat.stderr | 24 +- src/tools/clippy/tests/ui/needless_else.stderr | 2 +- src/tools/clippy/tests/ui/needless_if.fixed | 3 +- src/tools/clippy/tests/ui/needless_if.rs | 3 +- src/tools/clippy/tests/ui/needless_if.stderr | 14 +- .../tests/ui/needless_option_as_deref.stderr | 6 +- .../clippy/tests/ui/needless_pass_by_ref_mut.rs | 254 +++ .../tests/ui/needless_pass_by_ref_mut.stderr | 110 ++ .../ui/needless_return_with_question_mark.fixed | 40 + .../tests/ui/needless_return_with_question_mark.rs | 40 + .../ui/needless_return_with_question_mark.stderr | 10 + src/tools/clippy/tests/ui/needless_splitn.stderr | 26 +- src/tools/clippy/tests/ui/numbered_fields.stderr | 4 +- src/tools/clippy/tests/ui/option_env_unwrap.rs | 1 + src/tools/clippy/tests/ui/option_env_unwrap.stderr | 18 +- src/tools/clippy/tests/ui/option_if_let_else.fixed | 3 +- src/tools/clippy/tests/ui/option_if_let_else.rs | 3 +- .../clippy/tests/ui/option_if_let_else.stderr | 46 +- .../tests/ui/option_map_unit_fn_fixable.stderr | 38 +- src/tools/clippy/tests/ui/or_fun_call.fixed | 66 +- src/tools/clippy/tests/ui/or_fun_call.rs | 58 +- src/tools/clippy/tests/ui/or_fun_call.stderr | 178 ++- src/tools/clippy/tests/ui/or_then_unwrap.stderr | 6 +- .../clippy/tests/ui/panic_in_result_fn.stderr | 74 +- .../tests/ui/panic_in_result_fn_assertions.stderr | 12 +- src/tools/clippy/tests/ui/print_literal.stderr | 24 +- src/tools/clippy/tests/ui/ptr_arg.rs | 16 +- src/tools/clippy/tests/ui/ptr_arg.stderr | 46 +- src/tools/clippy/tests/ui/ptr_as_ptr.fixed | 16 +- src/tools/clippy/tests/ui/ptr_as_ptr.rs | 16 +- src/tools/clippy/tests/ui/ptr_as_ptr.stderr | 28 +- src/tools/clippy/tests/ui/question_mark.fixed | 17 + src/tools/clippy/tests/ui/question_mark.rs | 17 + src/tools/clippy/tests/ui/question_mark.stderr | 6 +- src/tools/clippy/tests/ui/range_contains.fixed | 2 + src/tools/clippy/tests/ui/range_contains.rs | 2 + src/tools/clippy/tests/ui/range_contains.stderr | 42 +- .../clippy/tests/ui/read_line_without_trim.fixed | 36 + .../clippy/tests/ui/read_line_without_trim.rs | 36 + .../clippy/tests/ui/read_line_without_trim.stderr | 73 + src/tools/clippy/tests/ui/read_zero_byte_vec.rs | 6 +- .../clippy/tests/ui/read_zero_byte_vec.stderr | 20 +- src/tools/clippy/tests/ui/readonly_write_lock.rs | 42 + .../clippy/tests/ui/readonly_write_lock.stderr | 16 + src/tools/clippy/tests/ui/redundant_allocation.rs | 9 +- .../clippy/tests/ui/redundant_allocation.stderr | 40 +- .../tests/ui/redundant_allocation_fixable.fixed | 12 +- .../tests/ui/redundant_allocation_fixable.rs | 12 +- .../tests/ui/redundant_allocation_fixable.stderr | 24 +- src/tools/clippy/tests/ui/redundant_guards.fixed | 146 ++ src/tools/clippy/tests/ui/redundant_guards.rs | 146 ++ src/tools/clippy/tests/ui/redundant_guards.stderr | 98 ++ src/tools/clippy/tests/ui/redundant_locals.rs | 120 ++ src/tools/clippy/tests/ui/redundant_locals.stderr | 136 ++ .../redundant_pattern_matching_drop_order.stderr | 44 +- .../ui/redundant_pattern_matching_ipaddr.fixed | 6 +- .../tests/ui/redundant_pattern_matching_ipaddr.rs | 6 +- .../ui/redundant_pattern_matching_ipaddr.stderr | 72 +- .../ui/redundant_pattern_matching_option.fixed | 14 + .../tests/ui/redundant_pattern_matching_option.rs | 14 + .../ui/redundant_pattern_matching_option.stderr | 128 +- .../ui/redundant_pattern_matching_poll.stderr | 36 +- .../ui/redundant_pattern_matching_result.stderr | 56 +- .../tests/ui/ref_binding_to_reference.stderr | 14 +- src/tools/clippy/tests/ui/rename.fixed | 6 +- src/tools/clippy/tests/ui/rename.rs | 6 +- src/tools/clippy/tests/ui/rename.stderr | 118 +- .../tests/ui/result_map_or_into_option.fixed | 2 +- .../clippy/tests/ui/result_map_or_into_option.rs | 2 +- .../tests/ui/result_map_unit_fn_fixable.stderr | 36 +- .../tests/ui/result_map_unit_fn_unfixable.stderr | 12 +- src/tools/clippy/tests/ui/self_assignment.rs | 4 +- src/tools/clippy/tests/ui/self_assignment.stderr | 6 +- .../tests/ui/semicolon_if_nothing_returned.fixed | 123 ++ .../tests/ui/semicolon_if_nothing_returned.rs | 7 +- .../tests/ui/semicolon_if_nothing_returned.stderr | 10 +- src/tools/clippy/tests/ui/shadow.rs | 7 +- src/tools/clippy/tests/ui/shadow.stderr | 92 +- .../tests/ui/significant_drop_in_scrutinee.rs | 3 +- .../tests/ui/significant_drop_in_scrutinee.stderr | 52 +- .../tests/ui/significant_drop_tightening.fixed | 50 + .../clippy/tests/ui/significant_drop_tightening.rs | 50 + .../tests/ui/significant_drop_tightening.stderr | 6 +- .../tests/ui/single_component_path_imports.fixed | 4 + .../tests/ui/single_component_path_imports.rs | 4 + .../tests/ui/single_component_path_imports.stderr | 4 +- .../single_component_path_imports_nested_first.rs | 2 + ...ngle_component_path_imports_nested_first.stderr | 4 +- .../ui/single_component_path_imports_self_after.rs | 1 + .../single_component_path_imports_self_before.rs | 1 + src/tools/clippy/tests/ui/single_match.fixed | 1 + src/tools/clippy/tests/ui/single_match.rs | 1 + src/tools/clippy/tests/ui/single_match.stderr | 72 +- src/tools/clippy/tests/ui/single_match_else.stderr | 18 +- .../clippy/tests/ui/slow_vector_initialization.rs | 16 + .../tests/ui/slow_vector_initialization.stderr | 62 +- src/tools/clippy/tests/ui/string_extend.stderr | 8 +- .../clippy/tests/ui/string_lit_chars_any.fixed | 50 + src/tools/clippy/tests/ui/string_lit_chars_any.rs | 50 + .../clippy/tests/ui/string_lit_chars_any.stderr | 58 + .../clippy/tests/ui/strlen_on_c_strings.stderr | 14 +- .../tests/ui/suspicious_xor_used_as_pow.stderr | 10 +- src/tools/clippy/tests/ui/swap.fixed | 3 +- src/tools/clippy/tests/ui/swap.rs | 3 +- src/tools/clippy/tests/ui/swap.stderr | 34 +- src/tools/clippy/tests/ui/to_digit_is_some.stderr | 4 +- .../clippy/tests/ui/trivially_copy_pass_by_ref.rs | 3 +- .../tests/ui/trivially_copy_pass_by_ref.stderr | 36 +- src/tools/clippy/tests/ui/try_err.fixed | 6 +- src/tools/clippy/tests/ui/try_err.rs | 6 +- src/tools/clippy/tests/ui/try_err.stderr | 44 +- .../clippy/tests/ui/tuple_array_conversions.rs | 30 + .../clippy/tests/ui/tuple_array_conversions.stderr | 36 +- src/tools/clippy/tests/ui/type_id_on_box.fixed | 40 + src/tools/clippy/tests/ui/type_id_on_box.rs | 40 + src/tools/clippy/tests/ui/type_id_on_box.stderr | 36 + src/tools/clippy/tests/ui/unnecessary_cast.fixed | 17 + src/tools/clippy/tests/ui/unnecessary_cast.rs | 17 + src/tools/clippy/tests/ui/unnecessary_cast.stderr | 88 +- .../clippy/tests/ui/unnecessary_cast_unfixable.rs | 22 + .../tests/ui/unnecessary_cast_unfixable.stderr | 16 + src/tools/clippy/tests/ui/unnecessary_clone.stderr | 12 +- .../clippy/tests/ui/unnecessary_filter_map.rs | 6 + .../clippy/tests/ui/unnecessary_filter_map.stderr | 8 +- src/tools/clippy/tests/ui/unnecessary_find_map.rs | 6 + .../clippy/tests/ui/unnecessary_find_map.stderr | 8 +- .../tests/ui/unnecessary_literal_unwrap.fixed | 21 + .../clippy/tests/ui/unnecessary_literal_unwrap.rs | 21 + .../tests/ui/unnecessary_literal_unwrap.stderr | 86 +- .../clippy/tests/ui/unnecessary_to_owned.fixed | 3 +- src/tools/clippy/tests/ui/unnecessary_to_owned.rs | 3 +- .../clippy/tests/ui/unsafe_removed_from_name.rs | 8 + .../tests/ui/unsafe_removed_from_name.stderr | 16 +- src/tools/clippy/tests/ui/unused_async.rs | 17 + src/tools/clippy/tests/ui/unused_async.stderr | 14 +- src/tools/clippy/tests/ui/unused_io_amount.rs | 2 +- src/tools/clippy/tests/ui/unused_peekable.rs | 3 +- src/tools/clippy/tests/ui/unused_peekable.stderr | 16 +- src/tools/clippy/tests/ui/unwrap.stderr | 9 +- src/tools/clippy/tests/ui/unwrap_expect_used.rs | 11 + .../clippy/tests/ui/unwrap_expect_used.stderr | 24 +- src/tools/clippy/tests/ui/unwrap_or.stderr | 4 +- .../clippy/tests/ui/unwrap_or_else_default.fixed | 62 +- .../clippy/tests/ui/unwrap_or_else_default.rs | 62 +- .../clippy/tests/ui/unwrap_or_else_default.stderr | 100 +- src/tools/clippy/tests/ui/useless_asref.fixed | 6 +- src/tools/clippy/tests/ui/useless_asref.rs | 6 +- src/tools/clippy/tests/ui/useless_asref.stderr | 44 +- src/tools/clippy/tests/ui/vec.fixed | 40 + src/tools/clippy/tests/ui/vec.rs | 40 + src/tools/clippy/tests/ui/vec.stderr | 24 +- .../clippy/tests/ui/wildcard_enum_match_arm.stderr | 12 +- src/tools/clippy/tests/ui/wildcard_imports.fixed | 1 + src/tools/clippy/tests/ui/wildcard_imports.rs | 1 + src/tools/clippy/tests/ui/wildcard_imports.stderr | 24 +- .../ui/wildcard_imports_2021.edition2018.fixed | 1 + .../ui/wildcard_imports_2021.edition2018.stderr | 24 +- .../ui/wildcard_imports_2021.edition2021.fixed | 1 + .../ui/wildcard_imports_2021.edition2021.stderr | 24 +- src/tools/clippy/tests/ui/wildcard_imports_2021.rs | 1 + src/tools/clippy/tests/ui/write_literal.stderr | 24 +- src/tools/clippy/tests/ui/write_literal_2.stderr | 28 +- src/tools/clippy/triagebot.toml | 5 + src/tools/clippy/util/fetch_prs_between.sh | 22 +- .../collect-license-metadata/src/path_tree.rs | 5 +- src/tools/compiletest/Cargo.toml | 2 +- src/tools/compiletest/src/header.rs | 47 +- src/tools/compiletest/src/header/cfg.rs | 4 +- src/tools/compiletest/src/lib.rs | 2 +- src/tools/compiletest/src/runtest.rs | 153 +- src/tools/compiletest/src/runtest/debugger.rs | 148 +- src/tools/compiletest/src/runtest/tests.rs | 8 +- src/tools/jsondocck/src/cache.rs | 6 +- src/tools/jsondoclint/src/main.rs | 11 +- src/tools/linkchecker/main.rs | 1 - src/tools/opt-dist/Cargo.toml | 23 + src/tools/opt-dist/README.md | 7 + src/tools/opt-dist/src/bolt.rs | 103 ++ src/tools/opt-dist/src/environment/linux.rs | 58 + src/tools/opt-dist/src/environment/mod.rs | 77 + src/tools/opt-dist/src/environment/windows.rs | 82 + src/tools/opt-dist/src/exec.rs | 179 +++ src/tools/opt-dist/src/main.rs | 215 +++ src/tools/opt-dist/src/metrics.rs | 106 ++ src/tools/opt-dist/src/tests.rs | 114 ++ src/tools/opt-dist/src/timer.rs | 167 ++ src/tools/opt-dist/src/training.rs | 223 +++ src/tools/opt-dist/src/utils/io.rs | 88 ++ src/tools/opt-dist/src/utils/mod.rs | 75 + src/tools/rust-analyzer/.editorconfig | 13 +- src/tools/rust-analyzer/Cargo.lock | 472 +++--- src/tools/rust-analyzer/Cargo.toml | 24 +- src/tools/rust-analyzer/crates/base-db/Cargo.toml | 2 +- .../rust-analyzer/crates/base-db/src/fixture.rs | 114 +- .../rust-analyzer/crates/base-db/src/input.rs | 6 +- src/tools/rust-analyzer/crates/cfg/Cargo.toml | 6 +- src/tools/rust-analyzer/crates/cfg/src/lib.rs | 4 +- src/tools/rust-analyzer/crates/flycheck/Cargo.toml | 4 +- src/tools/rust-analyzer/crates/hir-def/Cargo.toml | 8 +- src/tools/rust-analyzer/crates/hir-def/src/attr.rs | 42 +- src/tools/rust-analyzer/crates/hir-def/src/body.rs | 4 +- .../rust-analyzer/crates/hir-def/src/body/lower.rs | 71 +- .../crates/hir-def/src/body/pretty.rs | 14 +- .../rust-analyzer/crates/hir-def/src/body/scope.rs | 5 - .../rust-analyzer/crates/hir-def/src/body/tests.rs | 12 +- .../crates/hir-def/src/body/tests/block.rs | 77 + .../crates/hir-def/src/child_by_source.rs | 23 +- src/tools/rust-analyzer/crates/hir-def/src/data.rs | 47 +- .../rust-analyzer/crates/hir-def/src/data/adt.rs | 131 +- src/tools/rust-analyzer/crates/hir-def/src/db.rs | 26 +- .../crates/hir-def/src/dyn_map/keys.rs | 8 +- .../rust-analyzer/crates/hir-def/src/expander.rs | 87 +- .../rust-analyzer/crates/hir-def/src/find_path.rs | 2 +- .../rust-analyzer/crates/hir-def/src/generics.rs | 16 +- src/tools/rust-analyzer/crates/hir-def/src/hir.rs | 11 +- .../crates/hir-def/src/hir/type_ref.rs | 4 +- .../rust-analyzer/crates/hir-def/src/import_map.rs | 645 +++----- .../rust-analyzer/crates/hir-def/src/item_scope.rs | 25 +- .../rust-analyzer/crates/hir-def/src/item_tree.rs | 20 +- .../crates/hir-def/src/item_tree/lower.rs | 6 +- .../crates/hir-def/src/item_tree/pretty.rs | 8 +- .../rust-analyzer/crates/hir-def/src/lang_item.rs | 8 +- src/tools/rust-analyzer/crates/hir-def/src/lib.rs | 171 +- .../rust-analyzer/crates/hir-def/src/lower.rs | 8 +- .../macro_expansion_tests/builtin_derive_macro.rs | 76 + .../src/macro_expansion_tests/builtin_fn_macro.rs | 22 +- .../hir-def/src/macro_expansion_tests/mbe.rs | 91 ++ .../hir-def/src/macro_expansion_tests/mod.rs | 53 +- .../rust-analyzer/crates/hir-def/src/nameres.rs | 21 +- .../crates/hir-def/src/nameres/collector.rs | 120 +- .../crates/hir-def/src/nameres/diagnostics.rs | 15 +- .../crates/hir-def/src/nameres/path_resolution.rs | 124 +- .../hir-def/src/nameres/tests/incremental.rs | 18 +- src/tools/rust-analyzer/crates/hir-def/src/path.rs | 7 +- .../rust-analyzer/crates/hir-def/src/path/lower.rs | 4 +- .../rust-analyzer/crates/hir-def/src/pretty.rs | 4 +- .../rust-analyzer/crates/hir-def/src/resolver.rs | 68 +- .../rust-analyzer/crates/hir-expand/Cargo.toml | 6 +- .../crates/hir-expand/src/ast_id_map.rs | 79 +- .../crates/hir-expand/src/builtin_attr_macro.rs | 4 +- .../crates/hir-expand/src/builtin_derive_macro.rs | 196 ++- .../crates/hir-expand/src/builtin_fn_macro.rs | 14 +- .../rust-analyzer/crates/hir-expand/src/db.rs | 478 ++++-- .../rust-analyzer/crates/hir-expand/src/eager.rs | 237 ++- .../rust-analyzer/crates/hir-expand/src/fixup.rs | 16 +- .../rust-analyzer/crates/hir-expand/src/hygiene.rs | 50 +- .../rust-analyzer/crates/hir-expand/src/lib.rs | 249 +-- .../crates/hir-expand/src/mod_path.rs | 4 +- .../rust-analyzer/crates/hir-expand/src/name.rs | 23 +- src/tools/rust-analyzer/crates/hir-ty/Cargo.toml | 12 +- .../rust-analyzer/crates/hir-ty/src/autoderef.rs | 13 +- .../rust-analyzer/crates/hir-ty/src/chalk_db.rs | 68 +- .../rust-analyzer/crates/hir-ty/src/chalk_ext.rs | 3 +- .../rust-analyzer/crates/hir-ty/src/consteval.rs | 25 +- .../crates/hir-ty/src/consteval/tests.rs | 453 +++++- .../hir-ty/src/consteval/tests/intrinsics.rs | 355 ++++- src/tools/rust-analyzer/crates/hir-ty/src/db.rs | 24 +- .../rust-analyzer/crates/hir-ty/src/diagnostics.rs | 2 +- .../crates/hir-ty/src/diagnostics/decl_check.rs | 77 +- .../rust-analyzer/crates/hir-ty/src/display.rs | 115 +- src/tools/rust-analyzer/crates/hir-ty/src/infer.rs | 44 +- .../rust-analyzer/crates/hir-ty/src/infer/cast.rs | 46 + .../crates/hir-ty/src/infer/closure.rs | 54 +- .../crates/hir-ty/src/infer/coerce.rs | 6 +- .../rust-analyzer/crates/hir-ty/src/infer/expr.rs | 47 +- .../crates/hir-ty/src/infer/mutability.rs | 20 +- .../rust-analyzer/crates/hir-ty/src/infer/pat.rs | 4 +- .../rust-analyzer/crates/hir-ty/src/infer/unify.rs | 21 +- .../rust-analyzer/crates/hir-ty/src/layout.rs | 152 +- .../rust-analyzer/crates/hir-ty/src/layout/adt.rs | 28 +- .../crates/hir-ty/src/layout/tests.rs | 98 +- src/tools/rust-analyzer/crates/hir-ty/src/lib.rs | 11 +- src/tools/rust-analyzer/crates/hir-ty/src/lower.rs | 10 +- .../crates/hir-ty/src/method_resolution.rs | 54 +- src/tools/rust-analyzer/crates/hir-ty/src/mir.rs | 41 +- .../crates/hir-ty/src/mir/borrowck.rs | 19 +- .../rust-analyzer/crates/hir-ty/src/mir/eval.rs | 1636 +++++++++++++------- .../crates/hir-ty/src/mir/eval/shim.rs | 651 ++++++-- .../crates/hir-ty/src/mir/eval/shim/simd.rs | 177 +++ .../crates/hir-ty/src/mir/eval/tests.rs | 118 +- .../rust-analyzer/crates/hir-ty/src/mir/lower.rs | 689 +++++---- .../crates/hir-ty/src/mir/lower/as_place.rs | 77 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 7 +- .../crates/hir-ty/src/mir/monomorphization.rs | 48 +- .../rust-analyzer/crates/hir-ty/src/mir/pretty.rs | 38 +- src/tools/rust-analyzer/crates/hir-ty/src/tests.rs | 9 +- .../crates/hir-ty/src/tests/display_source_code.rs | 19 + .../crates/hir-ty/src/tests/macros.rs | 12 +- .../crates/hir-ty/src/tests/method_resolution.rs | 67 + .../crates/hir-ty/src/tests/never_type.rs | 6 + .../crates/hir-ty/src/tests/regression.rs | 26 +- .../crates/hir-ty/src/tests/simple.rs | 22 +- .../crates/hir-ty/src/tests/traits.rs | 68 + .../rust-analyzer/crates/hir-ty/src/traits.rs | 2 +- src/tools/rust-analyzer/crates/hir-ty/src/utils.rs | 14 +- src/tools/rust-analyzer/crates/hir/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/hir/src/attrs.rs | 41 +- src/tools/rust-analyzer/crates/hir/src/db.rs | 11 +- .../rust-analyzer/crates/hir/src/diagnostics.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/display.rs | 26 +- src/tools/rust-analyzer/crates/hir/src/from_id.rs | 5 +- .../rust-analyzer/crates/hir/src/has_source.rs | 36 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 250 ++- .../rust-analyzer/crates/hir/src/semantics.rs | 31 +- .../crates/hir/src/semantics/source_to_def.rs | 23 +- .../crates/hir/src/source_analyzer.rs | 2 +- .../src/handlers/add_missing_impl_members.rs | 184 ++- .../src/handlers/add_missing_match_arms.rs | 158 +- .../ide-assists/src/handlers/add_turbo_fish.rs | 4 +- .../ide-assists/src/handlers/change_visibility.rs | 75 +- .../convert_two_arm_bool_match_to_matches_macro.rs | 125 +- .../src/handlers/destructure_tuple_binding.rs | 2 +- .../src/handlers/desugar_doc_comment.rs | 4 +- .../ide-assists/src/handlers/expand_glob_import.rs | 164 +- .../ide-assists/src/handlers/extract_function.rs | 38 +- .../ide-assists/src/handlers/extract_module.rs | 2 +- .../ide-assists/src/handlers/fix_visibility.rs | 113 +- .../src/handlers/generate_default_from_new.rs | 38 +- .../src/handlers/generate_delegate_methods.rs | 166 +- .../src/handlers/generate_delegate_trait.rs | 1051 +++++++++++++ .../ide-assists/src/handlers/generate_derive.rs | 106 +- .../ide-assists/src/handlers/generate_function.rs | 7 +- .../ide-assists/src/handlers/generate_getter.rs | 814 ---------- .../src/handlers/generate_getter_or_setter.rs | 1014 ++++++++++++ .../ide-assists/src/handlers/generate_setter.rs | 175 --- .../src/handlers/generate_trait_from_impl.rs | 429 +++++ .../crates/ide-assists/src/handlers/inline_call.rs | 143 +- .../ide-assists/src/handlers/inline_macro.rs | 3 +- .../ide-assists/src/handlers/move_const_to_impl.rs | 22 +- .../src/handlers/promote_local_to_const.rs | 56 +- .../ide-assists/src/handlers/pull_assignment_up.rs | 2 +- .../src/handlers/remove_unused_imports.rs | 739 +++++++++ .../handlers/replace_derive_with_manual_impl.rs | 16 +- .../handlers/replace_named_generic_with_impl.rs | 2 +- .../src/handlers/unwrap_result_return_type.rs | 16 +- .../src/handlers/wrap_return_type_in_result.rs | 31 +- .../rust-analyzer/crates/ide-assists/src/lib.rs | 15 +- .../rust-analyzer/crates/ide-assists/src/tests.rs | 93 +- .../crates/ide-assists/src/tests/generated.rs | 140 +- .../rust-analyzer/crates/ide-assists/src/utils.rs | 15 +- .../src/completions/attribute/cfg.rs | 3 +- .../ide-completion/src/completions/extern_abi.rs | 2 + .../crates/ide-completion/src/completions/mod_.rs | 2 +- .../crates/ide-completion/src/context.rs | 4 +- .../crates/ide-completion/src/context/analysis.rs | 7 +- .../crates/ide-completion/src/item.rs | 21 +- .../rust-analyzer/crates/ide-completion/src/lib.rs | 2 +- .../crates/ide-completion/src/tests/attribute.rs | 1 + .../crates/ide-completion/src/tests/special.rs | 23 + src/tools/rust-analyzer/crates/ide-db/Cargo.toml | 2 +- .../crates/ide-db/src/apply_change.rs | 4 +- src/tools/rust-analyzer/crates/ide-db/src/defs.rs | 53 +- .../rust-analyzer/crates/ide-db/src/famous_defs.rs | 2 +- .../crates/ide-db/src/generated/lints.rs | 16 - .../rust-analyzer/crates/ide-db/src/helpers.rs | 18 +- .../crates/ide-db/src/imports/import_assets.rs | 8 +- .../crates/ide-db/src/items_locator.rs | 60 +- src/tools/rust-analyzer/crates/ide-db/src/lib.rs | 4 +- .../crates/ide-db/src/path_transform.rs | 2 +- .../rust-analyzer/crates/ide-db/src/rename.rs | 18 +- .../rust-analyzer/crates/ide-db/src/search.rs | 18 +- .../crates/ide-db/src/source_change.rs | 233 ++- .../crates/ide-diagnostics/Cargo.toml | 1 + .../src/handlers/break_outside_of_loop.rs | 9 +- .../src/handlers/expected_function.rs | 9 +- .../src/handlers/field_shorthand.rs | 40 +- .../ide-diagnostics/src/handlers/inactive_code.rs | 7 +- .../src/handlers/incoherent_impl.rs | 10 +- .../ide-diagnostics/src/handlers/incorrect_case.rs | 208 ++- .../src/handlers/invalid_derive_target.rs | 5 +- .../src/handlers/json_is_not_rust.rs | 5 +- .../ide-diagnostics/src/handlers/macro_error.rs | 21 +- .../src/handlers/malformed_derive.rs | 5 +- .../src/handlers/mismatched_arg_count.rs | 4 +- .../ide-diagnostics/src/handlers/missing_fields.rs | 6 +- .../src/handlers/missing_match_arms.rs | 9 +- .../ide-diagnostics/src/handlers/missing_unsafe.rs | 9 +- .../src/handlers/moved_out_of_ref.rs | 9 +- .../src/handlers/mutability_errors.rs | 181 ++- .../ide-diagnostics/src/handlers/no_such_field.rs | 9 +- .../src/handlers/private_assoc_item.rs | 21 +- .../ide-diagnostics/src/handlers/private_field.rs | 9 +- .../replace_filter_map_next_with_find_map.rs | 41 +- .../ide-diagnostics/src/handlers/type_mismatch.rs | 4 +- .../ide-diagnostics/src/handlers/typed_hole.rs | 5 +- .../src/handlers/undeclared_label.rs | 9 +- .../src/handlers/unimplemented_builtin_macro.rs | 10 +- .../ide-diagnostics/src/handlers/unlinked_file.rs | 14 +- .../src/handlers/unreachable_label.rs | 9 +- .../src/handlers/unresolved_extern_crate.rs | 9 +- .../src/handlers/unresolved_field.rs | 21 +- .../src/handlers/unresolved_import.rs | 9 +- .../src/handlers/unresolved_macro_call.rs | 4 +- .../src/handlers/unresolved_method.rs | 9 +- .../src/handlers/unresolved_module.rs | 29 +- .../src/handlers/unresolved_proc_macro.rs | 4 +- .../ide-diagnostics/src/handlers/useless_braces.rs | 75 +- .../crates/ide-diagnostics/src/lib.rs | 262 +++- .../crates/ide-diagnostics/src/tests.rs | 18 +- .../rust-analyzer/crates/ide-ssr/src/search.rs | 4 +- .../rust-analyzer/crates/ide/src/doc_links.rs | 11 +- .../crates/ide/src/goto_declaration.rs | 35 +- .../crates/ide/src/goto_definition.rs | 12 +- .../crates/ide/src/goto_implementation.rs | 88 +- .../crates/ide/src/highlight_related.rs | 9 +- src/tools/rust-analyzer/crates/ide/src/hover.rs | 17 +- .../rust-analyzer/crates/ide/src/hover/render.rs | 23 +- .../rust-analyzer/crates/ide/src/hover/tests.rs | 89 +- .../crates/ide/src/inlay_hints/adjustment.rs | 2 +- .../crates/ide/src/inlay_hints/chaining.rs | 12 +- .../crates/ide/src/interpret_function.rs | 6 +- src/tools/rust-analyzer/crates/ide/src/lib.rs | 13 +- src/tools/rust-analyzer/crates/ide/src/moniker.rs | 31 +- .../crates/ide/src/navigation_target.rs | 37 +- .../rust-analyzer/crates/ide/src/references.rs | 5 +- src/tools/rust-analyzer/crates/ide/src/rename.rs | 327 ++-- .../rust-analyzer/crates/ide/src/runnables.rs | 61 +- src/tools/rust-analyzer/crates/ide/src/ssr.rs | 57 +- .../rust-analyzer/crates/ide/src/static_index.rs | 72 +- .../crates/ide/src/syntax_highlighting.rs | 23 +- .../crates/ide/src/syntax_highlighting/escape.rs | 36 +- .../ide/src/syntax_highlighting/highlight.rs | 29 +- .../crates/ide/src/syntax_highlighting/html.rs | 3 +- .../crates/ide/src/syntax_highlighting/inject.rs | 2 +- .../crates/ide/src/syntax_highlighting/tags.rs | 2 + .../test_data/highlight_assoc_functions.html | 3 +- .../test_data/highlight_attributes.html | 3 +- .../test_data/highlight_crate_root.html | 3 +- .../test_data/highlight_default_library.html | 3 +- .../test_data/highlight_doctest.html | 3 +- .../test_data/highlight_extern_crate.html | 6 +- .../test_data/highlight_general.html | 3 +- .../test_data/highlight_injection.html | 3 +- .../test_data/highlight_keywords.html | 5 +- .../test_data/highlight_lifetimes.html | 3 +- .../test_data/highlight_macros.html | 17 +- .../test_data/highlight_module_docs_inline.html | 3 +- .../test_data/highlight_module_docs_outline.html | 3 +- .../test_data/highlight_operators.html | 3 +- .../test_data/highlight_rainbow.html | 3 +- .../test_data/highlight_strings.html | 16 +- .../test_data/highlight_unsafe.html | 3 +- .../crates/ide/src/syntax_highlighting/tests.rs | 27 +- .../crates/ide/src/view_memory_layout.rs | 409 +++++ src/tools/rust-analyzer/crates/intern/Cargo.toml | 2 +- .../rust-analyzer/crates/load-cargo/Cargo.toml | 25 + .../rust-analyzer/crates/load-cargo/src/lib.rs | 441 ++++++ .../rust-analyzer/crates/mbe/src/benchmark.rs | 11 +- src/tools/rust-analyzer/crates/mbe/src/expander.rs | 10 + .../crates/mbe/src/expander/matcher.rs | 12 +- .../crates/mbe/src/expander/transcriber.rs | 42 +- src/tools/rust-analyzer/crates/mbe/src/lib.rs | 84 +- .../rust-analyzer/crates/mbe/src/syntax_bridge.rs | 148 +- .../rust-analyzer/crates/mbe/src/token_map.rs | 11 + src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs | 2 +- .../rust-analyzer/crates/parser/src/grammar.rs | 136 +- .../crates/parser/src/grammar/generic_args.rs | 19 +- .../crates/parser/src/grammar/generic_params.rs | 3 +- .../crates/parser/src/grammar/items.rs | 5 +- src/tools/rust-analyzer/crates/parser/src/lib.rs | 3 + .../rust-analyzer/crates/parser/src/shortcuts.rs | 5 +- .../crates/parser/src/syntax_kind/generated.rs | 1 + .../crates/parser/src/tests/prefix_entries.rs | 1 - ...21_recover_from_missing_assoc_item_binding.rast | 48 + ...0021_recover_from_missing_assoc_item_binding.rs | 1 + .../0022_recover_from_missing_const_default.rast | 44 + .../err/0022_recover_from_missing_const_default.rs | 1 + .../parser/inline/ok/0040_crate_keyword_vis.rast | 63 - .../parser/inline/ok/0040_crate_keyword_vis.rs | 3 - .../parser/inline/ok/0125_crate_keyword_path.rast | 33 - .../parser/inline/ok/0125_crate_keyword_path.rs | 1 - src/tools/rust-analyzer/crates/paths/src/lib.rs | 15 +- .../rust-analyzer/crates/proc-macro-api/Cargo.toml | 2 +- .../crates/proc-macro-api/src/version.rs | 11 +- .../rust-analyzer/crates/proc-macro-srv/Cargo.toml | 4 +- .../crates/proc-macro-srv/src/server.rs | 21 +- src/tools/rust-analyzer/crates/profile/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/profile/src/tree.rs | 2 +- .../rust-analyzer/crates/project-model/Cargo.toml | 2 +- .../crates/project-model/src/build_scripts.rs | 17 +- .../crates/project-model/src/cargo_workspace.rs | 27 +- .../rust-analyzer/crates/project-model/src/lib.rs | 23 +- .../crates/project-model/src/manifest_path.rs | 8 +- .../crates/project-model/src/rustc_cfg.rs | 6 +- .../crates/project-model/src/sysroot.rs | 22 +- .../crates/project-model/src/target_data_layout.rs | 3 +- .../crates/project-model/src/workspace.rs | 92 +- .../rust-analyzer/crates/rust-analyzer/Cargo.toml | 13 +- .../crates/rust-analyzer/src/bin/logger.rs | 94 +- .../crates/rust-analyzer/src/bin/main.rs | 64 +- .../rust-analyzer/crates/rust-analyzer/src/cli.rs | 18 +- .../crates/rust-analyzer/src/cli/analysis_stats.rs | 166 +- .../crates/rust-analyzer/src/cli/diagnostics.rs | 12 +- .../crates/rust-analyzer/src/cli/flags.rs | 32 +- .../crates/rust-analyzer/src/cli/load_cargo.rs | 205 --- .../crates/rust-analyzer/src/cli/lsif.rs | 59 +- .../crates/rust-analyzer/src/cli/run_tests.rs | 89 ++ .../crates/rust-analyzer/src/cli/scip.rs | 72 +- .../crates/rust-analyzer/src/cli/ssr.rs | 15 +- .../crates/rust-analyzer/src/config.rs | 1 + .../crates/rust-analyzer/src/dispatch.rs | 30 +- .../crates/rust-analyzer/src/from_proto.rs | 27 +- .../crates/rust-analyzer/src/global_state.rs | 12 +- .../rust-analyzer/src/handlers/notification.rs | 28 +- .../crates/rust-analyzer/src/handlers/request.rs | 260 +++- .../rust-analyzer/src/integrated_benchmarks.rs | 2 +- .../rust-analyzer/crates/rust-analyzer/src/lib.rs | 13 +- .../crates/rust-analyzer/src/lsp_ext.rs | 27 + .../crates/rust-analyzer/src/main_loop.rs | 18 +- .../crates/rust-analyzer/src/reload.rs | 301 +--- .../crates/rust-analyzer/src/semantic_tokens.rs | 1 + .../crates/rust-analyzer/src/to_proto.rs | 621 +++++++- .../rust-analyzer/tests/slow-tests/support.rs | 26 +- .../rust-analyzer/crates/sourcegen/src/lib.rs | 4 +- src/tools/rust-analyzer/crates/stdx/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/syntax/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/syntax/rust.ungram | 6 + .../crates/syntax/src/ast/edit_in_place.rs | 85 +- .../crates/syntax/src/ast/generated/nodes.rs | 30 + .../rust-analyzer/crates/syntax/src/ast/make.rs | 93 ++ .../crates/syntax/src/ast/token_ext.rs | 61 +- src/tools/rust-analyzer/crates/syntax/src/lib.rs | 103 ++ .../crates/syntax/src/tests/ast_src.rs | 1 + .../rust-analyzer/crates/test-utils/src/fixture.rs | 95 +- .../crates/test-utils/src/minicore.rs | 69 +- src/tools/rust-analyzer/crates/tt/src/buffer.rs | 6 +- src/tools/rust-analyzer/crates/tt/src/lib.rs | 18 +- .../rust-analyzer/crates/vfs-notify/Cargo.toml | 3 +- src/tools/rust-analyzer/crates/vfs/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs | 8 +- src/tools/rust-analyzer/docs/dev/lsp-extensions.md | 47 +- src/tools/rust-analyzer/docs/dev/style.md | 13 + src/tools/rust-analyzer/docs/user/manual.adoc | 93 +- src/tools/rust-analyzer/lib/README.md | 9 + src/tools/rust-analyzer/lib/la-arena/Cargo.toml | 2 +- src/tools/rust-analyzer/lib/line-index/Cargo.toml | 6 +- src/tools/rust-analyzer/lib/line-index/src/lib.rs | 218 ++- .../rust-analyzer/lib/line-index/src/tests.rs | 129 +- src/tools/rust-analyzer/lib/line-index/tests/it.rs | 62 - src/tools/rust-analyzer/lib/lsp-server/Cargo.toml | 6 +- src/tools/rust-analyzer/lib/lsp-server/src/msg.rs | 2 +- src/tools/rust-analyzer/triagebot.toml | 4 + src/tools/rust-analyzer/xtask/Cargo.toml | 2 +- src/tools/rust-analyzer/xtask/src/flags.rs | 29 +- src/tools/rust-analyzer/xtask/src/install.rs | 10 +- src/tools/rust-analyzer/xtask/src/metrics.rs | 76 +- src/tools/rust-analyzer/xtask/src/publish.rs | 11 +- src/tools/rust-installer/install-template.sh | 2 +- src/tools/rustfmt/src/expr.rs | 12 +- src/tools/rustfmt/src/macros.rs | 28 +- src/tools/rustfmt/src/matches.rs | 2 +- src/tools/rustfmt/src/parse/macros/mod.rs | 2 +- src/tools/rustfmt/src/parse/session.rs | 35 +- src/tools/rustfmt/src/test/mod.rs | 4 + src/tools/rustfmt/src/utils.rs | 4 +- src/tools/tidy/config/black.toml | 15 + src/tools/tidy/config/requirements.in | 10 + src/tools/tidy/config/requirements.txt | 117 ++ src/tools/tidy/config/ruff.toml | 41 + src/tools/tidy/src/deps.rs | 29 +- src/tools/tidy/src/ext_tool_checks.rs | 435 ++++++ src/tools/tidy/src/features.rs | 1 + src/tools/tidy/src/fluent_alphabetical.rs | 2 +- src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 13 +- src/tools/tidy/src/pal.rs | 6 +- src/tools/tidy/src/style.rs | 4 - src/tools/tidy/src/ui_tests.rs | 10 +- src/version | 2 +- 2321 files changed, 54451 insertions(+), 23614 deletions(-) delete mode 100644 src/bootstrap/bolt.rs create mode 100755 src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh delete mode 100644 src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile delete mode 100755 src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/script.sh create mode 100755 src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh delete mode 100755 src/ci/stage-build.py delete mode 100644 src/doc/embedded-book/.github/bors.toml create mode 100644 src/doc/rustc-dev-guide/src/bound-vars-and-params.md create mode 100644 src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md create mode 100644 src/doc/rustc-dev-guide/src/solve/normalization.md create mode 100644 src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md create mode 100644 src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md create mode 100644 src/doc/rustc/src/platform-support/hermit.md create mode 100644 src/doc/rustc/src/platform-support/mips-release-6.md create mode 100644 src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md create mode 100644 src/doc/rustc/src/platform-support/unikraft-linux-musl.md create mode 100644 src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md create mode 100644 src/doc/rustc/src/symbol-mangling/index.md create mode 100644 src/doc/rustc/src/symbol-mangling/v0.md create mode 100644 src/doc/style-guide/src/editions.md create mode 100644 src/doc/unstable-book/src/compiler-flags/no-parallel-llvm.md create mode 100644 src/doc/unstable-book/src/compiler-flags/path-options.md delete mode 100644 src/doc/unstable-book/src/language-features/abi-thiscall.md create mode 100644 src/doc/unstable-book/src/language-features/start.md delete mode 100644 src/doc/unstable-book/src/library-features/default-free-fn.md delete mode 100644 src/librustdoc/html/static/js/source-script.js create mode 100644 src/librustdoc/html/static/js/src-script.js create mode 100644 src/librustdoc/passes/lint/redundant_explicit_links.rs create mode 100644 src/tools/build_helper/src/metrics.rs create mode 100644 src/tools/cargo/.github/renovate.json5 create mode 100644 src/tools/cargo/crates/xtask-bump-check/Cargo.toml create mode 100644 src/tools/cargo/crates/xtask-bump-check/src/main.rs create mode 100644 src/tools/cargo/crates/xtask-bump-check/src/xtask.rs delete mode 100644 src/tools/cargo/crates/xtask-unpublished/Cargo.toml delete mode 100644 src/tools/cargo/crates/xtask-unpublished/src/main.rs delete mode 100644 src/tools/cargo/crates/xtask-unpublished/src/xtask.rs delete mode 100644 src/tools/cargo/credential/cargo-credential-gnome-secret/Cargo.toml delete mode 100644 src/tools/cargo/credential/cargo-credential-gnome-secret/README.md delete mode 100644 src/tools/cargo/credential/cargo-credential-gnome-secret/build.rs delete mode 100644 src/tools/cargo/credential/cargo-credential-gnome-secret/src/libsecret.rs delete mode 100644 src/tools/cargo/credential/cargo-credential-gnome-secret/src/main.rs create mode 100644 src/tools/cargo/credential/cargo-credential-libsecret/Cargo.toml create mode 100644 src/tools/cargo/credential/cargo-credential-libsecret/README.md create mode 100644 src/tools/cargo/credential/cargo-credential-libsecret/src/lib.rs create mode 100644 src/tools/cargo/credential/cargo-credential-macos-keychain/src/lib.rs delete mode 100644 src/tools/cargo/credential/cargo-credential-macos-keychain/src/main.rs create mode 100644 src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs delete mode 100644 src/tools/cargo/credential/cargo-credential-wincred/src/main.rs create mode 100644 src/tools/cargo/credential/cargo-credential/examples/file-provider.rs create mode 100644 src/tools/cargo/credential/cargo-credential/examples/stdout-redirected.rs create mode 100644 src/tools/cargo/credential/cargo-credential/src/error.rs create mode 100644 src/tools/cargo/credential/cargo-credential/src/secret.rs create mode 100644 src/tools/cargo/credential/cargo-credential/src/stdio.rs create mode 100644 src/tools/cargo/credential/cargo-credential/tests/examples.rs delete mode 100644 src/tools/cargo/src/cargo/util/auth/asymmetric.rs create mode 100644 src/tools/cargo/src/cargo/util/credential/adaptor.rs create mode 100644 src/tools/cargo/src/cargo/util/credential/mod.rs create mode 100644 src/tools/cargo/src/cargo/util/credential/paseto.rs create mode 100644 src/tools/cargo/src/cargo/util/credential/process.rs create mode 100644 src/tools/cargo/src/cargo/util/credential/token.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_add/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_add/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_bench/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_bench/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_bench/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_build/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_build/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_build/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_check/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_check/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_check/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_clean/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_clean/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_clean/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/cargo_config.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_config/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_config/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_config/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_config/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_doc/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_doc/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_doc/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_fetch/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_fetch/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_fetch/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_fix/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_fix/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_fix/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_generate_lockfile/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_generate_lockfile/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_generate_lockfile/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_generate_lockfile/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_git_checkout/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_git_checkout/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_git_checkout/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_git_checkout/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_help/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_help/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_help/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_help/mod.rs create mode 120000 src/tools/cargo/tests/testsuite/cargo_init/auto_git/in create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/auto_git/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/auto_git/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/auto_git/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/auto_git/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/auto_git/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit/in/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit/out/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/in/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/out/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit/in/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit/out/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/in/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/out/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/in/src/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/out/src/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/in/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/out/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/both_lib_and_bin/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/both_lib_and_bin/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/both_lib_and_bin/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/confused_by_multiple_lib_files/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/confused_by_multiple_lib_files/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/confused_by_multiple_lib_files/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/out/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/out/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/in/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/out/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/in/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/out/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/empty_dir/.keep create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/empty_dir/mod.rs create mode 120000 src/tools/cargo/tests/testsuite/cargo_init/explicit_bin_with_git/in create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/explicit_bin_with_git/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/explicit_bin_with_git/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/explicit_bin_with_git/out/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/explicit_bin_with_git/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/explicit_bin_with_git/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/formats_source/in/rustfmt.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/formats_source/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/formats_source/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/formats_source/out/rustfmt.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/formats_source/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/formats_source/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/formats_source/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/in/.fossil/.keep create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/clean-glob create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/ignore-glob create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_autodetect/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_autodetect/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_autodetect/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_autodetect/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_autodetect/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/ignores_failure_to_format_source/in/rustfmt.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/ignores_failure_to_format_source/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/ignores_failure_to_format_source/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/ignores_failure_to_format_source/out/rustfmt.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/ignores_failure_to_format_source/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/ignores_failure_to_format_source/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/ignores_failure_to_format_source/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_bin_with_git/in/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_bin_with_git/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_bin_with_git/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_bin_with_git/out/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_bin_with_git/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_bin_with_git/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_lib_with_git/in/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_lib_with_git/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_lib_with_git/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_lib_with_git/out/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_lib_with_git/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inferred_lib_with_git/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/in/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/in/README.md create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/in/crates/foo/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/in/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/out/crates/foo/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/out/crates/foo/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/inherit_workspace_package_table/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/invalid_dir_name/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/invalid_dir_name/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/invalid_dir_name/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_nosrc/in/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_nosrc/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_nosrc/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_nosrc/out/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_nosrc/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_nosrc/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_src/in/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_src/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_src/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_src/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_src/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/lib_already_exists_src/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/mercurial_autodetect/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/mercurial_autodetect/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/mercurial_autodetect/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/mercurial_autodetect/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/mercurial_autodetect/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/multibin_project_name_clash/in/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/multibin_project_name_clash/in/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/multibin_project_name_clash/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/multibin_project_name_clash/out/case.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/multibin_project_name_clash/out/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/multibin_project_name_clash/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/multibin_project_name_clash/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/no_filename/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/no_filename/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/no_filename/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/path_contains_separator/in/.keep create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/path_contains_separator/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/path_contains_separator/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/path_contains_separator/out/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/path_contains_separator/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/path_contains_separator/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/in/.pijul/.keep create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/out/.ignore create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/reserved_name/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/reserved_name/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/reserved_name/stdout.log create mode 120000 src/tools/cargo/tests/testsuite/cargo_init/simple_bin/in create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_bin/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_bin/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_bin/out/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_bin/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_bin/stdout.log create mode 120000 src/tools/cargo/tests/testsuite/cargo_init/simple_git/in create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git_ignore_exists/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git_ignore_exists/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git_ignore_exists/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git_ignore_exists/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_git_ignore_exists/stdout.log create mode 120000 src/tools/cargo/tests/testsuite/cargo_init/simple_hg/in create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg_ignore_exists/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg_ignore_exists/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg_ignore_exists/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg_ignore_exists/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_hg_ignore_exists/stdout.log create mode 120000 src/tools/cargo/tests/testsuite/cargo_init/simple_lib/in create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_lib/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_lib/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_lib/out/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_lib/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/simple_lib/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/unknown_flags/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/unknown_flags/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/unknown_flags/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/with_argument/in/foo/.keep create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/with_argument/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/with_argument/out/foo/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/with_argument/out/foo/src/main.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/with_argument/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_init/with_argument/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_install/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_install/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_install/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_locate_project/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_locate_project/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_locate_project/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_locate_project/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_login/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_login/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_login/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_logout/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_logout/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_logout/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_logout/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_metadata/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_metadata/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_metadata/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_metadata/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_new/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_new/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_owner/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_owner/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_owner/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_package/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_package/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_package/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_pkgid/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_pkgid/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_pkgid/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_pkgid/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_publish/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_publish/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_publish/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_read_manifest/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_read_manifest/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_read_manifest/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_read_manifest/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/in/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/in/serde/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/in/serde/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/in/serde_derive/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/in/serde_derive/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/out/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/out/serde/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/out/serde/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/out/serde_derive/Cargo.toml create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/out/serde_derive/src/lib.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_keep_used_patch/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/gc_patch/out/Cargo.lock create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_report/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_report/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_report/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_report/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_run/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_run/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_run/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_rustc/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_rustc/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_rustc/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_rustdoc/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_rustdoc/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_search/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_search/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_search/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_test/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_test/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_test/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_test/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_tree/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_tree/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_tree/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_uninstall/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_uninstall/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_uninstall/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_uninstall/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_update/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_update/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_update/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_vendor/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_vendor/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_vendor/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_vendor/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_verify_project/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_verify_project/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_verify_project/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_verify_project/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_version/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_version/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_version/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_version/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_yank/help/mod.rs create mode 100644 src/tools/cargo/tests/testsuite/cargo_yank/help/stderr.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log create mode 100644 src/tools/cargo/tests/testsuite/cargo_yank/mod.rs delete mode 120000 src/tools/cargo/tests/testsuite/init/auto_git/in delete mode 100644 src/tools/cargo/tests/testsuite/init/auto_git/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/auto_git/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/auto_git/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/auto_git/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/auto_git/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit/in/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit/out/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit_nosrc/in/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit_nosrc/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit_nosrc/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit_nosrc/out/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit_nosrc/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_explicit_nosrc/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit/in/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit/out/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namenosrc/in/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namenosrc/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namenosrc/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namenosrc/out/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namenosrc/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namenosrc/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namesrc/in/src/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namesrc/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namesrc/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namesrc/out/src/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namesrc/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_namesrc/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_nosrc/in/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_nosrc/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_nosrc/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_nosrc/out/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_nosrc/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/bin_already_exists_implicit_nosrc/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/both_lib_and_bin/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/both_lib_and_bin/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/both_lib_and_bin/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/cant_create_library_when_both_binlib_present/in/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/cant_create_library_when_both_binlib_present/in/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/cant_create_library_when_both_binlib_present/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/cant_create_library_when_both_binlib_present/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/cant_create_library_when_both_binlib_present/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/confused_by_multiple_lib_files/in/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/confused_by_multiple_lib_files/in/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/confused_by_multiple_lib_files/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/confused_by_multiple_lib_files/out/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/confused_by_multiple_lib_files/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/confused_by_multiple_lib_files/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/confused_by_multiple_lib_files/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_both_binlib_present/in/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_both_binlib_present/in/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_both_binlib_present/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_both_binlib_present/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_both_binlib_present/out/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_both_binlib_present/out/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_both_binlib_present/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_both_binlib_present/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_instructed_and_has_lib_file/in/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_instructed_and_has_lib_file/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_instructed_and_has_lib_file/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_instructed_and_has_lib_file/out/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_instructed_and_has_lib_file/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_binary_when_instructed_and_has_lib_file/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_library_when_instructed_and_has_bin_file/in/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_library_when_instructed_and_has_bin_file/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_library_when_instructed_and_has_bin_file/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_library_when_instructed_and_has_bin_file/out/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_library_when_instructed_and_has_bin_file/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/creates_library_when_instructed_and_has_bin_file/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/empty_dir/.keep delete mode 100644 src/tools/cargo/tests/testsuite/init/empty_dir/mod.rs delete mode 120000 src/tools/cargo/tests/testsuite/init/explicit_bin_with_git/in delete mode 100644 src/tools/cargo/tests/testsuite/init/explicit_bin_with_git/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/explicit_bin_with_git/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/explicit_bin_with_git/out/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/explicit_bin_with_git/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/explicit_bin_with_git/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/formats_source/in/rustfmt.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/formats_source/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/formats_source/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/formats_source/out/rustfmt.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/formats_source/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/formats_source/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/formats_source/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/fossil_autodetect/in/.fossil/.keep delete mode 100644 src/tools/cargo/tests/testsuite/init/fossil_autodetect/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/fossil_autodetect/out/.fossil-settings/clean-glob delete mode 100644 src/tools/cargo/tests/testsuite/init/fossil_autodetect/out/.fossil-settings/ignore-glob delete mode 100644 src/tools/cargo/tests/testsuite/init/fossil_autodetect/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/fossil_autodetect/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/fossil_autodetect/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/fossil_autodetect/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/git_autodetect/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/git_autodetect/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/git_autodetect/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/git_autodetect/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/git_autodetect/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/git_ignore_exists_no_conflicting_entries/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/git_ignore_exists_no_conflicting_entries/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/git_ignore_exists_no_conflicting_entries/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/git_ignore_exists_no_conflicting_entries/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/git_ignore_exists_no_conflicting_entries/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/ignores_failure_to_format_source/in/rustfmt.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/ignores_failure_to_format_source/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/ignores_failure_to_format_source/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/ignores_failure_to_format_source/out/rustfmt.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/ignores_failure_to_format_source/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/ignores_failure_to_format_source/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/ignores_failure_to_format_source/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_bin_with_git/in/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_bin_with_git/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_bin_with_git/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_bin_with_git/out/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_bin_with_git/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_bin_with_git/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_lib_with_git/in/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_lib_with_git/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_lib_with_git/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_lib_with_git/out/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_lib_with_git/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/inferred_lib_with_git/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/README.md delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/crates/foo/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/in/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/crates/foo/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/inherit_workspace_package_table/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/invalid_dir_name/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/invalid_dir_name/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/invalid_dir_name/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_nosrc/in/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_nosrc/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_nosrc/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_nosrc/out/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_nosrc/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_nosrc/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_src/in/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_src/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_src/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_src/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_src/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/lib_already_exists_src/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/mercurial_autodetect/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/mercurial_autodetect/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/mercurial_autodetect/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/mercurial_autodetect/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/mercurial_autodetect/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/multibin_project_name_clash/in/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/multibin_project_name_clash/in/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/multibin_project_name_clash/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/multibin_project_name_clash/out/case.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/multibin_project_name_clash/out/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/multibin_project_name_clash/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/multibin_project_name_clash/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/no_filename/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/no_filename/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/no_filename/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/path_contains_separator/in/.keep delete mode 100644 src/tools/cargo/tests/testsuite/init/path_contains_separator/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/path_contains_separator/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/path_contains_separator/out/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/path_contains_separator/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/path_contains_separator/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/pijul_autodetect/in/.pijul/.keep delete mode 100644 src/tools/cargo/tests/testsuite/init/pijul_autodetect/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/pijul_autodetect/out/.ignore delete mode 100644 src/tools/cargo/tests/testsuite/init/pijul_autodetect/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/pijul_autodetect/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/pijul_autodetect/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/pijul_autodetect/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/reserved_name/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/reserved_name/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/reserved_name/stdout.log delete mode 120000 src/tools/cargo/tests/testsuite/init/simple_bin/in delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_bin/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_bin/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_bin/out/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_bin/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_bin/stdout.log delete mode 120000 src/tools/cargo/tests/testsuite/init/simple_git/in delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git_ignore_exists/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git_ignore_exists/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git_ignore_exists/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git_ignore_exists/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_git_ignore_exists/stdout.log delete mode 120000 src/tools/cargo/tests/testsuite/init/simple_hg/in delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg_ignore_exists/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg_ignore_exists/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg_ignore_exists/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg_ignore_exists/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_hg_ignore_exists/stdout.log delete mode 120000 src/tools/cargo/tests/testsuite/init/simple_lib/in delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_lib/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_lib/out/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_lib/out/src/lib.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_lib/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/simple_lib/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/unknown_flags/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/unknown_flags/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/unknown_flags/stdout.log delete mode 100644 src/tools/cargo/tests/testsuite/init/with_argument/in/foo/.keep delete mode 100644 src/tools/cargo/tests/testsuite/init/with_argument/mod.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/with_argument/out/foo/Cargo.toml delete mode 100644 src/tools/cargo/tests/testsuite/init/with_argument/out/foo/src/main.rs delete mode 100644 src/tools/cargo/tests/testsuite/init/with_argument/stderr.log delete mode 100644 src/tools/cargo/tests/testsuite/init/with_argument/stdout.log create mode 100644 src/tools/clippy/book/src/development/speedtest.md create mode 100644 src/tools/clippy/clippy_lints/src/absolute_paths.rs create mode 100644 src/tools/clippy/clippy_lints/src/error_impl_error.rs delete mode 100644 src/tools/clippy/clippy_lints/src/fn_null_check.rs create mode 100644 src/tools/clippy/clippy_lints/src/four_forward_slashes.rs create mode 100644 src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs create mode 100644 src/tools/clippy/clippy_lints/src/manual_float_methods.rs create mode 100644 src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs delete mode 100644 src/tools/clippy/clippy_lints/src/methods/expect_used.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/format_collect.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/iter_skip_zero.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/readonly_write_lock.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs delete mode 100644 src/tools/clippy/clippy_lints/src/methods/unwrap_or_else_default.rs delete mode 100644 src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs create mode 100644 src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs create mode 100644 src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs create mode 100644 src/tools/clippy/clippy_lints/src/redundant_locals.rs delete mode 100644 src/tools/clippy/clippy_test_deps/Cargo.toml delete mode 100644 src/tools/clippy/clippy_test_deps/src/lib.rs create mode 100644 src/tools/clippy/clippy_utils/src/ty/type_certainty/certainty.rs create mode 100644 src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs create mode 100644 src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr create mode 100644 src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr create mode 100644 src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs create mode 100644 src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/absolute_paths/auxiliary/helper.rs create mode 100644 src/tools/clippy/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml create mode 100644 src/tools/clippy/tests/ui/const_comparisons.rs create mode 100644 src/tools/clippy/tests/ui/const_comparisons.stderr create mode 100644 src/tools/clippy/tests/ui/error_impl_error.rs create mode 100644 src/tools/clippy/tests/ui/error_impl_error.stderr create mode 100644 src/tools/clippy/tests/ui/filter_map_bool_then.fixed create mode 100644 src/tools/clippy/tests/ui/filter_map_bool_then.rs create mode 100644 src/tools/clippy/tests/ui/filter_map_bool_then.stderr delete mode 100644 src/tools/clippy/tests/ui/fn_null_check.rs delete mode 100644 src/tools/clippy/tests/ui/fn_null_check.stderr create mode 100644 src/tools/clippy/tests/ui/format_collect.rs create mode 100644 src/tools/clippy/tests/ui/format_collect.stderr create mode 100644 src/tools/clippy/tests/ui/four_forward_slashes.fixed create mode 100644 src/tools/clippy/tests/ui/four_forward_slashes.rs create mode 100644 src/tools/clippy/tests/ui/four_forward_slashes.stderr create mode 100644 src/tools/clippy/tests/ui/four_forward_slashes_first_line.fixed create mode 100644 src/tools/clippy/tests/ui/four_forward_slashes_first_line.rs create mode 100644 src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr create mode 100644 src/tools/clippy/tests/ui/ignored_unit_patterns.fixed create mode 100644 src/tools/clippy/tests/ui/ignored_unit_patterns.rs create mode 100644 src/tools/clippy/tests/ui/ignored_unit_patterns.stderr create mode 100644 src/tools/clippy/tests/ui/incorrect_partial_ord_impl_on_ord_type.fixed create mode 100644 src/tools/clippy/tests/ui/incorrect_partial_ord_impl_on_ord_type.rs create mode 100644 src/tools/clippy/tests/ui/incorrect_partial_ord_impl_on_ord_type.stderr create mode 100644 src/tools/clippy/tests/ui/incorrect_partial_ord_impl_on_ord_type_fully_qual.rs create mode 100644 src/tools/clippy/tests/ui/incorrect_partial_ord_impl_on_ord_type_fully_qual.stderr create mode 100644 src/tools/clippy/tests/ui/iter_skip_zero.fixed create mode 100644 src/tools/clippy/tests/ui/iter_skip_zero.rs create mode 100644 src/tools/clippy/tests/ui/iter_skip_zero.stderr create mode 100644 src/tools/clippy/tests/ui/manual_float_methods.rs create mode 100644 src/tools/clippy/tests/ui/manual_float_methods.stderr create mode 100644 src/tools/clippy/tests/ui/manual_let_else_question_mark.fixed create mode 100644 src/tools/clippy/tests/ui/manual_let_else_question_mark.rs create mode 100644 src/tools/clippy/tests/ui/manual_let_else_question_mark.stderr create mode 100644 src/tools/clippy/tests/ui/methods_unfixable.rs create mode 100644 src/tools/clippy/tests/ui/methods_unfixable.stderr create mode 100644 src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs create mode 100644 src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr create mode 100644 src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed create mode 100644 src/tools/clippy/tests/ui/needless_return_with_question_mark.rs create mode 100644 src/tools/clippy/tests/ui/needless_return_with_question_mark.stderr create mode 100644 src/tools/clippy/tests/ui/read_line_without_trim.fixed create mode 100644 src/tools/clippy/tests/ui/read_line_without_trim.rs create mode 100644 src/tools/clippy/tests/ui/read_line_without_trim.stderr create mode 100644 src/tools/clippy/tests/ui/readonly_write_lock.rs create mode 100644 src/tools/clippy/tests/ui/readonly_write_lock.stderr create mode 100644 src/tools/clippy/tests/ui/redundant_guards.fixed create mode 100644 src/tools/clippy/tests/ui/redundant_guards.rs create mode 100644 src/tools/clippy/tests/ui/redundant_guards.stderr create mode 100644 src/tools/clippy/tests/ui/redundant_locals.rs create mode 100644 src/tools/clippy/tests/ui/redundant_locals.stderr create mode 100644 src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed create mode 100644 src/tools/clippy/tests/ui/string_lit_chars_any.fixed create mode 100644 src/tools/clippy/tests/ui/string_lit_chars_any.rs create mode 100644 src/tools/clippy/tests/ui/string_lit_chars_any.stderr create mode 100644 src/tools/clippy/tests/ui/type_id_on_box.fixed create mode 100644 src/tools/clippy/tests/ui/type_id_on_box.rs create mode 100644 src/tools/clippy/tests/ui/type_id_on_box.stderr create mode 100644 src/tools/clippy/tests/ui/unnecessary_cast_unfixable.rs create mode 100644 src/tools/clippy/tests/ui/unnecessary_cast_unfixable.stderr create mode 100644 src/tools/opt-dist/Cargo.toml create mode 100644 src/tools/opt-dist/README.md create mode 100644 src/tools/opt-dist/src/bolt.rs create mode 100644 src/tools/opt-dist/src/environment/linux.rs create mode 100644 src/tools/opt-dist/src/environment/mod.rs create mode 100644 src/tools/opt-dist/src/environment/windows.rs create mode 100644 src/tools/opt-dist/src/exec.rs create mode 100644 src/tools/opt-dist/src/main.rs create mode 100644 src/tools/opt-dist/src/metrics.rs create mode 100644 src/tools/opt-dist/src/tests.rs create mode 100644 src/tools/opt-dist/src/timer.rs create mode 100644 src/tools/opt-dist/src/training.rs create mode 100644 src/tools/opt-dist/src/utils/io.rs create mode 100644 src/tools/opt-dist/src/utils/mod.rs create mode 100644 src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs create mode 100644 src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs delete mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter.rs create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs delete mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_setter.rs create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs create mode 100644 src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs create mode 100644 src/tools/rust-analyzer/crates/load-cargo/Cargo.toml create mode 100644 src/tools/rust-analyzer/crates/load-cargo/src/lib.rs create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rast create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rs create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rs delete mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast delete mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs delete mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast delete mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs delete mode 100644 src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs create mode 100644 src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs delete mode 100644 src/tools/rust-analyzer/lib/line-index/tests/it.rs create mode 100644 src/tools/tidy/config/black.toml create mode 100644 src/tools/tidy/config/requirements.in create mode 100644 src/tools/tidy/config/requirements.txt create mode 100644 src/tools/tidy/config/ruff.toml create mode 100644 src/tools/tidy/src/ext_tool_checks.rs (limited to 'src') diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 2b2e9e9f9..ecb58a0e9 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -85,6 +85,10 @@ dependencies = [ [[package]] name = "build_helper" version = "0.1.0" +dependencies = [ + "serde", + "serde_derive", +] [[package]] name = "cc" @@ -475,9 +479,9 @@ dependencies = [ [[package]] name = "object" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" dependencies = [ "memchr", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 85eb543e4..74b9a23fa 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -36,7 +36,7 @@ filetime = "0.2" cc = "1.0.69" libc = "0.2" hex = "0.4" -object = { version = "0.31.1", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] } +object = { version = "0.32.0", 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. diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index 30dfa81c6..c497cabbd 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -67,7 +67,7 @@ fn main() { `cp config.example.toml config.toml`" ); } else if let Some(suggestion) = &changelog_suggestion { - println!("{}", suggestion); + println!("{suggestion}"); } let pre_commit = config.src.join(".git").join("hooks").join("pre-commit"); @@ -80,7 +80,7 @@ fn main() { `cp config.example.toml config.toml`" ); } else if let Some(suggestion) = &changelog_suggestion { - println!("{}", suggestion); + println!("{suggestion}"); } // Give a warning if the pre-commit script is in pre-commit and not pre-push. @@ -107,13 +107,13 @@ fn check_version(config: &Config) -> Option { let suggestion = if let Some(seen) = config.changelog_seen { if seen != VERSION { msg.push_str("warning: there have been changes to x.py since you last updated.\n"); - format!("update `config.toml` to use `changelog-seen = {}` instead", VERSION) + format!("update `config.toml` to use `changelog-seen = {VERSION}` instead") } else { return None; } } else { msg.push_str("warning: x.py has made several changes recently you may want to look at\n"); - format!("add `changelog-seen = {}` at the top of `config.toml`", VERSION) + format!("add `changelog-seen = {VERSION}` at the top of `config.toml`") }; msg.push_str("help: consider looking at the changes in `src/bootstrap/CHANGELOG.md`\n"); diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index e87125a49..10718aeb8 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -120,7 +120,7 @@ fn main() { // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { - cmd.arg(format!("-Clinker={}", host_linker)); + cmd.arg(format!("-Clinker={host_linker}")); } if env::var_os("RUSTC_HOST_FUSE_LD_LLD").is_some() { cmd.arg("-Clink-args=-fuse-ld=lld"); @@ -206,11 +206,11 @@ fn main() { env::vars().filter(|(k, _)| k.starts_with("RUST") || k.starts_with("CARGO")); let prefix = if is_test { "[RUSTC-SHIM] rustc --test" } else { "[RUSTC-SHIM] rustc" }; let prefix = match crate_name { - Some(crate_name) => format!("{} {}", prefix, crate_name), + Some(crate_name) => format!("{prefix} {crate_name}"), None => prefix.to_string(), }; for (i, (k, v)) in rust_env_vars.enumerate() { - eprintln!("{} env[{}]: {:?}={:?}", prefix, i, k, v); + eprintln!("{prefix} env[{i}]: {k:?}={v:?}"); } eprintln!("{} working directory: {}", prefix, env::current_dir().unwrap().display()); eprintln!( @@ -220,13 +220,13 @@ fn main() { env::join_paths(&dylib_path).unwrap(), cmd, ); - eprintln!("{} sysroot: {:?}", prefix, sysroot); - eprintln!("{} libdir: {:?}", prefix, libdir); + eprintln!("{prefix} sysroot: {sysroot:?}"); + eprintln!("{prefix} libdir: {libdir:?}"); } let start = Instant::now(); let (child, status) = { - let errmsg = format!("\nFailed to run:\n{:?}\n-------------", cmd); + let errmsg = format!("\nFailed to run:\n{cmd:?}\n-------------"); let mut child = cmd.spawn().expect(&errmsg); let status = child.wait().expect(&errmsg); (child, status) @@ -259,7 +259,7 @@ fn main() { // should run on success, after this block. } if verbose > 0 { - println!("\nDid not run successfully: {}\n{:?}\n-------------", status, cmd); + println!("\nDid not run successfully: {status}\n{cmd:?}\n-------------"); } if let Some(mut on_fail) = on_fail { @@ -271,7 +271,7 @@ fn main() { match status.code() { Some(i) => std::process::exit(i), None => { - eprintln!("rustc exited with {}", status); + eprintln!("rustc exited with {status}"); std::process::exit(0xfe); } } @@ -396,21 +396,20 @@ fn format_rusage_data(_child: Child) -> Option { let minflt = rusage.ru_minflt; let majflt = rusage.ru_majflt; if minflt != 0 || majflt != 0 { - init_str.push_str(&format!(" page reclaims: {} page faults: {}", minflt, majflt)); + init_str.push_str(&format!(" page reclaims: {minflt} page faults: {majflt}")); } let inblock = rusage.ru_inblock; let oublock = rusage.ru_oublock; if inblock != 0 || oublock != 0 { - init_str.push_str(&format!(" fs block inputs: {} fs block outputs: {}", inblock, oublock)); + init_str.push_str(&format!(" fs block inputs: {inblock} fs block outputs: {oublock}")); } let nvcsw = rusage.ru_nvcsw; let nivcsw = rusage.ru_nivcsw; if nvcsw != 0 || nivcsw != 0 { init_str.push_str(&format!( - " voluntary ctxt switches: {} involuntary ctxt switches: {}", - nvcsw, nivcsw + " voluntary ctxt switches: {nvcsw} involuntary ctxt switches: {nivcsw}" )); } diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index d2b85f7a6..4ecb33498 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -62,7 +62,7 @@ fn main() { } if let Ok(no_threads) = env::var("RUSTDOC_LLD_NO_THREADS") { cmd.arg("-Clink-arg=-fuse-ld=lld"); - cmd.arg(format!("-Clink-arg=-Wl,{}", no_threads)); + cmd.arg(format!("-Clink-arg=-Wl,{no_threads}")); } // Cargo doesn't pass RUSTDOCFLAGS to proc_macros: // https://github.com/rust-lang/cargo/issues/4423 @@ -82,12 +82,12 @@ fn main() { env::join_paths(&dylib_path).unwrap(), cmd, ); - eprintln!("sysroot: {:?}", sysroot); - eprintln!("libdir: {:?}", libdir); + eprintln!("sysroot: {sysroot:?}"); + eprintln!("libdir: {libdir:?}"); } std::process::exit(match cmd.status() { Ok(s) => s.code().unwrap_or(1), - Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e), + Err(e) => panic!("\n\nfailed to run {cmd:?}: {e}\n\n"), }) } diff --git a/src/bootstrap/bolt.rs b/src/bootstrap/bolt.rs deleted file mode 100644 index 5384181ea..000000000 --- a/src/bootstrap/bolt.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::path::Path; -use std::process::Command; - -/// Uses the `llvm-bolt` binary to instrument the artifact at the given `path` with BOLT. -/// When the instrumented artifact is executed, it will generate BOLT profiles into -/// `/tmp/prof.fdata..fdata`. -/// Creates the instrumented artifact at `output_path`. -pub fn instrument_with_bolt(path: &Path, output_path: &Path) { - let status = Command::new("llvm-bolt") - .arg("-instrument") - .arg(&path) - // Make sure that each process will write its profiles into a separate file - .arg("--instrumentation-file-append-pid") - .arg("-o") - .arg(output_path) - .status() - .expect("Could not instrument artifact using BOLT"); - - if !status.success() { - panic!("Could not instrument {} with BOLT, exit code {:?}", path.display(), status.code()); - } -} - -/// Uses the `llvm-bolt` binary to optimize the artifact at the given `path` with BOLT, -/// using merged profiles from `profile_path`. -/// -/// The recorded profiles have to be merged using the `merge-fdata` tool from LLVM and the merged -/// profile path should be then passed to this function. -/// -/// Creates the optimized artifact at `output_path`. -pub fn optimize_with_bolt(path: &Path, profile_path: &Path, output_path: &Path) { - let status = Command::new("llvm-bolt") - .arg(&path) - .arg("-data") - .arg(&profile_path) - .arg("-o") - .arg(output_path) - // Reorder basic blocks within functions - .arg("-reorder-blocks=ext-tsp") - // Reorder functions within the binary - .arg("-reorder-functions=hfsort+") - // Split function code into hot and code regions - .arg("-split-functions") - // Split as many basic blocks as possible - .arg("-split-all-cold") - // Move jump tables to a separate section - .arg("-jump-tables=move") - // Fold functions with identical code - .arg("-icf=1") - // Update DWARF debug info in the final binary - .arg("-update-debug-sections") - // Print optimization statistics - .arg("-dyno-stats") - .status() - .expect("Could not optimize artifact using BOLT"); - - if !status.success() { - panic!("Could not optimize {} with BOLT, exit code {:?}", path.display(), status.code()); - } -} diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 149350e62..f44a05a6b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -97,7 +97,7 @@ def _download(path, url, probably_big, verbose, exception): print("downloading {}".format(url), file=sys.stderr) try: - if probably_big or verbose: + if (probably_big or verbose) and "GITHUB_ACTIONS" not in os.environ: option = "-#" else: option = "-s" @@ -256,7 +256,7 @@ def default_build_triple(verbose): if uname is None: return 'x86_64-pc-windows-msvc' - kernel, cputype, processor = uname.decode(default_encoding).split() + kernel, cputype, processor = uname.decode(default_encoding).split(maxsplit=2) # 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. @@ -332,6 +332,7 @@ def default_build_triple(verbose): 'i786': 'i686', 'loongarch64': 'loongarch64', 'm68k': 'm68k', + 'csky': 'csky', 'powerpc': 'powerpc', 'powerpc64': 'powerpc64', 'powerpc64le': 'powerpc64le', @@ -472,7 +473,9 @@ class FakeArgs: class RustBuild(object): """Provide all the methods required to build Rust""" - def __init__(self, config_toml="", args=FakeArgs()): + def __init__(self, config_toml="", args=None): + if args is None: + args = FakeArgs() self.git_version = None self.nix_deps_dir = None self._should_fix_bins_and_dylibs = None @@ -914,12 +917,7 @@ class RustBuild(object): # preserve existing RUSTFLAGS env.setdefault("RUSTFLAGS", "") - # we need to explicitly add +xgot here so that we can successfully bootstrap - # a usable stage1 compiler - # FIXME: remove this if condition on the next bootstrap bump - # cfg(bootstrap) - if self.build_triple().startswith('mips'): - env["RUSTFLAGS"] += " -Ctarget-feature=+xgot" + target_features = [] if self.get_toml("crt-static", build_section) == "true": target_features += ["+crt-static"] diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 3c91e403d..dc06a4c97 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -4,7 +4,6 @@ Run these with `x test bootstrap`, or `python -m unittest src/bootstrap/bootstra from __future__ import absolute_import, division, print_function import os -import doctest import unittest import tempfile import hashlib @@ -16,12 +15,15 @@ from shutil import rmtree bootstrap_dir = os.path.dirname(os.path.abspath(__file__)) # For the import below, have Python search in src/bootstrap first. sys.path.insert(0, bootstrap_dir) -import bootstrap -import configure +import bootstrap # noqa: E402 +import configure # noqa: E402 -def serialize_and_parse(configure_args, bootstrap_args=bootstrap.FakeArgs()): +def serialize_and_parse(configure_args, bootstrap_args=None): from io import StringIO + if bootstrap_args is None: + bootstrap_args = bootstrap.FakeArgs() + section_order, sections, targets = configure.parse_args(configure_args) buffer = StringIO() configure.write_config_toml(buffer, section_order, targets, sections) @@ -129,7 +131,14 @@ class GenerateAndParseConfig(unittest.TestCase): class BuildBootstrap(unittest.TestCase): """Test that we generate the appropriate arguments when building bootstrap""" - def build_args(self, configure_args=[], args=[], env={}): + def build_args(self, configure_args=None, args=None, env=None): + if configure_args is None: + configure_args = [] + if args is None: + args = [] + if env is None: + env = {} + env = env.copy() env["PATH"] = os.environ["PATH"] diff --git a/src/bootstrap/build.rs b/src/bootstrap/build.rs index cd1f41802..e0e32d313 100644 --- a/src/bootstrap/build.rs +++ b/src/bootstrap/build.rs @@ -3,5 +3,5 @@ use std::env; fn main() { let host = env::var("HOST").unwrap(); println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rustc-env=BUILD_TRIPLE={}", host); + println!("cargo:rustc-env=BUILD_TRIPLE={host}"); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 05b66f947..b36661928 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -13,7 +13,7 @@ use std::process::Command; use std::time::{Duration, Instant}; use crate::cache::{Cache, Interned, INTERNER}; -use crate::config::{SplitDebuginfo, TargetSelection}; +use crate::config::{DryRun, SplitDebuginfo, TargetSelection}; use crate::doc; use crate::flags::{Color, Subcommand}; use crate::install; @@ -115,6 +115,43 @@ impl RunConfig<'_> { } INTERNER.intern_list(crates) } + + /// Given an `alias` selected by the `Step` and the paths passed on the command line, + /// return a list of the crates that should be built. + /// + /// Normally, people will pass *just* `library` if they pass it. + /// But it's possible (although strange) to pass something like `library std core`. + /// Build all crates anyway, as if they hadn't passed the other args. + pub fn make_run_crates(&self, alias: Alias) -> Interned> { + let has_alias = + self.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias.as_str())); + if !has_alias { + return self.cargo_crates_in_set(); + } + + let crates = match alias { + Alias::Library => self.builder.in_tree_crates("sysroot", Some(self.target)), + Alias::Compiler => self.builder.in_tree_crates("rustc-main", Some(self.target)), + }; + + let crate_names = crates.into_iter().map(|krate| krate.name.to_string()).collect(); + INTERNER.intern_list(crate_names) + } +} + +#[derive(Debug, Copy, Clone)] +pub enum Alias { + Library, + Compiler, +} + +impl Alias { + fn as_str(self) -> &'static str { + match self { + Alias::Library => "library", + Alias::Compiler => "compiler", + } + } } /// A description of the crates in this set, suitable for passing to `builder.info`. @@ -280,15 +317,17 @@ impl StepDescription { } fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool { - if builder.config.exclude.iter().any(|e| pathset.has(&e, builder.kind)) { - println!("Skipping {:?} because it is excluded", pathset); + if builder.config.skip.iter().any(|e| pathset.has(&e, builder.kind)) { + if !matches!(builder.config.dry_run, DryRun::SelfCheck) { + println!("Skipping {pathset:?} because it is excluded"); + } return true; } - if !builder.config.exclude.is_empty() { + if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) { builder.verbose(&format!( "{:?} not skipped for {:?} -- not in {:?}", - pathset, self.name, builder.config.exclude + pathset, self.name, builder.config.skip )); } false @@ -354,7 +393,7 @@ impl StepDescription { eprintln!( "note: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`" ); - crate::detail_exit_macro!(1); + crate::exit!(1); } } } @@ -432,8 +471,7 @@ impl<'a> ShouldRun<'a> { // `compiler` and `library` folders respectively. assert!( self.kind == Kind::Setup || !self.builder.src.join(alias).exists(), - "use `builder.path()` for real paths: {}", - alias + "use `builder.path()` for real paths: {alias}" ); self.paths.insert(PathSet::Set( std::iter::once(TaskPath { path: alias.into(), kind: Some(self.kind) }).collect(), @@ -665,6 +703,7 @@ impl<'a> Builder<'a> { llvm::Lld, llvm::CrtBeginEnd, tool::RustdocGUITest, + tool::OptimizedDist ), Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, @@ -897,21 +936,6 @@ impl<'a> Builder<'a> { Self::new_internal(build, kind, paths.to_owned()) } - /// Creates a new standalone builder for use outside of the normal process - pub fn new_standalone( - build: &mut Build, - kind: Kind, - paths: Vec, - stage: Option, - ) -> Builder<'_> { - // FIXME: don't mutate `build` - if let Some(stage) = stage { - build.config.stage = stage; - } - - Self::new_internal(build, kind, paths.to_owned()) - } - pub fn execute_cli(&self) { self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths); } @@ -1256,7 +1280,7 @@ impl<'a> Builder<'a> { out_dir.join(target.triple).join("doc") } } - _ => panic!("doc mode {:?} not expected", mode), + _ => panic!("doc mode {mode:?} not expected"), }; let rustdoc = self.rustdoc(compiler); self.clear_if_dirty(&my_out, &rustdoc); @@ -1333,7 +1357,7 @@ impl<'a> Builder<'a> { "error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component" ); eprintln!("help: try `rustup component add clippy`"); - crate::detail_exit_macro!(1); + crate::exit!(1); }); if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") { rustflags.arg("--cfg=bootstrap"); @@ -1602,6 +1626,7 @@ impl<'a> Builder<'a> { // 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.rpath_enabled(target) && util::use_host_linker(target) { + let libdir = self.sysroot_libdir_relative(compiler).to_str().unwrap(); 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 @@ -1609,15 +1634,15 @@ impl<'a> Builder<'a> { // so. Note that this is definitely a hack, and we should likely // flesh out rpath support more fully in the future. rustflags.arg("-Zosx-rpath-install-name"); - Some("-Wl,-rpath,@loader_path/../lib") + Some(format!("-Wl,-rpath,@loader_path/../{libdir}")) } else if !target.contains("windows") && !target.contains("aix") { rustflags.arg("-Clink-args=-Wl,-z,origin"); - Some("-Wl,-rpath,$ORIGIN/../lib") + Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}")) } else { None }; if let Some(rpath) = rpath { - rustflags.arg(&format!("-Clink-args={}", rpath)); + rustflags.arg(&format!("-Clink-args={rpath}")); } } @@ -1631,7 +1656,7 @@ impl<'a> Builder<'a> { if let Some(target_linker) = self.linker(target) { let target = crate::envify(&target.triple); - cargo.env(&format!("CARGO_TARGET_{}_LINKER", target), target_linker); + cargo.env(&format!("CARGO_TARGET_{target}_LINKER"), target_linker); } if self.is_fuse_ld_lld(target) { rustflags.arg("-Clink-args=-fuse-ld=lld"); @@ -1867,24 +1892,24 @@ impl<'a> Builder<'a> { }; let triple_underscored = target.triple.replace("-", "_"); let cc = ccacheify(&self.cc(target)); - cargo.env(format!("CC_{}", triple_underscored), &cc); + cargo.env(format!("CC_{triple_underscored}"), &cc); let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" "); - cargo.env(format!("CFLAGS_{}", triple_underscored), &cflags); + cargo.env(format!("CFLAGS_{triple_underscored}"), &cflags); if let Some(ar) = self.ar(target) { let ranlib = format!("{} s", ar.display()); cargo - .env(format!("AR_{}", triple_underscored), ar) - .env(format!("RANLIB_{}", triple_underscored), ranlib); + .env(format!("AR_{triple_underscored}"), ar) + .env(format!("RANLIB_{triple_underscored}"), ranlib); } if let Ok(cxx) = self.cxx(target) { let cxx = ccacheify(&cxx); let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" "); cargo - .env(format!("CXX_{}", triple_underscored), &cxx) - .env(format!("CXXFLAGS_{}", triple_underscored), cxxflags); + .env(format!("CXX_{triple_underscored}"), &cxx) + .env(format!("CXXFLAGS_{triple_underscored}"), cxxflags); } } @@ -1997,7 +2022,7 @@ impl<'a> Builder<'a> { if let Some(limit) = limit { if stage == 0 || self.config.default_codegen_backend().unwrap_or_default() == "llvm" { - rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={}", limit)); + rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}")); } } } @@ -2005,7 +2030,7 @@ impl<'a> Builder<'a> { if matches!(mode, Mode::Std) { if let Some(mir_opt_level) = self.config.rust_validate_mir_opts { rustflags.arg("-Zvalidate-mir"); - rustflags.arg(&format!("-Zmir-opt-level={}", mir_opt_level)); + rustflags.arg(&format!("-Zmir-opt-level={mir_opt_level}")); } // Always enable inlining MIR when building the standard library. // Without this flag, MIR inlining is disabled when incremental compilation is enabled. @@ -2015,6 +2040,13 @@ impl<'a> Builder<'a> { rustflags.arg("-Zinline-mir"); } + // set rustc args passed from command line + let rustc_args = + self.config.cmd.rustc_args().iter().map(|s| s.to_string()).collect::>(); + if !rustc_args.is_empty() { + cargo.env("RUSTFLAGS", &rustc_args.join(" ")); + } + Cargo { command: cargo, rustflags, rustdocflags, allow_features } } @@ -2030,9 +2062,9 @@ impl<'a> Builder<'a> { continue; } let mut out = String::new(); - out += &format!("\n\nCycle in build detected when adding {:?}\n", step); + out += &format!("\n\nCycle in build detected when adding {step:?}\n"); for el in stack.iter().rev() { - out += &format!("\t{:?}\n", el); + out += &format!("\t{el:?}\n"); } panic!("{}", out); } @@ -2059,7 +2091,7 @@ impl<'a> Builder<'a> { }; if self.config.print_step_timings && !self.config.dry_run() { - let step_string = format!("{:?}", step); + let step_string = format!("{step:?}"); let brace_index = step_string.find("{").unwrap_or(0); let type_string = type_name::(); println!( @@ -2095,7 +2127,7 @@ impl<'a> Builder<'a> { let desc = StepDescription::from::(kind); let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind)); - // Avoid running steps contained in --exclude + // Avoid running steps contained in --skip for pathset in &should_run.paths { if desc.is_excluded(self, pathset) { return None; @@ -2139,7 +2171,7 @@ impl<'a> Builder<'a> { let path = path.as_ref(); self.info(&format!("Opening doc {}", path.display())); if let Err(err) = opener::open(path) { - self.info(&format!("{}\n", err)); + self.info(&format!("{err}\n")); } } } diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index 31dcee582..43b4a34fe 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -68,13 +68,17 @@ macro_rules! std { } macro_rules! doc_std { - ($host:ident => $target:ident, stage = $stage:literal) => { + ($host:ident => $target:ident, stage = $stage:literal) => {{ + let config = configure("doc", &["A"], &["A"]); + let build = Build::new(config); + let builder = Builder::new(&build); doc::Std::new( $stage, TargetSelection::from_user(stringify!($target)), + &builder, DocumentationFormat::HTML, ) - }; + }}; } macro_rules! rustc { @@ -115,7 +119,7 @@ fn test_intersection() { #[test] fn test_exclude() { let mut config = configure("test", &["A"], &["A"]); - config.exclude = vec!["src/tools/tidy".into()]; + config.skip = vec!["src/tools/tidy".into()]; let cache = run_build(&[], config); // Ensure we have really excluded tidy @@ -133,7 +137,7 @@ fn test_exclude_kind() { // Ensure our test is valid, and `test::Rustc` would be run without the exclude. assert!(run_build(&[], config.clone()).contains::()); // Ensure tests for rustc are skipped. - config.exclude = vec![path.clone()]; + config.skip = vec![path.clone()]; assert!(!run_build(&[], config.clone()).contains::()); // Ensure builds for rustc are not skipped. assert!(run_build(&[], config).contains::()); @@ -583,6 +587,7 @@ mod dist { run: None, only_modified: false, skip: vec![], + extra_checks: None, }; let build = Build::new(config); @@ -654,6 +659,7 @@ mod dist { pass: None, run: None, only_modified: false, + extra_checks: None, }; // Make sure rustfmt binary not being found isn't an error. config.channel = "beta".to_string(); diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 5376c4ec9..53e4ff034 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -75,7 +75,7 @@ where { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s: &U = &*self; - f.write_fmt(format_args!("{:?}", s)) + f.write_fmt(format_args!("{s:?}")) } } @@ -236,7 +236,7 @@ impl Cache { .or_insert_with(|| Box::new(HashMap::::new())) .downcast_mut::>() .expect("invalid type mapped"); - assert!(!stepcache.contains_key(&step), "processing {:?} a second time", step); + assert!(!stepcache.contains_key(&step), "processing {step:?} a second time"); stepcache.insert(step, value); } diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index ade3bfed1..2496c2a9d 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -196,7 +196,7 @@ fn set_compiler( '0'..='6' => {} _ => return, } - let alternative = format!("e{}", gnu_compiler); + let alternative = format!("e{gnu_compiler}"); if Command::new(&alternative).output().is_ok() { cfg.compiler(alternative); } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 1a0f00478..bdefc41c9 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1,10 +1,8 @@ //! Implementation of compiling the compiler and standard library, in "check"-based modes. -use crate::builder::{crate_description, Builder, Kind, RunConfig, ShouldRun, Step}; +use crate::builder::{crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::Interned; -use crate::compile::{ - add_to_sysroot, make_run_crates, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, -}; +use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo}; use crate::config::TargetSelection; use crate::tool::{prepare_tool_cargo, SourceType}; use crate::INTERNER; @@ -89,7 +87,7 @@ impl Step for Std { } fn make_run(run: RunConfig<'_>) { - let crates = make_run_crates(&run, "library"); + let crates = run.make_run_crates(Alias::Library); run.builder.ensure(Std { target: run.target, crates }); } @@ -137,10 +135,11 @@ impl Step for Std { let hostdir = builder.sysroot_libdir(compiler, compiler.host); add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); } + drop(_guard); // don't run on std twice with x.py clippy // don't check test dependencies if we haven't built libtest - if builder.kind == Kind::Clippy || !self.crates.is_empty() { + if builder.kind == Kind::Clippy || !self.crates.iter().any(|krate| krate == "test") { return; } @@ -200,10 +199,11 @@ pub struct Rustc { impl Rustc { pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self { - let mut crates = vec![]; - for krate in builder.in_tree_crates("rustc-main", None) { - crates.push(krate.name.to_string()); - } + let crates = builder + .in_tree_crates("rustc-main", Some(target)) + .into_iter() + .map(|krate| krate.name.to_string()) + .collect(); Self { target, crates: INTERNER.intern_list(crates) } } } @@ -218,7 +218,7 @@ impl Step for Rustc { } fn make_run(run: RunConfig<'_>) { - let crates = make_run_crates(&run, "compiler"); + let crates = run.make_run_crates(Alias::Compiler); run.builder.ensure(Rustc { target: run.target, crates }); } @@ -307,6 +307,12 @@ impl Step for CodegenBackend { } fn run(self, builder: &Builder<'_>) { + // FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved + if builder.build.config.vendor && &self.backend == "gcc" { + println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled."); + return; + } + let compiler = builder.compiler(builder.top_stage, builder.config.build); let target = self.target; let backend = self.backend; @@ -322,7 +328,7 @@ impl Step for CodegenBackend { ); cargo .arg("--manifest-path") - .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend))); + .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml"))); rustc_cargo_env(builder, &mut cargo, target, compiler.stage); let _guard = builder.msg_check(&backend, target); @@ -525,5 +531,5 @@ fn codegen_backend_stamp( ) -> PathBuf { builder .cargo_out(compiler, Mode::Codegen, target) - .join(format!(".librustc_codegen_{}-check.stamp", backend)) + .join(format!(".librustc_codegen_{backend}-check.stamp")) } diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index c1d867a0b..7389816b4 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -26,8 +26,15 @@ impl Step for CleanAll { } fn run(self, builder: &Builder<'_>) -> Self::Output { - let Subcommand::Clean { all, .. } = builder.config.cmd else { unreachable!("wrong subcommand?") }; - clean_default(builder.build, all) + let Subcommand::Clean { all, stage } = builder.config.cmd else { + unreachable!("wrong subcommand?") + }; + + if all && stage.is_some() { + panic!("--all and --stage can't be used at the same time for `x clean`"); + } + + clean(builder.build, all, stage) } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -84,35 +91,70 @@ clean_crate_tree! { Std, Mode::Std, "sysroot"; } -fn clean_default(build: &Build, all: bool) { +fn clean(build: &Build, all: bool, stage: Option) { if build.config.dry_run() { return; } rm_rf("tmp".as_ref()); + // Clean the entire build directory if all { rm_rf(&build.out); - } else { - rm_rf(&build.out.join("tmp")); - rm_rf(&build.out.join("dist")); - rm_rf(&build.out.join("bootstrap")); - rm_rf(&build.out.join("rustfmt.stamp")); - - for host in &build.hosts { - let entries = match build.out.join(host.triple).read_dir() { - Ok(iter) => iter, - Err(_) => continue, - }; - - for entry in entries { - let entry = t!(entry); - if entry.file_name().to_str() == Some("llvm") { - continue; - } - let path = t!(entry.path().canonicalize()); - rm_rf(&path); + return; + } + + // Clean the target stage artifacts + if let Some(stage) = stage { + clean_specific_stage(build, stage); + return; + } + + // Follow the default behaviour + clean_default(build); +} + +fn clean_specific_stage(build: &Build, stage: u32) { + for host in &build.hosts { + let entries = match build.out.join(host.triple).read_dir() { + Ok(iter) => iter, + Err(_) => continue, + }; + + for entry in entries { + let entry = t!(entry); + let stage_prefix = format!("stage{}", stage); + + // if current entry is not related with the target stage, continue + if !entry.file_name().to_str().unwrap_or("").contains(&stage_prefix) { + continue; + } + + let path = t!(entry.path().canonicalize()); + rm_rf(&path); + } + } +} + +fn clean_default(build: &Build) { + rm_rf(&build.out.join("tmp")); + rm_rf(&build.out.join("dist")); + rm_rf(&build.out.join("bootstrap")); + rm_rf(&build.out.join("rustfmt.stamp")); + + for host in &build.hosts { + let entries = match build.out.join(host.triple).read_dir() { + Ok(iter) => iter, + Err(_) => continue, + }; + + for entry in entries { + let entry = t!(entry); + if entry.file_name().to_str() == Some("llvm") { + continue; } + let path = t!(entry.path().canonicalize()); + rm_rf(&path); } } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 14c3ef79a..9c68e5a78 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -23,7 +23,7 @@ use crate::builder::crate_description; use crate::builder::Cargo; use crate::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; use crate::cache::{Interned, INTERNER}; -use crate::config::{LlvmLibunwind, RustcLto, TargetSelection}; +use crate::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; use crate::dist; use crate::llvm; use crate::tool::SourceType; @@ -31,6 +31,7 @@ use crate::util::get_clang_cl_resource_dir; use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date}; use crate::LLVM_TOOLS; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; +use filetime::FileTime; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { @@ -55,17 +56,6 @@ impl Std { } } -/// Given an `alias` selected by the `Step` and the paths passed on the command line, -/// return a list of the crates that should be built. -/// -/// Normally, people will pass *just* `library` if they pass it. -/// But it's possible (although strange) to pass something like `library std core`. -/// Build all crates anyway, as if they hadn't passed the other args. -pub(crate) fn make_run_crates(run: &RunConfig<'_>, alias: &str) -> Interned> { - let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias)); - if has_alias { Default::default() } else { run.cargo_crates_in_set() } -} - impl Step for Std { type Output = (); const DEFAULT: bool = true; @@ -80,10 +70,15 @@ impl Step for Std { } fn make_run(run: RunConfig<'_>) { + // If the paths include "library", build the entire standard library. + let has_alias = + run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library")); + let crates = if has_alias { Default::default() } else { run.cargo_crates_in_set() }; + run.builder.ensure(Std { compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), target: run.target, - crates: make_run_crates(&run, "library"), + crates, force_recompile: false, }); } @@ -228,13 +223,6 @@ fn copy_third_party_objects( ) -> Vec<(PathBuf, DependencyType)> { let mut target_deps = vec![]; - // FIXME: remove this in 2021 - if target == "x86_64-fortanix-unknown-sgx" { - if env::var_os("X86_FORTANIX_SGX_LIBS").is_some() { - builder.info("Warning: X86_FORTANIX_SGX_LIBS environment variable is ignored, libunwind is now compiled as part of rustbuild"); - } - } - if builder.config.sanitizers_enabled(target) && compiler.stage != 0 { // The sanitizers are only copied in stage1 or above, // to avoid creating dependency on LLVM. @@ -274,7 +262,7 @@ fn copy_self_contained_objects( // to using gcc from a glibc-targeting toolchain for linking. // To do that we have to distribute musl startup objects as a part of Rust toolchain // and link with them manually in the self-contained mode. - if target.contains("musl") { + if target.contains("musl") && !target.contains("unikraft") { let srcdir = builder.musl_libdir(target).unwrap_or_else(|| { panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple) }); @@ -300,13 +288,14 @@ fn copy_self_contained_objects( let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained); target_deps.push((libunwind_path, DependencyType::TargetSelfContained)); } - } else if target.ends_with("-wasi") { + } else if target.contains("-wasi") { let srcdir = builder .wasi_root(target) .unwrap_or_else(|| { panic!("Target {:?} does not have a \"wasi-root\" key", target.triple) }) - .join("lib/wasm32-wasi"); + .join("lib") + .join(target.to_string().replace("-preview1", "")); for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] { copy_and_stamp( builder, @@ -336,6 +325,10 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } + if let Some(path) = builder.config.profiler_path(target) { + cargo.env("LLVM_PROFILER_RT_LIB", path); + } + // Determine if we're going to compile in optimized C intrinsics to // the `compiler-builtins` crate. These intrinsics live in LLVM's // `compiler-rt` repository, but our `src/llvm-project` submodule isn't @@ -406,9 +399,13 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car } } - if target.ends_with("-wasi") { + if target.contains("-wasi") { if let Some(p) = builder.wasi_root(target) { - let root = format!("native={}/lib/wasm32-wasi", p.to_str().unwrap()); + let root = format!( + "native={}/lib/{}", + p.to_str().unwrap(), + target.to_string().replace("-preview1", "") + ); cargo.rustflag("-L").rustflag(&root); } } @@ -508,6 +505,49 @@ impl Step for StdLink { }; add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); + + // Special case for stage0, to make `rustup toolchain link` and `x dist --stage 0` + // work for stage0-sysroot. We only do this if the stage0 compiler comes from beta, + // and is not set to a custom path. + if compiler.stage == 0 + && builder + .build + .config + .initial_rustc + .starts_with(builder.out.join(&compiler.host.triple).join("stage0/bin")) + { + // Copy bin files from stage0/bin to stage0-sysroot/bin + let sysroot = builder.out.join(&compiler.host.triple).join("stage0-sysroot"); + + let host = compiler.host.triple; + let stage0_bin_dir = builder.out.join(&host).join("stage0/bin"); + let sysroot_bin_dir = sysroot.join("bin"); + t!(fs::create_dir_all(&sysroot_bin_dir)); + builder.cp_r(&stage0_bin_dir, &sysroot_bin_dir); + + // Copy all *.so files from stage0/lib to stage0-sysroot/lib + let stage0_lib_dir = builder.out.join(&host).join("stage0/lib"); + if let Ok(files) = fs::read_dir(&stage0_lib_dir) { + for file in files { + let file = t!(file); + let path = file.path(); + if path.is_file() && is_dylib(&file.file_name().into_string().unwrap()) { + builder.copy(&path, &sysroot.join("lib").join(path.file_name().unwrap())); + } + } + } + + // Copy codegen-backends from stage0 + let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler); + t!(fs::create_dir_all(&sysroot_codegen_backends)); + let stage0_codegen_backends = builder + .out + .join(&host) + .join("stage0/lib/rustlib") + .join(&host) + .join("codegen-backends"); + builder.cp_r(&stage0_codegen_backends, &sysroot_codegen_backends); + } } } @@ -645,8 +685,8 @@ fn cp_rustc_component_to_ci_sysroot( contents: Vec, ) { let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false }); + let ci_rustc_dir = builder.config.ci_rustc_dir(); - let ci_rustc_dir = builder.out.join(&*builder.build.build.triple).join("ci-rustc"); for file in contents { let src = ci_rustc_dir.join(&file); let dst = sysroot.join(file); @@ -785,7 +825,7 @@ impl Step for Rustc { let is_collecting = if let Some(path) = &builder.config.rust_profile_generate { if compiler.stage == 1 { - cargo.rustflag(&format!("-Cprofile-generate={}", path)); + cargo.rustflag(&format!("-Cprofile-generate={path}")); // Apparently necessary to avoid overflowing the counters during // a Cargo build profile cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4"); @@ -795,7 +835,7 @@ impl Step for Rustc { } } else if let Some(path) = &builder.config.rust_profile_use { if compiler.stage == 1 { - cargo.rustflag(&format!("-Cprofile-use={}", path)); + cargo.rustflag(&format!("-Cprofile-use={path}")); cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function"); true } else { @@ -828,7 +868,7 @@ impl Step for Rustc { RustcLto::Fat => "fat", _ => unreachable!(), }; - cargo.rustflag(&format!("-Clto={}", lto_type)); + cargo.rustflag(&format!("-Clto={lto_type}")); cargo.rustflag("-Cembed-bitcode=yes"); } RustcLto::ThinLocal => { /* Do nothing, this is the default */ } @@ -853,16 +893,30 @@ impl Step for Rustc { compiler.host, target, ); + let stamp = librustc_stamp(builder, compiler, target); run_cargo( builder, cargo, vec![], - &librustc_stamp(builder, compiler, target), + &stamp, vec![], false, true, // Only ship rustc_driver.so and .rmeta files, not all intermediate .rlib files. ); + // When building `librustc_driver.so` (like `libLLVM.so`) on linux, it can contain + // unexpected debuginfo from dependencies, for example from the C++ standard library used in + // our LLVM wrapper. Unless we're explicitly requesting `librustc_driver` to be built with + // debuginfo (via the debuginfo level of the executables using it): strip this debuginfo + // away after the fact. + if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None + && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None + { + let target_root_dir = stamp.parent().unwrap(); + let rustc_driver = target_root_dir.join("librustc_driver.so"); + strip_debug(builder, target, &rustc_driver); + } + builder.ensure(RustcLink::from_rustc( self, builder.compiler(compiler.stage, builder.config.build), @@ -1079,7 +1133,7 @@ fn needs_codegen_config(run: &RunConfig<'_>) -> bool { needs_codegen_cfg } -const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_"; +pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_"; fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool { if path.path.to_str().unwrap().contains(&CODEGEN_BACKEND_PREFIX) { @@ -1162,7 +1216,7 @@ impl Step for CodegenBackend { let mut cargo = builder.cargo(compiler, Mode::Codegen, SourceType::InTree, target, "build"); cargo .arg("--manifest-path") - .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend))); + .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml"))); rustc_cargo_env(builder, &mut cargo, target, compiler.stage); let tmp_stamp = out_dir.join(".tmp.stamp"); @@ -1267,7 +1321,7 @@ fn codegen_backend_stamp( ) -> PathBuf { builder .cargo_out(compiler, Mode::Codegen, target) - .join(format!(".librustc_codegen_{}.stamp", backend)) + .join(format!(".librustc_codegen_{backend}.stamp")) } pub fn compiler_file( @@ -1282,7 +1336,7 @@ pub fn compiler_file( } let mut cmd = Command::new(compiler); cmd.args(builder.cflags(target, GitRepo::Rustc, c)); - cmd.arg(format!("-print-file-name={}", file)); + cmd.arg(format!("-print-file-name={file}")); let out = output(&mut cmd); PathBuf::from(out.trim()) } @@ -1334,6 +1388,16 @@ impl Step for Sysroot { let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); + // In some cases(see https://github.com/rust-lang/rust/issues/109314), when the stage0 + // compiler relies on more recent version of LLVM than the beta compiler, it may not + // be able to locate the correct LLVM in the sysroot. This situation typically occurs + // when we upgrade LLVM version while the beta compiler continues to use an older version. + // + // Make sure to add the correct version of LLVM into the stage0 sysroot. + if compiler.stage == 0 { + dist::maybe_install_llvm_target(builder, compiler.host, &sysroot); + } + // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0. if builder.download_rustc() && compiler.stage != 0 { assert_eq!( @@ -1381,7 +1445,7 @@ impl Step for Sysroot { // FIXME: this is wrong when compiler.host != build, but we don't support that today OsStr::new(std::env::consts::DLL_EXTENSION), ]; - let ci_rustc_dir = builder.ci_rustc_dir(builder.config.build); + let ci_rustc_dir = builder.config.ci_rustc_dir(); builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| { if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) { return true; @@ -1783,7 +1847,7 @@ pub fn run_cargo( }); if !ok { - crate::detail_exit_macro!(1); + crate::exit!(1); } // Ok now we need to actually find all the files listed in `toplevel`. We've @@ -1806,10 +1870,10 @@ pub fn run_cargo( }); let path_to_add = match max { Some(triple) => triple.0.to_str().unwrap(), - None => panic!("no output generated for {:?} {:?}", prefix, extension), + None => panic!("no output generated for {prefix:?} {extension:?}"), }; if is_dylib(path_to_add) { - let candidate = format!("{}.lib", path_to_add); + let candidate = format!("{path_to_add}.lib"); let candidate = PathBuf::from(candidate); if candidate.exists() { deps.push((candidate, DependencyType::Target)); @@ -1861,10 +1925,10 @@ pub fn stream_cargo( cargo.arg(arg); } - builder.verbose(&format!("running: {:?}", cargo)); + builder.verbose(&format!("running: {cargo:?}")); let mut child = match cargo.spawn() { Ok(child) => child, - Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cargo, e), + Err(e) => panic!("failed to execute command: {cargo:?}\nerror: {e}"), }; // Spawn Cargo slurping up its JSON output. We'll start building up the @@ -1877,12 +1941,12 @@ pub fn stream_cargo( Ok(msg) => { if builder.config.json_output { // Forward JSON to stdout. - println!("{}", line); + println!("{line}"); } cb(msg) } // If this was informational, just print it out and continue - Err(_) => println!("{}", line), + Err(_) => println!("{line}"), } } @@ -1890,9 +1954,8 @@ pub fn stream_cargo( let status = t!(child.wait()); if builder.is_verbose() && !status.success() { eprintln!( - "command did not execute successfully: {:?}\n\ - expected success, got: {}", - cargo, status + "command did not execute successfully: {cargo:?}\n\ + expected success, got: {status}" ); } status.success() @@ -1919,3 +1982,30 @@ pub enum CargoMessage<'a> { success: bool, }, } + +pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) { + // FIXME: to make things simpler for now, limit this to the host and target where we know + // `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not + // cross-compiling. Expand this to other appropriate targets in the future. + if target != "x86_64-unknown-linux-gnu" || target != builder.config.build || !path.exists() { + return; + } + + let previous_mtime = FileTime::from_last_modification_time(&path.metadata().unwrap()); + // Note: `output` will propagate any errors here. + output(Command::new("strip").arg("--strip-debug").arg(path)); + + // After running `strip`, we have to set the file modification time to what it was before, + // otherwise we risk Cargo invalidating its fingerprint and rebuilding the world next time + // bootstrap is invoked. + // + // An example of this is if we run this on librustc_driver.so. In the first invocation: + // - Cargo will build librustc_driver.so (mtime of 1) + // - Cargo will build rustc-main (mtime of 2) + // - Bootstrap will strip librustc_driver.so (changing the mtime to 3). + // + // In the second invocation of bootstrap, Cargo will see that the mtime of librustc_driver.so + // is greater than the mtime of rustc-main, and will rebuild rustc-main. That will then cause + // everything else (standard library, future stages...) to be rebuilt. + t!(filetime::set_file_mtime(path, previous_mtime)); +} diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index fe932fd6b..4821d20a8 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -20,10 +20,11 @@ use std::str::FromStr; use crate::cache::{Interned, INTERNER}; use crate::cc_detect::{ndk_compiler, Language}; use crate::channel::{self, GitInfo}; +use crate::compile::CODEGEN_BACKEND_PREFIX; pub use crate::flags::Subcommand; use crate::flags::{Color, Flags, Warnings}; use crate::util::{exe, output, t}; -use build_helper::detail_exit_macro; +use build_helper::exit; use once_cell::sync::OnceCell; use semver::Version; use serde::{Deserialize, Deserializer}; @@ -50,7 +51,7 @@ pub enum DryRun { UserSelected, } -#[derive(Copy, Clone, Default)] +#[derive(Copy, Clone, Default, PartialEq, Eq)] pub enum DebuginfoLevel { #[default] None, @@ -130,7 +131,7 @@ pub struct Config { pub sanitizers: bool, pub profiler: bool, pub omit_git_hash: bool, - pub exclude: Vec, + pub skip: Vec, pub include_default_paths: bool, pub rustc_error_format: Option, pub json_output: bool, @@ -232,8 +233,8 @@ pub struct Config { pub llvm_profile_use: Option, pub llvm_profile_generate: bool, pub llvm_libunwind_default: Option, - pub llvm_bolt_profile_generate: bool, - pub llvm_bolt_profile_use: Option, + + pub reproducible_artifacts: Vec, pub build: TargetSelection, pub hosts: Vec, @@ -356,7 +357,7 @@ impl FromStr for LlvmLibunwind { "no" => Ok(Self::No), "in-tree" => Ok(Self::InTree), "system" => Ok(Self::System), - invalid => Err(format!("Invalid value '{}' for rust.llvm-libunwind config.", invalid)), + invalid => Err(format!("Invalid value '{invalid}' for rust.llvm-libunwind config.")), } } } @@ -420,7 +421,7 @@ impl std::str::FromStr for RustcLto { "thin" => Ok(RustcLto::Thin), "fat" => Ok(RustcLto::Fat), "off" => Ok(RustcLto::Off), - _ => Err(format!("Invalid value for rustc LTO: {}", s)), + _ => Err(format!("Invalid value for rustc LTO: {s}")), } } } @@ -498,7 +499,7 @@ impl fmt::Display for TargetSelection { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.triple)?; if let Some(file) = self.file { - write!(f, "({})", file)?; + write!(f, "({file})")?; } Ok(()) } @@ -506,7 +507,7 @@ impl fmt::Display for TargetSelection { impl fmt::Debug for TargetSelection { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self) + write!(f, "{self}") } } @@ -533,7 +534,7 @@ pub struct Target { pub linker: Option, pub ndk: Option, pub sanitizers: Option, - pub profiler: Option, + pub profiler: Option, pub rpath: Option, pub crt_static: Option, pub musl_root: Option, @@ -646,7 +647,7 @@ macro_rules! define_config { panic!("overriding existing option") } else { eprintln!("overriding existing option: `{}`", stringify!($field)); - detail_exit_macro!(2); + exit!(2); } } else { self.$field = other.$field; @@ -745,7 +746,7 @@ impl Merge for Option { panic!("overriding existing option") } else { eprintln!("overriding existing option"); - detail_exit_macro!(2); + exit!(2); } } else { *self = other; @@ -862,9 +863,9 @@ define_config! { } } -#[derive(Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize)] #[serde(untagged)] -enum StringOrBool { +pub enum StringOrBool { String(String), Bool(bool), } @@ -875,11 +876,16 @@ impl Default for StringOrBool { } } -#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] -#[serde(untagged)] +impl StringOrBool { + fn is_string_or_true(&self) -> bool { + matches!(self, Self::String(_) | Self::Bool(true)) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] pub enum RustOptimize { - #[serde(deserialize_with = "deserialize_and_validate_opt_level")] String(String), + Int(u8), Bool(bool), } @@ -889,26 +895,73 @@ impl Default for RustOptimize { } } -fn deserialize_and_validate_opt_level<'de, D>(d: D) -> Result -where - D: serde::de::Deserializer<'de>, -{ - let v = String::deserialize(d)?; - if ["0", "1", "2", "3", "s", "z"].iter().find(|x| **x == v).is_some() { - Ok(v) - } else { - Err(format!(r#"unrecognized option for rust optimize: "{}", expected one of "0", "1", "2", "3", "s", "z""#, v)).map_err(serde::de::Error::custom) +impl<'de> Deserialize<'de> for RustOptimize { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_any(OptimizeVisitor) + } +} + +struct OptimizeVisitor; + +impl<'de> serde::de::Visitor<'de> for OptimizeVisitor { + type Value = RustOptimize; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str(r#"one of: 0, 1, 2, 3, "s", "z", true, false"#) + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + if ["s", "z"].iter().find(|x| **x == value).is_some() { + Ok(RustOptimize::String(value.to_string())) + } else { + Err(format_optimize_error_msg(value)).map_err(serde::de::Error::custom) + } + } + + fn visit_i64(self, value: i64) -> Result + where + E: serde::de::Error, + { + if matches!(value, 0..=3) { + Ok(RustOptimize::Int(value as u8)) + } else { + Err(format_optimize_error_msg(value)).map_err(serde::de::Error::custom) + } + } + + fn visit_bool(self, value: bool) -> Result + where + E: serde::de::Error, + { + Ok(RustOptimize::Bool(value)) } } +fn format_optimize_error_msg(v: impl std::fmt::Display) -> String { + format!( + r#"unrecognized option for rust optimize: "{v}", expected one of 0, 1, 2, 3, "s", "z", true, false"# + ) +} + impl RustOptimize { pub(crate) fn is_release(&self) -> bool { - if let RustOptimize::Bool(true) | RustOptimize::String(_) = &self { true } else { false } + match &self { + RustOptimize::Bool(true) | RustOptimize::String(_) => true, + RustOptimize::Int(i) => *i > 0, + RustOptimize::Bool(false) => false, + } } pub(crate) fn get_opt_level(&self) -> Option { match &self { RustOptimize::String(s) => Some(s.clone()), + RustOptimize::Int(i) => Some(i.to_string()), RustOptimize::Bool(_) => None, } } @@ -991,7 +1044,7 @@ define_config! { llvm_libunwind: Option = "llvm-libunwind", android_ndk: Option = "android-ndk", sanitizers: Option = "sanitizers", - profiler: Option = "profiler", + profiler: Option = "profiler", rpath: Option = "rpath", crt_static: Option = "crt-static", musl_root: Option = "musl-root", @@ -1054,7 +1107,7 @@ impl Config { .and_then(|table: toml::Value| TomlConfig::deserialize(table)) .unwrap_or_else(|err| { eprintln!("failed to parse TOML configuration '{}': {err}", file.display()); - detail_exit_macro!(2); + exit!(2); }) } Self::parse_inner(args, get_toml) @@ -1066,7 +1119,7 @@ impl Config { // Set flags. config.paths = std::mem::take(&mut flags.paths); - config.exclude = flags.exclude; + config.skip = flags.skip.into_iter().chain(flags.exclude).collect(); config.include_default_paths = flags.include_default_paths; config.rustc_error_format = flags.rustc_error_format; config.json_output = flags.json_output; @@ -1081,15 +1134,6 @@ impl Config { 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; - config.llvm_bolt_profile_use = flags.llvm_bolt_profile_use; - - if config.llvm_bolt_profile_generate && config.llvm_bolt_profile_use.is_some() { - eprintln!( - "Cannot use both `llvm_bolt_profile_generate` and `llvm_bolt_profile_use` at the same time" - ); - detail_exit_macro!(1); - } // Infer the rest of the configuration. @@ -1179,7 +1223,7 @@ impl Config { include_path.push("src"); include_path.push("bootstrap"); include_path.push("defaults"); - include_path.push(format!("config.{}.toml", include)); + include_path.push(format!("config.{include}.toml")); let included_toml = get_toml(&include_path); toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate); } @@ -1212,7 +1256,7 @@ impl Config { } } eprintln!("failed to parse override `{option}`: `{err}"); - detail_exit_macro!(2) + exit!(2) } toml.merge(override_toml, ReplaceOpt::Override); @@ -1328,6 +1372,25 @@ impl Config { let mut omit_git_hash = None; if let Some(rust) = toml.rust { + set(&mut config.channel, rust.channel); + + config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc); + // This list is incomplete, please help by expanding it! + if config.download_rustc_commit.is_some() { + // We need the channel used by the downloaded compiler to match the one we set for rustdoc; + // otherwise rustdoc-ui tests break. + let ci_channel = t!(fs::read_to_string(config.src.join("src/ci/channel"))); + let ci_channel = ci_channel.trim_end(); + if config.channel != ci_channel + && !(config.channel == "dev" && ci_channel == "nightly") + { + panic!( + "setting rust.channel={} is incompatible with download-rustc", + config.channel + ); + } + } + debug = rust.debug; debug_assertions = rust.debug_assertions; debug_assertions_std = rust.debug_assertions_std; @@ -1339,6 +1402,7 @@ impl Config { debuginfo_level_std = rust.debuginfo_level_std; debuginfo_level_tools = rust.debuginfo_level_tools; debuginfo_level_tests = rust.debuginfo_level_tests; + config.rust_split_debuginfo = rust .split_debuginfo .as_deref() @@ -1354,7 +1418,6 @@ impl Config { set(&mut config.jemalloc, rust.jemalloc); set(&mut config.test_compare_mode, rust.test_compare_mode); set(&mut config.backtrace, rust.backtrace); - set(&mut config.channel, rust.channel); config.description = rust.description; set(&mut config.rust_dist_src, rust.dist_src); set(&mut config.verbose_tests, rust.verbose_tests); @@ -1387,16 +1450,27 @@ impl Config { .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")); if let Some(ref backends) = rust.codegen_backends { - config.rust_codegen_backends = - backends.iter().map(|s| INTERNER.intern_str(s)).collect(); + let available_backends = vec!["llvm", "cranelift", "gcc"]; + + config.rust_codegen_backends = backends.iter().map(|s| { + if let Some(backend) = s.strip_prefix(CODEGEN_BACKEND_PREFIX) { + if available_backends.contains(&backend) { + panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'."); + } else { + println!("help: '{s}' for 'rust.codegen-backends' might fail. \ + Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \ + In this case, it would be referred to as '{backend}'."); + } + } + + INTERNER.intern_str(s) + }).collect(); } config.rust_codegen_units = rust.codegen_units.map(threads_from_config); config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use); config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate); - config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc); - config.rust_lto = rust .lto .as_deref() @@ -1408,6 +1482,8 @@ impl Config { config.rust_profile_generate = flags.rust_profile_generate; } + config.reproducible_artifacts = flags.reproducible_artifact; + // rust_info must be set before is_ci_llvm_available() is called. let default = config.channel == "dev"; config.omit_git_hash = omit_git_hash.unwrap_or(default); @@ -1452,7 +1528,7 @@ impl Config { let asserts = llvm_assertions.unwrap_or(false); config.llvm_from_ci = match llvm.download_ci_llvm { Some(StringOrBool::String(s)) => { - assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s); + assert!(s == "if-available", "unknown option `{s}` for download-ci-llvm"); crate::llvm::is_ci_llvm_available(&config, asserts) } Some(StringOrBool::Bool(b)) => b, @@ -1508,6 +1584,11 @@ impl Config { let mut target = Target::from_triple(&triple); if let Some(ref s) = cfg.llvm_config { + if config.download_rustc_commit.is_some() && triple == &*config.build.triple { + panic!( + "setting llvm_config for the host is incompatible with download-rustc" + ); + } target.llvm_config = Some(config.src.join(s)); } target.llvm_has_rust_patches = cfg.llvm_has_rust_patches; @@ -1673,6 +1754,18 @@ impl Config { } } + /// Runs a command, printing out nice contextual information if it fails. + /// Exits if the command failed to execute at all, otherwise returns its + /// `status.success()`. + #[deprecated = "use `Builder::try_run` instead where possible"] + pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> { + if self.dry_run() { + return Ok(()); + } + self.verbose(&format!("running: {cmd:?}")); + build_helper::util::try_run(cmd, self.is_verbose()) + } + /// A git invocation which runs inside the source directory. /// /// Use this rather than `Command::new("git")` in order to support out-of-tree builds. @@ -1709,10 +1802,10 @@ impl Config { pub(crate) fn artifact_version_part(&self, commit: &str) -> String { let (channel, version) = if self.rust_info.is_managed_git_subrepository() { let mut channel = self.git(); - channel.arg("show").arg(format!("{}:src/ci/channel", commit)); + channel.arg("show").arg(format!("{commit}:src/ci/channel")); let channel = output(&mut channel); let mut version = self.git(); - version.arg("show").arg(format!("{}:src/version", commit)); + version.arg("show").arg(format!("{commit}:src/version")); let version = output(&mut version); (channel.trim().to_owned(), version.trim().to_owned()) } else { @@ -1729,10 +1822,10 @@ impl Config { "help: consider using a git checkout or ensure these files are readable" ); if let Err(channel) = channel { - eprintln!("reading {}/src/ci/channel failed: {:?}", src, channel); + eprintln!("reading {src}/src/ci/channel failed: {channel:?}"); } if let Err(version) = version { - eprintln!("reading {}/src/version failed: {:?}", src, version); + eprintln!("reading {src}/src/version failed: {version:?}"); } panic!(); } @@ -1778,6 +1871,12 @@ impl Config { self.out.join(&*self.build.triple).join("ci-llvm") } + /// Directory where the extracted `rustc-dev` component is stored. + pub(crate) fn ci_rustc_dir(&self) -> PathBuf { + assert!(self.download_rustc()); + self.out.join(self.build.triple).join("ci-rustc") + } + /// Determine whether llvm should be linked dynamically. /// /// If `false`, llvm should be linked statically. @@ -1813,11 +1912,11 @@ impl Config { self.download_rustc_commit().is_some() } - pub(crate) fn download_rustc_commit(&self) -> Option<&'static str> { + pub(crate) fn download_rustc_commit(&self) -> Option<&str> { static DOWNLOAD_RUSTC: OnceCell> = OnceCell::new(); if self.dry_run() && DOWNLOAD_RUSTC.get().is_none() { // avoid trying to actually download the commit - return None; + return self.download_rustc_commit.as_deref(); } DOWNLOAD_RUSTC @@ -1852,7 +1951,7 @@ impl Config { pub fn verbose(&self, msg: &str) { if self.verbose > 0 { - println!("{}", msg); + println!("{msg}"); } } @@ -1864,12 +1963,24 @@ impl Config { self.target_config.values().any(|t| t.sanitizers == Some(true)) || self.sanitizers } + pub fn profiler_path(&self, target: TargetSelection) -> Option<&str> { + match self.target_config.get(&target)?.profiler.as_ref()? { + StringOrBool::String(s) => Some(s), + StringOrBool::Bool(_) => None, + } + } + pub fn profiler_enabled(&self, target: TargetSelection) -> bool { - self.target_config.get(&target).map(|t| t.profiler).flatten().unwrap_or(self.profiler) + self.target_config + .get(&target) + .and_then(|t| t.profiler.as_ref()) + .map(StringOrBool::is_string_or_true) + .unwrap_or(self.profiler) } pub fn any_profiler_enabled(&self) -> bool { - self.target_config.values().any(|t| t.profiler == Some(true)) || self.profiler + self.target_config.values().any(|t| matches!(&t.profiler, Some(p) if p.is_string_or_true())) + || self.profiler } pub fn rpath_enabled(&self, target: TargetSelection) -> bool { @@ -1930,10 +2041,9 @@ impl Config { { 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 + "Unexpected rustc version: {rustc_version}, we should use {prev_version}/{source_version} to build source with {source_version}" ); - detail_exit_macro!(1); + exit!(1); } } @@ -1945,7 +2055,7 @@ impl Config { Some(StringOrBool::Bool(true)) => false, Some(StringOrBool::String(s)) if s == "if-unchanged" => true, Some(StringOrBool::String(other)) => { - panic!("unrecognized option for download-rustc: {}", other) + panic!("unrecognized option for download-rustc: {other}") } }; @@ -1969,7 +2079,7 @@ impl Config { println!("help: maybe your repository history is too shallow?"); println!("help: consider disabling `download-rustc`"); println!("help: or fetch enough history to include one upstream commit"); - crate::detail_exit_macro!(1); + crate::exit!(1); } // Warn if there were changes to the compiler or standard library since the ancestor commit. diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs index 732df54cd..c340bb298 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/config/tests.rs @@ -184,7 +184,10 @@ fn rust_optimize() { assert_eq!(parse("").rust_optimize.is_release(), true); assert_eq!(parse("rust.optimize = false").rust_optimize.is_release(), false); assert_eq!(parse("rust.optimize = true").rust_optimize.is_release(), true); - assert_eq!(parse("rust.optimize = \"1\"").rust_optimize.get_opt_level(), Some("1".to_string())); + assert_eq!(parse("rust.optimize = 0").rust_optimize.is_release(), false); + assert_eq!(parse("rust.optimize = 1").rust_optimize.is_release(), true); + assert_eq!(parse("rust.optimize = 1").rust_optimize.get_opt_level(), Some("1".to_string())); + assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.is_release(), true); assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.get_opt_level(), Some("s".to_string())); } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index e8eebdfb5..15e8c1eb9 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -180,7 +180,7 @@ def p(msg): def err(msg): - print("configure: error: " + msg) + print("\nconfigure: ERROR: " + msg + "\n") sys.exit(1) def is_value_list(key): @@ -544,12 +544,21 @@ def write_config_toml(writer, section_order, targets, sections): def quit_if_file_exists(file): if os.path.isfile(file): - err("Existing '" + file + "' detected.") + msg = "Existing '{}' detected. Exiting".format(file) + + # If the output object directory isn't empty, we can get these errors + host_objdir = os.environ.get("OBJDIR_ON_HOST") + if host_objdir is not None: + msg += "\nIs objdir '{}' clean?".format(host_objdir) + + err(msg) if __name__ == "__main__": # If 'config.toml' already exists, exit the script at this point quit_if_file_exists('config.toml') + if "GITHUB_ACTIONS" in os.environ: + print("::group::Configure the build") p("processing command line") # Parse all known arguments into a configuration structure that reflects the # TOML we're going to write out @@ -572,3 +581,5 @@ if __name__ == "__main__": p("") p("run `python {}/x.py --help`".format(rust_dir)) + if "GITHUB_ACTIONS" in os.environ: + print("::endgroup::") diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index b34a4b2dc..32da4ac29 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -18,9 +18,7 @@ use std::process::Command; use object::read::archive::ArchiveFile; use object::BinaryFormat; -use sha2::Digest; -use crate::bolt::{instrument_with_bolt, optimize_with_bolt}; use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::channel; @@ -106,7 +104,12 @@ impl Step for JsonDocs { /// Builds the `rust-docs-json` installer component. fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - builder.ensure(crate::doc::Std::new(builder.top_stage, host, DocumentationFormat::JSON)); + builder.ensure(crate::doc::Std::new( + builder.top_stage, + host, + builder, + DocumentationFormat::JSON, + )); let dest = "share/doc/rust/json"; @@ -157,7 +160,7 @@ fn find_files(files: &[&str], path: &[PathBuf]) -> Vec { if let Some(file_path) = file_path { found.push(file_path); } else { - panic!("Could not find '{}' in {:?}", file, path); + panic!("Could not find '{file}' in {path:?}"); } } @@ -897,7 +900,9 @@ impl Step for Src { /// Creates the `rust-src` installer component fn run(self, builder: &Builder<'_>) -> GeneratedTarball { - builder.update_submodule(&Path::new("src/llvm-project")); + if !builder.config.dry_run() { + builder.update_submodule(&Path::new("src/llvm-project")); + } let tarball = Tarball::new_targetless(builder, "rust-src"); @@ -1078,13 +1083,6 @@ impl Step for Cargo { tarball.add_dir(etc.join("man"), "share/man/man1"); tarball.add_legal_and_readme_to("share/doc/cargo"); - for dirent in fs::read_dir(cargo.parent().unwrap()).expect("read_dir") { - let dirent = dirent.expect("read dir entry"); - if dirent.file_name().to_str().expect("utf8").starts_with("cargo-credential-") { - tarball.add_file(&dirent.path(), "libexec", 0o755); - } - } - Some(tarball.generate()) } } @@ -1480,8 +1478,8 @@ impl Step for Extended { rtf.push('}'); fn filter(contents: &str, marker: &str) -> String { - let start = format!("tool-{}-start", marker); - let end = format!("tool-{}-end", marker); + let start = format!("tool-{marker}-start"); + let end = format!("tool-{marker}-end"); let mut lines = Vec::new(); let mut omitted = false; for line in contents.lines() { @@ -1862,7 +1860,7 @@ impl Step for Extended { builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644); builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); - builder.info(&format!("building `msi` installer with {:?}", light)); + builder.info(&format!("building `msi` installer with {light:?}")); let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple); let mut cmd = Command::new(&light); cmd.arg("-nologo") @@ -1941,19 +1939,7 @@ fn install_llvm_file(builder: &Builder<'_>, source: &Path, destination: &Path) { return; } - // After LLVM is built, we modify (instrument or optimize) the libLLVM.so library file. - // This is not done in-place so that the built LLVM files are not "tainted" with BOLT. - // We perform the instrumentation/optimization here, on the fly, just before they are being - // packaged into some destination directory. - let postprocessed = if builder.config.llvm_bolt_profile_generate { - builder.ensure(BoltInstrument::new(source.to_path_buf())) - } else if let Some(path) = &builder.config.llvm_bolt_profile_use { - builder.ensure(BoltOptimize::new(source.to_path_buf(), path.into())) - } else { - source.to_path_buf() - }; - - builder.install(&postprocessed, destination, 0o644); + builder.install(&source, destination, 0o644); } /// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking. @@ -1996,7 +1982,7 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir { let mut cmd = Command::new(llvm_config); cmd.arg("--libfiles"); - builder.verbose(&format!("running {:?}", cmd)); + builder.verbose(&format!("running {cmd:?}")); let files = if builder.config.dry_run() { "".into() } else { output(&mut cmd) }; let build_llvm_out = &builder.llvm_out(builder.config.build); let target_llvm_out = &builder.llvm_out(target); @@ -2038,117 +2024,6 @@ pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection } } -/// Creates an output path to a BOLT-manipulated artifact for the given `file`. -/// The hash of the file is used to make sure that we don't mix BOLT artifacts amongst different -/// files with the same name. -/// -/// We need to keep the file-name the same though, to make sure that copying the manipulated file -/// to a directory will not change the final file path. -fn create_bolt_output_path(builder: &Builder<'_>, file: &Path, hash: &str) -> PathBuf { - let directory = builder.out.join("bolt").join(hash); - t!(fs::create_dir_all(&directory)); - directory.join(file.file_name().unwrap()) -} - -/// Instrument the provided file with BOLT. -/// Returns a path to the instrumented artifact. -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct BoltInstrument { - file: PathBuf, - hash: String, -} - -impl BoltInstrument { - fn new(file: PathBuf) -> Self { - let mut hasher = sha2::Sha256::new(); - hasher.update(t!(fs::read(&file))); - let hash = hex::encode(hasher.finalize().as_slice()); - - Self { file, hash } - } -} - -impl Step for BoltInstrument { - type Output = PathBuf; - - const ONLY_HOSTS: bool = false; - const DEFAULT: bool = false; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() - } - - fn run(self, builder: &Builder<'_>) -> PathBuf { - if builder.build.config.dry_run() { - return self.file.clone(); - } - - if builder.build.config.llvm_from_ci { - println!("warning: trying to use BOLT with LLVM from CI, this will probably not work"); - } - - println!("Instrumenting {} with BOLT", self.file.display()); - - let output_path = create_bolt_output_path(builder, &self.file, &self.hash); - if !output_path.is_file() { - instrument_with_bolt(&self.file, &output_path); - } - output_path - } -} - -/// Optimize the provided file with BOLT. -/// Returns a path to the optimized artifact. -/// -/// The hash is stored in the step to make sure that we don't optimize the same file -/// twice (even under different file paths). -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct BoltOptimize { - file: PathBuf, - profile: PathBuf, - hash: String, -} - -impl BoltOptimize { - fn new(file: PathBuf, profile: PathBuf) -> Self { - let mut hasher = sha2::Sha256::new(); - hasher.update(t!(fs::read(&file))); - hasher.update(t!(fs::read(&profile))); - let hash = hex::encode(hasher.finalize().as_slice()); - - Self { file, profile, hash } - } -} - -impl Step for BoltOptimize { - type Output = PathBuf; - - const ONLY_HOSTS: bool = false; - const DEFAULT: bool = false; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() - } - - fn run(self, builder: &Builder<'_>) -> PathBuf { - if builder.build.config.dry_run() { - return self.file.clone(); - } - - if builder.build.config.llvm_from_ci { - println!("warning: trying to use BOLT with LLVM from CI, this will probably not work"); - } - - println!("Optimizing {} with BOLT", self.file.display()); - - let output_path = create_bolt_output_path(builder, &self.file, &self.hash); - if !output_path.is_file() { - optimize_with_bolt(&self.file, &self.profile, &output_path); - } - output_path - } -} - #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct LlvmTools { pub target: TargetSelection, @@ -2175,7 +2050,7 @@ impl Step for LlvmTools { /* run only if llvm-config isn't used */ if let Some(config) = builder.config.target_config.get(&target) { if let Some(ref _s) = config.llvm_config { - builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target)); + builder.info(&format!("Skipping LlvmTools ({target}): external LLVM")); return None; } } @@ -2231,7 +2106,7 @@ impl Step for RustDev { /* run only if llvm-config isn't used */ if let Some(config) = builder.config.target_config.get(&target) { if let Some(ref _s) = config.llvm_config { - builder.info(&format!("Skipping RustDev ({}): external LLVM", target)); + builder.info(&format!("Skipping RustDev ({target}): external LLVM")); return None; } } @@ -2390,8 +2265,8 @@ impl Step for ReproducibleArtifacts { tarball.add_file(path, ".", 0o644); added_anything = true; } - if let Some(path) = builder.config.llvm_bolt_profile_use.as_ref() { - tarball.add_file(path, ".", 0o644); + for profile in &builder.config.reproducible_artifacts { + tarball.add_file(profile, ".", 0o644); added_anything = true; } if added_anything { Some(tarball.generate()) } else { None } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5ebfe0995..505f06ed1 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -11,13 +11,12 @@ use std::fs; use std::path::{Path, PathBuf}; use crate::builder::crate_description; -use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; +use crate::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; -use crate::compile::make_run_crates; use crate::config::{Config, TargetSelection}; use crate::tool::{self, prepare_tool_cargo, SourceType, Tool}; -use crate::util::{symlink_dir, t, up_to_date}; +use crate::util::{dir_is_empty, symlink_dir, t, up_to_date}; use crate::Mode; macro_rules! submodule_helper { @@ -148,7 +147,7 @@ impl Step for RustbookSrc

{ if !builder.config.dry_run() && !(up_to_date(&src, &index) || up_to_date(&rustbook, &index)) { - builder.info(&format!("Rustbook ({}) - {}", target, name)); + builder.info(&format!("Rustbook ({target}) - {name}")); let _ = fs::remove_dir_all(&out); builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(out)); @@ -198,11 +197,21 @@ impl Step for TheBook { let compiler = self.compiler; let target = self.target; + let absolute_path = builder.src.join(&relative_path); + let redirect_path = absolute_path.join("redirects"); + if !absolute_path.exists() + || !redirect_path.exists() + || dir_is_empty(&absolute_path) + || dir_is_empty(&redirect_path) + { + eprintln!("Please checkout submodule: {}", relative_path.display()); + crate::exit!(1); + } // build book builder.ensure(RustbookSrc { target, name: INTERNER.intern_str("book"), - src: INTERNER.intern_path(builder.src.join(&relative_path)), + src: INTERNER.intern_path(absolute_path.clone()), parent: Some(self), }); @@ -210,8 +219,8 @@ impl Step for TheBook { for edition in &["first-edition", "second-edition", "2018-edition"] { builder.ensure(RustbookSrc { target, - name: INTERNER.intern_string(format!("book/{}", edition)), - src: INTERNER.intern_path(builder.src.join(&relative_path).join(edition)), + name: INTERNER.intern_string(format!("book/{edition}")), + src: INTERNER.intern_path(absolute_path.join(edition)), // There should only be one book that is marked as the parent for each target, so // treat the other editions as not having a parent. parent: Option::::None, @@ -221,9 +230,12 @@ impl Step for TheBook { // build the version info page and CSS let shared_assets = builder.ensure(SharedAssets { target }); + // build the command first so we don't nest GHA groups + builder.rustdoc_cmd(compiler); + // build the redirect pages - builder.msg_doc(compiler, "book redirect pages", target); - for file in t!(fs::read_dir(builder.src.join(&relative_path).join("redirects"))) { + let _guard = builder.msg_doc(compiler, "book redirect pages", target); + for file in t!(fs::read_dir(redirect_path)) { let file = t!(file); let path = file.path(); let path = path.to_str().unwrap(); @@ -306,7 +318,7 @@ impl Step for Standalone { fn run(self, builder: &Builder<'_>) { let target = self.target; let compiler = self.compiler; - builder.msg_doc(compiler, "standalone", target); + let _guard = builder.msg_doc(compiler, "standalone", target); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); @@ -424,8 +436,18 @@ pub struct Std { } impl Std { - pub(crate) fn new(stage: u32, target: TargetSelection, format: DocumentationFormat) -> Self { - Std { stage, target, format, crates: INTERNER.intern_list(vec![]) } + pub(crate) fn new( + stage: u32, + target: TargetSelection, + builder: &Builder<'_>, + format: DocumentationFormat, + ) -> Self { + let crates = builder + .in_tree_crates("sysroot", Some(target)) + .into_iter() + .map(|krate| krate.name.to_string()) + .collect(); + Std { stage, target, format, crates: INTERNER.intern_list(crates) } } } @@ -447,7 +469,7 @@ impl Step for Std { } else { DocumentationFormat::HTML }, - crates: make_run_crates(&run, "library"), + crates: run.make_run_crates(Alias::Library), }); } @@ -455,7 +477,7 @@ impl Step for Std { /// /// This will generate all documentation for the standard library and its /// dependencies. This is largely just a wrapper around `cargo doc`. - fn run(mut self, builder: &Builder<'_>) { + fn run(self, builder: &Builder<'_>) { let stage = self.stage; let target = self.target; let out = match self.format { @@ -493,20 +515,17 @@ impl Step for Std { return; } - // Look for library/std, library/core etc in the `x.py doc` arguments and - // open the corresponding rendered docs. - if self.crates.is_empty() { - self.crates = INTERNER.intern_list(vec!["library".to_owned()]); - }; - - for requested_crate in &*self.crates { - if requested_crate == "library" { - // For `x.py doc library --open`, open `std` by default. - let index = out.join("std").join("index.html"); - builder.open_in_browser(index); - } else if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) { - let index = out.join(requested_crate).join("index.html"); - builder.open_in_browser(index); + if builder.paths.iter().any(|path| path.ends_with("library")) { + // For `x.py doc library --open`, open `std` by default. + let index = out.join("std").join("index.html"); + builder.open_in_browser(index); + } else { + for requested_crate in &*self.crates { + if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) { + let index = out.join(requested_crate).join("index.html"); + builder.open_in_browser(index); + break; + } } } } @@ -539,9 +558,6 @@ impl DocumentationFormat { } /// Build the documentation for public standard library crates. -/// -/// `requested_crates` can be used to build only a subset of the crates. If empty, all crates will -/// be built. fn doc_std( builder: &Builder<'_>, format: DocumentationFormat, @@ -554,16 +570,12 @@ fn doc_std( if builder.no_std(target) == Some(true) { panic!( "building std documentation for no_std target {target} is not supported\n\ - Set `docs = false` in the config to disable documentation, or pass `--exclude doc::library`." + Set `docs = false` in the config to disable documentation, or pass `--skip library`." ); } let compiler = builder.compiler(stage, builder.config.build); - let description = - format!("library{} in {} format", crate_description(&requested_crates), format.as_str()); - let _guard = builder.msg_doc(compiler, &description, target); - let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" }; let target_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name); @@ -592,22 +604,18 @@ fn doc_std( cargo.rustdocflag("--document-private-items").rustdocflag("--document-hidden-items"); } - // HACK: because we use `--manifest-path library/sysroot/Cargo.toml`, cargo thinks we only want to document that specific crate, not its dependencies. - // Override its default. - let built_crates = if requested_crates.is_empty() { - builder - .in_tree_crates("sysroot", None) - .into_iter() - .map(|krate| krate.name.to_string()) - .collect() - } else { - requested_crates.to_vec() - }; - - for krate in built_crates { + for krate in requested_crates { + if krate == "sysroot" { + // The sysroot crate is an implementation detail, don't include it in public docs. + continue; + } cargo.arg("-p").arg(krate); } + let description = + format!("library{} in {} format", crate_description(&requested_crates), format.as_str()); + let _guard = builder.msg_doc(compiler, &description, target); + builder.run(&mut cargo.into()); builder.cp_r(&out_dir, &out); } @@ -621,20 +629,10 @@ pub struct Rustc { impl Rustc { pub(crate) fn new(stage: u32, target: TargetSelection, builder: &Builder<'_>) -> Self { - // Find dependencies for top level crates. - let root_crates = vec![ - INTERNER.intern_str("rustc_driver"), - INTERNER.intern_str("rustc_codegen_llvm"), - INTERNER.intern_str("rustc_codegen_ssa"), - ]; - let crates: Vec<_> = root_crates - .iter() - .flat_map(|krate| { - builder - .in_tree_crates(krate, Some(target)) - .into_iter() - .map(|krate| krate.name.to_string()) - }) + let crates = builder + .in_tree_crates("rustc-main", Some(target)) + .into_iter() + .map(|krate| krate.name.to_string()) .collect(); Self { stage, target, crates: INTERNER.intern_list(crates) } } @@ -656,7 +654,7 @@ impl Step for Rustc { run.builder.ensure(Rustc { stage: run.builder.top_stage, target: run.target, - crates: make_run_crates(&run, "compiler"), + crates: run.make_run_crates(Alias::Compiler), }); } @@ -666,7 +664,7 @@ impl Step for Rustc { /// Compiler documentation is distributed separately, so we make sure /// we do not merge it with the other documentation from std, test and /// proc_macros. This is largely just a wrapper around `cargo doc`. - fn run(mut self, builder: &Builder<'_>) { + fn run(self, builder: &Builder<'_>) { let stage = self.stage; let target = self.target; @@ -726,24 +724,26 @@ impl Step for Rustc { let mut to_open = None; - if self.crates.is_empty() { - self.crates = INTERNER.intern_list(vec!["rustc_driver".to_owned()]); - }; - for krate in &*self.crates { // Create all crate output directories first to make sure rustdoc uses // relative links. // FIXME: Cargo should probably do this itself. - t!(fs::create_dir_all(out_dir.join(krate))); + let dir_name = krate.replace("-", "_"); + t!(fs::create_dir_all(out_dir.join(&*dir_name))); cargo.arg("-p").arg(krate); if to_open.is_none() { - to_open = Some(krate); + to_open = Some(dir_name); } } builder.run(&mut cargo.into()); - // Let's open the first crate documentation page: - if let Some(krate) = to_open { + + if builder.paths.iter().any(|path| path.ends_with("compiler")) { + // For `x.py doc compiler --open`, open `rustc_middle` by default. + let index = out.join("rustc_middle").join("index.html"); + builder.open_in_browser(index); + } else if let Some(krate) = to_open { + // Let's open the first crate documentation page: let index = out.join(krate).join("index.html"); builder.open_in_browser(index); } @@ -812,8 +812,6 @@ macro_rules! tool_doc { SourceType::Submodule }; - builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); - // Symlink compiler docs to the output directory of rustdoc documentation. let out_dirs = [ builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"), @@ -852,6 +850,8 @@ macro_rules! tool_doc { cargo.rustdocflag("--show-type-layout"); cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); + + let _guard = builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); builder.run(&mut cargo.into()); } } @@ -894,19 +894,10 @@ tool_doc!( "-p", "cargo-credential", "-p", - "cargo-credential-1password", - "-p", "mdman", // FIXME: this trips a license check in tidy. // "-p", // "resolver-tests", - // FIXME: we should probably document these, but they're different per-platform so we can't use `tool_doc`. - // "-p", - // "cargo-credential-gnome-secret", - // "-p", - // "cargo-credential-macos-keychain", - // "-p", - // "cargo-credential-wincred", ] ); tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["-p", "tidy"]); @@ -975,7 +966,7 @@ impl Step for UnstableBookGen { fn run(self, builder: &Builder<'_>) { let target = self.target; - builder.info(&format!("Generating unstable book md files ({})", target)); + builder.info(&format!("Generating unstable book md files ({target})")); let out = builder.md_doc_out(target).join("unstable-book"); builder.create_dir(&out); builder.remove_dir(&out); @@ -1073,7 +1064,16 @@ impl Step for RustcBook { // config.toml), then this needs to explicitly update the dylib search // path. builder.add_rustc_lib_path(self.compiler, &mut cmd); + let doc_generator_guard = builder.msg( + Kind::Run, + self.compiler.stage, + "lint-docs", + self.compiler.host, + self.target, + ); builder.run(&mut cmd); + drop(doc_generator_guard); + // Run rustbook/mdbook to generate the HTML pages. builder.ensure(RustbookSrc { target: self.target, diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 120b3c9c4..ffc380579 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/112931 +Last change is for: https://github.com/rust-lang/rust/pull/113996 diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index cb40521dd..a4135b06e 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -7,7 +7,7 @@ use std::{ process::{Command, Stdio}, }; -use build_helper::util::try_run; +use build_helper::ci::CiEnv; use once_cell::sync::OnceCell; use xz2::bufread::XzDecoder; @@ -21,6 +21,12 @@ use crate::{ static SHOULD_FIX_BINS_AND_DYLIBS: OnceCell = OnceCell::new(); +/// `Config::try_run` wrapper for this module to avoid warnings on `try_run`, since we don't have access to a `builder` yet. +fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> { + #[allow(deprecated)] + config.try_run(cmd) +} + /// Generic helpers that are useful anywhere in bootstrap. impl Config { pub fn is_verbose(&self) -> bool { @@ -51,17 +57,6 @@ impl Config { tmp } - /// Runs a command, printing out nice contextual information if it fails. - /// Exits if the command failed to execute at all, otherwise returns its - /// `status.success()`. - pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> { - if self.dry_run() { - return Ok(()); - } - self.verbose(&format!("running: {:?}", cmd)); - try_run(cmd, self.is_verbose()) - } - /// Runs a command, printing out nice contextual information if it fails. /// Returns false if do not execute at all, otherwise returns its /// `status.success()`. @@ -69,7 +64,7 @@ impl Config { if self.dry_run() { return true; } - self.verbose(&format!("running: {:?}", cmd)); + self.verbose(&format!("running: {cmd:?}")); check_run(cmd, self.is_verbose()) } @@ -156,14 +151,16 @@ impl Config { ]; } "; - nix_build_succeeded = self - .try_run(Command::new("nix-build").args(&[ + nix_build_succeeded = try_run( + self, + Command::new("nix-build").args(&[ Path::new("-E"), Path::new(NIX_EXPR), Path::new("-o"), &nix_deps_dir, - ])) - .is_ok(); + ]), + ) + .is_ok(); nix_deps_dir }); if !nix_build_succeeded { @@ -188,7 +185,7 @@ impl Config { patchelf.args(&["--set-interpreter", dynamic_linker.trim_end()]); } - self.try_run(patchelf.arg(fname)).unwrap(); + let _ = try_run(self, patchelf.arg(fname)); } fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) { @@ -209,11 +206,10 @@ impl Config { } fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { - println!("downloading {}", url); + println!("downloading {url}"); // Try curl. If that fails and we are on windows, fallback to PowerShell. let mut curl = Command::new("curl"); curl.args(&[ - "-#", "-y", "30", "-Y", @@ -224,6 +220,12 @@ impl Config { "3", "-SRf", ]); + // Don't print progress in CI; the \r wrapping looks bad and downloads don't take long enough for progress to be useful. + if CiEnv::is_ci() { + curl.arg("-s"); + } else { + curl.arg("--progress-bar"); + } curl.arg(url); let f = File::create(tempfile).unwrap(); curl.stdout(Stdio::from(f)); @@ -231,7 +233,7 @@ impl Config { if self.build.contains("windows-msvc") { eprintln!("Fallback to PowerShell"); for _ in 0..3 { - if self.try_run(Command::new("PowerShell.exe").args(&[ + if try_run(self, Command::new("PowerShell.exe").args(&[ "/nologo", "-Command", "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", @@ -246,9 +248,9 @@ impl Config { } } if !help_on_error.is_empty() { - eprintln!("{}", help_on_error); + eprintln!("{help_on_error}"); } - crate::detail_exit_macro!(1); + crate::exit!(1); } } @@ -402,7 +404,11 @@ impl Config { fn ci_component_contents(&self, stamp_file: &str) -> Vec { assert!(self.download_rustc()); - let ci_rustc_dir = self.out.join(&*self.build.triple).join("ci-rustc"); + if self.dry_run() { + return vec![]; + } + + let ci_rustc_dir = self.ci_rustc_dir(); let stamp_file = ci_rustc_dir.join(stamp_file); let contents_file = t!(File::open(&stamp_file), stamp_file.display().to_string()); t!(BufReader::new(contents_file).lines().collect()) @@ -419,7 +425,7 @@ impl Config { self.download_toolchain( &version, "ci-rustc", - commit, + &format!("{commit}-{}", self.llvm_assertions), &extra_components, Self::download_ci_component, ); @@ -495,8 +501,15 @@ impl Config { /// Download a single component of a CI-built toolchain (not necessarily a published nightly). // NOTE: intentionally takes an owned string to avoid downloading multiple times by accident - fn download_ci_component(&self, filename: String, prefix: &str, commit: &str) { - Self::download_component(self, DownloadSource::CI, filename, prefix, commit, "ci-rustc") + fn download_ci_component(&self, filename: String, prefix: &str, commit_with_assertions: &str) { + Self::download_component( + self, + DownloadSource::CI, + filename, + prefix, + commit_with_assertions, + "ci-rustc", + ) } fn download_component( @@ -516,11 +529,18 @@ impl Config { let bin_root = self.out.join(self.build.triple).join(destination); let tarball = cache_dir.join(&filename); let (base_url, url, should_verify) = match mode { - DownloadSource::CI => ( - self.stage0_metadata.config.artifacts_server.clone(), - format!("{key}/{filename}"), - false, - ), + DownloadSource::CI => { + let dist_server = if self.llvm_assertions { + self.stage0_metadata.config.artifacts_with_llvm_assertions_server.clone() + } else { + self.stage0_metadata.config.artifacts_server.clone() + }; + let url = format!( + "{}/{filename}", + key.strip_suffix(&format!("-{}", self.llvm_assertions)).unwrap() + ); + (dist_server, url, false) + } DownloadSource::Dist => { let dist_server = env::var("RUSTUP_DIST_SERVER") .unwrap_or(self.stage0_metadata.config.dist_server.to_string()); @@ -626,7 +646,7 @@ download-rustc = false fn download_ci_llvm(&self, llvm_sha: &str) { let llvm_assertions = self.llvm_assertions; - let cache_prefix = format!("llvm-{}-{}", llvm_sha, llvm_assertions); + let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}"); let cache_dst = self.out.join("cache"); let rustc_cache = cache_dst.join(cache_prefix); if !rustc_cache.exists() { diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index a882336c3..e0291e407 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -68,7 +68,10 @@ pub struct Flags { #[arg(global(true), long, value_name = "PATH")] /// build paths to exclude - pub exclude: Vec, + pub exclude: Vec, // keeping for client backward compatibility + #[arg(global(true), long, value_name = "PATH")] + /// build paths to skip + pub skip: Vec, #[arg(global(true), long)] /// include default paths in addition to the provided ones pub include_default_paths: bool, @@ -149,12 +152,9 @@ pub struct Flags { /// generate PGO profile with llvm built for rustc #[arg(global(true), long)] pub llvm_profile_generate: bool, - /// generate BOLT profile for LLVM build + /// Additional reproducible artifacts that should be added to the reproducible artifacts archive. #[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, + pub reproducible_artifact: Vec, #[arg(global(true))] /// paths for the subcommand pub paths: Vec, @@ -189,11 +189,11 @@ impl Flags { let build = Build::new(config); let paths = Builder::get_help(&build, subcommand); if let Some(s) = paths { - println!("{}", s); + println!("{s}"); } else { panic!("No paths available for subcommand `{}`", subcommand.as_str()); } - crate::detail_exit_macro!(0); + crate::exit!(0); } Flags::parse_from(it) @@ -321,7 +321,7 @@ pub enum Subcommand { 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, + skip: Vec, #[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) @@ -339,6 +339,10 @@ pub enum Subcommand { /// whether to automatically update stderr/stdout files bless: bool, #[arg(long)] + /// comma-separated list of other files types to check (accepts py, py:lint, + /// py:fmt, shell) + extra_checks: Option, + #[arg(long)] /// rerun tests even if the inputs are unchanged force_rerun: bool, #[arg(long)] @@ -366,7 +370,11 @@ pub enum Subcommand { /// Clean out build directories Clean { #[arg(long)] + /// Clean the entire build directory (not used by default) all: bool, + #[arg(long, value_name = "N")] + /// Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used. + stage: Option, }, /// Build distribution artifacts Dist, @@ -472,6 +480,13 @@ impl Subcommand { } } + pub fn extra_checks(&self) -> Option<&str> { + match *self { + Subcommand::Test { ref extra_checks, .. } => extra_checks.as_ref().map(String::as_str), + _ => None, + } + } + pub fn only_modified(&self) -> bool { match *self { Subcommand::Test { only_modified, .. } => only_modified, @@ -538,7 +553,7 @@ pub fn get_completion(shell: G, path: &Path) -> Opt } else { std::fs::read_to_string(path).unwrap_or_else(|_| { eprintln!("couldn't read {}", path.display()); - crate::detail_exit_macro!(1) + crate::exit!(1) }) }; let mut buf = Vec::new(); diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index ebf068b2c..d658be0b8 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -22,7 +22,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F cmd.arg("--check"); } cmd.args(paths); - let cmd_debug = format!("{:?}", cmd); + let cmd_debug = format!("{cmd:?}"); let mut cmd = cmd.spawn().expect("running rustfmt"); // poor man's async: return a closure that'll wait for rustfmt's completion move |block: bool| -> bool { @@ -40,7 +40,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F code, run `./x.py fmt` instead.", cmd_debug, ); - crate::detail_exit_macro!(1); + crate::exit!(1); } true } @@ -66,13 +66,17 @@ fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> { /// Return whether the format cache can be reused. fn verify_rustfmt_version(build: &Builder<'_>) -> bool { - let Some((version, stamp_file)) = get_rustfmt_version(build) else {return false;}; + let Some((version, stamp_file)) = get_rustfmt_version(build) else { + return false; + }; !program_out_of_date(&stamp_file, &version) } /// Updates the last rustfmt version used fn update_rustfmt_version(build: &Builder<'_>) { - let Some((version, stamp_file)) = get_rustfmt_version(build) else {return;}; + let Some((version, stamp_file)) = get_rustfmt_version(build) else { + return; + }; t!(std::fs::write(stamp_file, version)) } @@ -109,9 +113,9 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { } let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config)); let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config)); - let mut ignore_fmt = ignore::overrides::OverrideBuilder::new(&build.src); + let mut fmt_override = ignore::overrides::OverrideBuilder::new(&build.src); for ignore in rustfmt_config.ignore { - ignore_fmt.add(&format!("!{}", ignore)).expect(&ignore); + fmt_override.add(&format!("!{ignore}")).expect(&ignore); } let git_available = match Command::new("git") .arg("--version") @@ -148,14 +152,16 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { .map(|entry| { entry.split(' ').nth(1).expect("every git status entry should list a path") }); + let mut untracked_count = 0; for untracked_path in untracked_paths { - println!("skip untracked path {} during rustfmt invocations", untracked_path); + println!("skip untracked path {untracked_path} during rustfmt invocations"); // The leading `/` makes it an exact match against the // repository root, rather than a glob. Without that, if you // have `foo.rs` in the repository root it will also match // against anything like `compiler/rustc_foo/src/foo.rs`, // preventing the latter from being formatted. - ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path); + untracked_count += 1; + fmt_override.add(&format!("!/{untracked_path}")).expect(&untracked_path); } // Only check modified files locally to speed up runtime. // We still check all files in CI to avoid bugs in `get_modified_rs_files` letting regressions slip through; @@ -168,10 +174,25 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { println!("formatting modified file {file}"); } } else { - println!("formatting {} modified files", files.len()); + let pluralized = |count| if count > 1 { "files" } else { "file" }; + let untracked_msg = if untracked_count == 0 { + "".to_string() + } else { + format!( + ", skipped {} untracked {}", + untracked_count, + pluralized(untracked_count), + ) + }; + println!( + "formatting {} modified {}{}", + files.len(), + pluralized(files.len()), + untracked_msg + ); } for file in files { - ignore_fmt.add(&format!("/{file}")).expect(&file); + fmt_override.add(&format!("/{file}")).expect(&file); } } Ok(None) => {} @@ -192,11 +213,11 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { println!("Could not find usable git. Skipping git-aware format checks"); } - let ignore_fmt = ignore_fmt.build().unwrap(); + let fmt_override = fmt_override.build().unwrap(); let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { eprintln!("./x.py fmt is not supported on this channel"); - crate::detail_exit_macro!(1); + crate::exit!(1); }); assert!(rustfmt_path.exists(), "{}", rustfmt_path.display()); let src = build.src.clone(); @@ -248,7 +269,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { None => WalkBuilder::new(src.clone()), } .types(matcher) - .overrides(ignore_fmt) + .overrides(fmt_override) .build_parallel(); // there is a lot of blocking involved in spawning a child process and reading files to format. diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 0a7aff622..4396bbc51 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -27,7 +27,7 @@ use std::process::{Command, Stdio}; use std::str; use build_helper::ci::{gha, CiEnv}; -use build_helper::detail_exit_macro; +use build_helper::exit; use channel::GitInfo; use config::{DryRun, Target}; use filetime::FileTime; @@ -36,10 +36,9 @@ use once_cell::sync::OnceCell; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; use crate::util::{ - exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, + dir_is_empty, exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, }; -mod bolt; mod builder; mod cache; mod cc_detect; @@ -131,9 +130,16 @@ const EXTRA_CHECK_CFGS: &[(Option, &'static str, Option<&[&'static str]>)] (Some(Mode::Std), "freebsd13", None), (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ + // #[cfg(bootstrap)] + (Some(Mode::Std), "target_vendor", Some(&["unikraft"])), (Some(Mode::Std), "target_env", Some(&["libnx"])), - // (Some(Mode::Std), "target_os", Some(&[])), - (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])), + (Some(Mode::Std), "target_os", Some(&["teeos"])), + // #[cfg(bootstrap)] mips32r6, mips64r6 + ( + Some(Mode::Std), + "target_arch", + Some(&["asmjs", "spirv", "nvptx", "xtensa", "mips32r6", "mips64r6", "csky"]), + ), /* 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), @@ -191,7 +197,7 @@ pub enum GitRepo { /// although most functions are implemented as free functions rather than /// methods specifically on this structure itself (to make it easier to /// organize). -#[cfg_attr(not(feature = "build-metrics"), derive(Clone))] +#[derive(Clone)] pub struct Build { /// User-specified configuration from `config.toml`. config: Config, @@ -333,7 +339,6 @@ forward! { create(path: &Path, s: &str), remove(f: &Path), tempdir() -> PathBuf, - try_run(cmd: &mut Command) -> Result<(), ()>, llvm_link_shared() -> bool, download_rustc() -> bool, initial_rustfmt() -> Option, @@ -478,7 +483,7 @@ impl Build { .unwrap() .trim(); if local_release.split('.').take(2).eq(version.split('.').take(2)) { - build.verbose(&format!("auto-detected local-rebuild {}", local_release)); + build.verbose(&format!("auto-detected local-rebuild {local_release}")); build.local_rebuild = true; } @@ -531,10 +536,6 @@ impl Build { /// /// `relative_path` should be relative to the root of the git repository, not an absolute path. pub(crate) fn update_submodule(&self, relative_path: &Path) { - fn dir_is_empty(dir: &Path) -> bool { - t!(std::fs::read_dir(dir)).next().is_none() - } - if !self.config.submodules(&self.rust_info()) { return; } @@ -617,7 +618,9 @@ impl Build { } // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). + #[allow(deprecated)] // diff-index reports the modifications through the exit status let has_local_modifications = self + .config .try_run( Command::new("git") .args(&["diff-index", "--quiet", "HEAD"]) @@ -709,9 +712,9 @@ impl Build { if failures.len() > 0 { eprintln!("\n{} command(s) did not execute successfully:\n", failures.len()); for failure in failures.iter() { - eprintln!(" - {}\n", failure); + eprintln!(" - {failure}\n"); } - detail_exit_macro!(1); + exit!(1); } #[cfg(feature = "build-metrics")] @@ -822,11 +825,6 @@ impl Build { self.stage_out(compiler, mode).join(&*target.triple).join(self.cargo_dir()) } - /// Directory where the extracted `rustc-dev` component is stored. - fn ci_rustc_dir(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("ci-rustc") - } - /// Root output directory for LLVM compiled for `target` /// /// Note that if LLVM is configured externally then the directory returned @@ -960,7 +958,7 @@ impl Build { if self.config.dry_run() { return; } - self.verbose(&format!("running: {:?}", cmd)); + self.verbose(&format!("running: {cmd:?}")); run(cmd, self.is_verbose()) } @@ -969,19 +967,43 @@ impl Build { if self.config.dry_run() { return; } - self.verbose(&format!("running: {:?}", cmd)); + self.verbose(&format!("running: {cmd:?}")); run_suppressed(cmd) } /// Runs a command, printing out nice contextual information if it fails. /// Exits if the command failed to execute at all, otherwise returns its /// `status.success()`. - fn try_run_quiet(&self, cmd: &mut Command) -> bool { + fn run_quiet_delaying_failure(&self, cmd: &mut Command) -> bool { if self.config.dry_run() { return true; } - self.verbose(&format!("running: {:?}", cmd)); - try_run_suppressed(cmd) + if !self.fail_fast { + self.verbose(&format!("running: {cmd:?}")); + if !try_run_suppressed(cmd) { + let mut failures = self.delayed_failures.borrow_mut(); + failures.push(format!("{cmd:?}")); + return false; + } + } else { + self.run_quiet(cmd); + } + true + } + + /// Runs a command, printing out contextual info if it fails, and delaying errors until the build finishes. + pub(crate) fn run_delaying_failure(&self, cmd: &mut Command) -> bool { + if !self.fail_fast { + #[allow(deprecated)] // can't use Build::try_run, that's us + if self.config.try_run(cmd).is_err() { + let mut failures = self.delayed_failures.borrow_mut(); + failures.push(format!("{cmd:?}")); + return false; + } + } else { + self.run(cmd); + } + true } pub fn is_verbose_than(&self, level: usize) -> bool { @@ -991,7 +1013,7 @@ impl Build { /// Prints a message if this build is configured in more verbose mode than `level`. fn verbose_than(&self, level: usize, msg: &str) { if self.is_verbose_than(level) { - println!("{}", msg); + println!("{msg}"); } } @@ -999,11 +1021,13 @@ impl Build { match self.config.dry_run { DryRun::SelfCheck => return, DryRun::Disabled | DryRun::UserSelected => { - println!("{}", msg); + println!("{msg}"); } } } + #[must_use = "Groups should not be dropped until the Step finishes running"] + #[track_caller] fn msg_check( &self, what: impl Display, @@ -1012,6 +1036,8 @@ impl Build { self.msg(Kind::Check, self.config.stage, what, self.config.build, target) } + #[must_use = "Groups should not be dropped until the Step finishes running"] + #[track_caller] fn msg_doc( &self, compiler: Compiler, @@ -1021,6 +1047,8 @@ impl Build { self.msg(Kind::Doc, compiler.stage, what, compiler.host, target.into()) } + #[must_use = "Groups should not be dropped until the Step finishes running"] + #[track_caller] fn msg_build( &self, compiler: Compiler, @@ -1033,6 +1061,8 @@ impl Build { /// Return a `Group` guard for a [`Step`] that is built for each `--stage`. /// /// [`Step`]: crate::builder::Step + #[must_use = "Groups should not be dropped until the Step finishes running"] + #[track_caller] fn msg( &self, action: impl Into, @@ -1059,6 +1089,8 @@ impl Build { /// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`. /// /// [`Step`]: crate::builder::Step + #[must_use = "Groups should not be dropped until the Step finishes running"] + #[track_caller] fn msg_unstaged( &self, action: impl Into, @@ -1070,6 +1102,8 @@ impl Build { self.group(&msg) } + #[must_use = "Groups should not be dropped until the Step finishes running"] + #[track_caller] fn msg_sysroot_tool( &self, action: impl Into, @@ -1088,6 +1122,7 @@ impl Build { self.group(&msg) } + #[track_caller] fn group(&self, msg: &str) -> Option { match self.config.dry_run { DryRun::SelfCheck => None, @@ -1111,7 +1146,7 @@ impl Build { match which { GitRepo::Rustc => { let sha = self.rust_sha().unwrap_or(&self.version); - Some(format!("/rustc/{}", sha)) + Some(format!("/rustc/{sha}")) } GitRepo::Llvm => Some(String::from("/rustc/llvm")), } @@ -1164,10 +1199,10 @@ impl Build { let map = format!("{}={}", self.src.display(), map_to); let cc = self.cc(target); if cc.ends_with("clang") || cc.ends_with("gcc") { - base.push(format!("-fdebug-prefix-map={}", map)); + base.push(format!("-fdebug-prefix-map={map}")); } else if cc.ends_with("clang-cl.exe") { base.push("-Xclang".into()); - base.push(format!("-fdebug-prefix-map={}", map)); + base.push(format!("-fdebug-prefix-map={map}")); } } base @@ -1196,9 +1231,7 @@ impl Build { } match self.cxx.borrow().get(&target) { Some(p) => Ok(p.path().into()), - None => { - Err(format!("target `{}` is not configured as a host, only as a target", target)) - } + None => Err(format!("target `{target}` is not configured as a host, only as a target")), } } @@ -1241,7 +1274,7 @@ impl Build { } let no_threads = util::lld_flag_no_threads(target.contains("windows")); - options[1] = Some(format!("-Clink-arg=-Wl,{}", no_threads)); + options[1] = Some(format!("-Clink-arg=-Wl,{no_threads}")); } IntoIterator::into_iter(options).flatten() @@ -1368,11 +1401,11 @@ impl Build { if !self.config.omit_git_hash { format!("{}-beta.{}", num, self.beta_prerelease_version()) } else { - format!("{}-beta", num) + format!("{num}-beta") } } - "nightly" => format!("{}-nightly", num), - _ => format!("{}-dev", num), + "nightly" => format!("{num}-nightly"), + _ => format!("{num}-dev"), } } @@ -1420,7 +1453,7 @@ impl Build { "stable" => num.to_string(), "beta" => "beta".to_string(), "nightly" => "nightly".to_string(), - _ => format!("{}-dev", num), + _ => format!("{num}-dev"), } } @@ -1451,7 +1484,7 @@ impl Build { /// Returns the `a.b.c` version that the given package is at. fn release_num(&self, package: &str) -> String { - let toml_file_name = self.src.join(&format!("src/tools/{}/Cargo.toml", package)); + let toml_file_name = self.src.join(&format!("src/tools/{package}/Cargo.toml")); let toml = t!(fs::read_to_string(&toml_file_name)); for line in toml.lines() { if let Some(stripped) = @@ -1461,7 +1494,7 @@ impl Build { } } - panic!("failed to find version in {}'s Cargo.toml", package) + panic!("failed to find version in {package}'s Cargo.toml") } /// Returns `true` if unstable features should be enabled for the compiler @@ -1507,6 +1540,7 @@ impl Build { } } } + ret.sort_unstable_by_key(|krate| krate.name); // reproducible order needed for tests ret } @@ -1520,7 +1554,7 @@ impl Build { "Error: Unable to find the stamp file {}, did you try to keep a nonexistent build stage?", stamp.display() ); - crate::detail_exit_macro!(1); + crate::exit!(1); } let mut paths = Vec::new(); @@ -1552,7 +1586,7 @@ impl Build { if self.config.dry_run() { return; } - self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst)); + self.verbose_than(1, &format!("Copy {src:?} to {dst:?}")); if src == dst { return; } @@ -1643,7 +1677,7 @@ impl Build { return; } let dst = dstdir.join(src.file_name().unwrap()); - self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst)); + self.verbose_than(1, &format!("Install {src:?} to {dst:?}")); t!(fs::create_dir_all(dstdir)); if !src.exists() { panic!("Error: File \"{}\" not found!", src.display()); @@ -1677,7 +1711,7 @@ impl Build { let iter = match fs::read_dir(dir) { Ok(v) => v, Err(_) if self.config.dry_run() => return vec![].into_iter(), - Err(err) => panic!("could not read dir {:?}: {:?}", dir, err), + Err(err) => panic!("could not read dir {dir:?}: {err:?}"), }; iter.map(|e| t!(e)).collect::>().into_iter() } @@ -1712,7 +1746,7 @@ Alternatively, set `download-ci-llvm = true` in that `[llvm]` section to download LLVM rather than building it. " ); - detail_exit_macro!(1); + exit!(1); } } diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 7e27960f3..c841cb340 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -299,7 +299,7 @@ impl Step for Llvm { let llvm_exp_targets = match builder.config.llvm_experimental_targets { Some(ref s) => s, - None => "AVR;M68k", + None => "AVR;M68k;CSKY", }; let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" }; @@ -342,12 +342,6 @@ impl Step for Llvm { if let Some(path) = builder.config.llvm_profile_use.as_ref() { cfg.define("LLVM_PROFDATA_FILE", &path); } - if builder.config.llvm_bolt_profile_generate - || builder.config.llvm_bolt_profile_use.is_some() - { - // Relocations are required for BOLT to work. - ldflags.push_all("-Wl,-q"); - } // Disable zstd to avoid a dependency on libzstd.so. cfg.define("LLVM_ENABLE_ZSTD", "OFF"); @@ -380,12 +374,12 @@ impl Step for Llvm { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } - if target.starts_with("riscv") + if (target.starts_with("riscv") || target.starts_with("csky")) && !target.contains("freebsd") && !target.contains("openbsd") && !target.contains("netbsd") { - // RISC-V GCC erroneously requires linking against + // RISC-V and CSKY GCC erroneously requires linking against // `libatomic` when using 1-byte and 2-byte C++ // atomics but the LLVM build system check cannot // detect this. Therefore it is set manually here. @@ -491,25 +485,50 @@ impl Step for Llvm { cfg.build(); - // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned - // libLLVM.dylib will be built. However, llvm-config will still look - // for a versioned path like libLLVM-14.dylib. Manually create a symbolic - // link to make llvm-config happy. - if builder.llvm_link_shared() && target.contains("apple-darwin") { + // Helper to find the name of LLVM's shared library on darwin and linux. + let find_llvm_lib_name = |extension| { let mut cmd = Command::new(&res.llvm_config); let version = output(cmd.arg("--version")); let major = version.split('.').next().unwrap(); - let lib_name = match llvm_version_suffix { - Some(s) => format!("libLLVM-{}{}.dylib", major, s), - None => format!("libLLVM-{}.dylib", major), + let lib_name = match &llvm_version_suffix { + Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.{extension}"), + None => format!("libLLVM-{major}.{extension}"), }; + lib_name + }; + // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned + // libLLVM.dylib will be built. However, llvm-config will still look + // for a versioned path like libLLVM-14.dylib. Manually create a symbolic + // link to make llvm-config happy. + if builder.llvm_link_shared() && target.contains("apple-darwin") { + let lib_name = find_llvm_lib_name("dylib"); let lib_llvm = out_dir.join("build").join("lib").join(lib_name); if !lib_llvm.exists() { t!(builder.symlink_file("libLLVM.dylib", &lib_llvm)); } } + // When building LLVM as a shared library on linux, it can contain unexpected debuginfo: + // some can come from the C++ standard library. Unless we're explicitly requesting LLVM to + // be built with debuginfo, strip it away after the fact, to make dist artifacts smaller. + if builder.llvm_link_shared() + && builder.config.llvm_optimize + && !builder.config.llvm_release_debuginfo + { + // Find the name of the LLVM shared library that we just built. + let lib_name = find_llvm_lib_name("so"); + + // If the shared library exists in LLVM's `/build/lib/` or `/lib/` folders, strip its + // debuginfo. + crate::compile::strip_debug(builder, target, &out_dir.join("lib").join(&lib_name)); + crate::compile::strip_debug( + builder, + target, + &out_dir.join("build").join("lib").join(&lib_name), + ); + } + t!(stamp.write()); res @@ -525,11 +544,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { let version = output(cmd.arg("--version")); let mut parts = version.split('.').take(2).filter_map(|s| s.parse::().ok()); if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) { - if major >= 14 { + if major >= 15 { return; } } - panic!("\n\nbad LLVM version: {}, need >=14.0\n\n", version) + panic!("\n\nbad LLVM version: {version}, need >=15.0\n\n") } fn configure_cmake( @@ -559,6 +578,8 @@ fn configure_cmake( if target.contains("netbsd") { cfg.define("CMAKE_SYSTEM_NAME", "NetBSD"); + } else if target.contains("dragonfly") { + cfg.define("CMAKE_SYSTEM_NAME", "DragonFly"); } else if target.contains("freebsd") { cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD"); } else if target.contains("windows") { @@ -569,7 +590,12 @@ fn configure_cmake( cfg.define("CMAKE_SYSTEM_NAME", "SunOS"); } else if target.contains("linux") { cfg.define("CMAKE_SYSTEM_NAME", "Linux"); + } else { + builder.info( + "could not determine CMAKE_SYSTEM_NAME from the target `{target}`, build may fail", + ); } + // When cross-compiling we should also set CMAKE_SYSTEM_VERSION, but in // that case like CMake we cannot easily determine system version either. // @@ -679,10 +705,10 @@ fn configure_cmake( } } if builder.config.llvm_clang_cl.is_some() { - cflags.push(&format!(" --target={}", target)); + cflags.push(&format!(" --target={target}")); } for flag in extra_compiler_flags { - cflags.push(&format!(" {}", flag)); + cflags.push(&format!(" {flag}")); } cfg.define("CMAKE_C_FLAGS", cflags); let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::Cxx).join(" ").into(); @@ -691,10 +717,10 @@ fn configure_cmake( cxxflags.push(s); } if builder.config.llvm_clang_cl.is_some() { - cxxflags.push(&format!(" --target={}", target)); + cxxflags.push(&format!(" --target={target}")); } for flag in extra_compiler_flags { - cxxflags.push(&format!(" {}", flag)); + cxxflags.push(&format!(" {flag}")); } cfg.define("CMAKE_CXX_FLAGS", cxxflags); if let Some(ar) = builder.ar(target) { @@ -765,7 +791,7 @@ fn configure_llvm(builder: &Builder<'_>, target: TargetSelection, cfg: &mut cmak fn get_var(var_base: &str, host: &str, target: &str) -> Option { let kind = if host == target { "HOST" } else { "TARGET" }; let target_u = target.replace("-", "_"); - env::var_os(&format!("{}_{}", var_base, target)) + env::var_os(&format!("{var_base}_{target}")) .or_else(|| env::var_os(&format!("{}_{}", var_base, target_u))) .or_else(|| env::var_os(&format!("{}_{}", kind, var_base))) .or_else(|| env::var_os(var_base)) @@ -1056,6 +1082,9 @@ fn supported_sanitizers( "s390x-unknown-linux-musl" => { common_libs("linux", "s390x", &["asan", "lsan", "msan", "tsan"]) } + "x86_64-unknown-linux-ohos" => { + common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) + } _ => Vec::new(), } } @@ -1124,8 +1153,8 @@ impl Step for CrtBeginEnd { return out_dir; } - let crtbegin_src = builder.src.join("src/llvm-project/compiler-rt/lib/crt/crtbegin.c"); - let crtend_src = builder.src.join("src/llvm-project/compiler-rt/lib/crt/crtend.c"); + let crtbegin_src = builder.src.join("src/llvm-project/compiler-rt/lib/builtins/crtbegin.c"); + let crtend_src = builder.src.join("src/llvm-project/compiler-rt/lib/builtins/crtend.c"); if up_to_date(&crtbegin_src, &out_dir.join("crtbegin.o")) && up_to_date(&crtend_src, &out_dir.join("crtendS.o")) { diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs index 5990f33b9..cf8d33dfc 100644 --- a/src/bootstrap/metrics.rs +++ b/src/bootstrap/metrics.rs @@ -7,7 +7,10 @@ use crate::builder::{Builder, Step}; use crate::util::t; use crate::Build; -use serde_derive::{Deserialize, Serialize}; +use build_helper::metrics::{ + JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test, + TestOutcome, TestSuite, TestSuiteMetadata, +}; use std::cell::RefCell; use std::fs::File; use std::io::BufWriter; @@ -37,6 +40,13 @@ pub(crate) struct BuildMetrics { state: RefCell, } +/// NOTE: this isn't really cloning anything, but `x suggest` doesn't need metrics so this is probably ok. +impl Clone for BuildMetrics { + fn clone(&self) -> Self { + Self::init() + } +} + impl BuildMetrics { pub(crate) fn init() -> Self { let state = RefCell::new(MetricsState { @@ -241,98 +251,7 @@ struct StepMetrics { test_suites: Vec, } -#[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, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -struct JsonInvocation { - // Unix timestamp in seconds - // - // This is necessary to easily correlate this invocation with logs or other data. - start_time: u64, - duration_including_children_sec: f64, - children: Vec, -} - -#[derive(Serialize, Deserialize)] -#[serde(tag = "kind", rename_all = "snake_case")] -enum JsonNode { - RustbuildStep { - #[serde(rename = "type")] - type_: String, - debug_repr: String, - - duration_excluding_children_sec: f64, - system_stats: JsonStepSystemStats, - - children: Vec, - }, - TestSuite(TestSuite), -} - -#[derive(Serialize, Deserialize)] -struct TestSuite { - metadata: TestSuiteMetadata, - tests: Vec, -} - -#[derive(Serialize, Deserialize)] -#[serde(tag = "kind", rename_all = "snake_case")] -pub(crate) enum TestSuiteMetadata { - CargoPackage { - crates: Vec, - target: String, - host: String, - stage: u32, - }, - Compiletest { - suite: String, - mode: String, - compare_mode: Option, - 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, - Failed, - Ignored { ignore_reason: Option }, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -struct JsonInvocationSystemStats { - cpu_threads_count: usize, - cpu_model: String, - - memory_total_bytes: u64, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -struct JsonStepSystemStats { - cpu_utilization_percent: f64, -} - -#[derive(Deserialize)] +#[derive(serde_derive::Deserialize)] struct OnlyFormatVersion { #[serde(default)] // For version 0 the field was not present. format_version: usize, diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 947613796..a9865e262 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -63,7 +63,7 @@ prepare: ci-msvc-py: $(Q)$(CFG_SRC_DIR)/x.py test --stage 2 tidy ci-msvc-ps1: - $(Q)$(CFG_SRC_DIR)/x.ps1 test --stage 2 --exclude tidy + $(Q)$(CFG_SRC_DIR)/x.ps1 test --stage 2 --skip tidy ci-msvc: ci-msvc-py ci-msvc-ps1 ## MingW native builders @@ -72,7 +72,7 @@ ci-msvc: ci-msvc-py ci-msvc-ps1 ci-mingw-x: $(Q)$(CFG_SRC_DIR)/x test --stage 2 tidy ci-mingw-bootstrap: - $(Q)$(BOOTSTRAP) test --stage 2 --exclude tidy + $(Q)$(BOOTSTRAP) test --stage 2 --skip tidy ci-mingw: ci-mingw-x ci-mingw-bootstrap .PHONY: dist diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs index 98a468c88..6802bf451 100644 --- a/src/bootstrap/render_tests.rs +++ b/src/bootstrap/render_tests.rs @@ -30,7 +30,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bo if !run_tests(builder, cmd, stream) { if builder.fail_fast { - crate::detail_exit_macro!(1); + crate::exit!(1); } else { let mut failures = builder.delayed_failures.borrow_mut(); failures.push(format!("{cmd:?}")); @@ -141,9 +141,9 @@ impl<'a> Renderer<'a> { self.builder.metrics.record_test( &test.name, match outcome { - Outcome::Ok | Outcome::BenchOk => crate::metrics::TestOutcome::Passed, - Outcome::Failed => crate::metrics::TestOutcome::Failed, - Outcome::Ignored { reason } => crate::metrics::TestOutcome::Ignored { + Outcome::Ok | Outcome::BenchOk => build_helper::metrics::TestOutcome::Passed, + Outcome::Failed => build_helper::metrics::TestOutcome::Failed, + Outcome::Ignored { reason } => build_helper::metrics::TestOutcome::Ignored { ignore_reason: reason.map(|s| s.to_string()), }, }, diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index c97b75927..4082f5bb9 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -24,11 +24,9 @@ impl Step for ExpandYamlAnchors { /// anchors in them, since GitHub Actions doesn't support them. fn run(self, builder: &Builder<'_>) { builder.info("Expanding YAML anchors in the GitHub Actions configuration"); - try_run( - builder, + builder.run_delaying_failure( &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("generate").arg(&builder.src), - ) - .unwrap(); + ); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -40,19 +38,6 @@ impl Step for ExpandYamlAnchors { } } -fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> { - if !builder.fail_fast { - if let Err(e) = builder.try_run(cmd) { - let mut failures = builder.delayed_failures.borrow_mut(); - failures.push(format!("{:?}", cmd)); - return Err(e); - } - } else { - builder.run(cmd); - } - Ok(()) -} - #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct BuildManifest; diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 8f5ba4273..7e83b508e 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -104,7 +104,7 @@ You should install cmake, or set `download-ci-llvm = true` in the than building it. " ); - crate::detail_exit_macro!(1); + crate::exit!(1); } } @@ -188,7 +188,7 @@ than building it. // Externally configured LLVM requires FileCheck to exist let filecheck = build.llvm_filecheck(build.build); if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { - panic!("FileCheck executable {:?} does not exist", filecheck); + panic!("FileCheck executable {filecheck:?} does not exist"); } } @@ -206,7 +206,7 @@ than building it. } // Make sure musl-root is valid - if target.contains("musl") { + if target.contains("musl") && !target.contains("unikraft") { // If this is a native target (host is also musl) and no musl-root is given, // fall back to the system toolchain in /usr before giving up if build.musl_root(*target).is_none() && build.config.build == *target { diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 34c6ccf13..30730f504 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -32,6 +32,7 @@ static SETTINGS_HASHES: &[&str] = &[ "56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922", "af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0", "3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541", + "47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923", ]; static RUST_ANALYZER_SETTINGS: &str = include_str!("../etc/rust_analyzer_settings.json"); @@ -92,7 +93,7 @@ impl FromStr for Profile { Ok(Profile::Tools) } "none" => Ok(Profile::None), - _ => Err(format!("unknown profile: '{}'", s)), + _ => Err(format!("unknown profile: '{s}'")), } } } @@ -167,7 +168,7 @@ pub fn setup(config: &Config, profile: Profile) { println!("To get started, try one of the following commands:"); for cmd in suggestions { - println!("- `x.py {}`", cmd); + println!("- `x.py {cmd}`"); } if profile != Profile::Dist { @@ -203,14 +204,13 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) { "note: this will use the configuration in {}", profile.include_path(&config.src).display() ); - crate::detail_exit_macro!(1); + crate::exit!(1); } let settings = format!( "# Includes one of the default files in src/bootstrap/defaults\n\ - profile = \"{}\"\n\ - changelog-seen = {}\n", - profile, VERSION + profile = \"{profile}\"\n\ + changelog-seen = {VERSION}\n" ); t!(fs::write(path, settings)); @@ -341,7 +341,7 @@ fn ensure_stage1_toolchain_placeholder_exists(stage_path: &str) -> bool { return false; }; - let pathbuf = pathbuf.join(format!("rustc{}", EXE_SUFFIX)); + let pathbuf = pathbuf.join(format!("rustc{EXE_SUFFIX}")); if pathbuf.exists() { return true; @@ -389,12 +389,12 @@ pub fn interactive_path() -> io::Result { io::stdin().read_line(&mut input)?; if input.is_empty() { eprintln!("EOF on stdin, when expecting answer to question. Giving up."); - crate::detail_exit_macro!(1); + crate::exit!(1); } break match parse_with_abbrev(&input) { Ok(profile) => profile, Err(err) => { - eprintln!("error: {}", err); + eprintln!("error: {err}"); eprintln!("note: press Ctrl+C to exit"); continue; } diff --git a/src/bootstrap/suggest.rs b/src/bootstrap/suggest.rs index ff20ebec2..f225104bd 100644 --- a/src/bootstrap/suggest.rs +++ b/src/bootstrap/suggest.rs @@ -4,18 +4,11 @@ use std::str::FromStr; use std::path::PathBuf; -use crate::{ - builder::{Builder, Kind}, - tool::Tool, -}; +use clap::Parser; -#[cfg(feature = "build-metrics")] -pub fn suggest(builder: &Builder<'_>, run: bool) { - panic!("`x suggest` is not supported with `build-metrics`") -} +use crate::{builder::Builder, tool::Tool}; /// Suggests a list of possible `x.py` commands to run based on modified files in branch. -#[cfg(not(feature = "build-metrics"))] pub fn suggest(builder: &Builder<'_>, run: bool) { let suggestions = builder.tool_cmd(Tool::SuggestTests).output().expect("failed to run `suggest-tests` tool"); @@ -67,12 +60,13 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { if run { for sug in suggestions { - let mut build = builder.build.clone(); - - let builder = - Builder::new_standalone(&mut build, Kind::parse(&sug.0).unwrap(), sug.2, sug.1); - - builder.execute_cli() + let mut build: crate::Build = builder.build.clone(); + build.config.paths = sug.2; + build.config.cmd = crate::flags::Flags::parse_from(["x.py", sug.0]).cmd; + if let Some(stage) = sug.1 { + build.config.stage = stage; + } + build.build(); } } else { println!("help: consider using the `--run` flag to automatically run suggested tests"); diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/tarball.rs index 7fa8a4d9d..95d909c57 100644 --- a/src/bootstrap/tarball.rs +++ b/src/bootstrap/tarball.rs @@ -309,7 +309,7 @@ impl<'a> Tarball<'a> { let mut cmd = self.builder.tool_cmd(crate::tool::Tool::RustInstaller); let package_name = self.package_name(); - self.builder.info(&format!("Dist {}", package_name)); + self.builder.info(&format!("Dist {package_name}")); let _time = crate::util::timeit(self.builder); build_cli(&self, &mut cmd); @@ -344,7 +344,7 @@ impl<'a> Tarball<'a> { .unwrap_or("gz"); GeneratedTarball { - path: crate::dist::distdir(self.builder).join(format!("{}.tar.{}", package_name, ext)), + path: crate::dist::distdir(self.builder).join(format!("{package_name}.tar.{ext}")), decompressed_output, work: self.temp_dir, } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index eed7a584b..d0d62db08 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -4,6 +4,7 @@ //! our CI. use std::env; +use std::ffi::OsStr; use std::ffi::OsString; use std::fs; use std::iter; @@ -48,32 +49,6 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[ // build for, so there is no entry for "aarch64-apple-darwin" here. ]; -fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> { - if !builder.fail_fast { - if let Err(e) = builder.try_run(cmd) { - let mut failures = builder.delayed_failures.borrow_mut(); - failures.push(format!("{:?}", cmd)); - return Err(e); - } - } else { - builder.run(cmd); - } - Ok(()) -} - -fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool { - if !builder.fail_fast { - if !builder.try_run_quiet(cmd) { - let mut failures = builder.delayed_failures.borrow_mut(); - failures.push(format!("{:?}", cmd)); - return false; - } - } else { - builder.run_quiet(cmd); - } - true -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CrateBootstrap { path: Interned, @@ -117,14 +92,8 @@ impl Step for CrateBootstrap { SourceType::InTree, &[], ); - builder.info(&format!( - "{} {} stage0 ({})", - builder.kind.description(), - path, - bootstrap_host, - )); let crate_name = path.rsplit_once('/').unwrap().1; - run_cargo_test(cargo, &[], &[], crate_name, compiler, bootstrap_host, builder); + run_cargo_test(cargo, &[], &[], crate_name, crate_name, compiler, bootstrap_host, builder); } } @@ -154,15 +123,16 @@ impl Step for Linkcheck { if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() { panic!( "Linkcheck currently does not support builds with different hosts and targets. -You can skip linkcheck with --exclude src/tools/linkchecker" +You can skip linkcheck with --skip src/tools/linkchecker" ); } - builder.info(&format!("Linkcheck ({})", host)); + builder.info(&format!("Linkcheck ({host})")); // Test the linkchecker itself. let bootstrap_host = builder.config.build; let compiler = builder.compiler(0, bootstrap_host); + let cargo = tool::prepare_tool_cargo( builder, compiler, @@ -173,7 +143,16 @@ You can skip linkcheck with --exclude src/tools/linkchecker" SourceType::InTree, &[], ); - run_cargo_test(cargo, &[], &[], "linkchecker", compiler, bootstrap_host, builder); + run_cargo_test( + cargo, + &[], + &[], + "linkchecker", + "linkchecker self tests", + compiler, + bootstrap_host, + builder, + ); if builder.doc_tests == DocTests::No { return; @@ -182,13 +161,14 @@ You can skip linkcheck with --exclude src/tools/linkchecker" // Build all the default documentation. builder.default_doc(&[]); + // Build the linkchecker before calling `msg`, since GHA doesn't support nested groups. + let mut linkchecker = builder.tool_cmd(Tool::Linkchecker); + // Run the linkchecker. + let _guard = + builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host); let _time = util::timeit(&builder); - try_run( - builder, - builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")), - ) - .unwrap(); + builder.run_delaying_failure(linkchecker.arg(builder.out.join(host.triple).join("doc"))); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -241,8 +221,9 @@ impl Step for HtmlCheck { builder.default_doc(&[]); builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder)); - try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target))) - .unwrap(); + builder.run_delaying_failure( + builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)), + ); } } @@ -281,15 +262,13 @@ impl Step for Cargotest { let _time = util::timeit(&builder); let mut cmd = builder.tool_cmd(Tool::CargoTest); - try_run( - builder, + builder.run_delaying_failure( cmd.arg(&cargo) .arg(&out_dir) .args(builder.config.test_args()) .env("RUSTC", builder.rustc(compiler)) .env("RUSTDOC", builder.rustdoc(compiler)), - ) - .unwrap(); + ); } } @@ -340,7 +319,7 @@ impl Step for Cargo { #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( - crate::metrics::TestSuiteMetadata::CargoPackage { + build_helper::metrics::TestSuiteMetadata::CargoPackage { crates: vec!["cargo".into()], target: self.host.triple.to_string(), host: self.host.triple.to_string(), @@ -409,7 +388,7 @@ impl Step for RustAnalyzer { cargo.env("SKIP_SLOW_TESTS", "1"); cargo.add_rustc_lib_path(builder, compiler); - run_cargo_test(cargo, &[], &[], "rust-analyzer", compiler, host, builder); + run_cargo_test(cargo, &[], &[], "rust-analyzer", "rust-analyzer", compiler, host, builder); } } @@ -458,7 +437,7 @@ impl Step for Rustfmt { cargo.add_rustc_lib_path(builder, compiler); - run_cargo_test(cargo, &[], &[], "rustfmt", compiler, host, builder); + run_cargo_test(cargo, &[], &[], "rustfmt", "rustfmt", compiler, host, builder); } } @@ -506,7 +485,16 @@ impl Step for RustDemangler { cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler); cargo.add_rustc_lib_path(builder, compiler); - run_cargo_test(cargo, &[], &[], "rust-demangler", compiler, host, builder); + run_cargo_test( + cargo, + &[], + &[], + "rust-demangler", + "rust-demangler", + compiler, + host, + builder, + ); } } @@ -550,6 +538,13 @@ impl Miri { cargo.env("RUST_BACKTRACE", "1"); let mut cargo = Command::from(cargo); + let _guard = builder.msg( + Kind::Build, + compiler.stage + 1, + "miri sysroot", + compiler.host, + compiler.host, + ); builder.run(&mut cargo); // # Determine where Miri put its sysroot. @@ -563,7 +558,7 @@ impl Miri { if builder.config.dry_run() { String::new() } else { - builder.verbose(&format!("running: {:?}", cargo)); + builder.verbose(&format!("running: {cargo:?}")); let out = cargo.output().expect("We already ran `cargo miri setup` before and that worked"); assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code"); @@ -571,7 +566,7 @@ impl Miri { let stdout = String::from_utf8(out.stdout) .expect("`cargo miri setup` stdout is not valid UTF-8"); let sysroot = stdout.trim_end(); - builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {:?}", sysroot)); + builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {sysroot:?}")); sysroot.to_owned() } } @@ -627,16 +622,14 @@ impl Step for Miri { SourceType::InTree, &[], ); + let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "miri", host, host); + cargo.add_rustc_lib_path(builder, compiler); // miri tests need to know about the stage sysroot cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", sysroot); cargo.env("MIRI", &miri); - // propagate --bless - if builder.config.cmd.bless() { - cargo.env("MIRI_BLESS", "Gesundheit"); - } // Set the target. cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg()); @@ -654,8 +647,8 @@ impl Step for Miri { 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"); + // `MIRI_SKIP_UI_CHECKS` and `RUSTC_BLESS` are incompatible + cargo.env_remove("RUSTC_BLESS"); // Optimizations can change error locations and remove UB so don't run `fail` tests. cargo.args(&["tests/pass", "tests/panic"]); @@ -739,7 +732,16 @@ impl Step for CompiletestTest { &[], ); cargo.allow_features("test"); - run_cargo_test(cargo, &[], &[], "compiletest", compiler, host, builder); + run_cargo_test( + cargo, + &[], + &[], + "compiletest", + "compiletest self test", + compiler, + host, + builder, + ); } } @@ -790,18 +792,16 @@ impl Step for Clippy { cargo.add_rustc_lib_path(builder, compiler); let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder); - // propagate --bless - if builder.config.cmd.bless() { - cargo.env("BLESS", "Gesundheit"); - } + let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host); - if builder.try_run(&mut cargo).is_ok() { + #[allow(deprecated)] // Clippy reports errors if it blessed the outputs + if builder.config.try_run(&mut cargo).is_ok() { // The tests succeeded; nothing to do. return; } if !builder.config.cmd.bless() { - crate::detail_exit_macro!(1); + crate::exit!(1); } } } @@ -855,7 +855,7 @@ impl Step for RustdocTheme { util::lld_flag_no_threads(self.compiler.host.contains("windows")), ); } - try_run(builder, &mut cmd).unwrap(); + builder.run_delaying_failure(&mut cmd); } } @@ -870,7 +870,8 @@ impl Step for RustdocJSStd { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.suite_path("tests/rustdoc-js-std") + let default = run.builder.config.nodejs.is_some(); + run.suite_path("tests/rustdoc-js-std").default_condition(default) } fn make_run(run: RunConfig<'_>) { @@ -878,38 +879,42 @@ impl Step for RustdocJSStd { } fn run(self, builder: &Builder<'_>) { - if let Some(ref nodejs) = builder.config.nodejs { - let mut command = Command::new(nodejs); - command - .arg(builder.src.join("src/tools/rustdoc-js/tester.js")) - .arg("--crate-name") - .arg("std") - .arg("--resource-suffix") - .arg(&builder.version) - .arg("--doc-folder") - .arg(builder.doc_out(self.target)) - .arg("--test-folder") - .arg(builder.src.join("tests/rustdoc-js-std")); - for path in &builder.paths { - if let Some(p) = - util::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder) - { - if !p.ends_with(".js") { - eprintln!("A non-js file was given: `{}`", path.display()); - panic!("Cannot run rustdoc-js-std tests"); - } - command.arg("--test-file").arg(path); + let nodejs = + builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests"); + let mut command = Command::new(nodejs); + command + .arg(builder.src.join("src/tools/rustdoc-js/tester.js")) + .arg("--crate-name") + .arg("std") + .arg("--resource-suffix") + .arg(&builder.version) + .arg("--doc-folder") + .arg(builder.doc_out(self.target)) + .arg("--test-folder") + .arg(builder.src.join("tests/rustdoc-js-std")); + for path in &builder.paths { + if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder) { + if !p.ends_with(".js") { + eprintln!("A non-js file was given: `{}`", path.display()); + panic!("Cannot run rustdoc-js-std tests"); } + command.arg("--test-file").arg(path); } - builder.ensure(crate::doc::Std::new( - builder.top_stage, - self.target, - DocumentationFormat::HTML, - )); - builder.run(&mut command); - } else { - builder.info("No nodejs found, skipping \"tests/rustdoc-js-std\" tests"); } + builder.ensure(crate::doc::Std::new( + builder.top_stage, + self.target, + builder, + DocumentationFormat::HTML, + )); + let _guard = builder.msg( + Kind::Test, + builder.top_stage, + "rustdoc-js-std", + builder.config.build, + self.target, + ); + builder.run(&mut command); } } @@ -925,7 +930,8 @@ impl Step for RustdocJSNotStd { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.suite_path("tests/rustdoc-js") + let default = run.builder.config.nodejs.is_some(); + run.suite_path("tests/rustdoc-js").default_condition(default) } fn make_run(run: RunConfig<'_>) { @@ -934,18 +940,14 @@ impl Step for RustdocJSNotStd { } fn run(self, builder: &Builder<'_>) { - if builder.config.nodejs.is_some() { - builder.ensure(Compiletest { - compiler: self.compiler, - target: self.target, - mode: "js-doc-test", - suite: "rustdoc-js", - path: "tests/rustdoc-js", - compare_mode: None, - }); - } else { - builder.info("No nodejs found, skipping \"tests/rustdoc-js\" tests"); - } + builder.ensure(Compiletest { + compiler: self.compiler, + target: self.target, + mode: "js-doc-test", + suite: "rustdoc-js", + path: "tests/rustdoc-js", + compare_mode: None, + }); } } @@ -1050,6 +1052,13 @@ impl Step for RustdocGUI { } let _time = util::timeit(&builder); + let _guard = builder.msg_sysroot_tool( + Kind::Test, + self.compiler.stage, + "rustdoc-gui", + self.compiler.host, + self.target, + ); crate::render_tests::try_run_tests(builder, &mut cmd, true); } } @@ -1086,6 +1095,14 @@ impl Step for Tidy { if builder.config.cmd.bless() { cmd.arg("--bless"); } + if let Some(s) = builder.config.cmd.extra_checks() { + cmd.arg(format!("--extra-checks={s}")); + } + let mut args = std::env::args_os(); + if let Some(_) = args.find(|arg| arg == OsStr::new("--")) { + cmd.arg("--"); + cmd.args(args); + } if builder.config.channel == "dev" || builder.config.channel == "nightly" { builder.info("fmt check"); @@ -1096,17 +1113,17 @@ impl Step for Tidy { error: no `rustfmt` binary found in {PATH} info: `rust.channel` is currently set to \"{CHAN}\" help: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file -help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` to `x.py test`", +help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`", PATH = inferred_rustfmt_dir.display(), CHAN = builder.config.channel, ); - crate::detail_exit_macro!(1); + crate::exit!(1); } crate::format::format(&builder, !builder.config.cmd.bless(), &[]); } builder.info("tidy check"); - try_run(builder, &mut cmd).unwrap(); + builder.run_delaying_failure(&mut cmd); builder.ensure(ExpandYamlAnchors); @@ -1123,7 +1140,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` eprintln!( "x.py completions were changed; run `x.py run generate-completions` to update them" ); - crate::detail_exit_macro!(1); + crate::exit!(1); } } } @@ -1151,11 +1168,9 @@ impl Step for ExpandYamlAnchors { /// by the user before committing CI changes. fn run(self, builder: &Builder<'_>) { builder.info("Ensuring the YAML anchors in the GitHub Actions config were expanded"); - try_run( - builder, + builder.run_delaying_failure( &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src), - ) - .unwrap(); + ); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -1435,7 +1450,7 @@ help: to test the compiler, use `--stage 1` instead help: to test the standard library, use `--stage 0 library/std` instead note: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`." ); - crate::detail_exit_macro!(1); + crate::exit!(1); } let mut compiler = self.compiler; @@ -1572,6 +1587,8 @@ note: if you're sure you want to do this, please open an issue as to why. In the if let Some(ref nodejs) = builder.config.nodejs { cmd.arg("--nodejs").arg(nodejs); + } else if mode == "js-doc-test" { + panic!("need nodejs to run js-doc-test suite"); } if let Some(ref npm) = builder.config.npm { cmd.arg("--npm").arg(npm); @@ -1642,7 +1659,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--run-clang-based-tests-with").arg(clang_exe); } - for exclude in &builder.config.exclude { + for exclude in &builder.config.skip { cmd.arg("--skip"); cmd.arg(&exclude); } @@ -1827,7 +1844,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( - crate::metrics::TestSuiteMetadata::Compiletest { + build_helper::metrics::TestSuiteMetadata::Compiletest { suite: suite.into(), mode: mode.into(), compare_mode: None, @@ -1852,7 +1869,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( - crate::metrics::TestSuiteMetadata::Compiletest { + build_helper::metrics::TestSuiteMetadata::Compiletest { suite: suite.into(), mode: mode.into(), compare_mode: Some(compare_mode.into()), @@ -1893,14 +1910,6 @@ impl Step for BookTest { /// /// This uses the `rustdoc` that sits next to `compiler`. fn run(self, builder: &Builder<'_>) { - let host = self.compiler.host; - let _guard = builder.msg( - Kind::Test, - self.compiler.stage, - &format!("book {}", self.name), - host, - host, - ); // External docs are different from local because: // - Some books need pre-processing by mdbook before being tested. // - They need to save their state to toolstate. @@ -1943,12 +1952,12 @@ impl BookTest { let _guard = builder.msg( Kind::Test, compiler.stage, - format_args!("rustbook {}", self.path.display()), + format_args!("mdbook {}", self.path.display()), compiler.host, compiler.host, ); let _time = util::timeit(&builder); - let toolstate = if try_run(builder, &mut rustbook_cmd).is_ok() { + let toolstate = if builder.run_delaying_failure(&mut rustbook_cmd) { ToolState::TestPass } else { ToolState::TestFail @@ -1959,8 +1968,12 @@ impl BookTest { /// This runs `rustdoc --test` on all `.md` files in the path. fn run_local_doc(self, builder: &Builder<'_>) { let compiler = self.compiler; + let host = self.compiler.host; - builder.ensure(compile::Std::new(compiler, compiler.host)); + builder.ensure(compile::Std::new(compiler, host)); + + let _guard = + builder.msg(Kind::Test, compiler.stage, &format!("book {}", self.name), host, host); // Do a breadth-first traversal of the `src/doc` directory and just run // tests for all files that end in `*.md` @@ -2074,10 +2087,11 @@ impl Step for ErrorIndex { let mut tool = tool::ErrorIndex::command(builder); tool.arg("markdown").arg(&output); - let _guard = + let guard = builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host); let _time = util::timeit(&builder); builder.run_quiet(&mut tool); + drop(guard); // The tests themselves need to link to std, so make sure it is // available. builder.ensure(compile::Std::new(compiler, compiler.host)); @@ -2106,9 +2120,9 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> cmd.arg("--test-args").arg(test_args); if builder.config.verbose_tests { - try_run(builder, &mut cmd).is_ok() + builder.run_delaying_failure(&mut cmd) } else { - try_run_quiet(builder, &mut cmd) + builder.run_quiet_delaying_failure(&mut cmd) } } @@ -2134,7 +2148,7 @@ impl Step for RustcGuide { let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); - let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)).is_ok() { + let toolstate = if builder.run_delaying_failure(rustbook_cmd.arg("linkcheck").arg(&src)) { ToolState::TestPass } else { ToolState::TestFail @@ -2185,11 +2199,12 @@ impl Step for CrateLibrustc { /// Given a `cargo test` subcommand, add the appropriate flags and run it. /// /// Returns whether the test succeeded. -fn run_cargo_test( +fn run_cargo_test<'a>( cargo: impl Into, libtest_args: &[&str], crates: &[Interned], primary_crate: &str, + description: impl Into>, compiler: Compiler, target: TargetSelection, builder: &Builder<'_>, @@ -2197,10 +2212,13 @@ fn run_cargo_test( let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder); let _time = util::timeit(&builder); + let _group = description.into().and_then(|what| { + builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target) + }); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( - crate::metrics::TestSuiteMetadata::CargoPackage { + build_helper::metrics::TestSuiteMetadata::CargoPackage { crates: crates.iter().map(|c| c.to_string()).collect(), target: target.triple.to_string(), host: compiler.host.triple.to_string(), @@ -2223,9 +2241,11 @@ fn prepare_cargo_test( ) -> Command { let mut cargo = cargo.into(); - // If bless is passed, give downstream crates a way to use it - if builder.config.cmd.bless() { - cargo.env("RUSTC_BLESS", "1"); + // Propegate `--bless` if it has not already been set/unset + // Any tools that want to use this should bless if `RUSTC_BLESS` is set to + // anything other than `0`. + if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") { + cargo.env("RUSTC_BLESS", "Gesundheit"); } // Pass in some standard flags then iterate over the graph we've discovered @@ -2348,7 +2368,7 @@ impl Step for Crate { // `std_cargo` actually does the wrong thing: it passes `--sysroot build/host/stage2`, // but we want to use the force-recompile std we just built in `build/host/stage2-test-sysroot`. // Override it. - if builder.download_rustc() { + if builder.download_rustc() && compiler.stage > 0 { let sysroot = builder .out .join(compiler.host.triple) @@ -2362,14 +2382,16 @@ impl Step for Crate { _ => panic!("can only test libraries"), }; - let _guard = builder.msg( - builder.kind, - compiler.stage, - crate_description(&self.crates), - compiler.host, + run_cargo_test( + cargo, + &[], + &self.crates, + &self.crates[0], + &*crate_description(&self.crates), + compiler, target, + builder, ); - run_cargo_test(cargo, &[], &self.crates, &self.crates[0], compiler, target, builder); } } @@ -2462,18 +2484,12 @@ impl Step for CrateRustdoc { dylib_path.insert(0, PathBuf::from(&*libdir)); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - let _guard = builder.msg_sysroot_tool( - builder.kind, - compiler.stage, - "rustdoc", - compiler.host, - target, - ); run_cargo_test( cargo, &[], &[INTERNER.intern_str("rustdoc:0.0.0")], "rustdoc", + "rustdoc", compiler, target, builder, @@ -2529,13 +2545,12 @@ impl Step for CrateRustdocJsonTypes { &[] }; - 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", + "rustdoc-json-types", compiler, target, builder, @@ -2574,7 +2589,7 @@ impl Step for RemoteCopyLibs { builder.ensure(compile::Std::new(compiler, target)); - builder.info(&format!("REMOTE copy libs to emulator ({})", target)); + builder.info(&format!("REMOTE copy libs to emulator ({target})")); let server = builder.ensure(tool::RemoteTestServer { compiler, target }); @@ -2676,6 +2691,10 @@ impl Step for Bootstrap { /// Tests the build system itself. fn run(self, builder: &Builder<'_>) { + let host = builder.config.build; + let compiler = builder.compiler(0, host); + let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host); + let mut check_bootstrap = Command::new(&builder.python()); check_bootstrap .args(["-m", "unittest", "bootstrap_test.py"]) @@ -2684,10 +2703,8 @@ impl Step for Bootstrap { .current_dir(builder.src.join("src/bootstrap/")); // NOTE: we intentionally don't pass test_args here because the args for unittest and cargo test are mutually incompatible. // Use `python -m unittest` manually if you want to pass arguments. - try_run(builder, &mut check_bootstrap).unwrap(); + builder.run_delaying_failure(&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")) @@ -2704,7 +2721,7 @@ impl Step for Bootstrap { } // 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. - run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", compiler, host, builder); + run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", None, compiler, host, builder); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -2755,8 +2772,14 @@ impl Step for TierCheck { cargo.arg("--verbose"); } - builder.info("platform support check"); - try_run(builder, &mut cargo.into()).unwrap(); + let _guard = builder.msg( + Kind::Test, + self.compiler.stage, + "platform support check", + self.compiler.host, + self.compiler.host, + ); + builder.run_delaying_failure(&mut cargo.into()); } } @@ -2803,8 +2826,6 @@ impl Step for RustInstaller { /// Ensure the version placeholder replacement tool builds fn run(self, builder: &Builder<'_>) { - builder.info("test rust-installer"); - let bootstrap_host = builder.config.build; let compiler = builder.compiler(0, bootstrap_host); let cargo = tool::prepare_tool_cargo( @@ -2817,7 +2838,15 @@ impl Step for RustInstaller { SourceType::InTree, &[], ); - run_cargo_test(cargo, &[], &[], "installer", compiler, bootstrap_host, builder); + + let _guard = builder.msg( + Kind::Test, + compiler.stage, + "rust-installer", + bootstrap_host, + bootstrap_host, + ); + run_cargo_test(cargo, &[], &[], "installer", None, 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 @@ -2836,7 +2865,7 @@ impl Step for RustInstaller { cmd.env("CARGO", &builder.initial_cargo); cmd.env("RUSTC", &builder.initial_rustc); cmd.env("TMP_DIR", &tmpdir); - try_run(builder, &mut cmd).unwrap(); + builder.run_delaying_failure(&mut cmd); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 06c031788..e6d27757a 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -34,6 +34,7 @@ struct ToolBuild { } impl Builder<'_> { + #[track_caller] fn msg_tool( &self, mode: Mode, @@ -107,7 +108,8 @@ impl Step for ToolBuild { ); let mut cargo = Command::from(cargo); - let is_expected = builder.try_run(&mut cargo).is_ok(); + #[allow(deprecated)] // we check this in `is_optional_tool` in a second + let is_expected = builder.config.try_run(&mut cargo).is_ok(); builder.save_toolstate( tool, @@ -116,7 +118,7 @@ impl Step for ToolBuild { if !is_expected { if !is_optional_tool { - crate::detail_exit_macro!(1); + crate::exit!(1); } else { None } @@ -303,6 +305,7 @@ bootstrap_tool!( 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"; + OptimizedDist, "src/tools/opt-dist", "opt-dist"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] @@ -555,39 +558,6 @@ impl Step for Cargo { allow_features: "", }) .expect("expected to build -- essential tool"); - - let build_cred = |name, path| { - // These credential helpers are currently experimental. - // Any build failures will be ignored. - let _ = builder.ensure(ToolBuild { - compiler: self.compiler, - target: self.target, - tool: name, - mode: Mode::ToolRustc, - path, - is_optional_tool: true, - source_type: SourceType::Submodule, - extra_features: Vec::new(), - allow_features: "", - }); - }; - - if self.target.contains("windows") { - build_cred( - "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/credential/cargo-credential-macos-keychain", - ); - } - build_cred( - "cargo-credential-1password", - "src/tools/cargo/credential/cargo-credential-1password", - ); cargo_bin_path } } diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 9c4d0ea26..308023537 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -83,15 +83,15 @@ static NIGHTLY_TOOLS: &[(&str, &str)] = &[ fn print_error(tool: &str, submodule: &str) { eprintln!(); - eprintln!("We detected that this PR updated '{}', but its tests failed.", tool); + eprintln!("We detected that this PR updated '{tool}', but its tests failed."); eprintln!(); - eprintln!("If you do intend to update '{}', please check the error messages above and", tool); + eprintln!("If you do intend to update '{tool}', please check the error messages above and"); eprintln!("commit another update."); eprintln!(); - eprintln!("If you do NOT intend to update '{}', please ensure you did not accidentally", tool); - eprintln!("change the submodule at '{}'. You may ask your reviewer for the", submodule); + eprintln!("If you do NOT intend to update '{tool}', please ensure you did not accidentally"); + eprintln!("change the submodule at '{submodule}'. You may ask your reviewer for the"); eprintln!("proper steps."); - crate::detail_exit_macro!(3); + crate::exit!(3); } fn check_changed_files(toolstates: &HashMap, ToolState>) { @@ -105,8 +105,8 @@ fn check_changed_files(toolstates: &HashMap, ToolState>) { let output = match output { Ok(o) => o, Err(e) => { - eprintln!("Failed to get changed files: {:?}", e); - crate::detail_exit_macro!(1); + eprintln!("Failed to get changed files: {e:?}"); + crate::exit!(1); } }; @@ -114,12 +114,12 @@ fn check_changed_files(toolstates: &HashMap, ToolState>) { for (tool, submodule) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) { let changed = output.lines().any(|l| l.starts_with('M') && l.ends_with(submodule)); - eprintln!("Verifying status of {}...", tool); + eprintln!("Verifying status of {tool}..."); if !changed { continue; } - eprintln!("This PR updated '{}', verifying if status is 'test-pass'...", submodule); + eprintln!("This PR updated '{submodule}', verifying if status is 'test-pass'..."); if toolstates[*tool] != ToolState::TestPass { print_error(tool, submodule); } @@ -172,12 +172,12 @@ impl Step for ToolStateCheck { for (tool, _) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) { if !toolstates.contains_key(*tool) { did_error = true; - eprintln!("error: Tool `{}` was not recorded in tool state.", tool); + eprintln!("error: Tool `{tool}` was not recorded in tool state."); } } if did_error { - crate::detail_exit_macro!(1); + crate::exit!(1); } check_changed_files(&toolstates); @@ -190,7 +190,7 @@ impl Step for ToolStateCheck { if state != ToolState::TestPass { if !is_nightly { did_error = true; - eprintln!("error: Tool `{}` should be test-pass but is {}", tool, state); + eprintln!("error: Tool `{tool}` should be test-pass but is {state}"); } else if in_beta_week { let old_state = old_toolstate .iter() @@ -200,17 +200,15 @@ impl Step for ToolStateCheck { if state < old_state { did_error = true; eprintln!( - "error: Tool `{}` has regressed from {} to {} during beta week.", - tool, old_state, state + "error: Tool `{tool}` has regressed from {old_state} to {state} during beta week." ); } else { // This warning only appears in the logs, which most // people won't read. It's mostly here for testing and // debugging. eprintln!( - "warning: Tool `{}` is not test-pass (is `{}`), \ - this should be fixed before beta is branched.", - tool, state + "warning: Tool `{tool}` is not test-pass (is `{state}`), \ + this should be fixed before beta is branched." ); } } @@ -223,7 +221,7 @@ impl Step for ToolStateCheck { } if did_error { - crate::detail_exit_macro!(1); + crate::exit!(1); } if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() { @@ -262,6 +260,8 @@ impl Builder<'_> { /// `rust.save-toolstates` in `config.toml`. If unspecified, nothing will be /// done. The file is updated immediately after this function completes. pub fn save_toolstate(&self, tool: &str, state: ToolState) { + use std::io::Write; + // If we're in a dry run setting we don't want to save toolstates as // that means if we e.g. panic down the line it'll look like we tested // everything (but we actually haven't). @@ -286,7 +286,8 @@ impl Builder<'_> { current_toolstates.insert(tool.into(), state); t!(file.seek(SeekFrom::Start(0))); t!(file.set_len(0)); - t!(serde_json::to_writer(file, ¤t_toolstates)); + t!(serde_json::to_writer(&file, ¤t_toolstates)); + t!(writeln!(file)); // make sure this ends in a newline } } } @@ -320,7 +321,7 @@ fn checkout_toolstate_repo() { Err(_) => false, }; if !success { - panic!("git clone unsuccessful (status: {:?})", status); + panic!("git clone unsuccessful (status: {status:?})"); } } @@ -333,7 +334,7 @@ fn prepare_toolstate_config(token: &str) { Err(_) => false, }; if !success { - panic!("git config key={} value={} failed (status: {:?})", key, value, status); + panic!("git config key={key} value={value} failed (status: {status:?})"); } } @@ -343,7 +344,7 @@ fn prepare_toolstate_config(token: &str) { git_config("user.name", "Rust Toolstate Update"); git_config("credential.helper", "store"); - let credential = format!("https://{}:x-oauth-basic@github.com\n", token,); + let credential = format!("https://{token}:x-oauth-basic@github.com\n",); let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials"); t!(fs::write(&git_credential_path, credential)); } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index b291584b3..3c4a21434 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -46,9 +46,9 @@ pub use t; /// executable for a particular target. pub fn exe(name: &str, target: TargetSelection) -> String { if target.contains("windows") { - format!("{}.exe", name) + format!("{name}.exe") } else if target.contains("uefi") { - format!("{}.efi", name) + format!("{name}.efi") } else { name.to_string() } @@ -153,16 +153,6 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result< } } -/// The CI environment rustbuild is running in. This mainly affects how the logs -/// are printed. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum CiEnv { - /// Not a CI environment. - None, - /// The GitHub Actions environment, for Linux (including Docker), Windows and macOS builds. - GitHubActions, -} - pub fn forcing_clang_based_tests() -> bool { if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") { match &var.to_string_lossy().to_lowercase()[..] { @@ -171,9 +161,8 @@ pub fn forcing_clang_based_tests() -> bool { other => { // Let's make sure typos don't go unnoticed panic!( - "Unrecognized option '{}' set in \ - RUSTBUILD_FORCE_CLANG_BASED_TESTS", - other + "Unrecognized option '{other}' set in \ + RUSTBUILD_FORCE_CLANG_BASED_TESTS" ) } } @@ -229,7 +218,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) { if try_run(cmd, print_cmd_on_fail).is_err() { - crate::detail_exit_macro!(1); + crate::exit!(1); } } @@ -237,15 +226,14 @@ pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { let status = match cmd.status() { Ok(status) => status, Err(e) => { - println!("failed to execute command: {:?}\nerror: {}", cmd, e); + println!("failed to execute command: {cmd:?}\nerror: {e}"); return false; } }; if !status.success() && print_cmd_on_fail { println!( - "\n\ncommand did not execute successfully: {:?}\n\ - expected success, got: {}\n\n", - cmd, status + "\n\ncommand did not execute successfully: {cmd:?}\n\ + expected success, got: {status}\n\n" ); } status.success() @@ -253,14 +241,14 @@ pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { pub fn run_suppressed(cmd: &mut Command) { if !try_run_suppressed(cmd) { - crate::detail_exit_macro!(1); + crate::exit!(1); } } pub fn try_run_suppressed(cmd: &mut Command) -> bool { let output = match cmd.output() { Ok(status) => status, - Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), + Err(e) => fail(&format!("failed to execute command: {cmd:?}\nerror: {e}")), }; if !output.status.success() { println!( @@ -293,7 +281,7 @@ pub fn make(host: &str) -> PathBuf { pub fn output(cmd: &mut Command) -> String { let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, - Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), + Err(e) => fail(&format!("failed to execute command: {cmd:?}\nerror: {e}")), }; if !output.status.success() { panic!( @@ -308,7 +296,7 @@ pub fn output(cmd: &mut Command) -> String { pub fn output_result(cmd: &mut Command) -> Result { let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, - Err(e) => return Err(format!("failed to run command: {:?}: {}", cmd, e)), + Err(e) => return Err(format!("failed to run command: {cmd:?}: {e}")), }; if !output.status.success() { return Err(format!( @@ -338,7 +326,7 @@ pub fn up_to_date(src: &Path, dst: &Path) -> bool { let threshold = mtime(dst); let meta = match fs::metadata(src) { Ok(meta) => meta, - Err(e) => panic!("source {:?} failed to get metadata: {}", src, e), + Err(e) => panic!("source {src:?} failed to get metadata: {e}"), }; if meta.is_dir() { dir_up_to_date(src, threshold) @@ -503,3 +491,7 @@ pub fn lld_flag_no_threads(is_windows: bool) -> &'static str { }); if is_windows { windows } else { other } } + +pub fn dir_is_empty(dir: &Path) -> bool { + t!(std::fs::read_dir(dir)).next().is_none() +} diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 852f2e209..b83b19878 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -14,7 +14,8 @@ for example: ./src/ci/docker/run.sh x86_64-gnu ``` -Images will output artifacts in an `obj` dir at the root of a repository. +Images will output artifacts in an `obj` dir at the root of a repository. Note +that the script will overwrite the contents of this directory. To match conditions in rusts CI, also set the environment variable `DEPLOY=1`, e.g.: ``` diff --git a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile index 699938c37..85b0f3b10 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile @@ -1,6 +1,7 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ make \ ninja-build \ diff --git a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile index 57e63cd39..015caafc5 100644 --- a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile @@ -1,6 +1,7 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 -RUN apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update -y && apt-get install -y --no-install-recommends \ bc \ bzip2 \ ca-certificates \ @@ -13,6 +14,7 @@ RUN apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y --no- git \ libc6-dev \ libc6-dev-armhf-cross \ + libssl-dev \ make \ ninja-build \ python3 \ @@ -33,14 +35,14 @@ WORKDIR /build # the kernel. This file was generated by running `make vexpress_defconfig` # followed by `make menuconfig` and then enabling the IPv6 protocol page. COPY host-x86_64/armhf-gnu/vexpress_config /build/.config -RUN curl https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.253.tar.xz | \ +RUN curl https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.14.320.tar.xz | \ tar xJf - && \ - cd /build/linux-4.4.253 && \ + cd /build/linux-4.14.320 && \ cp /build/.config . && \ make -j$(nproc) all && \ cp arch/arm/boot/zImage /tmp && \ cd /build && \ - rm -rf linux-4.4.253 + rm -rf linux-4.14.320 # Compile an instance of busybox as this provides a lightweight system and init # binary which we will boot into. Only trick here is configuring busybox to @@ -58,7 +60,7 @@ RUN curl https://www.busybox.net/downloads/busybox-1.32.1.tar.bz2 | tar xjf - && # Download the ubuntu rootfs, which we'll use as a chroot for all our tests. WORKDIR /tmp RUN mkdir rootfs/ubuntu -RUN curl https://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.1-base-armhf.tar.gz | \ +RUN curl https://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04.2-base-armhf.tar.gz | \ tar xzf - -C rootfs/ubuntu && \ cd rootfs && mkdir proc sys dev etc etc/init.d diff --git a/src/ci/docker/host-x86_64/armhf-gnu/vexpress_config b/src/ci/docker/host-x86_64/armhf-gnu/vexpress_config index b39e5dcf3..54c3ae18d 100644 --- a/src/ci/docker/host-x86_64/armhf-gnu/vexpress_config +++ b/src/ci/docker/host-x86_64/armhf-gnu/vexpress_config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.4.253 Kernel Configuration +# Linux/arm 4.14.320 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -49,8 +49,8 @@ CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set CONFIG_CROSS_MEMORY_ATTACH=y -# CONFIG_FHANDLE is not set -CONFIG_USELIB=y +CONFIG_FHANDLE=y +# CONFIG_USELIB is not set # CONFIG_AUDIT is not set CONFIG_HAVE_ARCH_AUDITSYSCALL=y @@ -60,6 +60,7 @@ CONFIG_HAVE_ARCH_AUDITSYSCALL=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_IRQ_DOMAIN=y @@ -68,6 +69,8 @@ CONFIG_HANDLE_DOMAIN_IRQ=y # CONFIG_IRQ_DOMAIN_DEBUG is not set CONFIG_IRQ_FORCED_THREADING=y CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_ARCH_HAS_TICK_BROADCAST=y @@ -97,28 +100,31 @@ CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TREE_RCU=y # CONFIG_RCU_EXPERT is not set CONFIG_SRCU=y +CONFIG_TREE_SRCU=y # CONFIG_TASKS_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_EXPEDITE_BOOT is not set +CONFIG_RCU_NEED_SEGCBLIST=y CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 CONFIG_GENERIC_SCHED_CLOCK=y CONFIG_CGROUPS=y -# CONFIG_CGROUP_DEBUG is not set -# CONFIG_CGROUP_FREEZER is not set +# CONFIG_MEMCG is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUP_PIDS is not set -# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CGROUP_RDMA is not set +# CONFIG_CGROUP_FREEZER is not set CONFIG_CPUSETS=y CONFIG_PROC_PID_CPUSET=y +# CONFIG_CGROUP_DEVICE is not set # CONFIG_CGROUP_CPUACCT is not set -# CONFIG_MEMCG is not set # CONFIG_CGROUP_PERF is not set -# CONFIG_CGROUP_SCHED is not set -# CONFIG_BLK_CGROUP is not set +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_SOCK_CGROUP_DATA is not set # CONFIG_CHECKPOINT_RESTORE is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set @@ -149,13 +155,19 @@ CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set CONFIG_SYSFS_SYSCALL=y # CONFIG_SYSCTL_SYSCALL is not set +CONFIG_POSIX_TIMERS=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_PRINTK=y +CONFIG_PRINTK_NMI=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +CONFIG_HAVE_FUTEX_CMPXCHG=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y @@ -169,6 +181,7 @@ CONFIG_MEMBARRIER=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_USE_VMALLOC=y +# CONFIG_PC104 is not set # # Kernel Performance Events And Counters @@ -180,25 +193,30 @@ CONFIG_SLUB_DEBUG=y CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y +CONFIG_SLAB_MERGE_DEFAULT=y +# CONFIG_SLAB_FREELIST_RANDOM is not set +# CONFIG_SLAB_FREELIST_HARDENED is not set CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SYSTEM_DATA_VERIFICATION is not set CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set # CONFIG_JUMP_LABEL is not set -# CONFIG_UPROBES is not set +CONFIG_UPROBES=y # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_NMI=y CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y @@ -208,20 +226,39 @@ CONFIG_HAVE_PERF_USER_STACK_DUMP=y CONFIG_HAVE_ARCH_JUMP_LABEL=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_GCC_PLUGINS=y +# CONFIG_GCC_PLUGINS is not set CONFIG_HAVE_CC_STACKPROTECTOR=y # CONFIG_CC_STACKPROTECTOR is not set CONFIG_CC_STACKPROTECTOR_NONE=y # CONFIG_CC_STACKPROTECTOR_REGULAR is not set # CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_THIN_ARCHIVES=y CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_MODULES_USE_ELF_REL=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_HAVE_EXIT_THREAD=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=8 +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_BITS=8 +# CONFIG_HAVE_ARCH_HASH is not set +# CONFIG_ISA_BUS_API is not set CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OLD_SIGACTION=y +# CONFIG_CPU_NO_EFFICIENT_FFS is not set +# CONFIG_HAVE_ARCH_VMAP_STACK is not set +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +# CONFIG_REFCOUNT_FULL is not set # # GCOV-based kernel profiling @@ -240,13 +277,19 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_MODULE_SIG is not set # CONFIG_MODULE_COMPRESS is not set +# CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_MODULES_TREE_LOOKUP=y CONFIG_BLOCK=y # CONFIG_LBDAF is not set +CONFIG_BLK_SCSI_REQUEST=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_BSGLIB is not set # CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_DEV_ZONED is not set # CONFIG_BLK_CMDLINE_PARSER is not set +# CONFIG_BLK_WBT is not set +CONFIG_BLK_DEBUG_FS=y +# CONFIG_BLK_SED_OPAL is not set # # Partition Types @@ -254,6 +297,7 @@ CONFIG_BLOCK=y # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y CONFIG_EFI_PARTITION=y +CONFIG_BLK_MQ_VIRTIO=y # # IO Schedulers @@ -263,6 +307,9 @@ CONFIG_IOSCHED_NOOP=y # CONFIG_IOSCHED_CFQ is not set CONFIG_DEFAULT_NOOP=y CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +# CONFIG_IOSCHED_BFQ is not set CONFIG_INLINE_SPIN_UNLOCK_IRQ=y CONFIG_INLINE_READ_UNLOCK=y CONFIG_INLINE_READ_UNLOCK_IRQ=y @@ -279,10 +326,6 @@ CONFIG_FREEZER=y # CONFIG_MMU=y CONFIG_ARCH_MULTIPLATFORM=y -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set @@ -292,9 +335,6 @@ CONFIG_ARCH_MULTIPLATFORM=y # CONFIG_ARCH_IOP33X is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_DOVE is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_LPC32XX is not set @@ -302,7 +342,6 @@ CONFIG_ARCH_MULTIPLATFORM=y # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C24XX is not set -# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP1 is not set @@ -319,7 +358,9 @@ CONFIG_ARCH_MULTI_V6_V7=y # CONFIG_ARCH_MULTI_CPU_AUTO is not set # CONFIG_ARCH_VIRT is not set # CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_ACTIONS is not set # CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_ARTPEC is not set # CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_BCM is not set # CONFIG_ARCH_BERLIN is not set @@ -340,16 +381,19 @@ CONFIG_ARCH_MULTI_V6_V7=y # CONFIG_SOC_AM33XX is not set # CONFIG_SOC_AM43XX is not set # CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_ROCKCHIP is not set # CONFIG_ARCH_SOCFPGA is not set # CONFIG_PLAT_SPEAR is not set # CONFIG_ARCH_STI is not set # CONFIG_ARCH_S5PV210 is not set # CONFIG_ARCH_EXYNOS is not set -# CONFIG_ARCH_SHMOBILE_MULTI is not set +# CONFIG_ARCH_RENESAS is not set # CONFIG_ARCH_SUNXI is not set # CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_TANGO is not set # CONFIG_ARCH_TEGRA is not set # CONFIG_ARCH_UNIPHIER is not set # CONFIG_ARCH_U8500 is not set @@ -367,6 +411,7 @@ CONFIG_PLAT_VERSATILE=y # Processor Type # CONFIG_CPU_V7=y +CONFIG_CPU_THUMB_CAPABLE=y CONFIG_CPU_32v6K=y CONFIG_CPU_32v7=y CONFIG_CPU_ABRT_EV7=y @@ -393,12 +438,14 @@ CONFIG_SWP_EMULATE=y # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_CPU_SPECTRE=y CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDEN_BRANCH_HISTORY=y CONFIG_KUSER_HELPERS=y CONFIG_VDSO=y CONFIG_OUTER_CACHE=y CONFIG_OUTER_CACHE_SYNC=y CONFIG_MIGHT_HAVE_CACHE_L2X0=y CONFIG_CACHE_L2X0=y +# CONFIG_CACHE_L2X0_PMU is not set # CONFIG_PL310_ERRATA_588369 is not set # CONFIG_PL310_ERRATA_727915 is not set CONFIG_PL310_ERRATA_753970=y @@ -408,7 +455,7 @@ CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_ARM_HEAVY_MB=y CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y -# CONFIG_ARM_KERNMEM_PERMS is not set +CONFIG_DEBUG_ALIGN_RODATA=y CONFIG_MULTI_IRQ_HANDLER=y # CONFIG_ARM_ERRATA_430973 is not set CONFIG_ARM_ERRATA_643719=y @@ -419,7 +466,11 @@ CONFIG_ARM_ERRATA_720789=y # CONFIG_ARM_ERRATA_775420 is not set # CONFIG_ARM_ERRATA_798181 is not set # CONFIG_ARM_ERRATA_773022 is not set -CONFIG_ICST=y +# CONFIG_ARM_ERRATA_818325_852422 is not set +# CONFIG_ARM_ERRATA_821420 is not set +# CONFIG_ARM_ERRATA_825619 is not set +# CONFIG_ARM_ERRATA_852421 is not set +# CONFIG_ARM_ERRATA_852423 is not set # # Bus support @@ -427,6 +478,15 @@ CONFIG_ICST=y # CONFIG_PCI is not set # CONFIG_PCI_DOMAINS_GENERIC is not set # CONFIG_PCI_SYSCALL is not set + +# +# DesignWare PCI Core Support +# + +# +# PCI Endpoint +# +# CONFIG_PCI_ENDPOINT is not set # CONFIG_PCCARD is not set # @@ -465,6 +525,7 @@ CONFIG_HZ_100=y CONFIG_HZ=100 # CONFIG_SCHED_HRTICK is not set # CONFIG_THUMB2_KERNEL is not set +CONFIG_ARM_PATCH_IDIV=y CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set @@ -487,9 +548,9 @@ CONFIG_BALLOON_COMPACTION=y CONFIG_COMPACTION=y CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_ARCH_WANTS_THP_SWAP is not set # CONFIG_CLEANCACHE is not set # CONFIG_FRONTSWAP is not set CONFIG_CMA=y @@ -499,13 +560,17 @@ CONFIG_CMA_AREAS=7 # CONFIG_ZPOOL is not set # CONFIG_ZBUD is not set # CONFIG_ZSMALLOC is not set +CONFIG_GENERIC_EARLY_IOREMAP=y # CONFIG_IDLE_PAGE_TRACKING is not set +# CONFIG_PERCPU_STATS is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_ALIGNMENT_TRAP=y # CONFIG_UACCESS_WITH_MEMCPY is not set # CONFIG_SECCOMP is not set CONFIG_SWIOTLB=y CONFIG_IOMMU_HELPER=y +# CONFIG_PARAVIRT is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set # CONFIG_XEN is not set # @@ -524,6 +589,7 @@ CONFIG_CMDLINE_FROM_BOOTLOADER=y # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set CONFIG_AUTO_ZRELADDR=y +# CONFIG_EFI is not set # # CPU Power Management @@ -539,7 +605,7 @@ CONFIG_AUTO_ZRELADDR=y # CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_CPU_IDLE_GOV_MENU is not set # # ARM CPU Idle Drivers @@ -565,8 +631,10 @@ CONFIG_NEON=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +CONFIG_ELFCORE=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_SCRIPT=y +# CONFIG_BINFMT_FLAT is not set # CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set CONFIG_COREDUMP=y @@ -599,7 +667,9 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y +CONFIG_UNIX_SCM=y # CONFIG_UNIX_DIAG is not set +# CONFIG_TLS is not set CONFIG_XFRM=y # CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set @@ -624,15 +694,17 @@ CONFIG_NET_IP_TUNNEL=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_XFRM_TUNNEL is not set CONFIG_INET_TUNNEL=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y -# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_INET_UDP_DIAG is not set +# CONFIG_INET_RAW_DIAG is not set +# CONFIG_INET_DIAG_DESTROY is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" @@ -644,7 +716,6 @@ CONFIG_IPV6=y # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set # CONFIG_IPV6_MIP6 is not set -# CONFIG_IPV6_ILA is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set CONFIG_INET6_XFRM_MODE_TRANSPORT=y @@ -656,9 +727,12 @@ CONFIG_IPV6_SIT=y # CONFIG_IPV6_SIT_6RD is not set CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_GRE is not set +# CONFIG_IPV6_FOU is not set +# CONFIG_IPV6_FOU_TUNNEL is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NET_PTP_CLASSIFY is not set # CONFIG_NETWORK_PHY_TIMESTAMPING is not set @@ -673,7 +747,6 @@ CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_HAVE_NET_DSA=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -689,9 +762,11 @@ CONFIG_HAVE_NET_DSA=y # CONFIG_VSOCKETS is not set # CONFIG_NETLINK_DIAG is not set # CONFIG_MPLS is not set +# CONFIG_NET_NSH is not set # CONFIG_HSR is not set # CONFIG_NET_SWITCHDEV is not set # CONFIG_NET_L3_MASTER_DEV is not set +# CONFIG_NET_NCSI is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -706,30 +781,35 @@ CONFIG_NET_FLOW_LIMIT=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set -# CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set +# CONFIG_AF_KCM is not set +# CONFIG_STREAM_PARSER is not set # CONFIG_WIRELESS is not set # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set -# CONFIG_RFKILL_REGULATOR is not set CONFIG_NET_9P=y CONFIG_NET_9P_VIRTIO=y # CONFIG_NET_9P_DEBUG is not set # CONFIG_CAIF is not set # CONFIG_CEPH_LIB is not set # CONFIG_NFC is not set +# CONFIG_PSAMPLE is not set +# CONFIG_NET_IFE is not set # CONFIG_LWTUNNEL is not set CONFIG_DST_CACHE=y -CONFIG_HAVE_BPF_JIT=y +CONFIG_GRO_CELLS=y +# CONFIG_NET_DEVLINK is not set +CONFIG_MAY_USE_DEVLINK=y +CONFIG_HAVE_EBPF_JIT=y # # Device Drivers # CONFIG_ARM_AMBA=y -# CONFIG_TEGRA_AHB is not set # # Generic Driver Options @@ -747,12 +827,18 @@ CONFIG_EXTRA_FIRMWARE="" CONFIG_ALLOW_DEV_COREDUMP=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y CONFIG_REGMAP_MMIO=y # CONFIG_DMA_SHARED_BUFFER is not set # CONFIG_DMA_CMA is not set +CONFIG_GENERIC_ARCH_TOPOLOGY=y # # Bus devices @@ -761,9 +847,10 @@ CONFIG_ARM_CCI=y CONFIG_ARM_CCI400_COMMON=y # CONFIG_ARM_CCI400_PMU is not set CONFIG_ARM_CCI400_PORT_CTRL=y -# CONFIG_ARM_CCI500_PMU is not set +# CONFIG_ARM_CCI5xx_PMU is not set # CONFIG_ARM_CCN is not set # CONFIG_BRCMSTB_GISB_ARB is not set +# CONFIG_SIMPLE_PM_BUS is not set CONFIG_VEXPRESS_CONFIG=y # CONFIG_CONNECTOR is not set CONFIG_MTD=y @@ -774,6 +861,10 @@ CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_AR7_PARTS is not set +# +# Partition parsers +# + # # User Modules And Translation Layers # @@ -821,6 +912,8 @@ CONFIG_MTD_RAM=y CONFIG_MTD_PHYSMAP=y # CONFIG_MTD_PHYSMAP_COMPAT is not set CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PHYSMAP_OF_VERSATILE is not set +# CONFIG_MTD_PHYSMAP_OF_GEMINI is not set CONFIG_MTD_PLATRAM=y # @@ -859,7 +952,6 @@ CONFIG_OF_ADDRESS=y CONFIG_OF_IRQ=y CONFIG_OF_NET=y CONFIG_OF_MDIO=y -CONFIG_OF_MTD=y CONFIG_OF_RESERVED_MEM=y # CONFIG_OF_OVERLAY is not set CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y @@ -873,9 +965,10 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_RAM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set -# CONFIG_MG_DISK is not set CONFIG_VIRTIO_BLK=y +# CONFIG_VIRTIO_BLK_SCSI is not set # CONFIG_BLK_DEV_RBD is not set +# CONFIG_NVME_FC is not set # # Misc devices @@ -889,13 +982,10 @@ CONFIG_VIRTIO_BLK=y # CONFIG_ISL29003 is not set # CONFIG_ISL29020 is not set # CONFIG_SENSORS_TSL2550 is not set -# CONFIG_SENSORS_BH1780 is not set # CONFIG_SENSORS_BH1770 is not set # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_ARM_CHARLCD is not set -# CONFIG_BMP085_I2C is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_SRAM is not set CONFIG_VEXPRESS_SYSCFG=y @@ -908,6 +998,7 @@ CONFIG_VEXPRESS_SYSCFG=y # CONFIG_EEPROM_LEGACY is not set # CONFIG_EEPROM_MAX6875 is not set # CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set # # Texas Instruments shared transport line discipline @@ -928,6 +1019,10 @@ CONFIG_VEXPRESS_SYSCFG=y # SCIF Bus Driver # +# +# VOP Bus Driver +# + # # Intel MIC Host Driver # @@ -943,10 +1038,14 @@ CONFIG_VEXPRESS_SYSCFG=y # # Intel MIC Coprocessor State Management (COSM) Drivers # + +# +# VOP Driver +# # CONFIG_ECHO is not set # CONFIG_CXL_BASE is not set -# CONFIG_CXL_KERNEL_API is not set -# CONFIG_CXL_EEH is not set +# CONFIG_CXL_AFU_DRIVER_OPS is not set +# CONFIG_CXL_LIB is not set # # SCSI device support @@ -1034,8 +1133,9 @@ CONFIG_NET_CORE=y # CONFIG_EQUALIZER is not set # CONFIG_NET_TEAM is not set # CONFIG_MACVLAN is not set -# CONFIG_IPVLAN is not set # CONFIG_VXLAN is not set +# CONFIG_GTP is not set +# CONFIG_MACSEC is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -1052,13 +1152,12 @@ CONFIG_VIRTIO_NET=y # # Distributed Switch Architecture drivers # -# CONFIG_NET_DSA_MV88E6XXX is not set -# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_ALACRITECH=y # CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMAZON=y +CONFIG_NET_VENDOR_AQUANTIA=y CONFIG_NET_VENDOR_ARC=y -# CONFIG_ARC_EMAC is not set -# CONFIG_EMAC_ROCKCHIP is not set # CONFIG_NET_VENDOR_AURORA is not set CONFIG_NET_CADENCE=y # CONFIG_MACB is not set @@ -1077,26 +1176,36 @@ CONFIG_NET_VENDOR_FARADAY=y # CONFIG_FTGMAC100 is not set CONFIG_NET_VENDOR_HISILICON=y # CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HISI_FEMAC is not set # CONFIG_HIP04_ETH is not set # CONFIG_HNS is not set # CONFIG_HNS_DSAF is not set # CONFIG_HNS_ENET is not set +CONFIG_NET_VENDOR_HUAWEI=y CONFIG_NET_VENDOR_INTEL=y CONFIG_NET_VENDOR_I825XX=y CONFIG_NET_VENDOR_MARVELL=y # CONFIG_MVMDIO is not set +# CONFIG_MVNETA_BM is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLXSW_CORE is not set +# CONFIG_MLXFW is not set CONFIG_NET_VENDOR_MICREL=y # CONFIG_KS8851_MLL is not set CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_NETRONOME=y CONFIG_NET_VENDOR_8390=y # CONFIG_AX88796 is not set # CONFIG_ETHOC is not set CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCOM_EMAC is not set +# CONFIG_RMNET is not set CONFIG_NET_VENDOR_RENESAS=y CONFIG_NET_VENDOR_ROCKER=y CONFIG_NET_VENDOR_SAMSUNG=y # CONFIG_SXGBE_ETH is not set CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SOLARFLARE=y CONFIG_NET_VENDOR_SMSC=y CONFIG_SMC91X=y # CONFIG_SMC911X is not set @@ -1104,47 +1213,58 @@ CONFIG_SMSC911X=y # CONFIG_SMSC911X_ARCH_HOOKS is not set CONFIG_NET_VENDOR_STMICRO=y # CONFIG_STMMAC_ETH is not set -CONFIG_NET_VENDOR_SYNOPSYS=y -# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set CONFIG_NET_VENDOR_VIA=y # CONFIG_VIA_RHINE is not set # CONFIG_VIA_VELOCITY is not set CONFIG_NET_VENDOR_WIZNET=y # CONFIG_WIZNET_W5100 is not set # CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_SYNOPSYS=y +# CONFIG_DWC_XLGMAC is not set +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_BUS=y +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_HISI_FEMAC is not set CONFIG_PHYLIB=y +CONFIG_SWPHY=y +# CONFIG_LED_TRIGGER_PHY is not set # # MII PHY device drivers # +# CONFIG_AMD_PHY is not set # CONFIG_AQUANTIA_PHY is not set # CONFIG_AT803X_PHY is not set -# CONFIG_AMD_PHY is not set -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_TERANETICS_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set # CONFIG_BCM7XXX_PHY is not set # CONFIG_BCM87XX_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +CONFIG_FIXED_PHY=y # CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set +# CONFIG_INTEL_XWAY_PHY is not set # CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set # CONFIG_MICREL_PHY is not set -# CONFIG_DP83848_PHY is not set -# CONFIG_DP83867_PHY is not set # CONFIG_MICROCHIP_PHY is not set -# CONFIG_FIXED_PHY is not set -# CONFIG_MDIO_BITBANG is not set -# CONFIG_MDIO_BUS_MUX_GPIO is not set -# CONFIG_MDIO_BUS_MUX_MMIOREG is not set -# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set CONFIG_USB_NET_DRIVERS=y @@ -1163,7 +1283,6 @@ CONFIG_USB_NET_DRIVERS=y # # CONFIG_WAN is not set # CONFIG_ISDN is not set -# CONFIG_NVM is not set # # Input device support @@ -1178,10 +1297,7 @@ CONFIG_INPUT_LEDS=y # # Userland interfaces # -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set @@ -1195,6 +1311,7 @@ CONFIG_INPUT_KEYBOARD=y CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_QT1070 is not set # CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_GPIO is not set # CONFIG_KEYBOARD_GPIO_POLLED is not set @@ -1212,20 +1329,24 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_SUNKBD is not set # CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_CAP11XX is not set # CONFIG_KEYBOARD_BCM is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y CONFIG_MOUSE_PS2_LOGIPS2PP=y CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y CONFIG_MOUSE_PS2_CYPRESS=y CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MOUSE_PS2_ELANTECH is not set # CONFIG_MOUSE_PS2_SENTELIC is not set # CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_PS2_FOCALTECH=y +CONFIG_MOUSE_PS2_SMBUS=y # CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_BCM5974 is not set @@ -1239,6 +1360,7 @@ CONFIG_MOUSE_PS2_FOCALTECH=y # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set +# CONFIG_RMI4_CORE is not set # # Hardware I/O ports @@ -1252,6 +1374,7 @@ CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_PS2MULT is not set # CONFIG_SERIO_ARC_PS2 is not set # CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_GPIO_PS2 is not set # CONFIG_USERIO is not set # CONFIG_GAMEPORT is not set @@ -1266,7 +1389,6 @@ CONFIG_VT_CONSOLE_SLEEP=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_SERIAL_NONSTANDARD is not set @@ -1274,7 +1396,7 @@ CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_TRACE_SINK is not set CONFIG_LDISC_AUTOLOAD=y CONFIG_DEVMEM=y -CONFIG_DEVKMEM=y +# CONFIG_DEVKMEM is not set # # Serial drivers @@ -1302,7 +1424,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_FSL_LPUART is not set # CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set # CONFIG_SERIAL_ST_ASC is not set -# CONFIG_SERIAL_STM32 is not set +# CONFIG_SERIAL_DEV_BUS is not set CONFIG_HVC_DRIVER=y # CONFIG_HVC_DCC is not set CONFIG_VIRTIO_CONSOLE=y @@ -1313,6 +1435,7 @@ CONFIG_HW_RANDOM_VIRTIO=y # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set # CONFIG_XILLYBUS is not set +CONFIG_RANDOM_TRUST_BOOTLOADER=y # # I2C support @@ -1365,16 +1488,8 @@ CONFIG_I2C_VERSATILE=y # CONFIG_SPI is not set # CONFIG_SPMI is not set # CONFIG_HSI is not set - -# -# PPS support -# # CONFIG_PPS is not set -# -# PPS generators support -# - # # PTP clock support # @@ -1384,10 +1499,7 @@ CONFIG_I2C_VERSATILE=y # Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. # CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y -CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y -CONFIG_GPIO_DEVRES=y CONFIG_OF_GPIO=y # CONFIG_DEBUG_GPIO is not set # CONFIG_GPIO_SYSFS is not set @@ -1399,14 +1511,15 @@ CONFIG_GPIO_GENERIC=y # CONFIG_GPIO_74XX_MMIO is not set # CONFIG_GPIO_ALTERA is not set # CONFIG_GPIO_DWAPB is not set -# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_FTGPIO010 is not set CONFIG_GPIO_GENERIC_PLATFORM=y # CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_MOCKUP is not set +# CONFIG_GPIO_MPC8XXX is not set # CONFIG_GPIO_PL061 is not set # CONFIG_GPIO_SYSCON is not set # CONFIG_GPIO_XILINX is not set # CONFIG_GPIO_ZEVIO is not set -# CONFIG_GPIO_ZX is not set # # I2C GPIO expanders @@ -1417,21 +1530,30 @@ CONFIG_GPIO_GENERIC_PLATFORM=y # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_TPIC2810 is not set # # MFD GPIO expanders # - -# -# SPI or I2C GPIO expanders -# -# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_HTC_EGPIO is not set # # USB GPIO expanders # # CONFIG_W1 is not set +# CONFIG_POWER_AVS is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMKONA is not set +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_VERSATILE is not set +CONFIG_POWER_RESET_VEXPRESS=y +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_SYSCON_REBOOT_MODE is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set @@ -1440,6 +1562,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_BATTERY_DS2781 is not set # CONFIG_BATTERY_DS2782 is not set # CONFIG_BATTERY_SBS is not set +# CONFIG_CHARGER_SBS is not set # CONFIG_BATTERY_BQ27XXX is not set # CONFIG_BATTERY_MAX17040 is not set # CONFIG_BATTERY_MAX17042 is not set @@ -1447,24 +1570,16 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_LP8727 is not set # CONFIG_CHARGER_GPIO is not set # CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_LTC3651 is not set +# CONFIG_CHARGER_DETECTOR_MAX14656 is not set # CONFIG_CHARGER_BQ2415X is not set -# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set # CONFIG_CHARGER_BQ24735 is not set # CONFIG_CHARGER_BQ25890 is not set # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_RT5033 is not set # CONFIG_CHARGER_RT9455 is not set -CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_BRCMSTB is not set -# CONFIG_POWER_RESET_GPIO is not set -# CONFIG_POWER_RESET_GPIO_RESTART is not set -# CONFIG_POWER_RESET_LTC2952 is not set -# CONFIG_POWER_RESET_RESTART is not set -# CONFIG_POWER_RESET_VERSATILE is not set -CONFIG_POWER_RESET_VEXPRESS=y -# CONFIG_POWER_RESET_SYSCON is not set -# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set -# CONFIG_POWER_AVS is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1486,6 +1601,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASPEED is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS620 is not set # CONFIG_SENSORS_DS1621 is not set @@ -1503,6 +1619,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_POWR1220 is not set # CONFIG_SENSORS_LINEAGE is not set # CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2990 is not set # CONFIG_SENSORS_LTC4151 is not set # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4222 is not set @@ -1518,8 +1635,8 @@ CONFIG_HWMON=y # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MAX31790 is not set -# CONFIG_SENSORS_HTU21 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_TC654 is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM73 is not set # CONFIG_SENSORS_LM75 is not set @@ -1546,6 +1663,7 @@ CONFIG_HWMON=y # CONFIG_PMBUS is not set # CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set # CONFIG_SENSORS_SHTC1 is not set # CONFIG_SENSORS_DME1737 is not set # CONFIG_SENSORS_EMC1403 is not set @@ -1555,6 +1673,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_STTS751 is not set # CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_ADC128D818 is not set # CONFIG_SENSORS_ADS1015 is not set @@ -1562,10 +1681,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_AMC6821 is not set # CONFIG_SENSORS_INA209 is not set # CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set # CONFIG_SENSORS_TC74 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP102 is not set # CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set # CONFIG_SENSORS_TMP401 is not set # CONFIG_SENSORS_TMP421 is not set CONFIG_SENSORS_VEXPRESS=y @@ -1588,16 +1709,13 @@ CONFIG_SSB_POSSIBLE=y # # CONFIG_SSB is not set CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# # CONFIG_BCMA is not set # # Multifunction device drivers # CONFIG_MFD_CORE=y +# CONFIG_MFD_ACT8945A is not set # CONFIG_MFD_AS3711 is not set # CONFIG_MFD_AS3722 is not set # CONFIG_PMIC_ADP5520 is not set @@ -1605,7 +1723,8 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_ATMEL_FLEXCOM is not set # CONFIG_MFD_ATMEL_HLCDC is not set # CONFIG_MFD_BCM590XX is not set -# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set # CONFIG_MFD_CROS_EC is not set # CONFIG_MFD_ASIC3 is not set # CONFIG_PMIC_DA903X is not set @@ -1617,15 +1736,14 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_DLN2 is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_MFD_HI6421_PMIC is not set -# CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set -# CONFIG_INTEL_SOC_PMIC is not set # CONFIG_MFD_KEMPLD is not set # CONFIG_MFD_88PM800 is not set # CONFIG_MFD_88PM805 is not set # CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77620 is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX77843 is not set @@ -1639,7 +1757,7 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_RETU is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_UCB1400_CORE is not set -# CONFIG_MFD_PM8921_CORE is not set +# CONFIG_MFD_PM8XXX is not set # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RTSX_USB is not set # CONFIG_MFD_RC5T583 is not set @@ -1656,16 +1774,19 @@ CONFIG_MFD_SYSCON=y # CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_TI_LMU is not set # CONFIG_MFD_PALMAS is not set # CONFIG_TPS6105X is not set # CONFIG_TPS65010 is not set # CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65086 is not set # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set # CONFIG_MFD_TPS65218 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_TPS65912 is not set # CONFIG_MFD_TPS65912_I2C is not set # CONFIG_MFD_TPS80031 is not set # CONFIG_TWL4030_CORE is not set @@ -1702,31 +1823,57 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y # CONFIG_REGULATOR_LP872X is not set # CONFIG_REGULATOR_LP8755 is not set # CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_LTC3676 is not set # CONFIG_REGULATOR_MAX1586 is not set # CONFIG_REGULATOR_MAX8649 is not set # CONFIG_REGULATOR_MAX8660 is not set # CONFIG_REGULATOR_MAX8952 is not set -# CONFIG_REGULATOR_MAX8973 is not set # CONFIG_REGULATOR_MT6311 is not set # CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PV88060 is not set +# CONFIG_REGULATOR_PV88080 is not set +# CONFIG_REGULATOR_PV88090 is not set # CONFIG_REGULATOR_TPS51632 is not set # CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS65023 is not set # CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_VCTRL is not set CONFIG_REGULATOR_VEXPRESS=y +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +CONFIG_RC_DECODERS=y +# CONFIG_LIRC is not set +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_SHARP_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_IR_XMP_DECODER=y +# CONFIG_RC_DEVICES is not set # CONFIG_MEDIA_SUPPORT is not set # # Graphics support # +# CONFIG_IMX_IPUV3_CORE is not set # CONFIG_DRM is not set +# +# ACP (Audio CoProcessor) Configuration +# +# CONFIG_DRM_LIB_RANDOM is not set + # # Frame buffer Devices # CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set CONFIG_FB_CMDLINE=y +CONFIG_FB_NOTIFY=y # CONFIG_FB_DDC is not set # CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y @@ -1736,6 +1883,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set # CONFIG_FB_SVGALIB is not set @@ -1760,7 +1908,19 @@ CONFIG_PLAT_VERSATILE_CLCD=y # CONFIG_FB_AUO_K190X is not set # CONFIG_FB_SIMPLE is not set # CONFIG_FB_SSD1307 is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_PLATFORM is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +# CONFIG_BACKLIGHT_PM8941_WLED is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set # CONFIG_VGASTATE is not set CONFIG_VIDEOMODE_HELPERS=y @@ -1776,16 +1936,11 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_VGA16 is not set CONFIG_LOGO_LINUX_CLUT224=y CONFIG_SOUND=y -CONFIG_SOUND_OSS_CORE=y -CONFIG_SOUND_OSS_CORE_PRECLAIM=y +# CONFIG_SOUND_OSS_CORE is not set CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y -# CONFIG_SND_SEQUENCER is not set -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=y -CONFIG_SND_PCM_OSS=y -CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_OSSEMUL is not set CONFIG_SND_PCM_TIMER=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y @@ -1794,11 +1949,9 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set CONFIG_SND_VMASTER=y -# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_SEQUENCER is not set # CONFIG_SND_OPL3_LIB_SEQ is not set # CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set -# CONFIG_SND_EMU10K1_SEQ is not set CONFIG_SND_AC97_CODEC=y # CONFIG_SND_DRIVERS is not set @@ -1820,7 +1973,6 @@ CONFIG_SND_USB=y # CONFIG_SND_USB_TONEPORT is not set # CONFIG_SND_USB_VARIAX is not set # CONFIG_SND_SOC is not set -# CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=y # @@ -1836,9 +1988,11 @@ CONFIG_HID_GENERIC=y # Special HID drivers # CONFIG_HID_A4TECH=y +# CONFIG_HID_ACCUTOUCH is not set # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y # CONFIG_HID_APPLEIR is not set +# CONFIG_HID_ASUS is not set # CONFIG_HID_AUREAL is not set CONFIG_HID_BELKIN=y # CONFIG_HID_BETOP_FF is not set @@ -1846,7 +2000,7 @@ CONFIG_HID_CHERRY=y CONFIG_HID_CHICONY=y # CONFIG_HID_CORSAIR is not set # CONFIG_HID_PRODIKEYS is not set -# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CMEDIA is not set CONFIG_HID_CYPRESS=y CONFIG_HID_DRAGONRISE=y # CONFIG_DRAGONRISE_FF is not set @@ -1864,9 +2018,11 @@ CONFIG_HID_EZKEY=y # CONFIG_HID_WALTOP is not set CONFIG_HID_GYRATION=y # CONFIG_HID_ICADE is not set +CONFIG_HID_ITE=y CONFIG_HID_TWINHAN=y CONFIG_HID_KENSINGTON=y # CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LED is not set # CONFIG_HID_LENOVO is not set CONFIG_HID_LOGITECH=y # CONFIG_HID_LOGITECH_HIDPP is not set @@ -1875,9 +2031,11 @@ CONFIG_HID_LOGITECH=y # CONFIG_LOGIG940_FF is not set # CONFIG_LOGIWHEELS_FF is not set # CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MAYFLASH is not set CONFIG_HID_MICROSOFT=y CONFIG_HID_MONTEREY=y # CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTI is not set CONFIG_HID_NTRIG=y # CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y @@ -1887,6 +2045,7 @@ CONFIG_HID_PETALYNX=y # CONFIG_HID_PICOLCD is not set # CONFIG_HID_PLANTRONICS is not set # CONFIG_HID_PRIMAX is not set +# CONFIG_HID_RETRODE is not set # CONFIG_HID_ROCCAT is not set # CONFIG_HID_SAITEK is not set CONFIG_HID_SAMSUNG=y @@ -1905,6 +2064,7 @@ CONFIG_HID_TOPSEED=y # CONFIG_HID_THINGM is not set CONFIG_HID_THRUSTMASTER=y # CONFIG_THRUSTMASTER_FF is not set +# CONFIG_HID_UDRAW_PS3 is not set # CONFIG_HID_WACOM is not set # CONFIG_HID_WIIMOTE is not set # CONFIG_HID_XINMO is not set @@ -1912,6 +2072,7 @@ CONFIG_HID_ZEROPLUS=y # CONFIG_ZEROPLUS_FF is not set # CONFIG_HID_ZYDACRON is not set # CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_ALPS is not set # # USB HID support @@ -1938,7 +2099,7 @@ CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_ULPI_BUS is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set CONFIG_USB_MON=y # CONFIG_USB_WUSB_CBAF is not set @@ -2016,7 +2177,6 @@ CONFIG_USB_ISP1760_HOST_ROLE=y # CONFIG_USB_SEVSEG is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_IDMOUSE is not set @@ -2030,7 +2190,9 @@ CONFIG_USB_ISP1760_HOST_ROLE=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HUB_USB251XB is not set # CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set # CONFIG_USB_LINK_LAYER_TEST is not set # CONFIG_USB_CHAOSKEY is not set @@ -2039,28 +2201,30 @@ CONFIG_USB_ISP1760_HOST_ROLE=y # # CONFIG_USB_PHY is not set # CONFIG_NOP_USB_XCEIV is not set -# CONFIG_AM335X_PHY_USB is not set # CONFIG_USB_GPIO_VBUS is not set # CONFIG_USB_ISP1301 is not set # CONFIG_USB_ULPI is not set # CONFIG_USB_GADGET is not set -# CONFIG_USB_LED_TRIG is not set -# CONFIG_UWB is not set -CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set # -# MMC/SD/SDIO Card Drivers +# USB Power Delivery and Type-C drivers # +# CONFIG_TYPEC_UCSI is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y CONFIG_MMC_BLOCK=y CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_SDIO_UART is not set # CONFIG_MMC_TEST is not set # # MMC/SD/SDIO Host Controller Drivers # +# CONFIG_MMC_DEBUG is not set CONFIG_MMC_ARMMMCI=y # CONFIG_MMC_SDHCI is not set # CONFIG_MMC_DW is not set @@ -2072,6 +2236,7 @@ CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y # CONFIG_LEDS_CLASS_FLASH is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set # # LED drivers @@ -2083,6 +2248,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_PCA9532 is not set CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set # CONFIG_LEDS_LP5562 is not set @@ -2096,12 +2262,15 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_TCA6507 is not set # CONFIG_LEDS_TLC591XX is not set # CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL319X is not set +# CONFIG_LEDS_IS31FL32XX is not set # # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set # CONFIG_LEDS_SYSCON is not set +# CONFIG_LEDS_USER is not set # # LED Triggers @@ -2109,6 +2278,8 @@ CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_DISK is not set +# CONFIG_LEDS_TRIGGER_MTD is not set CONFIG_LEDS_TRIGGER_HEARTBEAT=y # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set CONFIG_LEDS_TRIGGER_CPU=y @@ -2120,10 +2291,10 @@ CONFIG_LEDS_TRIGGER_CPU=y # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set # CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_LEDS_TRIGGER_PANIC is not set # CONFIG_ACCESSIBILITY is not set CONFIG_EDAC_ATOMIC_SCRUB=y CONFIG_EDAC_SUPPORT=y -# CONFIG_EDAC is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -2131,6 +2302,7 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_SYSTOHC=y CONFIG_RTC_SYSTOHC_DEVICE="rtc0" # CONFIG_RTC_DEBUG is not set +CONFIG_RTC_NVMEM=y # # RTC interfaces @@ -2149,32 +2321,37 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_DS1307 is not set # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set -# CONFIG_RTC_DRV_DS3232 is not set # CONFIG_RTC_DRV_HYM8563 is not set # CONFIG_RTC_DRV_MAX6900 is not set # CONFIG_RTC_DRV_RS5C372 is not set # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_ISL12057 is not set # CONFIG_RTC_DRV_X1205 is not set -# CONFIG_RTC_DRV_PCF2127 is not set # CONFIG_RTC_DRV_PCF8523 is not set -# CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_BQ32K is not set # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8010 is not set # CONFIG_RTC_DRV_RX8581 is not set # CONFIG_RTC_DRV_RX8025 is not set # CONFIG_RTC_DRV_EM3027 is not set -# CONFIG_RTC_DRV_RV3029C2 is not set # CONFIG_RTC_DRV_RV8803 is not set # # SPI RTC drivers # +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set # # Platform RTC drivers @@ -2201,13 +2378,20 @@ CONFIG_RTC_INTF_DEV=y # # CONFIG_RTC_DRV_PL030 is not set CONFIG_RTC_DRV_PL031=y +# CONFIG_RTC_DRV_FTRTC010 is not set # CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_R7301 is not set # # HID Sensor RTC drivers # # CONFIG_RTC_DRV_HID_SENSOR_TIME is not set # CONFIG_DMADEVICES is not set + +# +# DMABUF options +# +# CONFIG_SYNC_FILE is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set # CONFIG_VIRT_DRIVERS is not set @@ -2224,7 +2408,9 @@ CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y # # Microsoft Hyper-V guest support # +# CONFIG_HYPERV_TSCPAGE is not set # CONFIG_STAGING is not set +# CONFIG_GOLDFISH is not set # CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y @@ -2233,26 +2419,29 @@ CONFIG_COMMON_CLK=y # # Common Clock Framework # +CONFIG_ICST=y CONFIG_COMMON_CLK_VERSATILE=y CONFIG_CLK_SP810=y CONFIG_CLK_VEXPRESS_OSC=y +# CONFIG_CLK_HSDK is not set # CONFIG_COMMON_CLK_SI5351 is not set # CONFIG_COMMON_CLK_SI514 is not set # CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE706 is not set # CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set # CONFIG_CLK_QORIQ is not set +# CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PXA is not set -# CONFIG_COMMON_CLK_CDCE706 is not set - -# -# Hardware Spinlock drivers -# +# CONFIG_COMMON_CLK_PIC32 is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_HWSPINLOCK is not set # # Clock Source drivers # -CONFIG_CLKSRC_OF=y -CONFIG_CLKSRC_PROBE=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y CONFIG_CLKSRC_MMIO=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y @@ -2272,12 +2461,13 @@ CONFIG_IOMMU_SUPPORT=y # Generic IOMMU Pagetable Support # # CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set # CONFIG_ARM_SMMU is not set # # Remoteproc drivers # -# CONFIG_STE_MODEM_RPROC is not set +# CONFIG_REMOTEPROC is not set # # Rpmsg drivers @@ -2286,7 +2476,23 @@ CONFIG_IOMMU_SUPPORT=y # # SOC (System On Chip) specific Drivers # + +# +# Amlogic SoC drivers +# + +# +# Broadcom SoC drivers +# # CONFIG_SOC_BRCMSTB is not set + +# +# i.MX SoC drivers +# + +# +# Qualcomm SoC drivers +# # CONFIG_SUNXI_SRAM is not set # CONFIG_SOC_TI is not set # CONFIG_PM_DEVFREQ is not set @@ -2296,6 +2502,7 @@ CONFIG_IOMMU_SUPPORT=y # CONFIG_PWM is not set CONFIG_IRQCHIP=y CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_MAX_NR=1 # CONFIG_IPACK_BUS is not set # CONFIG_RESET_CONTROLLER is not set # CONFIG_FMC is not set @@ -2304,9 +2511,9 @@ CONFIG_ARM_GIC=y # PHY Subsystem # # CONFIG_GENERIC_PHY is not set +# CONFIG_BCM_KONA_USB2_PHY is not set # CONFIG_PHY_PXA_28NM_HSIC is not set # CONFIG_PHY_PXA_28NM_USB2 is not set -# CONFIG_BCM_KONA_USB2_PHY is not set # CONFIG_POWERCAP is not set # CONFIG_MCB is not set @@ -2320,21 +2527,30 @@ CONFIG_ARM_PMU=y # Android # # CONFIG_ANDROID is not set -# CONFIG_NVMEM is not set +# CONFIG_DAX is not set +CONFIG_NVMEM=y # CONFIG_STM is not set # CONFIG_INTEL_TH is not set +# CONFIG_FPGA is not set # -# FPGA Configuration Support +# FSI support # -# CONFIG_FPGA is not set +# CONFIG_FSI is not set +# CONFIG_TEE is not set # # Firmware Drivers # CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_PSCI_CHECKER is not set # CONFIG_FIRMWARE_MEMMAP is not set CONFIG_HAVE_ARM_SMCCC=y +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# Tegra firmware driver +# # # File systems @@ -2359,7 +2575,11 @@ CONFIG_FS_MBCACHE=y # CONFIG_NILFS2_FS is not set # CONFIG_F2FS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set CONFIG_FILE_LOCKING=y +CONFIG_MANDATORY_FILE_LOCKING=y +# CONFIG_FS_ENCRYPTION is not set CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY_USER=y @@ -2389,6 +2609,7 @@ CONFIG_FAT_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set # CONFIG_NTFS_FS is not set # @@ -2406,6 +2627,7 @@ CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -2429,7 +2651,8 @@ CONFIG_UBIFS_FS=y CONFIG_UBIFS_FS_LZO=y CONFIG_UBIFS_FS_ZLIB=y # CONFIG_UBIFS_ATIME_SUPPORT is not set -# CONFIG_LOGFS is not set +# CONFIG_UBIFS_FS_ENCRYPTION is not set +CONFIG_UBIFS_FS_SECURITY=y CONFIG_CRAMFS=y CONFIG_SQUASHFS=y CONFIG_SQUASHFS_FILE_CACHE=y @@ -2442,6 +2665,7 @@ CONFIG_SQUASHFS_ZLIB=y # CONFIG_SQUASHFS_LZ4 is not set CONFIG_SQUASHFS_LZO=y # CONFIG_SQUASHFS_XZ is not set +# CONFIG_SQUASHFS_ZSTD is not set # CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 @@ -2538,6 +2762,7 @@ CONFIG_NLS_ISO8859_1=y # printk and dmesg options # # CONFIG_PRINTK_TIME is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -2564,6 +2789,7 @@ CONFIG_SECTION_MISMATCH_WARN_ONLY=y # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_MAGIC_SYSRQ_SERIAL=y CONFIG_DEBUG_KERNEL=y # @@ -2571,6 +2797,9 @@ CONFIG_DEBUG_KERNEL=y # # CONFIG_PAGE_EXTENSION is not set # CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_PAGE_REF is not set +# CONFIG_DEBUG_RODATA_TEST is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set @@ -2578,6 +2807,8 @@ CONFIG_HAVE_DEBUG_KMEMLEAK=y # CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_VM is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_PER_CPU_MAPS is not set # CONFIG_DEBUG_SHIRQ is not set @@ -2585,11 +2816,12 @@ CONFIG_DEBUG_MEMORY_INIT=y # # Debug Lockups and Hangs # -# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_SOFTLOCKUP_DETECTOR is not set CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_WQ_WATCHDOG is not set # CONFIG_PANIC_ON_OOPS is not set CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 @@ -2598,7 +2830,6 @@ CONFIG_PANIC_TIMEOUT=0 # CONFIG_SCHEDSTATS is not set # CONFIG_SCHED_STACK_END_CHECK is not set # CONFIG_DEBUG_TIMEKEEPING is not set -# CONFIG_TIMER_STATS is not set # # Lock Debugging (spinlocks, mutexes, etc...) @@ -2613,7 +2844,9 @@ CONFIG_PANIC_TIMEOUT=0 # CONFIG_DEBUG_ATOMIC_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_LOCK_TORTURE_TEST is not set -# CONFIG_STACKTRACE is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +CONFIG_STACKTRACE=y +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_LIST is not set @@ -2626,29 +2859,38 @@ CONFIG_DEBUG_BUGVERBOSE=y # RCU Debugging # # CONFIG_PROVE_RCU is not set -# CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_PERF_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=21 -# CONFIG_RCU_TRACE is not set +CONFIG_RCU_TRACE=y # CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_TRACE_CLOCK=y CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_SCHED_TRACER is not set +# CONFIG_HWLAT_TRACER is not set # CONFIG_ENABLE_DEFAULT_TRACERS is not set # CONFIG_FTRACE_SYSCALLS is not set # CONFIG_TRACER_SNAPSHOT is not set @@ -2657,18 +2899,21 @@ CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ALL_BRANCHES is not set # CONFIG_STACK_TRACER is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_UPROBE_EVENT is not set -# CONFIG_PROBE_EVENTS is not set +CONFIG_UPROBE_EVENTS=y +CONFIG_PROBE_EVENTS=y # CONFIG_TRACEPOINT_BENCHMARK is not set # CONFIG_RING_BUFFER_BENCHMARK is not set # CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set CONFIG_TRACING_EVENTS_GPIO=y +# CONFIG_DMA_API_DEBUG is not set # # Runtime Testing # # CONFIG_LKDTM is not set # CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_SORT is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_RBTREE_TEST is not set # CONFIG_INTERVAL_TREE_TEST is not set @@ -2678,21 +2923,29 @@ CONFIG_TRACING_EVENTS_GPIO=y # CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_UUID is not set # CONFIG_TEST_RHASHTABLE is not set # CONFIG_TEST_HASH is not set -# CONFIG_DMA_API_DEBUG is not set # CONFIG_TEST_LKM is not set # CONFIG_TEST_USER_COPY is not set # CONFIG_TEST_BPF is not set # CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_SYSCTL is not set # CONFIG_TEST_UDELAY is not set -# CONFIG_MEMTEST is not set # CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_MEMTEST is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set -# CONFIG_ARM_PTDUMP is not set +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set +# CONFIG_UBSAN is not set +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y # CONFIG_STRICT_DEVMEM is not set +# CONFIG_ARM_PTDUMP is not set +# CONFIG_UNWINDER_FRAME_POINTER is not set +CONFIG_UNWINDER_ARM=y CONFIG_ARM_UNWIND=y CONFIG_DEBUG_USER=y # CONFIG_DEBUG_LL is not set @@ -2700,7 +2953,6 @@ CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" # CONFIG_DEBUG_UART_8250 is not set CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" # CONFIG_PID_IN_CONTEXTIDR is not set -# CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_CORESIGHT is not set # @@ -2710,6 +2962,9 @@ CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_STATIC_USERMODEHELPER is not set CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" CONFIG_CRYPTO=y @@ -2727,9 +2982,12 @@ CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_RNG=m CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_RNG_DEFAULT=m -CONFIG_CRYPTO_PCOMP2=y CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_ACOMP2=y # CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_ECDH is not set CONFIG_CRYPTO_MANAGER=m CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_USER is not set @@ -2791,6 +3049,7 @@ CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_SHA1 is not set CONFIG_CRYPTO_SHA256=m # CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA3 is not set # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set @@ -2798,6 +3057,7 @@ CONFIG_CRYPTO_SHA256=m # Ciphers # CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_TI is not set # CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_BLOWFISH is not set @@ -2818,7 +3078,6 @@ CONFIG_CRYPTO_AES=y # Compression # CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_ZLIB is not set CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set # CONFIG_CRYPTO_LZ4 is not set @@ -2831,7 +3090,6 @@ CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_DRBG_MENU=m CONFIG_CRYPTO_DRBG_HMAC=y # CONFIG_CRYPTO_DRBG_HASH is not set -# CONFIG_CRYPTO_DRBG_CTR is not set CONFIG_CRYPTO_DRBG=m CONFIG_CRYPTO_JITTERENTROPY=m # CONFIG_CRYPTO_USER_API_HASH is not set @@ -2844,7 +3102,7 @@ CONFIG_CRYPTO_JITTERENTROPY=m # Certificates for signature checking # # CONFIG_ARM_CRYPTO is not set -# CONFIG_BINARY_PRINTF is not set +CONFIG_BINARY_PRINTF=y # # Library routines @@ -2868,6 +3126,7 @@ CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC32_SLICEBY4 is not set # CONFIG_CRC32_SARWATE is not set # CONFIG_CRC32_BIT is not set +# CONFIG_CRC4 is not set # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set # CONFIG_CRC8 is not set @@ -2896,19 +3155,25 @@ CONFIG_DECOMPRESS_LZ4=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_HAS_IOMEM=y CONFIG_HAS_DMA=y +# CONFIG_SGL_ALLOC is not set +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_VIRT_OPS is not set CONFIG_CPU_RMAP=y CONFIG_DQL=y CONFIG_GLOB=y # CONFIG_GLOB_SELFTEST is not set CONFIG_NLATTR=y -CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +# CONFIG_IRQ_POLL is not set CONFIG_LIBFDT=y CONFIG_FONT_SUPPORT=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y # CONFIG_SG_SPLIT is not set +CONFIG_SG_POOL=y CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y +# CONFIG_STRING_SELFTEST is not set # CONFIG_VIRTUALIZATION is not set diff --git a/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile index 17203994c..cbac2310d 100644 --- a/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile @@ -16,6 +16,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config +COPY scripts/cmake.sh /scripts/ +RUN /scripts/cmake.sh COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile index 437760870..07260be35 100644 --- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile @@ -19,6 +19,7 @@ RUN apt-get update -y && apt-get install -y --no-install-recommends \ g++ \ libc6-dev \ libc6-dev-riscv64-cross \ + libssl-dev \ make \ ninja-build \ patch \ @@ -94,6 +95,9 @@ RUN mkdir build && cd build && \ WORKDIR /tmp RUN rm -rf /tmp/riscv-pk +COPY scripts/cmake.sh /scripts/ +RUN /scripts/cmake.sh + COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile index ea4a2a242..f5274104d 100644 --- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile @@ -12,7 +12,6 @@ RUN yum upgrade -y && \ automake \ bzip2 \ file \ - cmake3 \ gcc \ gcc-c++ \ git \ @@ -35,7 +34,7 @@ RUN yum upgrade -y && \ zlib-devel.x86_64 \ && yum clean all -RUN mkdir -p /rustroot/bin && ln -s /usr/bin/cmake3 /rustroot/bin/cmake +RUN mkdir -p /rustroot/bin ENV PATH=/rustroot/bin:$PATH ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib @@ -48,6 +47,9 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/ RUN ./build-gcc.sh && yum remove -y gcc gcc-c++ +COPY scripts/cmake.sh /tmp/ +RUN ./cmake.sh + # Now build LLVM+Clang, afterwards configuring further compilations to use the # clang/clang++ compilers. COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile index 6b7b32a8b..5dc282403 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile @@ -1,15 +1,12 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh COPY scripts/rustbuild-setup.sh /scripts/ RUN sh /scripts/rustbuild-setup.sh -USER rustbuild WORKDIR /tmp -USER root - RUN apt-get install -y --no-install-recommends rpm2cpio cpio COPY host-x86_64/dist-powerpc64le-linux/shared.sh host-x86_64/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh /tmp/ RUN ./build-powerpc64le-toolchain.sh 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 index 10075907b..470cef1a8 100644 --- 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 @@ -10,7 +10,7 @@ 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_BINUTILS_V_2_36=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-various-1/Dockerfile b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile index 4576e6d4f..8f4ad0f4e 100644 --- a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile @@ -1,6 +1,7 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ automake \ bison \ @@ -73,8 +74,8 @@ RUN env \ CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv6 -marm -mfpu=vfp" \ bash musl.sh armhf && \ env \ - CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a" \ - CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv7-a" \ + CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a+fp" \ + CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv7-a+fp" \ bash musl.sh armv7hf && \ env \ CC=mips-openwrt-linux-gcc \ @@ -147,7 +148,7 @@ ENV TARGETS=$TARGETS,armv7a-none-eabi ENV CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft" \ CFLAGS_arm_unknown_linux_musleabi="-march=armv6 -marm" \ CFLAGS_arm_unknown_linux_musleabihf="-march=armv6 -marm -mfpu=vfp" \ - CFLAGS_armv7_unknown_linux_musleabihf="-march=armv7-a" \ + CFLAGS_armv7_unknown_linux_musleabihf="-march=armv7-a+fp" \ CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ CC_mips64el_unknown_linux_muslabi64=mips64el-linux-gnuabi64-gcc \ diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 0f5df95a0..670e37b9d 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh @@ -9,7 +9,7 @@ RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \ build-essential \ # gcc-multilib can not be installed together with gcc-arm-linux-gnueabi - g++-8-multilib \ + g++-9-multilib \ libedit-dev \ libgmp-dev \ libisl-dev \ @@ -24,7 +24,7 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no # Needed for apt-key to work: dirmngr \ gpg-agent \ - g++-8-arm-linux-gnueabi + g++-9-arm-linux-gnueabi RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main' @@ -51,8 +51,8 @@ ENV \ AR_x86_64_sun_solaris=x86_64-sun-solaris2.10-ar \ CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \ CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++ \ - CC_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-gcc-8 \ - CXX_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-g++-8 \ + CC_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-gcc-9 \ + CXX_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-g++-9 \ AR_x86_64_fortanix_unknown_sgx=ar \ CC_x86_64_fortanix_unknown_sgx=clang-11 \ CFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ @@ -67,14 +67,14 @@ ENV \ CXX_i686_unknown_uefi=clang++-11 \ CC_x86_64_unknown_uefi=clang-11 \ CXX_x86_64_unknown_uefi=clang++-11 \ - CC=gcc-8 \ - CXX=g++-8 + CC=gcc-9 \ + CXX=g++-9 WORKDIR /build COPY scripts/musl.sh /build RUN env \ - CC=arm-linux-gnueabi-gcc-8 CFLAGS="-march=armv7-a" \ - CXX=arm-linux-gnueabi-g++-8 CXXFLAGS="-march=armv7-a" \ + CC=arm-linux-gnueabi-gcc-9 CFLAGS="-march=armv7-a" \ + CXX=arm-linux-gnueabi-g++-9 CXXFLAGS="-march=armv7-a" \ bash musl.sh armv7 && \ rm -rf /build/* @@ -93,6 +93,9 @@ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/ RUN /tmp/build-wasi-toolchain.sh +COPY host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh /tmp/ +RUN /tmp/build-wasi-threads-toolchain.sh + COPY scripts/freebsd-toolchain.sh /tmp/ RUN /tmp/freebsd-toolchain.sh i686 @@ -114,6 +117,7 @@ ENV TARGETS=x86_64-unknown-fuchsia ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-wasi +ENV TARGETS=$TARGETS,wasm32-wasi-preview1-threads ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,x86_64-pc-solaris ENV TARGETS=$TARGETS,x86_64-sun-solaris @@ -129,13 +133,14 @@ ENV TARGETS=$TARGETS,i686-unknown-uefi ENV TARGETS=$TARGETS,x86_64-unknown-uefi # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 -# we need asm in the search path for gcc-8 (for gnux32) but not in the search path of the +# we need asm in the search path for gcc-9 (for gnux32) but not in the search path of the # cross compilers. -# Luckily one of the folders is /usr/local/include so symlink /usr/include/asm-generic there -RUN ln -s /usr/include/asm-generic /usr/local/include/asm +# Luckily one of the folders is /usr/local/include so symlink /usr/include/x86_64-linux-gnu/asm there +RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \ --set target.wasm32-wasi.wasi-root=/wasm32-wasi \ + --set target.wasm32-wasi-preview1-threads.wasi-root=/wasm32-wasi-preview1-threads \ --musl-root-armv7=/musl-armv7 ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh new file mode 100755 index 000000000..689fe5286 --- /dev/null +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +set -ex + +# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz +curl https://ci-mirrors.rust-lang.org/rustc/2023-05-17-clang%2Bllvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz | \ + tar xJf - +bin="$PWD/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04/bin" + +git clone https://github.com/WebAssembly/wasi-libc + +cd wasi-libc +git reset --hard ec4566beae84e54952637f0bf61bee4b4cacc087 +make -j$(nproc) \ + CC="$bin/clang" \ + NM="$bin/llvm-nm" \ + AR="$bin/llvm-ar" \ + THREAD_MODEL=posix \ + INSTALL_DIR=/wasm32-wasi-preview1-threads \ + install + +cd .. +rm -rf wasi-libc +rm -rf clang+llvm* diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh index b867db6a1..4b0d36068 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh @@ -2,15 +2,15 @@ set -ex -# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.6/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz -curl https://ci-mirrors.rust-lang.org/rustc/2022-12-06-clang%2Bllvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \ +# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz +curl https://ci-mirrors.rust-lang.org/rustc/2023-05-17-clang%2Bllvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz | \ tar xJf - -bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin" +bin="$PWD/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04/bin" git clone https://github.com/WebAssembly/wasi-libc cd wasi-libc -git reset --hard 7018e24d8fe248596819d2e884761676f3542a04 +git reset --hard ec4566beae84e54952637f0bf61bee4b4cacc087 make -j$(nproc) \ CC="$bin/clang" \ NM="$bin/llvm-nm" \ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index c2fd2e3a9..319989df3 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -12,7 +12,6 @@ RUN yum upgrade -y && \ automake \ bzip2 \ file \ - cmake3 \ gcc \ gcc-c++ \ git \ @@ -35,7 +34,7 @@ RUN yum upgrade -y && \ zlib-devel.x86_64 \ && yum clean all -RUN mkdir -p /rustroot/bin && ln -s /usr/bin/cmake3 /rustroot/bin/cmake +RUN mkdir -p /rustroot/bin ENV PATH=/rustroot/bin:$PATH ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib @@ -48,13 +47,18 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/ RUN ./build-gcc.sh && yum remove -y gcc gcc-c++ +# LLVM 17 needs cmake 3.20 or higher. +COPY scripts/cmake.sh /tmp/ +RUN ./cmake.sh + # Now build LLVM+Clang, afterwards configuring further compilations to use the # clang/clang++ compilers. COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ -# rustc-perf version from 2023-03-15 +# rustc-perf version from 2023-05-30 +# Should also be changed in the opt-dist tool for other environments. ENV PERF_COMMIT 8b2ac3042e1ff2c0074455a0a3618adef97156b1 RUN curl -LS -o perf.zip https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \ unzip perf.zip && \ @@ -81,7 +85,9 @@ ENV RUST_CONFIGURE_ARGS \ --set rust.jemalloc \ --set rust.use-lld=true \ --set rust.lto=thin -ENV SCRIPT python3 ../src/ci/stage-build.py python3 ../x.py dist \ + +ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \ + ./build/$HOSTS/stage0-tools-bin/opt-dist python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ build-manifest bootstrap 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 6f04dcad9..c9a6a2dd0 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 @@ -1,6 +1,7 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ make \ ninja-build \ @@ -11,6 +12,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins python3 \ git \ cmake \ + bzip2 \ xz-utils \ sudo \ gdb \ @@ -21,10 +23,6 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins WORKDIR /build/ -# Build cmake before musl toolchain, as we replace the compiler during that step. -COPY scripts/cmake.sh /scripts/ -RUN /scripts/cmake.sh - 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/dist-x86_64-netbsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/Dockerfile index d03c36454..effdc99d9 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/Dockerfile @@ -1,11 +1,14 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 +ARG DEBIAN_FRONTEND=noninteractive COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -RUN DEBIAN_FRONTEND=noninteractive apt-get install -y zlib1g-dev +RUN apt-get install -y zlib1g-dev COPY host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh /tmp/ -RUN /tmp/build-netbsd-toolchain.sh +# GCC 10 changed the default to -fno-common, which causes errors with the NetBSD-9.0 sources like: +# /usr/bin/ld: buf.o:(.bss+0x0): multiple definition of `debug_file'; arch.o:(.bss+0x0): first defined here +RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile index b5abf6564..61811c419 100644 --- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile @@ -24,10 +24,10 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu -# Exclude some tests that are unlikely to be platform specific, to speed up +# Skip some tests that are unlikely to be platform specific, to speed up # this slow job. ENV SCRIPT python3 ../x.py --stage 2 test \ - --exclude src/bootstrap \ - --exclude tests/rustdoc-js \ - --exclude src/tools/error_index_generator \ - --exclude src/tools/linkchecker + --skip src/bootstrap \ + --skip tests/rustdoc-js \ + --skip src/tools/error_index_generator \ + --skip src/tools/linkchecker diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile index 34b93be41..0a49eab4d 100644 --- a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile @@ -26,11 +26,13 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/ -RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt +RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt \ + && pip3 install virtualenv COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ # NOTE: intentionally uses python2 for x.py so we can test it still works. # validate-toolstate only runs in our CI, so it's ok for it to only support python3. -ENV SCRIPT python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest +ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \ + --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index 1dc7b7987..4fe66014c 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -1,6 +1,7 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ clang-11 \ g++ \ make \ @@ -15,23 +16,20 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins gdb \ libssl-dev \ pkg-config \ + bzip2 \ xz-utils \ wget \ patch \ ovmf \ + ovmf-ia32 \ qemu-efi-aarch64 \ qemu-system-arm \ qemu-system-x86 \ && rm -rf /var/lib/apt/lists/* -RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \ +RUN curl -sL https://nodejs.org/dist/v18.12.0/node-v18.12.0-linux-x64.tar.xz | \ tar -xJ -# Install 32-bit OVMF files for the i686-unknown-uefi test. This package -# is not available in ubuntu 20.04, so download a 22.04 package. -RUN curl -sL --output ovmf-ia32.deb http://mirrors.kernel.org/ubuntu/pool/universe/e/edk2/ovmf-ia32_2022.02-3_all.deb -RUN dpkg -i ovmf-ia32.deb && rm ovmf-ia32.deb - WORKDIR /build/ COPY scripts/musl-toolchain.sh /build/ RUN bash musl-toolchain.sh x86_64 && rm -rf build @@ -42,7 +40,7 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ - --set build.nodejs=/node-v15.14.0-linux-x64/bin/node \ + --set build.nodejs=/node-v18.12.0-linux-x64/bin/node \ --set rust.lld # Some run-make tests have assertions about code size, and enabling debug @@ -58,6 +56,8 @@ ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_T tests/ui \ tests/mir-opt \ tests/codegen-units \ + tests/codegen \ + tests/assembly \ library/core ENV NVPTX_TARGETS=nvptx64-nvidia-cuda diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py index ffae7b0d4..3577643ca 100755 --- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py +++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py @@ -109,12 +109,7 @@ def build_and_run(tmp_dir, target): '-drive', f'format=raw,file=fat:rw:{esp}', capture=True, - # Ubuntu 20.04 (which is what the Dockerfile currently - # uses) provides QEMU 4.2.1, which segfaults on - # shutdown under some circumstances. That has been - # fixed in newer versions of QEMU, but for now just - # don't check the exit status. - check=False, + check=True, # Set a timeout to kill the VM in case something goes wrong. timeout=60).stdout diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile index ef1fde1c3..02b4664eb 100644 --- a/src/ci/docker/host-x86_64/wasm32/Dockerfile +++ b/src/ci/docker/host-x86_64/wasm32/Dockerfile @@ -1,6 +1,7 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ make \ ninja-build \ @@ -13,6 +14,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins sudo \ gdb \ xz-utils \ + libssl-dev \ bzip2 \ && rm -rf /var/lib/apt/lists/* @@ -53,7 +55,8 @@ COPY static/gitconfig /etc/gitconfig # Emscripten installation is user-specific ENV NO_CHANGE_USER=1 +RUN chown 10719 -R /emsdk-portable/ # Exclude library/alloc due to OOM in benches. ENV SCRIPT python3 ../x.py test --stage 2 --host='' --target $TARGETS \ - --exclude library/alloc + --skip library/alloc diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile index 735d4d4df..e4534d0f8 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ 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 deleted file mode 100644 index 93d18bcf1..000000000 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -FROM ubuntu:22.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.11 \ - git \ - cmake \ - sudo \ - gdb \ - llvm-14-tools \ - llvm-14-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 - -# 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 \ - --llvm-root=/usr/lib/llvm-14 \ - --enable-llvm-link-shared \ - --set rust.thin-lto-import-instr-limit=10 - -COPY host-x86_64/x86_64-gnu-llvm-14/script.sh /tmp/ - -ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/script.sh b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/script.sh deleted file mode 100755 index 0120fd982..000000000 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/script.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -set -ex - -# Only run the stage 1 tests on merges, not on PR CI jobs. -if [[ -z "${PR_CI_JOB}" ]]; then -../x.py --stage 1 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.py --stage 1 test tests/mir-opt \ - --host='' --target=i686-unknown-linux-gnu -fi - -# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux. -../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-llvm-15/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile index 06a8f7eeb..444e0275d 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 @@ -1,4 +1,4 @@ -FROM ubuntu:23.04 +FROM ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive @@ -10,7 +10,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ file \ curl \ ca-certificates \ - python3 \ + python3.11 \ git \ cmake \ sudo \ @@ -49,20 +49,6 @@ ENV RUST_CONFIGURE_ARGS \ --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 +COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/ + +ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh new file mode 100755 index 000000000..390304b6a --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -ex + +# Only run the stage 1 tests on merges, not on PR CI jobs. +if [[ -z "${PR_CI_JOB}" ]]; then +../x.py --stage 1 test --skip 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.py --stage 1 test tests/mir-opt \ + --host='' --target=i686-unknown-linux-gnu +fi + +# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux. +../x.py --stage 2 test --skip 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-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile index 7c75d0df5..1e2b802e6 100644 --- 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 @@ -45,20 +45,6 @@ ENV RUST_CONFIGURE_ARGS \ --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 +COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/ + +ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile index 9fdc78406..d8113e067 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile @@ -1,7 +1,8 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 # Avoid interactive prompts while installing `tzdata` dependency with `DEBIAN_FRONTEND`. -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ make \ ninja-build \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile index fbec368c9..9025e9bb0 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 4b218d577..8bd8beb87 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -63,6 +63,11 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then uname -m >> $hash_key docker --version >> $hash_key + + # Include cache version. Currently it is needed to bust Docker + # cache key after opting in into the old Docker build backend. + echo "1" >> $hash_key + cksum=$(sha512sum $hash_key | \ awk '{print $1}') @@ -79,7 +84,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then loaded_images=$(/usr/bin/timeout -k 720 600 docker load -i /tmp/rustci_docker_cache \ | sed 's/.* sha/sha/') set -e - echo "Downloaded containers:\n$loaded_images" + printf "Downloaded containers:\n$loaded_images\n" fi dockerfile="$docker_dir/$image/Dockerfile" @@ -89,12 +94,20 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then else context="$script_dir" fi + echo "::group::Building docker image for $image" + + # As of August 2023, Github Actions have updated Docker to 23.X, + # which uses the BuildKit by default. It currently throws aways all + # intermediate layers, which breaks our usage of S3 layer caching. + # Therefore we opt-in to the old build backend for now. + export DOCKER_BUILDKIT=0 retry docker \ build \ --rm \ -t rust-ci \ -f "$dockerfile" \ "$context" + echo "::endgroup::" if [ "$CI" != "" ]; then s3url="s3://$SCCACHE_BUCKET/docker/$cksum" @@ -264,6 +277,7 @@ docker \ --env BASE_COMMIT="$BASE_COMMIT" \ --env DIST_TRY_BUILD \ --env PR_CI_JOB \ + --env OBJDIR_ON_HOST="$objdir" \ --init \ --rm \ rust-ci \ diff --git a/src/ci/docker/scripts/cmake.sh b/src/ci/docker/scripts/cmake.sh index f124dbdaa..822666c89 100755 --- a/src/ci/docker/scripts/cmake.sh +++ b/src/ci/docker/scripts/cmake.sh @@ -18,9 +18,9 @@ exit 1 set -x } -# LLVM 12 requires CMake 3.13.4 or higher. -# This script is not necessary for images using Ubuntu 20.04 or newer. -CMAKE=3.13.4 +# LLVM 17 requires CMake 3.20 or higher. +# This script is not necessary for images using Ubuntu 22.04 or newer. +CMAKE=3.20.3 curl -L https://github.com/Kitware/CMake/releases/download/v$CMAKE/cmake-$CMAKE.tar.gz | tar xzf - mkdir cmake-build diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index af01f9ccb..f78d446c8 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -15,12 +15,10 @@ import hashlib import json import os import platform -import re import shutil -import signal import subprocess import sys -from typing import ClassVar, List, Optional +from typing import ClassVar, List @dataclass @@ -523,7 +521,7 @@ class TestEnvironment: env_vars += '\n "RUST_BACKTRACE=0",' # Use /tmp as the test temporary directory - env_vars += f'\n "RUST_TEST_TMPDIR=/tmp",' + env_vars += '\n "RUST_TEST_TMPDIR=/tmp",' cml.write( self.CML_TEMPLATE.format(env_vars=env_vars, exe_name=exe_name) diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 8027e6996..2cc0bfd9d 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -14,7 +14,6 @@ # step CI will fail. --- - ############################### # YAML Anchors Definition # ############################### @@ -30,7 +29,6 @@ # The expand-yaml-anchors tool will automatically remove this block from the # output YAML file. x--expand-yaml-anchors--remove: - - &shared-ci-variables CI_JOB_NAME: ${{ matrix.name }} CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse @@ -90,7 +88,7 @@ x--expand-yaml-anchors--remove: <<: *base-job - &job-macos-xl - os: macos-latest # We use the standard runner for now + os: macos-13 # We use the standard runner for now <<: *base-job - &job-windows-8c @@ -318,12 +316,12 @@ jobs: matrix: include: - name: mingw-check - <<: *job-linux-16c + <<: *job-linux-4c - name: mingw-check-tidy - <<: *job-linux-16c + <<: *job-linux-4c - - name: x86_64-gnu-llvm-14 + - name: x86_64-gnu-llvm-15 <<: *job-linux-16c - name: x86_64-gnu-tools @@ -469,11 +467,6 @@ jobs: RUST_BACKTRACE: 1 <<: *job-linux-8c - - name: x86_64-gnu-llvm-14 - env: - RUST_BACKTRACE: 1 - <<: *job-linux-8c - - name: x86_64-gnu-nopt <<: *job-linux-4c @@ -525,7 +518,7 @@ jobs: - name: x86_64-apple-1 env: &env-x86_64-apple-tests - SCRIPT: ./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps + SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.8 @@ -643,7 +636,7 @@ jobs: --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: PGO_HOST=x86_64-pc-windows-msvc python src/ci/stage-build.py python x.py dist bootstrap --include-default-paths + SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c @@ -668,9 +661,6 @@ jobs: --enable-profiler SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 - # Hack around this SDK version, because it doesn't work with clang. - # See https://github.com/rust-lang/rust/issues/88796 - WINDOWS_SDK_20348_HACK: 1 <<: *job-windows-8c - name: dist-i686-mingw diff --git a/src/ci/run.sh b/src/ci/run.sh index 48fb40d6a..b8cb758bf 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -8,7 +8,7 @@ fi if [ "$NO_CHANGE_USER" = "" ]; then if [ "$LOCAL_USER_ID" != "" ]; then - useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user + id -u user &>/dev/null || useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user export HOME=/home/user unset LOCAL_USER_ID @@ -154,13 +154,25 @@ fi # check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure # Pipelines it happened that the certificates were marked as expired. datecheck() { - echo "== clock drift check ==" + # If an error has happened, we do not want to start a new group, because that will collapse + # a previous group that might have contained the error log. + exit_code=$? + + if [ $exit_code -eq 0 ] + then + echo "::group::Clock drift check" + fi + echo -n " local time: " date echo -n " network time: " curl -fs --head http://ci-caches.rust-lang.org | grep ^Date: \ | sed 's/Date: //g' || true - echo "== end clock drift check ==" + + if [ $exit_code -eq 0 ] + then + echo "::endgroup::" + fi } datecheck trap datecheck EXIT @@ -171,12 +183,16 @@ trap datecheck EXIT # sccache server at the start of the build, but no need to worry if this fails. SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true +# Our build may overwrite config.toml, so we remove it here +rm -f config.toml + $SRC/configure $RUST_CONFIGURE_ARGS retry make prepare # Display the CPU and memory information. This helps us know why the CI timing # is fluctuating. +echo "::group::Display CPU and Memory information" if isMacOS; then system_profiler SPHardwareDataType || true sysctl hw || true @@ -186,6 +202,7 @@ else cat /proc/meminfo || true ncpus=$(grep processor /proc/cpuinfo | wc -l) fi +echo "::endgroup::" if [ ! -z "$SCRIPT" ]; then echo "Executing ${SCRIPT}" @@ -218,4 +235,6 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then CARGO_INCREMENTAL=0 ../x check fi +echo "::group::sccache stats" sccache --show-stats || true +echo "::endgroup::" diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index 02b72625d..cbb4d5765 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -39,11 +39,6 @@ if isMacOS; then ciCommandSetEnv AR "ar" elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then - if [[ ${WINDOWS_SDK_20348_HACK-0} -eq 1 ]]; then - rm -rf '/c/Program Files (x86)/Windows Kits/10/include/10.0.20348.0' - mv '/c/Program Files (x86)/Windows Kits/10/include/'10.0.{19041,20348}.0 - fi - # If we're compiling for MSVC then we, like most other distribution builders, # switch to clang as the compiler. This'll allow us eventually to enable LTO # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think diff --git a/src/ci/scripts/setup-environment.sh b/src/ci/scripts/setup-environment.sh index 0bc35f932..d3c55a4d6 100755 --- a/src/ci/scripts/setup-environment.sh +++ b/src/ci/scripts/setup-environment.sh @@ -10,7 +10,7 @@ source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" # Load extra environment variables vars="${EXTRA_VARIABLES-}" -echo "${vars}" | jq '' >/dev/null # Validate JSON and exit on errors +echo "${vars}" | jq '.' >/dev/null # Validate JSON and exit on errors for key in $(echo "${vars}" | jq "keys[]" -r); do # On Windows, for whatever reason, $key contains the BOM character in it, # and that messes up `jq ".${key}"`. This line strips the BOM from the key. diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py deleted file mode 100755 index 3bb3b1418..000000000 --- a/src/ci/stage-build.py +++ /dev/null @@ -1,1037 +0,0 @@ -#!/usr/bin/env python3 -# ignore-tidy-linelength - -# Compatible with Python 3.6+ - -import contextlib -import getpass -import glob -import json -import logging -import os -import pprint -import shutil -import subprocess -import sys -import time -import traceback -import urllib.request -from io import StringIO -from pathlib import Path -from typing import Callable, ContextManager, Dict, Iterable, Iterator, List, Optional, \ - Tuple, Union - -PGO_HOST = os.environ["PGO_HOST"] -CHANNEL = os.environ.get("RUST_RELEASE_CHANNEL", "") - -LOGGER = logging.getLogger("stage-build") - -LLVM_PGO_CRATES = [ - "syn-1.0.89", - "cargo-0.60.0", - "serde-1.0.136", - "ripgrep-13.0.0", - "regex-1.5.5", - "clap-3.1.6", - "hyper-0.14.18" -] - -RUSTC_PGO_CRATES = [ - "externs", - "ctfe-stress-5", - "cargo-0.60.0", - "token-stream-stress", - "match-stress", - "tuple-stress", - "diesel-1.4.8", - "bitmaps-3.1.0" -] - -LLVM_BOLT_CRATES = LLVM_PGO_CRATES - - -def is_try_build() -> bool: - return os.environ.get("DIST_TRY_BUILD", "0") != "0" - - -class Pipeline: - # Paths - def checkout_path(self) -> Path: - """ - The root checkout, where the source is located. - """ - raise NotImplementedError - - def downloaded_llvm_dir(self) -> Path: - """ - Directory where the host LLVM is located. - """ - raise NotImplementedError - - def build_root(self) -> Path: - """ - The main directory where the build occurs. - """ - raise NotImplementedError - - def build_artifacts(self) -> Path: - return self.build_root() / "build" / PGO_HOST - - def rustc_stage_0(self) -> Path: - return self.build_artifacts() / "stage0" / "bin" / "rustc" - - def cargo_stage_0(self) -> Path: - return self.build_artifacts() / "stage0" / "bin" / "cargo" - - def rustc_stage_2(self) -> Path: - return self.build_artifacts() / "stage2" / "bin" / "rustc" - - def opt_artifacts(self) -> Path: - raise NotImplementedError - - def llvm_profile_dir_root(self) -> Path: - return self.opt_artifacts() / "llvm-pgo" - - def llvm_profile_merged_file(self) -> Path: - return self.opt_artifacts() / "llvm-pgo.profdata" - - def rustc_perf_dir(self) -> Path: - return self.opt_artifacts() / "rustc-perf" - - def build_rustc_perf(self): - raise NotImplementedError() - - def rustc_profile_dir_root(self) -> Path: - return self.opt_artifacts() / "rustc-pgo" - - def rustc_profile_merged_file(self) -> Path: - return self.opt_artifacts() / "rustc-pgo.profdata" - - def rustc_profile_template_path(self) -> Path: - """ - The profile data is written into a single filepath that is being repeatedly merged when each - rustc invocation ends. Empirically, this can result in some profiling data being lost. That's - why we override the profile path to include the PID. This will produce many more profiling - files, but the resulting profile will produce a slightly faster rustc binary. - """ - return self.rustc_profile_dir_root() / "default_%m_%p.profraw" - - def supports_bolt(self) -> bool: - raise NotImplementedError - - def llvm_bolt_profile_merged_file(self) -> Path: - return self.opt_artifacts() / "bolt.profdata" - - def metrics_path(self) -> Path: - return self.build_root() / "build" / "metrics.json" - - def executable_extension(self) -> str: - raise NotImplementedError - - def skipped_tests(self) -> Iterable[str]: - return () - - -class LinuxPipeline(Pipeline): - def checkout_path(self) -> Path: - return Path("/checkout") - - def downloaded_llvm_dir(self) -> Path: - return Path("/rustroot") - - def build_root(self) -> Path: - return self.checkout_path() / "obj" - - def opt_artifacts(self) -> Path: - return Path("/tmp/tmp-multistage/opt-artifacts") - - def build_rustc_perf(self): - # /tmp/rustc-perf comes from the Dockerfile - shutil.copytree("/tmp/rustc-perf", self.rustc_perf_dir()) - cmd(["chown", "-R", f"{getpass.getuser()}:", self.rustc_perf_dir()]) - - with change_cwd(self.rustc_perf_dir()): - cmd([self.cargo_stage_0(), "build", "-p", "collector"], env=dict( - RUSTC=str(self.rustc_stage_0()), - RUSTC_BOOTSTRAP="1" - )) - - def supports_bolt(self) -> bool: - return True - - def executable_extension(self) -> str: - return "" - - def skipped_tests(self) -> Iterable[str]: - # This test fails because of linker errors, as of June 2023. - yield "tests/ui/process/nofile-limit.rs" - - -class WindowsPipeline(Pipeline): - def __init__(self): - self.checkout_dir = Path(os.getcwd()) - - def checkout_path(self) -> Path: - return self.checkout_dir - - def downloaded_llvm_dir(self) -> Path: - return self.checkout_path() / "citools" / "clang-rust" - - def build_root(self) -> Path: - return self.checkout_path() - - def opt_artifacts(self) -> Path: - return self.checkout_path() / "opt-artifacts" - - def rustc_stage_0(self) -> Path: - return super().rustc_stage_0().with_suffix(".exe") - - def cargo_stage_0(self) -> Path: - return super().cargo_stage_0().with_suffix(".exe") - - def rustc_stage_2(self) -> Path: - return super().rustc_stage_2().with_suffix(".exe") - - def build_rustc_perf(self): - # rustc-perf version from 2023-03-15 - perf_commit = "8b2ac3042e1ff2c0074455a0a3618adef97156b1" - rustc_perf_zip_path = self.opt_artifacts() / "perf.zip" - - def download_rustc_perf(): - download_file( - f"https://github.com/rust-lang/rustc-perf/archive/{perf_commit}.zip", - rustc_perf_zip_path - ) - with change_cwd(self.opt_artifacts()): - unpack_archive(rustc_perf_zip_path) - move_path(Path(f"rustc-perf-{perf_commit}"), self.rustc_perf_dir()) - delete_file(rustc_perf_zip_path) - - retry_action(download_rustc_perf, "Download rustc-perf") - - with change_cwd(self.rustc_perf_dir()): - cmd([self.cargo_stage_0(), "build", "-p", "collector"], env=dict( - RUSTC=str(self.rustc_stage_0()), - RUSTC_BOOTSTRAP="1" - )) - - def rustc_profile_template_path(self) -> Path: - """ - On Windows, we don't have enough space to use separate files for each rustc invocation. - Therefore, we use a single file for the generated profiles. - """ - return self.rustc_profile_dir_root() / "default_%m.profraw" - - def supports_bolt(self) -> bool: - return False - - def executable_extension(self) -> str: - return ".exe" - - def skipped_tests(self) -> Iterable[str]: - # This test fails as of June 2023 - yield "tests\\codegen\\vec-shrink-panik.rs" - - -def get_timestamp() -> float: - return time.time() - - -Duration = float - - -def iterate_timers(timer: "Timer", name: str, level: int = 0) -> Iterator[ - Tuple[int, str, Duration]]: - """ - Hierarchically iterate the children of a timer, in a depth-first order. - """ - yield (level, name, timer.total_duration()) - for (child_name, child_timer) in timer.children: - yield from iterate_timers(child_timer, child_name, level=level + 1) - - -class Timer: - def __init__(self, parent_names: Tuple[str, ...] = ()): - self.children: List[Tuple[str, Timer]] = [] - self.section_active = False - self.parent_names = parent_names - self.duration_excluding_children: Duration = 0 - - @contextlib.contextmanager - def section(self, name: str) -> ContextManager["Timer"]: - assert not self.section_active - self.section_active = True - - start = get_timestamp() - exc = None - - child_timer = Timer(parent_names=self.parent_names + (name,)) - full_name = " > ".join(child_timer.parent_names) - try: - LOGGER.info(f"Section `{full_name}` starts") - yield child_timer - except BaseException as exception: - exc = exception - raise - finally: - end = get_timestamp() - duration = end - start - - child_timer.duration_excluding_children = duration - child_timer.total_duration() - self.add_child(name, child_timer) - if exc is None: - LOGGER.info(f"Section `{full_name}` ended: OK ({duration:.2f}s)") - else: - LOGGER.info(f"Section `{full_name}` ended: FAIL ({duration:.2f}s)") - self.section_active = False - - def total_duration(self) -> Duration: - return self.duration_excluding_children + sum( - c.total_duration() for (_, c) in self.children) - - def has_children(self) -> bool: - return len(self.children) > 0 - - def print_stats(self): - rows = [] - for (child_name, child_timer) in self.children: - for (level, name, duration) in iterate_timers(child_timer, child_name, level=0): - label = f"{' ' * level}{name}:" - rows.append((label, duration)) - - # Empty row - rows.append(("", "")) - - total_duration_label = "Total duration:" - total_duration = self.total_duration() - rows.append((total_duration_label, humantime(total_duration))) - - space_after_label = 2 - max_label_length = max(16, max(len(label) for (label, _) in rows)) + space_after_label - - table_width = max_label_length + 23 - divider = "-" * table_width - - with StringIO() as output: - print(divider, file=output) - for (label, duration) in rows: - if isinstance(duration, Duration): - pct = (duration / total_duration) * 100 - value = f"{duration:>12.2f}s ({pct:>5.2f}%)" - else: - value = f"{duration:>{len(total_duration_label) + 7}}" - print(f"{label:<{max_label_length}} {value}", file=output) - print(divider, file=output, end="") - LOGGER.info(f"Timer results\n{output.getvalue()}") - - def add_child(self, name: str, timer: "Timer"): - self.children.append((name, timer)) - - def add_duration(self, name: str, duration: Duration): - timer = Timer(parent_names=self.parent_names + (name,)) - timer.duration_excluding_children = duration - self.add_child(name, timer) - - -class BuildStep: - def __init__(self, type: str, children: List["BuildStep"], duration: float): - self.type = type - self.children = children - self.duration = duration - - def find_all_by_type(self, type: str) -> Iterator["BuildStep"]: - if type == self.type: - yield self - for child in self.children: - yield from child.find_all_by_type(type) - - def __repr__(self): - return f"BuildStep(type={self.type}, duration={self.duration}, children={len(self.children)})" - - -def load_last_metrics(path: Path) -> BuildStep: - """ - Loads the metrics of the most recent bootstrap execution from a metrics.json file. - """ - with open(path, "r") as f: - metrics = json.load(f) - invocation = metrics["invocations"][-1] - - def parse(entry) -> Optional[BuildStep]: - if "kind" not in entry or entry["kind"] != "rustbuild_step": - return None - type = entry.get("type", "") - duration = entry.get("duration_excluding_children_sec", 0) - children = [] - - for child in entry.get("children", ()): - step = parse(child) - if step is not None: - children.append(step) - duration += step.duration - return BuildStep(type=type, children=children, duration=duration) - - children = [parse(child) for child in invocation.get("children", ())] - return BuildStep( - type="root", - children=children, - duration=invocation.get("duration_including_children_sec", 0) - ) - - -@contextlib.contextmanager -def change_cwd(dir: Path): - """ - Temporarily change working directory to `dir`. - """ - cwd = os.getcwd() - LOGGER.debug(f"Changing working dir from `{cwd}` to `{dir}`") - os.chdir(dir) - try: - yield - finally: - LOGGER.debug(f"Reverting working dir to `{cwd}`") - os.chdir(cwd) - - -def humantime(time_s: float) -> str: - hours = time_s // 3600 - time_s = time_s % 3600 - minutes = time_s // 60 - seconds = time_s % 60 - - result = "" - if hours > 0: - result += f"{int(hours)}h " - if minutes > 0: - result += f"{int(minutes)}m " - result += f"{round(seconds)}s" - return result - - -def move_path(src: Path, dst: Path): - LOGGER.info(f"Moving `{src}` to `{dst}`") - shutil.move(src, dst) - - -def delete_file(path: Path): - LOGGER.info(f"Deleting file `{path}`") - os.unlink(path) - - -def delete_directory(path: Path): - LOGGER.info(f"Deleting directory `{path}`") - shutil.rmtree(path) - - -def unpack_archive(archive: Path, target_dir: Optional[Path] = None): - LOGGER.info(f"Unpacking archive `{archive}`") - shutil.unpack_archive(str(archive), extract_dir=str(target_dir) if target_dir is not None else None) - - -def download_file(src: str, target: Path): - LOGGER.info(f"Downloading `{src}` into `{target}`") - urllib.request.urlretrieve(src, str(target)) - - -def retry_action(action, name: str, max_fails: int = 5): - LOGGER.info(f"Attempting to perform action `{name}` with retry") - for iteration in range(max_fails): - LOGGER.info(f"Attempt {iteration + 1}/{max_fails}") - try: - action() - return - except BaseException: # also catch ctrl+c/sysexit - LOGGER.error(f"Action `{name}` has failed\n{traceback.format_exc()}") - - raise Exception(f"Action `{name}` has failed after {max_fails} attempts") - - -def cmd( - args: List[Union[str, Path]], - env: Optional[Dict[str, str]] = None, - output_path: Optional[Path] = None -): - args = [str(arg) for arg in args] - - environment = os.environ.copy() - - cmd_str = "" - if env is not None: - environment.update(env) - cmd_str += " ".join(f"{k}={v}" for (k, v) in (env or {}).items()) - cmd_str += " " - cmd_str += " ".join(args) - if output_path is not None: - cmd_str += f" > {output_path}" - LOGGER.info(f"Executing `{cmd_str}`") - - if output_path is not None: - with open(output_path, "w") as f: - return subprocess.run( - args, - env=environment, - check=True, - stdout=f - ) - 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, - profiles: List[str], - scenarios: List[str], - crates: List[str], - env: Optional[Dict[str, str]] = None -): - env = env if env is not None else {} - - # Compile libcore, both in opt-level=0 and opt-level=3 - with change_cwd(pipeline.build_root()): - cmd([ - pipeline.rustc_stage_2(), - "--edition", "2021", - "--crate-type", "lib", - str(pipeline.checkout_path() / "library/core/src/lib.rs"), - "--out-dir", pipeline.opt_artifacts() - ], env=dict(RUSTC_BOOTSTRAP="1", **env)) - - cmd([ - pipeline.rustc_stage_2(), - "--edition", "2021", - "--crate-type", "lib", - "-Copt-level=3", - str(pipeline.checkout_path() / "library/core/src/lib.rs"), - "--out-dir", pipeline.opt_artifacts() - ], env=dict(RUSTC_BOOTSTRAP="1", **env)) - - # Run rustc-perf benchmarks - # Benchmark using profile_local with eprintln, which essentially just means - # don't actually benchmark -- just make sure we run rustc a bunch of times. - with change_cwd(pipeline.rustc_perf_dir()): - cmd([ - pipeline.cargo_stage_0(), - "run", - "-p", "collector", "--bin", "collector", "--", - "profile_local", "eprintln", - pipeline.rustc_stage_2(), - "--id", "Test", - "--cargo", pipeline.cargo_stage_0(), - "--profiles", ",".join(profiles), - "--scenarios", ",".join(scenarios), - "--include", ",".join(crates) - ], env=dict( - RUST_LOG="collector=debug", - RUSTC=str(pipeline.rustc_stage_0()), - RUSTC_BOOTSTRAP="1", - **env - )) - - -# https://stackoverflow.com/a/31631711/1107768 -def format_bytes(size: int) -> str: - """Return the given bytes as a human friendly KiB, MiB or GiB string.""" - KB = 1024 - MB = KB ** 2 # 1,048,576 - GB = KB ** 3 # 1,073,741,824 - TB = KB ** 4 # 1,099,511,627,776 - - if size < KB: - return f"{size} B" - elif KB <= size < MB: - return f"{size / KB:.2f} KiB" - elif MB <= size < GB: - return f"{size / MB:.2f} MiB" - elif GB <= size < TB: - return f"{size / GB:.2f} GiB" - else: - return str(size) - - -# https://stackoverflow.com/a/63307131/1107768 -def count_files(path: Path) -> int: - return sum(1 for p in path.rglob("*") if p.is_file()) - - -def count_files_with_prefix(path: Path) -> int: - return sum(1 for p in glob.glob(f"{path}*") if Path(p).is_file()) - - -# https://stackoverflow.com/a/55659577/1107768 -def get_path_size(path: Path) -> int: - if path.is_dir(): - return sum(p.stat().st_size for p in path.rglob("*")) - return path.stat().st_size - - -def get_path_prefix_size(path: Path) -> int: - """ - Get size of all files beginning with the prefix `path`. - Alternative to shell `du -sh *`. - """ - return sum(Path(p).stat().st_size for p in glob.glob(f"{path}*")) - - -def get_files(directory: Path, filter: Optional[Callable[[Path], bool]] = None) -> Iterable[Path]: - for file in os.listdir(directory): - path = directory / file - if filter is None or filter(path): - yield path - - -def bootstrap_build( - pipeline: Pipeline, - args: List[str], - env: Optional[Dict[str, str]] = None, - targets: Iterable[str] = ("library/std", ) -): - if env is None: - env = {} - else: - env = dict(env) - env["RUST_BACKTRACE"] = "1" - arguments = [ - sys.executable, - pipeline.checkout_path() / "x.py", - "build", - "--target", PGO_HOST, - "--host", PGO_HOST, - "--stage", "2", - ] + list(targets) + args - cmd(arguments, env=env) - - -def create_pipeline() -> Pipeline: - if sys.platform == "linux": - return LinuxPipeline() - elif sys.platform in ("cygwin", "win32"): - return WindowsPipeline() - else: - raise Exception(f"Optimized build is not supported for platform {sys.platform}") - - -def gather_llvm_profiles(pipeline: Pipeline, runner: BenchmarkRunner): - LOGGER.info("Running benchmarks with PGO instrumented LLVM") - - runner.run_llvm(pipeline) - - profile_path = pipeline.llvm_profile_merged_file() - LOGGER.info(f"Merging LLVM PGO profiles to {profile_path}") - cmd([ - pipeline.downloaded_llvm_dir() / "bin" / "llvm-profdata", - "merge", - "-o", profile_path, - pipeline.llvm_profile_dir_root() - ]) - - LOGGER.info("LLVM PGO statistics") - LOGGER.info(f"{profile_path}: {format_bytes(get_path_size(profile_path))}") - LOGGER.info( - f"{pipeline.llvm_profile_dir_root()}: {format_bytes(get_path_size(pipeline.llvm_profile_dir_root()))}") - LOGGER.info(f"Profile file count: {count_files(pipeline.llvm_profile_dir_root())}") - - # We don't need the individual .profraw files now that they have been merged - # into a final .profdata - delete_directory(pipeline.llvm_profile_dir_root()) - - -def gather_rustc_profiles(pipeline: Pipeline, runner: BenchmarkRunner): - LOGGER.info("Running benchmarks with PGO instrumented rustc") - - runner.run_rustc(pipeline) - - profile_path = pipeline.rustc_profile_merged_file() - LOGGER.info(f"Merging Rustc PGO profiles to {profile_path}") - cmd([ - pipeline.build_artifacts() / "llvm" / "bin" / "llvm-profdata", - "merge", - "-o", profile_path, - pipeline.rustc_profile_dir_root() - ]) - - LOGGER.info("Rustc PGO statistics") - LOGGER.info(f"{profile_path}: {format_bytes(get_path_size(profile_path))}") - LOGGER.info( - f"{pipeline.rustc_profile_dir_root()}: {format_bytes(get_path_size(pipeline.rustc_profile_dir_root()))}") - LOGGER.info(f"Profile file count: {count_files(pipeline.rustc_profile_dir_root())}") - - # We don't need the individual .profraw files now that they have been merged - # into a final .profdata - delete_directory(pipeline.rustc_profile_dir_root()) - - -def gather_llvm_bolt_profiles(pipeline: Pipeline, runner: BenchmarkRunner): - LOGGER.info("Running benchmarks with BOLT instrumented LLVM") - - runner.run_bolt(pipeline) - - merged_profile_path = pipeline.llvm_bolt_profile_merged_file() - profile_files_path = Path("/tmp/prof.fdata") - LOGGER.info(f"Merging LLVM BOLT profiles to {merged_profile_path}") - - profile_files = sorted(glob.glob(f"{profile_files_path}*")) - cmd([ - "merge-fdata", - *profile_files, - ], output_path=merged_profile_path) - - LOGGER.info("LLVM BOLT statistics") - LOGGER.info(f"{merged_profile_path}: {format_bytes(get_path_size(merged_profile_path))}") - LOGGER.info( - f"{profile_files_path}: {format_bytes(get_path_prefix_size(profile_files_path))}") - LOGGER.info(f"Profile file count: {count_files_with_prefix(profile_files_path)}") - - -def clear_llvm_files(pipeline: Pipeline): - """ - Rustbuild currently doesn't support rebuilding LLVM when PGO options - change (or any other llvm-related options); so just clear out the relevant - directories ourselves. - """ - LOGGER.info("Clearing LLVM build files") - delete_directory(pipeline.build_artifacts() / "llvm") - delete_directory(pipeline.build_artifacts() / "lld") - - -def print_binary_sizes(pipeline: Pipeline): - bin_dir = pipeline.build_artifacts() / "stage2" / "bin" - binaries = get_files(bin_dir) - - lib_dir = pipeline.build_artifacts() / "stage2" / "lib" - libraries = get_files(lib_dir, lambda p: p.suffix == ".so") - - paths = sorted(binaries) + sorted(libraries) - with StringIO() as output: - for path in paths: - path_str = f"{path.name}:" - print(f"{path_str:<50}{format_bytes(path.stat().st_size):>14}", file=output) - LOGGER.info(f"Rustc binary size\n{output.getvalue()}") - - -def print_free_disk_space(pipeline: Pipeline): - usage = shutil.disk_usage(pipeline.opt_artifacts()) - total = usage.total - used = usage.used - free = usage.free - - logging.info( - f"Free disk space: {format_bytes(free)} out of total {format_bytes(total)} ({(used / total) * 100:.2f}% used)") - - -def log_metrics(step: BuildStep): - substeps: List[Tuple[int, BuildStep]] = [] - - def visit(step: BuildStep, level: int): - substeps.append((level, step)) - for child in step.children: - visit(child, level=level + 1) - - visit(step, 0) - - output = StringIO() - for (level, step) in substeps: - label = f"{'.' * level}{step.type}" - print(f"{label:<65}{step.duration:>8.2f}s", file=output) - logging.info(f"Build step durations\n{output.getvalue()}") - - -def record_metrics(pipeline: Pipeline, timer: Timer): - metrics = load_last_metrics(pipeline.metrics_path()) - if metrics is None: - return - llvm_steps = tuple(metrics.find_all_by_type("bootstrap::llvm::Llvm")) - llvm_duration = sum(step.duration for step in llvm_steps) - - rustc_steps = tuple(metrics.find_all_by_type("bootstrap::compile::Rustc")) - rustc_duration = sum(step.duration for step in rustc_steps) - - # The LLVM step is part of the Rustc step - rustc_duration = max(0, rustc_duration - llvm_duration) - - if llvm_duration > 0: - timer.add_duration("LLVM", llvm_duration) - if rustc_duration > 0: - timer.add_duration("Rustc", rustc_duration) - - log_metrics(metrics) - - -def run_tests(pipeline: Pipeline): - """ - After `dist` is executed, we extract its archived components into a sysroot directory, - and then use that extracted rustc as a stage0 compiler. - Then we run a subset of tests using that compiler, to have a basic smoke test which checks - whether the optimization pipeline hasn't broken something. - """ - build_dir = pipeline.build_root() / "build" - dist_dir = build_dir / "dist" - - def extract_dist_dir(name: str) -> Path: - target_dir = build_dir / "optimized-dist" - target_dir.mkdir(parents=True, exist_ok=True) - unpack_archive(dist_dir / f"{name}.tar.xz", target_dir=target_dir) - extracted_path = target_dir / name - assert extracted_path.is_dir() - return extracted_path - - # Extract rustc, libstd, cargo and src archives to create the optimized sysroot - rustc_dir = extract_dist_dir(f"rustc-{CHANNEL}-{PGO_HOST}") / "rustc" - libstd_dir = extract_dist_dir(f"rust-std-{CHANNEL}-{PGO_HOST}") / f"rust-std-{PGO_HOST}" - cargo_dir = extract_dist_dir(f"cargo-{CHANNEL}-{PGO_HOST}") / "cargo" - extracted_src_dir = extract_dist_dir(f"rust-src-{CHANNEL}") / "rust-src" - - # We need to manually copy libstd to the extracted rustc sysroot - shutil.copytree( - libstd_dir / "lib" / "rustlib" / PGO_HOST / "lib", - rustc_dir / "lib" / "rustlib" / PGO_HOST / "lib" - ) - - # Extract sources - they aren't in the `rustc-{CHANNEL}-{host}` tarball, so we need to manually copy libstd - # sources to the extracted sysroot. We need sources available so that `-Zsimulate-remapped-rust-src-base` - # works correctly. - shutil.copytree( - extracted_src_dir / "lib" / "rustlib" / "src", - rustc_dir / "lib" / "rustlib" / "src" - ) - - rustc_path = rustc_dir / "bin" / f"rustc{pipeline.executable_extension()}" - assert rustc_path.is_file() - cargo_path = cargo_dir / "bin" / f"cargo{pipeline.executable_extension()}" - assert cargo_path.is_file() - - # Specify path to a LLVM config so that LLVM is not rebuilt. - # It doesn't really matter which LLVM config we choose, because no sysroot will be compiled. - llvm_config = pipeline.build_artifacts() / "llvm" / "bin" / f"llvm-config{pipeline.executable_extension()}" - assert llvm_config.is_file() - - config_content = f"""profile = "user" -changelog-seen = 2 - -[build] -rustc = "{rustc_path.as_posix()}" -cargo = "{cargo_path.as_posix()}" - -[target.{PGO_HOST}] -llvm-config = "{llvm_config.as_posix()}" -""" - logging.info(f"Using following `config.toml` for running tests:\n{config_content}") - - # Simulate a stage 0 compiler with the extracted optimized dist artifacts. - with open("config.toml", "w") as f: - f.write(config_content) - - args = [ - sys.executable, - pipeline.checkout_path() / "x.py", - "test", - "--stage", "0", - "tests/assembly", - "tests/codegen", - "tests/codegen-units", - "tests/incremental", - "tests/mir-opt", - "tests/pretty", - "tests/run-pass-valgrind", - "tests/ui", - ] - for test_path in pipeline.skipped_tests(): - args.extend(["--exclude", test_path]) - cmd(args=args, env=dict( - COMPILETEST_FORCE_STAGE0="1" - )) - - -def execute_build_pipeline(timer: Timer, pipeline: Pipeline, runner: BenchmarkRunner, dist_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) - - pipeline.build_rustc_perf() - - """ - Stage 1: Build PGO instrumented rustc - - We use a normal build of LLVM, because gathering PGO profiles for LLVM and `rustc` at the same time - can cause issues. - """ - with timer.section("Stage 1 (rustc PGO)") as stage1: - with stage1.section("Build PGO instrumented rustc and LLVM") as rustc_pgo_instrument: - bootstrap_build(pipeline, args=[ - "--rust-profile-generate", - pipeline.rustc_profile_dir_root() - ]) - record_metrics(pipeline, rustc_pgo_instrument) - - with stage1.section("Gather profiles"): - gather_rustc_profiles(pipeline, runner) - print_free_disk_space(pipeline) - - with stage1.section("Build PGO optimized rustc") as rustc_pgo_use: - bootstrap_build(pipeline, args=[ - "--rust-profile-use", - pipeline.rustc_profile_merged_file() - ]) - record_metrics(pipeline, rustc_pgo_use) - dist_build_args += [ - "--rust-profile-use", - pipeline.rustc_profile_merged_file() - ] - - """ - Stage 2: Gather LLVM PGO profiles - """ - with timer.section("Stage 2 (LLVM PGO)") as stage2: - # Clear normal LLVM artifacts - clear_llvm_files(pipeline) - - with stage2.section("Build PGO instrumented LLVM") as llvm_pgo_instrument: - bootstrap_build(pipeline, args=[ - "--llvm-profile-generate", - # We want to keep the already built PGO-optimized `rustc`. - "--keep-stage", "0", - "--keep-stage", "1" - ], env=dict( - LLVM_PROFILE_DIR=str(pipeline.llvm_profile_dir_root() / "prof-%p") - )) - record_metrics(pipeline, llvm_pgo_instrument) - - with stage2.section("Gather profiles"): - gather_llvm_profiles(pipeline, runner) - - dist_build_args += [ - "--llvm-profile-use", - pipeline.llvm_profile_merged_file(), - ] - print_free_disk_space(pipeline) - - # Clear PGO-instrumented LLVM artifacts - clear_llvm_files(pipeline) - - """ - Stage 3: Build BOLT instrumented LLVM - - We build a PGO optimized LLVM in this step, then instrument it with BOLT and gather BOLT profiles. - Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build. - BOLT instrumentation is performed "on-the-fly" when the LLVM library is copied to the sysroot of rustc, - therefore the LLVM artifacts on disk are not "tainted" with BOLT instrumentation and they can be reused. - """ - if pipeline.supports_bolt(): - with timer.section("Stage 3 (LLVM BOLT)") as stage3: - with stage3.section("Build BOLT instrumented LLVM") as llvm_bolt_instrument: - bootstrap_build(pipeline, args=[ - "--llvm-profile-use", - pipeline.llvm_profile_merged_file(), - "--llvm-bolt-profile-generate", - # We want to keep the already built PGO-optimized `rustc`. - "--keep-stage", "0", - "--keep-stage", "1" - ]) - record_metrics(pipeline, llvm_bolt_instrument) - - with stage3.section("Gather profiles"): - gather_llvm_bolt_profiles(pipeline, runner) - - dist_build_args += [ - "--llvm-bolt-profile-use", - pipeline.llvm_bolt_profile_merged_file() - ] - print_free_disk_space(pipeline) - - # We want to keep the already built PGO-optimized `rustc`. - dist_build_args += [ - "--keep-stage", "0", - "--keep-stage", "1" - ] - - """ - Final stage: Build PGO optimized rustc + PGO/BOLT optimized LLVM - """ - with timer.section("Final stage (dist build)") as final_stage: - cmd(dist_build_args) - record_metrics(pipeline, final_stage) - - # Try builds can be in various broken states, so we don't want to gatekeep them with tests - # Do not run tests, as they are broken for beta/stable versions in this script - # if not is_try_build(): - # with timer.section("Run tests"): - # run_tests(pipeline) - - -def run(runner: BenchmarkRunner): - logging.basicConfig( - level=logging.DEBUG, - format="%(name)s %(levelname)-4s: %(message)s", - ) - - LOGGER.info(f"Running multi-stage build using Python {sys.version}") - LOGGER.info(f"Environment values\n{pprint.pformat(dict(os.environ), indent=2)}") - - build_args = sys.argv[1:] - - # Skip components that are not needed for try builds to speed them up - if is_try_build(): - LOGGER.info("Skipping building of unimportant components for a try build") - for target in ("rust-docs", "rustc-docs", "rust-docs-json", "rust-analyzer", - "rustc-src", "clippy", "miri", "rustfmt"): - build_args.extend(["--exclude", target]) - - timer = Timer() - pipeline = create_pipeline() - - try: - execute_build_pipeline(timer, pipeline, runner, build_args) - except BaseException as e: - LOGGER.error("The multi-stage build has failed") - raise e - finally: - timer.print_stats() - print_free_disk_space(pipeline) - - print_binary_sizes(pipeline) - - -if __name__ == "__main__": - runner = DefaultBenchmarkRunner() - run(runner) diff --git a/src/doc/book/redirects/using-rust-without-the-standard-library.md b/src/doc/book/redirects/using-rust-without-the-standard-library.md index 75145429d..0fbdfebdd 100644 --- a/src/doc/book/redirects/using-rust-without-the-standard-library.md +++ b/src/doc/book/redirects/using-rust-without-the-standard-library.md @@ -7,11 +7,11 @@ --- -This particular chapter has moved to [the Unstable Book][2]. +This particular chapter has moved to [the Rustonomicon][2]. -* **[In the Unstable Rust Book: `lang_items` — Writing an executable without stdlib][2]** +* **[In the Rustonomicon: Beneath std][2]** * [In the first edition: Ch 4.12 — Using Rust without the Standard Library][1] [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/using-rust-without-the-standard-library.html -[2]: ../unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib +[2]: ../nomicon/beneath-std.html diff --git a/src/doc/book/src/ch08-02-strings.md b/src/doc/book/src/ch08-02-strings.md index 9663d36ab..f38803ee3 100644 --- a/src/doc/book/src/ch08-02-strings.md +++ b/src/doc/book/src/ch08-02-strings.md @@ -244,7 +244,7 @@ encoded UTF-8 example strings from Listing 8-14. First, this one: In this case, `len` will be 4, which means the vector storing the string “Hola” is 4 bytes long. Each of these letters takes 1 byte when encoded in UTF-8. The following line, however, may surprise you. (Note that this string begins with -the capital Cyrillic letter Ze, not the Arabic number 3.) +the capital Cyrillic letter Ze, not the number 3.) ```rust {{#rustdoc_include ../listings/ch08-common-collections/listing-08-14/src/main.rs:russian}} diff --git a/src/doc/book/src/ch10-03-lifetime-syntax.md b/src/doc/book/src/ch10-03-lifetime-syntax.md index 5229ab74b..498f01f0b 100644 --- a/src/doc/book/src/ch10-03-lifetime-syntax.md +++ b/src/doc/book/src/ch10-03-lifetime-syntax.md @@ -8,13 +8,13 @@ One detail we didn’t discuss in the [“References and Borrowing”][references-and-borrowing] section in Chapter 4 is that every reference in Rust has a *lifetime*, which is the scope for which that reference is valid. Most of the time, lifetimes are implicit and inferred, -just like most of the time, types are inferred. We only must annotate types +just like most of the time, types are inferred. We must only annotate types when multiple types are possible. In a similar way, we must annotate lifetimes when the lifetimes of references could be related in a few different ways. Rust requires us to annotate the relationships using generic lifetime parameters to ensure the actual references used at runtime will definitely be valid. -Annotating lifetimes is not even a concept most other programming languages +Annotating lifetimes is not a concept most other programming languages have, so this is going to feel unfamiliar. Although we won’t cover lifetimes in their entirety in this chapter, we’ll discuss common ways you might encounter lifetime syntax so you can get comfortable with the concept. @@ -44,7 +44,7 @@ The outer scope declares a variable named `r` with no initial value, and the inner scope declares a variable named `x` with the initial value of 5. Inside the inner scope, we attempt to set the value of `r` as a reference to `x`. Then the inner scope ends, and we attempt to print the value in `r`. This code won’t -compile because the value `r` is referring to has gone out of scope before we +compile because what the value `r` is referring to has gone out of scope before we try to use it. Here is the error message: ```console diff --git a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md index 9abc5a608..5f6653dcd 100644 --- a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md +++ b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md @@ -24,7 +24,7 @@ See [the announcement of Rust 1.51][5] for details. [4]: ../../cargo/reference/resolver.html#feature-resolver-version-2 [5]: https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver [workspace]: ../../cargo/reference/workspaces.html -[virtual workspace]: ../../cargo/reference/workspaces.html#virtual-manifest +[virtual workspace]: ../../cargo/reference/workspaces.html#virtual-workspace [`resolver` field]: ../../cargo/reference/resolver.html#resolver-versions ## Migration diff --git a/src/doc/edition-guide/src/rust-2021/reserving-syntax.md b/src/doc/edition-guide/src/rust-2021/reserving-syntax.md index db711a7d1..a4a7114a6 100644 --- a/src/doc/edition-guide/src/rust-2021/reserving-syntax.md +++ b/src/doc/edition-guide/src/rust-2021/reserving-syntax.md @@ -17,7 +17,7 @@ we've decided to reserve syntax for prefixed identifiers and literals: `prefix#identifier`, `prefix"string"`, `prefix'c'`, and `prefix#123`, where `prefix` can be any identifier. (Except those prefixes that already have a meaning, such as `b'...'` (byte -strings) and `r"..."` (raw strings).) +chars) and `r"..."` (raw strings).) This provides syntax we can expand into in the future without requiring an edition boundary. We may use this for temporary syntax until the next edition, @@ -82,4 +82,4 @@ This `z` prefix is no longer allowed in Rust 2021, so in order to call this macr ```rust,ignore my_macro!(z "hey"); -``` \ No newline at end of file +``` diff --git a/src/doc/embedded-book/.github/bors.toml b/src/doc/embedded-book/.github/bors.toml deleted file mode 100644 index c3cfa378d..000000000 --- a/src/doc/embedded-book/.github/bors.toml +++ /dev/null @@ -1,4 +0,0 @@ -block_labels = ["needs-decision"] -delete_merged_branches = true -required_approvals = 1 -status = ["build"] diff --git a/src/doc/embedded-book/.github/workflows/ci.yml b/src/doc/embedded-book/.github/workflows/ci.yml index b1e3d552e..9018d1146 100644 --- a/src/doc/embedded-book/.github/workflows/ci.yml +++ b/src/doc/embedded-book/.github/workflows/ci.yml @@ -1,9 +1,11 @@ name: CI on: - push: - branches: [ staging, trying, master ] - pull_request: + push: # Run CI for all branches except GitHub merge queue tmp branches + branches-ignore: + - "gh-readonly-queue/**" + pull_request: # Run CI for PRs on any branch + merge_group: # Run CI for the GitHub merge queue jobs: build: diff --git a/src/doc/embedded-book/src/start/qemu.md b/src/doc/embedded-book/src/start/qemu.md index d4dfc361d..f7241b873 100644 --- a/src/doc/embedded-book/src/start/qemu.md +++ b/src/doc/embedded-book/src/start/qemu.md @@ -388,7 +388,7 @@ Let's break down that QEMU command: program compiled for the Cortex-M4F, which has a hardware FPU, will make QEMU error during its execution. -- `-machine lm3s6965evb`. This tells QEMU to emulate the LM3S6965EVB, a +- `-machine lm3s6965evb`. This tells QEMU to emulate the LM3S6965EVB, an evaluation board that contains a LM3S6965 microcontroller. - `-nographic`. This tells QEMU to not launch its GUI. diff --git a/src/doc/embedded-book/src/unsorted/math.md b/src/doc/embedded-book/src/unsorted/math.md index 91271710e..4367b867b 100644 --- a/src/doc/embedded-book/src/unsorted/math.md +++ b/src/doc/embedded-book/src/unsorted/math.md @@ -70,6 +70,7 @@ If you need to perform more complex operations like DSP signal processing or adv algebra on your MCU, the following crates might help you - [CMSIS DSP library binding](https://github.com/jacobrosenthal/cmsis-dsp-sys) +- [`constgebra`](https://crates.io/crates/constgebra) - [`micromath`](https://github.com/tarcieri/micromath) - [`microfft`](https://crates.io/crates/microfft) - [`nalgebra`](https://github.com/dimforge/nalgebra) diff --git a/src/doc/nomicon/src/atomics.md b/src/doc/nomicon/src/atomics.md index 6aef6aee6..72a2d56fd 100644 --- a/src/doc/nomicon/src/atomics.md +++ b/src/doc/nomicon/src/atomics.md @@ -76,7 +76,7 @@ For instance, say we convince the compiler to emit this logic: ```text initial state: x = 0, y = 1 -THREAD 1 THREAD2 +THREAD 1 THREAD 2 y = 3; if x == 1 { x = 1; y *= 2; } diff --git a/src/doc/nomicon/src/exception-safety.md b/src/doc/nomicon/src/exception-safety.md index ca1a39416..8404bb859 100644 --- a/src/doc/nomicon/src/exception-safety.md +++ b/src/doc/nomicon/src/exception-safety.md @@ -161,9 +161,9 @@ impl<'a, T> Hole<'a, T> { unsafe { let elt = ptr::read(&data[pos]); Hole { - data: data, + data, elt: Some(elt), - pos: pos, + pos, } } } diff --git a/src/doc/nomicon/src/ffi.md b/src/doc/nomicon/src/ffi.md index 55be225de..b76f0b2ac 100644 --- a/src/doc/nomicon/src/ffi.md +++ b/src/doc/nomicon/src/ffi.md @@ -586,6 +586,7 @@ are: * `aapcs` * `cdecl` * `fastcall` +* `thiscall` * `vectorcall` This is currently hidden behind the `abi_vectorcall` gate and is subject to change. * `Rust` diff --git a/src/doc/nomicon/src/leaking.md b/src/doc/nomicon/src/leaking.md index ea29595f4..d90fed571 100644 --- a/src/doc/nomicon/src/leaking.md +++ b/src/doc/nomicon/src/leaking.md @@ -134,10 +134,10 @@ impl Rc { // Wouldn't it be nice if heap::allocate worked like this? let ptr = heap::allocate::>(); ptr::write(ptr, RcBox { - data: data, + data, ref_count: 1, }); - Rc { ptr: ptr } + Rc { ptr } } } @@ -194,7 +194,7 @@ pub fn scoped<'a, F>(f: F) -> JoinGuard<'a> ``` Here `f` is some closure for the other thread to execute. Saying that -`F: Send +'a` is saying that it closes over data that lives for `'a`, and it +`F: Send + 'a` is saying that it closes over data that lives for `'a`, and it either owns that data or the data was Sync (implying `&data` is Send). Because JoinGuard has a lifetime, it keeps all the data it closes over diff --git a/src/doc/nomicon/src/vec/vec-final.md b/src/doc/nomicon/src/vec/vec-final.md index 696391d10..e680e0d65 100644 --- a/src/doc/nomicon/src/vec/vec-final.md +++ b/src/doc/nomicon/src/vec/vec-final.md @@ -23,7 +23,7 @@ impl RawVec { // `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: NonNull::dangling(), - cap: cap, + cap, } } diff --git a/src/doc/nomicon/src/vec/vec-zsts.md b/src/doc/nomicon/src/vec/vec-zsts.md index 8f2529727..6715f9478 100644 --- a/src/doc/nomicon/src/vec/vec-zsts.md +++ b/src/doc/nomicon/src/vec/vec-zsts.md @@ -39,7 +39,7 @@ impl RawVec { // `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: NonNull::dangling(), - cap: cap, + cap, } } diff --git a/src/doc/reference/.github/workflows/main.yml b/src/doc/reference/.github/workflows/main.yml index 4456c3c9c..aff208478 100644 --- a/src/doc/reference/.github/workflows/main.yml +++ b/src/doc/reference/.github/workflows/main.yml @@ -1,5 +1,7 @@ name: CI -on: [push, pull_request] +on: + pull_request: + merge_group: jobs: test: diff --git a/src/doc/reference/src/attributes/codegen.md b/src/doc/reference/src/attributes/codegen.md index 8629e835d..c929f979c 100644 --- a/src/doc/reference/src/attributes/codegen.md +++ b/src/doc/reference/src/attributes/codegen.md @@ -361,15 +361,20 @@ trait object whose methods are attributed. ## The `instruction_set` attribute -The *`instruction_set` attribute* may be applied to a function to enable code generation for a specific -instruction set supported by the target architecture. It uses the [_MetaListPath_] syntax and a path -comprised of the architecture and instruction set to specify how to generate the code for -architectures where a single program may utilize multiple instruction sets. +The *`instruction_set` [attribute]* may be applied to a function to control which instruction set the function will be generated for. +This allows mixing more than one instruction set in a single program on CPU architectures that support it. +It uses the [_MetaListPath_] syntax, and a path comprised of the architecture family name and instruction set name. -The following values are available on targets for the `ARMv4` and `ARMv5te` architectures: +[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax + +It is a compilation error to use the `instruction_set` attribute on a target that does not support it. + +### On ARM -* `arm::a32` - Uses ARM code. -* `arm::t32` - Uses Thumb code. +For the `ARMv4T` and `ARMv5te` architectures, the following are supported: + +* `arm::a32` - Generate the function as A32 "ARM" code. +* `arm::t32` - Generate the function as T32 "Thumb" code. ```rust,ignore @@ -380,4 +385,7 @@ fn foo_arm_code() {} fn bar_thumb_code() {} ``` -[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax +Using the `instruction_set` attribute has the following effects: + +* If the address of the function is taken as a function pointer, the low bit of the address will be set to 0 (arm) or 1 (thumb) depending on the instruction set. +* Any inline assembly in the function must use the specified instruction set instead of the target default. diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md index 31963d1e5..9d1732d07 100644 --- a/src/doc/reference/src/behavior-considered-undefined.md +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -42,9 +42,12 @@ code. All this also applies when values of these types are passed in a (nested) field of a compound type, but not behind pointer indirections. -* Mutating immutable data. All data inside a [`const`] item is immutable. Moreover, all - data reached through a shared reference or data owned by an immutable binding - is immutable, unless that data is contained within an [`UnsafeCell`]. +* Mutating immutable bytes. All bytes inside a [`const`] item are immutable. + The bytes owned by an immutable binding are immutable, unless those bytes are part of an [`UnsafeCell`]. + + Moreover, the bytes [pointed to] by a shared reference, including transitively through other references (both shared and mutable) and `Box`es, are immutable; transitivity includes those references stored in fields of compound types. + + A mutation is any write of more than 0 bytes which overlaps with any of the relevant bytes (even if that write does not change the memory contents). * Invoking undefined behavior via compiler intrinsics. * Executing code compiled with platform features that the current platform does not support (see [`target_feature`]), *except* if the platform explicitly documents this to be safe. @@ -74,6 +77,11 @@ code. > `rustc_layout_scalar_valid_range_*` attributes. * Incorrect use of inline assembly. For more details, refer to the [rules] to follow when writing code that uses inline assembly. +* **In [const context](const_eval.md#const-context)**: transmuting or otherwise + reinterpreting a pointer (reference, raw pointer, or function pointer) into + some allocated object as a non-pointer type (such as integers). + 'Reinterpreting' refers to loading the pointer value at integer type without a + cast, e.g. by doing raw pointer casts or using a union. **Note:** Uninitialized memory is also implicitly invalid for any type that has a restricted set of valid values. In other words, the only cases in which @@ -86,13 +94,16 @@ reading uninitialized memory is permitted are inside `union`s and in "padding" > vice versa, undefined behavior in Rust can cause adverse affects on code > executed by any FFI calls to other languages. +### Pointed-to bytes + +The span of bytes a pointer or reference "points to" is determined by the pointer value and the size of the pointee type (using `size_of_val`). + ### Dangling pointers [dangling]: #dangling-pointers A reference/pointer is "dangling" if it is null or not all of the bytes it -points to are part of the same live allocation (so in particular they all have to be -part of *some* allocation). The span of bytes it points to is determined by the -pointer value and the size of the pointee type (using `size_of_val`). +[points to] are part of the same live allocation (so in particular they all have to be +part of *some* allocation). If the size is 0, then the pointer must either point inside of a live allocation (including pointing just after the last byte of the allocation), or it must be @@ -116,3 +127,5 @@ must never exceed `isize::MAX`. [dereference expression]: expressions/operator-expr.md#the-dereference-operator [place expression context]: expressions.md#place-expressions-and-value-expressions [rules]: inline-assembly.md#rules-for-inline-assembly +[points to]: #pointed-to-bytes +[pointed to]: #pointed-to-bytes diff --git a/src/doc/reference/src/destructors.md b/src/doc/reference/src/destructors.md index 84aac89d3..17afc3676 100644 --- a/src/doc/reference/src/destructors.md +++ b/src/doc/reference/src/destructors.md @@ -284,7 +284,7 @@ An *extending pattern* is either * An [identifier pattern] that binds by reference or mutable reference. * A [struct][struct pattern], [tuple][tuple pattern], [tuple struct][tuple struct pattern], or [slice][slice pattern] pattern where at least one of the - direct subpatterns is a extending pattern. + direct subpatterns is an extending pattern. So `ref x`, `V(ref x)` and `[ref x, y]` are all extending patterns, but `x`, `&ref x` and `&(ref x,)` are not. diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md index b2411cd8e..ad4cc5f54 100644 --- a/src/doc/reference/src/expressions.md +++ b/src/doc/reference/src/expressions.md @@ -162,7 +162,7 @@ Explicitly, the assignee expressions are: - Place expressions. - [Underscores][_UnderscoreExpression_]. - [Tuples][_TupleExpression_] of assignee expressions. -- [Slices][_ArrayExpression_] of assingee expressions. +- [Slices][_ArrayExpression_] of assignee expressions. - [Tuple structs][_StructExpression_] of assignee expressions. - [Structs][_StructExpression_] of assignee expressions (with optionally named fields). diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md index 691f801e8..8b6429636 100644 --- a/src/doc/reference/src/expressions/operator-expr.md +++ b/src/doc/reference/src/expressions/operator-expr.md @@ -243,8 +243,8 @@ The operands of all of these operators are evaluated in [value expression contex | `+` | Addition | | Addition | `std::ops::Add` | `std::ops::AddAssign` | | `-` | Subtraction | | Subtraction | `std::ops::Sub` | `std::ops::SubAssign` | | `*` | Multiplication | | Multiplication | `std::ops::Mul` | `std::ops::MulAssign` | -| `/` | Division* | | Division | `std::ops::Div` | `std::ops::DivAssign` | -| `%` | Remainder** | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` | +| `/` | Division*† | | Division | `std::ops::Div` | `std::ops::DivAssign` | +| `%` | Remainder**† | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` | | `&` | Bitwise AND | [Logical AND] | | `std::ops::BitAnd` | `std::ops::BitAndAssign` | | | | Bitwise OR | [Logical OR] | | `std::ops::BitOr` | `std::ops::BitOrAssign` | | `^` | Bitwise XOR | [Logical XOR] | | `std::ops::BitXor` | `std::ops::BitXorAssign` | @@ -258,6 +258,8 @@ The operands of all of these operators are evaluated in [value expression contex \*\*\* Arithmetic right shift on signed integer types, logical right shift on unsigned integer types. +† For integer types, division by zero panics. + Here are examples of these operators being used. ```rust diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md index 25ae37bc3..982f57ba7 100644 --- a/src/doc/reference/src/items/external-blocks.md +++ b/src/doc/reference/src/items/external-blocks.md @@ -90,6 +90,8 @@ There are also some platform-specific ABI strings: `__fastcall` and GCC and clang's `__attribute__((fastcall))` * `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's `__vectorcall` and clang's `__attribute__((vectorcall))` +* `extern "thiscall"` -- The default for C++ member functions on MSVC -- corresponds to MSVC's + `__thiscall` and GCC and clang's `__attribute__((thiscall))` * `extern "efiapi"` -- The ABI used for [UEFI] functions. ## Variadic functions diff --git a/src/doc/reference/src/trait-bounds.md b/src/doc/reference/src/trait-bounds.md index 0a6731288..a7cd5a7d9 100644 --- a/src/doc/reference/src/trait-bounds.md +++ b/src/doc/reference/src/trait-bounds.md @@ -156,6 +156,79 @@ fn call_on_ref_zero(f: F) where F: for<'a> Fn(&'a i32) { } ``` +## Implied bounds + +Lifetime bounds required for types to be well-formed are sometimes inferred. + +```rust +fn requires_t_outlives_a<'a, T>(x: &'a T) {} +``` +The type parameter `T` is required to outlive `'a` for the type `&'a T` to be well-formed. +This is inferred because the function signature contains the type `&'a T` which is +only valid if `T: 'a` holds. + +Implied bounds are added for all parameters and outputs of functions. Inside of `requires_t_outlives_a` +you can assume `T: 'a` to hold even if you don't explicitly specify this: + +```rust +fn requires_t_outlives_a_not_implied<'a, T: 'a>() {} + +fn requires_t_outlives_a<'a, T>(x: &'a T) { + // This compiles, because `T: 'a` is implied by + // the reference type `&'a T`. + requires_t_outlives_a_not_implied::<'a, T>(); +} +``` + +```rust,compile_fail,E0309 +# fn requires_t_outlives_a_not_implied<'a, T: 'a>() {} +fn not_implied<'a, T>() { + // This errors, because `T: 'a` is not implied by + // the function signature. + requires_t_outlives_a_not_implied::<'a, T>(); +} +``` + +Only lifetime bounds are implied, trait bounds still have to be explicitly added. +The following example therefore causes an error: + +```rust,compile_fail,E0277 +use std::fmt::Debug; +struct IsDebug(T); +// error[E0277]: `T` doesn't implement `Debug` +fn doesnt_specify_t_debug(x: IsDebug) {} +``` + +Lifetime bounds are also inferred for type definitions and impl blocks for any type: + +```rust +struct Struct<'a, T> { + // This requires `T: 'a` to be well-formed + // which is inferred by the compiler. + field: &'a T, +} + +enum Enum<'a, T> { + // This requires `T: 'a` to be well-formed, + // which is inferred by the compiler. + // + // Note that `T: 'a` is required even when only + // using `Enum::OtherVariant`. + SomeVariant(&'a T), + OtherVariant, +} + +trait Trait<'a, T: 'a> {} + +// This would error because `T: 'a` is not implied by any type +// in the impl header. +// impl<'a, T> Trait<'a, T> for () {} + +// This compiles as `T: 'a` is implied by the self type `&'a T`. +impl<'a, T> Trait<'a, T> for &'a T {} +``` + + [LIFETIME_OR_LABEL]: tokens.md#lifetimes-and-loop-labels [_GenericParams_]: items/generics.md [_TypePath_]: paths.md#paths-in-types diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index 191567a42..4c87954f3 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -549,13 +549,28 @@ The `align` modifier can also be applied on an `enum`. When it is, the effect on the `enum`'s alignment is the same as if the `enum` was wrapped in a newtype `struct` with the same `align` modifier. -

- -***Warning:*** Dereferencing an unaligned pointer is [undefined behavior] and -it is possible to [safely create unaligned pointers to `packed` fields][27060]. -Like all ways to create undefined behavior in safe Rust, this is a bug. - -
+> Note: References to unaligned fields are not allowed because it is [undefined behavior]. +> When fields are unaligned due to an alignment modifier, consider the following options for using references and dereferences: +> +> ```rust +> #[repr(packed)] +> struct Packed { +> f1: u8, +> f2: u16, +> } +> let mut e = Packed { f1: 1, f2: 2 }; +> // Instead of creating a reference to a field, copy the value to a local variable. +> let x = e.f2; +> // Or in situations like `println!` which creates a reference, use braces +> // to change it to a copy of the value. +> println!("{}", {e.f2}); +> // Or if you need a pointer, use the unaligned methods for reading and writing +> // instead of dereferencing the pointer directly. +> let ptr: *const u16 = std::ptr::addr_of!(e.f2); +> let value = unsafe { ptr.read_unaligned() }; +> let mut_ptr: *mut u16 = std::ptr::addr_of_mut!(e.f2); +> unsafe { mut_ptr.write_unaligned(3) } +> ``` ### The `transparent` Representation @@ -587,7 +602,6 @@ used with any other representation. [enumerations]: items/enumerations.md [zero-variant enums]: items/enumerations.md#zero-variant-enums [undefined behavior]: behavior-considered-undefined.md -[27060]: https://github.com/rust-lang/rust/issues/27060 [55149]: https://github.com/rust-lang/rust/issues/55149 [`PhantomData`]: special-types-and-traits.md#phantomdatat [Default]: #the-default-representation diff --git a/src/doc/reference/src/types/never.md b/src/doc/reference/src/types/never.md index e32674272..3fbd2ad5c 100644 --- a/src/doc/reference/src/types/never.md +++ b/src/doc/reference/src/types/never.md @@ -7,16 +7,17 @@ The never type `!` is a type with no values, representing the result of computations that never complete. Expressions of type `!` can be coerced into any other type. - -```rust,ignore -let x: ! = panic!(); -// Can be coerced into any type. -let y: u32 = x; +The `!` type can **only** appear in function return types presently, +indicating it is a diverging function that never returns. + +```rust +fn foo() -> ! { + panic!("This call never returns."); +} ``` -**NB.** The never type was expected to be stabilized in 1.41, but due -to some last minute regressions detected the stabilization was -temporarily reverted. The `!` type can only appear in function return -types presently. See [the tracking -issue](https://github.com/rust-lang/rust/issues/35121) for more -details. +```rust +extern "C" { + pub fn no_return_extern_func() -> !; +} +``` diff --git a/src/doc/reference/src/types/textual.md b/src/doc/reference/src/types/textual.md index 7f3899d70..65d563312 100644 --- a/src/doc/reference/src/types/textual.md +++ b/src/doc/reference/src/types/textual.md @@ -8,7 +8,7 @@ or 0xE000 to 0x10FFFF range. It is immediate [Undefined Behavior] to create a `char` that falls outside this range. A `[char]` is effectively a UCS-4 / UTF-32 string of length 1. -A value of type `str` is represented the same way as `[u8]`, it is a slice of +A value of type `str` is represented the same way as `[u8]`, a slice of 8-bit unsigned bytes. However, the Rust standard library makes extra assumptions about `str`: methods working on `str` assume and ensure that the data in there is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause diff --git a/src/doc/reference/src/unsafe-keyword.md b/src/doc/reference/src/unsafe-keyword.md index 5fa5deea6..a29fc9432 100644 --- a/src/doc/reference/src/unsafe-keyword.md +++ b/src/doc/reference/src/unsafe-keyword.md @@ -27,9 +27,9 @@ this can be changed by enabling the [`unsafe_op_in_unsafe_fn`] lint. By putting operations into an unsafe block, the programmer states that they have taken care of satisfying the extra safety conditions of all operations inside that block. Unsafe blocks are the logical dual to unsafe functions: -where unsafe functions define a proof obligation that callers must uphold, unsafe blocks state that all relevant proof obligations have been discharged. +where unsafe functions define a proof obligation that callers must uphold, unsafe blocks state that all relevant proof obligations of functions or operations called inside the block have been discharged. There are many ways to discharge proof obligations; -for example, there could be run-time checks or data structure invariants that guarantee that certain properties are definitely true, or the unsafe block could be inside an `unsafe fn` and use its own proof obligations to discharge the proof obligations of its callees. +for example, there could be run-time checks or data structure invariants that guarantee that certain properties are definitely true, or the unsafe block could be inside an `unsafe fn`, in which case the block can use the proof obligations of that function to discharge the proof obligations arising inside the block. Unsafe blocks are used to wrap foreign libraries, make direct use of hardware or implement features not directly present in the language. For example, Rust provides the language features necessary to implement memory-safe concurrency in the language but the implementation of threads and message passing in the standard library uses unsafe blocks. diff --git a/src/doc/rust-by-example/README.md b/src/doc/rust-by-example/README.md index e43b044c8..2529a3fad 100644 --- a/src/doc/rust-by-example/README.md +++ b/src/doc/rust-by-example/README.md @@ -40,6 +40,7 @@ Please see the [CONTRIBUTING.md] file for more details. * [French](https://github.com/Songbird0/FR_RBE) * [Russian](https://github.com/ruRust/rust-by-example) * [Vietnamese](https://github.com/EyesCrypto-Insights/rust-by-example-vn) +* [Portuguese](https://github.com/nazarepiedady/rust-com-exemplos) ## License diff --git a/src/doc/rust-by-example/src/error/panic.md b/src/doc/rust-by-example/src/error/panic.md index 5524dbf6f..8e3f10109 100644 --- a/src/doc/rust-by-example/src/error/panic.md +++ b/src/doc/rust-by-example/src/error/panic.md @@ -15,5 +15,8 @@ fn drink(beverage: &str) { fn main() { drink("water"); drink("lemonade"); + drink("still water"); } ``` + +The first call to `drink` works. The second panics and thus the third is never called. diff --git a/src/doc/rust-by-example/src/flow_control/loop/nested.md b/src/doc/rust-by-example/src/flow_control/loop/nested.md index 01c55a559..01e8f3971 100644 --- a/src/doc/rust-by-example/src/flow_control/loop/nested.md +++ b/src/doc/rust-by-example/src/flow_control/loop/nested.md @@ -5,7 +5,7 @@ loops. In these cases, the loops must be annotated with some `'label`, and the label must be passed to the `break`/`continue` statement. ```rust,editable -#![allow(unreachable_code)] +#![allow(unreachable_code, unused_labels)] fn main() { 'outer: loop { @@ -26,4 +26,4 @@ fn main() { println!("Exited the outer loop"); } -``` \ No newline at end of file +``` diff --git a/src/doc/rust-by-example/src/hello/print/fmt.md b/src/doc/rust-by-example/src/hello/print/fmt.md index c3c78f6b1..b6f676061 100644 --- a/src/doc/rust-by-example/src/hello/print/fmt.md +++ b/src/doc/rust-by-example/src/hello/print/fmt.md @@ -78,8 +78,11 @@ RGB (0, 3, 254) 0x0003FE RGB (0, 0, 0) 0x000000 ``` -Two hints if you get stuck: +Three hints if you get stuck: +* The formula for calculating a color in the RGB color space is: +`RGB = (R*65536)+(G*256)+B , (when R is RED, G is GREEN and B is BLUE)`. +For more see [RGB color format & calculation][rgb_color]. * You [may need to list each color more than once][named_parameters]. * You can [pad with zeros to a width of 2][fmt_width] with `:0>2`. @@ -87,6 +90,7 @@ Two hints if you get stuck: [`std::fmt`][fmt] +[rgb_color]: https://www.rapidtables.com/web/color/RGB_Color.html#rgb-format [named_parameters]: https://doc.rust-lang.org/std/fmt/#named-parameters [deadbeef]: https://en.wikipedia.org/wiki/Deadbeef#Magic_debug_values [fmt]: https://doc.rust-lang.org/std/fmt/ diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md index fdf6c5050..131651e38 100644 --- a/src/doc/rustc-dev-guide/README.md +++ b/src/doc/rustc-dev-guide/README.md @@ -118,7 +118,7 @@ git submodule update --remote src/doc/rustc-dev-guide git add -u git commit -m "Update rustc-dev-guide" # Note that you can use -i, which is short for --incremental, in the following command -./x.py test --incremental src/doc/rustc-dev-guide # This is optional and should succeed anyway +./x test --incremental src/doc/rustc-dev-guide # This is optional and should succeed anyway # Open a PR in rust-lang/rust ``` diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 9f7c9cf1b..97f3503ae 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -40,12 +40,12 @@ - [Using Git](./git.md) - [Mastering @rustbot](./rustbot.md) - [Walkthrough: a typical contribution](./walkthrough.md) -- [Procedures for Breaking Changes](./bug-fix-procedure.md) -- [Implementing new features](./implementing_new_features.md) +- [Implementing new language features](./implementing_new_features.md) - [Stability attributes](./stability.md) - [Stabilizing Features](./stabilization_guide.md) - [Feature Gates](./feature-gates.md) - [Coding conventions](./conventions.md) +- [Procedures for Breaking Changes](./bug-fix-procedure.md) - [Using external repositories](./external-repos.md) - [Fuzzing](./fuzzing.md) - [Notification groups](notification-groups/about.md) @@ -109,9 +109,10 @@ - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) - [Generic arguments](./generic_arguments.md) - [Constants in the type system](./constants.md) + - [Bound vars and Parameters](./bound-vars-and-params.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - - [Early and Late Bound Parameters](./early-late-bound.md) + - [Early and Late Bound Parameter Definitions](./early-late-bound.md) - [Higher-ranked trait bounds](./traits/hrtb.md) - [Caching subtleties](./traits/caching.md) - [Specialization](./traits/specialization.md) @@ -124,11 +125,13 @@ - [Canonicalization](./solve/canonicalization.md) - [Coinduction](./solve/coinduction.md) - [Proof trees](./solve/proof-trees.md) + - [Normalization](./solve/normalization.md) - [Type checking](./type-checking.md) - [Method Lookup](./method-lookup.md) - [Variance](./variance.md) - [Opaque Types](./opaque-types-type-alias-impl-trait.md) - [Inference details](./opaque-types-impl-trait-inference.md) + - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) - [Pattern and Exhaustiveness Checking](./pat-exhaustive-checking.md) - [MIR dataflow](./mir/dataflow.md) - [Drop elaboration](./mir/drop-elaboration.md) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 944ebf5a8..f43f86e5f 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -66,7 +66,6 @@ You might also find the following sites useful: of the team procedures, active working groups, and the team calendar. - [std-dev-guide] -- a similar guide for developing the standard library. - [The t-compiler zulip][z] -- [The Forge](https://forge.rust-lang.org/) has more documentation about various procedures. - `#contribute` and `#wg-rustup` on [Discord](https://discord.gg/rust-lang). - The [Rust Internals forum][rif], a place to ask questions and discuss Rust's internals diff --git a/src/doc/rustc-dev-guide/src/appendix/background.md b/src/doc/rustc-dev-guide/src/appendix/background.md index 0b83b010f..05d01be0f 100644 --- a/src/doc/rustc-dev-guide/src/appendix/background.md +++ b/src/doc/rustc-dev-guide/src/appendix/background.md @@ -300,7 +300,7 @@ does not. > Thanks to `mem`, `scottmcm`, and `Levi` on the official Discord for the > recommendations, and to `tinaun` for posting a link to a [twitter thread from -> Graydon Hoare](https://twitter.com/graydon_pub/status/1039615569132118016) +> Graydon Hoare](https://web.archive.org/web/20181230012554/https://twitter.com/graydon_pub/status/1039615569132118016) > which had some more recommendations! > > Other sources: https://gcc.gnu.org/wiki/ListOfCompilerBooks diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index a02011149..08af10f89 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -90,16 +90,16 @@ so let's go through each in detail. `src/llvm-project` to ensure submodule updates aren't reverted. Some commands you should execute are: - * `./x.py build src/llvm` - test that LLVM still builds - * `./x.py build src/tools/lld` - same for LLD - * `./x.py build` - build the rest of rustc + * `./x build src/llvm` - test that LLVM still builds + * `./x build src/tools/lld` - same for LLD + * `./x build` - build the rest of rustc You'll likely need to update [`llvm-wrapper/*.cpp`][`llvm-wrapper`] to compile with updated LLVM bindings. Note that you should use `#ifdef` and such to ensure that the bindings still compile on older LLVM versions. - Note that `profile = "compiler"` and other defaults set by `./x.py setup` + Note that `profile = "compiler"` and other defaults set by `./x setup` download LLVM from CI instead of building it from source. You should disable this temporarily to make sure your changes are being used. This is done by having the following setting in `config.toml`: diff --git a/src/doc/rustc-dev-guide/src/bound-vars-and-params.md b/src/doc/rustc-dev-guide/src/bound-vars-and-params.md new file mode 100644 index 000000000..50d5cefb1 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/bound-vars-and-params.md @@ -0,0 +1,59 @@ +# Bound vars and parameters + +## Early-bound parameters + +Early-bound parameters in rustc are identified by an index, stored in the +[`ParamTy`] struct for types or the [`EarlyBoundRegion`] struct for lifetimes. +The index counts from the outermost declaration in scope. This means that as you +add more binders inside, the index doesn't change. + +For example, + +```rust,ignore +trait Foo { + type Bar = (Self, T, U); +} +``` + +Here, the type `(Self, T, U)` would be `($0, $1, $2)`, where `$N` means a +[`ParamTy`] with the index of `N`. + +In rustc, the [`Generics`] structure carries this information. So the +[`Generics`] for `Bar` above would be just like for `U` and would indicate the +'parent' generics of `Foo`, which declares `Self` and `T`. You can read more +in [this chapter](./generics.md). + +[`ParamTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamTy.html +[`EarlyBoundRegion`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.EarlyBoundRegion.html +[`Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html + +## Late-bound parameters + +Late-bound parameters in `rustc` are handled differently. We indicate their +presence by a [`Binder`] type. The [`Binder`] doesn't know how many variables +there are at that binding level. This can only be determined by walking the +type itself and collecting them. So a type like `for<'a, 'b> ('a, 'b)` would be +`for (^0.a, ^0.b)`. Here, we just write `for` because we don't know the names +of the things bound within. + +Moreover, a reference to a late-bound lifetime is written `^0.a`: + +- The `0` is the index; it identifies that this lifetime is bound in the + innermost binder (the `for`). +- The `a` is the "name"; late-bound lifetimes in rustc are identified by a + "name" -- the [`BoundRegionKind`] enum. This enum can contain a + [`DefId`][defid] or it might have various "anonymous" numbered names. The + latter arise from types like `fn(&u32, &u32)`, which are equivalent to + something like `for<'a, 'b> fn(&'a u32, &'b u32)`, but the names of those + lifetimes must be generated. + +This setup of not knowing the full set of variables at a binding level has some +advantages and some disadvantages. The disadvantage is that you must walk the +type to find out what is bound at the given level and so forth. The advantage +is primarily that, when constructing types from Rust syntax, if we encounter +anonymous regions like in `fn(&u32)`, we just create a fresh index and don't have +to update the binder. + +[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html +[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html +[defid]: ./hir.html#identifiers-in-the-hir diff --git a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md index e69ce48f9..388e39b93 100644 --- a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md +++ b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md @@ -304,7 +304,7 @@ self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS, We want to convert this into an error. In some cases, there may be an existing error for this scenario. In others, we will need to allocate a fresh diagnostic code. [Instructions for allocating a fresh diagnostic -code can be found here.](./diagnostics/diagnostic-codes.md) You may want +code can be found here.](./diagnostics/error-codes.md) You may want to mention in the extended description that the compiler behavior changed on this point, and include a reference to the tracking issue for the change. @@ -325,7 +325,7 @@ general, if the test used to have `#[deny(overlapping_inherent_impls)]`, that can just be removed. ``` -./x.py test +./x test ``` #### All done! diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md index d53896f81..936c75f36 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md @@ -96,7 +96,7 @@ However, it takes a very long time to build because one must first build the new compiler with an older compiler and then use that to build the new compiler with itself. For development, you usually only want the `stage1` compiler, -which you can build with `./x.py build library`. +which you can build with `./x build library`. See [Building the compiler](./how-to-build-and-run.html#building-the-compiler). ### Stage 3: the same-result test @@ -107,7 +107,7 @@ to be identical to before, unless something has broken. ### Building the stages -`x.py` tries to be helpful and pick the stage you most likely meant for each subcommand. +`x` tries to be helpful and pick the stage you most likely meant for each subcommand. These defaults are as follows: - `check`: `--stage 0` @@ -152,7 +152,7 @@ bootstrapping the compiler. This is a detailed look into the separate bootstrap stages. -The convention `x.py` uses is that: +The convention `x` uses is that: - A `--stage N` flag means to run the stage N compiler (`stageN/rustc`). - A "stage N artifact" is a build artifact that is _produced_ by the stage N compiler. @@ -161,7 +161,7 @@ The convention `x.py` uses is that: #### Build artifacts -Anything you can build with `x.py` is a _build artifact_. +Anything you can build with `x` is a _build artifact_. Build artifacts include, but are not limited to: - binaries, like `stage0-rustc/rustc-main` @@ -173,27 +173,27 @@ Build artifacts include, but are not limited to: #### Examples -- `./x.py build --stage 0` means to build with the beta `rustc`. -- `./x.py doc --stage 0` means to document using the beta `rustdoc`. -- `./x.py test --stage 0 library/std` means to run tests on the standard library - without building `rustc` from source ('build with stage 0, then test the +- `./x build --stage 0` means to build with the beta `rustc`. +- `./x doc --stage 0` means to document using the beta `rustdoc`. +- `./x test --stage 0 library/std` means to run tests on the standard library + without building `rustc` from source ('build with stage 0, then test the artifacts'). If you're working on the standard library, this is normally the test command you want. -- `./x.py test tests/ui` means to build the stage 1 compiler and run +- `./x test tests/ui` means to build the stage 1 compiler and run `compiletest` on it. If you're working on the compiler, this is normally the test command you want. #### Examples of what *not* to do -- `./x.py test --stage 0 tests/ui` is not useful: it runs tests on the +- `./x test --stage 0 tests/ui` is not useful: it runs tests on the _beta_ compiler and doesn't build `rustc` from source. Use `test tests/ui` instead, which builds stage 1 from source. -- `./x.py test --stage 0 compiler/rustc` builds the compiler but runs no tests: +- `./x test --stage 0 compiler/rustc` builds the compiler but runs no tests: it's running `cargo test -p rustc`, but cargo doesn't understand Rust's tests. You shouldn't need to use this, use `test` instead (without arguments). -- `./x.py build --stage 0 compiler/rustc` builds the compiler, but does not build - libstd or even libcore. Most of the time, you'll want `./x.py build - library` instead, which allows compiling programs without needing to define +- `./x build --stage 0 compiler/rustc` builds the compiler, but does not build + libstd or even libcore. Most of the time, you'll want `./x build +library` instead, which allows compiling programs without needing to define lang items. ### Building vs. running @@ -243,7 +243,7 @@ artifacts into the appropriate place, skipping the cargo invocation. For instance, you might want to build an ARM version of rustc using an x86 machine. Building stage2 `std` is different when you are cross-compiling. -This is because `x.py` uses a trick: if `HOST` and `TARGET` are the same, +This is because `x` uses a trick: if `HOST` and `TARGET` are the same, it will reuse stage1 `std` for stage2! This is sound because stage1 `std` was compiled with the stage1 compiler, i.e. a compiler using the source code you currently have checked out. So it should be identical (and therefore ABI-compatible) @@ -362,7 +362,7 @@ You can find more discussion about sysroots in: ## Passing flags to commands invoked by `bootstrap` -`x.py` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping. +`x` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping. The `RUSTFLAGS_BOOTSTRAP` environment variable is passed as `RUSTFLAGS` to the bootstrap stage (stage0), and `RUSTFLAGS_NOT_BOOTSTRAP` is passed when building artifacts for later stages. `RUSTFLAGS` will work, but also affects the build of `bootstrap` itself, so it will be rare to want @@ -395,7 +395,7 @@ If `./stageN/bin/rustc` gives an error about environment variables, that usually means something is quite wrong -- or you're trying to compile e.g. `rustc` or `std` or something that depends on environment variables. In the unlikely case that you actually need to invoke rustc in such a situation, -you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x.py` command. +you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x` command. Finally, bootstrap makes use of the [cc-rs crate] which has [its own method][env-vars] of configuring C compilers and C flags via environment @@ -408,7 +408,7 @@ variables. In this part, we will investigate the build command's stdout in an action (similar, but more detailed and complete documentation compare to topic above). -When you execute `x.py build --dry-run` command, the build output will be something +When you execute `x build --dry-run` command, the build output will be something like the following: ```text diff --git a/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md b/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md index 4ec3f958a..df3037469 100644 --- a/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md +++ b/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md @@ -3,22 +3,22 @@ You might want to build and package up the compiler for distribution. You’ll want to run this command to do it: - ```bash - ./x.py dist - ``` +```bash +./x dist +``` # Install distribution artifacts If you’ve built a distribution artifact you might want to install it and test that it works on your target system. You’ll want to run this command: - ```bash - ./x.py install - ``` +```bash +./x install +``` Note: If you are testing out a modification to a compiler, you might want to use it to compile some project. - Usually, you do not want to use `./x.py install` for testing. + Usually, you do not want to use `./x install` for testing. Rather, you should create a toolchain as discussed in [here][create-rustup-toolchain]. diff --git a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md index 4e72bf994..948571ce8 100644 --- a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md +++ b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md @@ -10,13 +10,13 @@ like the standard library (std) or the compiler (rustc). as rustdoc is under active development: ```bash - ./x.py doc + ./x doc ``` If you want to be sure the documentation looks the same as on CI: ```bash - ./x.py doc --stage 1 + ./x doc --stage 1 ``` This ensures that (current) rustdoc gets built, @@ -26,9 +26,9 @@ like the standard library (std) or the compiler (rustc). you can build just the documentation you want: ```bash - ./x.py doc src/doc/book - ./x.py doc src/doc/nomicon - ./x.py doc compiler library + ./x doc src/doc/book + ./x doc src/doc/nomicon + ./x doc compiler library ``` See [the nightly docs index page](https://doc.rust-lang.org/nightly/) for a full list of books. @@ -36,7 +36,7 @@ like the standard library (std) or the compiler (rustc). - Document internal rustc items Compiler documentation is not built by default. - To create it by default with `x.py doc`, modify `config.toml`: + To create it by default with `x doc`, modify `config.toml`: ```toml [build] diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 6444aab5f..0865f1955 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 @@ -5,9 +5,6 @@ The compiler is built using a tool called `x.py`. You will need to have Python installed to run it. -For instructions on how to install Python and other prerequisites, -see [the `rust-lang/rust` README][readme]. - ## Get the source code The main repository is [`rust-lang/rust`][repo]. This contains the compiler, @@ -15,7 +12,6 @@ the standard library (including `core`, `alloc`, `test`, `proc_macro`, etc), and a bunch of tools (e.g. `rustdoc`, the bootstrapping infrastructure, etc). [repo]: https://github.com/rust-lang/rust -[readme]: https://github.com/rust-lang/rust#building-on-a-unix-like-system The very first step to work on `rustc` is to clone the repository: @@ -57,7 +53,75 @@ if you want to learn more about `x.py`, [read this chapter][bootstrap]. [bootstrap]: ./bootstrapping.md -### Running `x.py` slightly more conveniently +Also, using `x` rather than `x.py` is recommended as: + +> `./x` is the most likely to work on every system (on Unix it runs the shell script +> that does python version detection, on Windows it will probably run the +> powershell script - certainly less likely to break than `./x.py` which often just +> opens the file in an editor).[^1] + +(You can find the platform related scripts around the `x.py`, like `x.ps1`) + +Notice that this is not absolute, for instance, using Nushell in VSCode on Win10, +typing `x` or `./x` still open the `x.py` in editor rather invoke the program :) + +In the rest of documents, we use `x` to represent the straightly usage of `x.py`, which +means the following command: + +```bash +./x check +``` + +could be replaced by: + +```bash +./x.py check +``` + +### Running `x.py` + +The `x.py` command can be run directly on most Unix systems in the following format: + +```sh +./x [flags] +``` + +This is how the documentation and examples assume you are running `x.py`. +Some alternative ways are: + +```sh +# On a Unix shell if you don't have the necessary `python3` command +./x [flags] + +# In Windows Powershell (if powershell is configured to run scripts) +./x [flags] +./x.ps1 [flags] + +# On the Windows Command Prompt (if .py files are configured to run Python) +x.py [flags] + +# You can also run Python yourself, e.g.: +python x.py [flags] +``` + +On Windows, the Powershell commands may give you an error that looks like this: +``` +PS C:\Users\vboxuser\rust> ./x +./x : File C:\Users\vboxuser\rust\x.ps1 cannot be loaded because running scripts is disabled on this system. For more +information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170. +At line:1 char:1 ++ ./x ++ ~~~ + + CategoryInfo : SecurityError: (:) [], PSSecurityException + + FullyQualifiedErrorId : UnauthorizedAccess +``` + +You can avoid this error by allowing powershell to run local scripts: +``` +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +``` + +#### Running `x.py` slightly more conveniently There is a binary that wraps `x.py` called `x` in `src/tools/x`. All it does is run `x.py`, but it can be installed system-wide and run from any subdirectory @@ -65,9 +129,14 @@ of a checkout. It also looks up the appropriate version of `python` to use. You can install it with `cargo install --path src/tools/x`. +To clarify that this is another global installed binary util, which is +similar to the one declared in section [What is `x.py`](#what-is-xpy), but +it works as an independent process to execute the `x.py` rather than calling the +shell to run the platform related scripts. + ## Create a `config.toml` -To start, run `./x.py setup` and select the `compiler` defaults. This will do some initialization +To start, run `./x setup` and select the `compiler` defaults. This will do some initialization and create a `config.toml` for you with reasonable defaults. If you use a different default (which you'll likely want to do if you want to contribute to an area of rust other than the compiler, such as rustdoc), make sure to read information about that default (located in `src/bootstrap/defaults`) @@ -77,35 +146,35 @@ Alternatively, you can write `config.toml` by hand. See `config.example.toml` fo settings and explanations of them. See `src/bootstrap/defaults` for common settings to change. If you have already built `rustc` and you change settings related to LLVM, then you may have to -execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x.py +execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x clean` will not cause a rebuild of LLVM. -## Common `x.py` commands +## Common `x` commands -Here are the basic invocations of the `x.py` commands most commonly used when +Here are the basic invocations of the `x` commands most commonly used when working on `rustc`, `std`, `rustdoc`, and other tools. -| Command | When to use it | -| --- | --- | -| `./x.py check` | Quick check to see if most things compile; [rust-analyzer can run this automatically for you][rust-analyzer] | -| `./x.py build` | Builds `rustc`, `std`, and `rustdoc` | -| `./x.py test` | Runs all tests | -| `./x.py fmt` | Formats all code | +| Command | When to use it | +| ----------- | ------------------------------------------------------------------------------------------------------------ | +| `./x check` | Quick check to see if most things compile; [rust-analyzer can run this automatically for you][rust-analyzer] | +| `./x build` | Builds `rustc`, `std`, and `rustdoc` | +| `./x test` | Runs all tests | +| `./x fmt` | Formats all code | As written, these commands are reasonable starting points. However, there are additional options and arguments for each of them that are worth learning for -serious development work. In particular, `./x.py build` and `./x.py test` +serious development work. In particular, `./x build` and `./x test` provide many ways to compile or test a subset of the code, which can save a lot of time. -Also, note that `x.py` supports all kinds of path suffixes for `compiler`, `library`, -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`. +Also, note that `x` supports all kinds of path suffixes for `compiler`, `library`, +and `src/tools` directories. So, you can simply run `x test tidy` instead of +`x test src/tools/tidy`. Or, `x build std` instead of `x build library/std`. [rust-analyzer]: suggested.html#configuring-rust-analyzer-for-rustc -See the chapters on [building](how-to-build-and-run), -[testing](../tests/intro), and [rustdoc](../rustdoc) for more details. +See the chapters on +[testing](../tests/running.md) and [rustdoc](../rustdoc.md) for more details. ### Building the compiler @@ -113,11 +182,11 @@ Note that building will require a relatively large amount of storage space. You may want to have upwards of 10 or 15 gigabytes available to build the compiler. Once you've created a `config.toml`, you are now ready to run -`x.py`. There are a lot of options here, but let's start with what is +`x`. There are a lot of options here, but let's start with what is probably the best "go to" command for building a local compiler: ```bash -./x.py build library +./x build library ``` This may *look* like it only builds the standard library, but that is not the case. @@ -140,10 +209,10 @@ see [the section on avoiding rebuilds for std][keep-stage]. Sometimes you don't need a full build. When doing some kind of "type-based refactoring", like renaming a method, or changing the -signature of some function, you can use `./x.py check` instead for a much faster build. +signature of some function, you can use `./x check` instead for a much faster build. Note that this whole command just gives you a subset of the full `rustc` -build. The **full** `rustc` build (what you get with `./x.py build +build. The **full** `rustc` build (what you get with `./x build --stage 2 compiler/rustc`) has quite a few more steps: - Build `rustc` with the stage1 compiler. @@ -160,10 +229,10 @@ the compiler unless you are planning to use a recently added nightly feature. Instead, you can just build using the bootstrap compiler. ```bash -./x.py build --stage 0 library +./x build --stage 0 library ``` -If you choose the `library` profile when running `x.py setup`, you can omit `--stage 0` (it's the +If you choose the `library` profile when running `x setup`, you can omit `--stage 0` (it's the default). ## Creating a rustup toolchain @@ -198,7 +267,7 @@ LLVM version: 11.0 ``` The rustup toolchain points to the specified toolchain compiled in your `build` directory, -so the rustup toolchain will be updated whenever `x.py build` or `x.py test` are run for +so the rustup toolchain will be updated whenever `x build` or `x test` are run for that toolchain/stage. **Note:** the toolchain we've built does not include `cargo`. In this case, `rustup` will @@ -213,25 +282,25 @@ custom toolchain for a project (e.g. via `rustup override set stage1`) you may want to build this component: ```bash -./x.py build proc-macro-srv-cli +./x build proc-macro-srv-cli ``` ## Building targets for cross-compilation To produce a compiler that can cross-compile for other targets, -pass any number of `target` flags to `x.py build`. +pass any number of `target` flags to `x build`. For example, if your host platform is `x86_64-unknown-linux-gnu` and your cross-compilation target is `wasm32-wasi`, you can build with: ```bash -./x.py build --target x86_64-unknown-linux-gnu --target wasm32-wasi +./x build --target x86_64-unknown-linux-gnu --target wasm32-wasi ``` Note that if you want the resulting compiler to be able to build crates that involve proc macros or build scripts, you must be sure to explicitly build target support for the host platform (in this case, `x86_64-unknown-linux-gnu`). -If you want to always build for other targets without needing to pass flags to `x.py build`, +If you want to always build for other targets without needing to pass flags to `x build`, you can configure this in the `[build]` section of your `config.toml` like so: ```toml @@ -260,24 +329,24 @@ then once you have built your compiler you will be able to use it to cross-compi cargo +stage1 build --target wasm32-wasi ``` -## Other `x.py` commands +## Other `x` commands -Here are a few other useful `x.py` commands. We'll cover some of them in detail +Here are a few other useful `x` commands. We'll cover some of them in detail in other sections: - Building things: - - `./x.py build` – builds everything using the stage 1 compiler, + - `./x build` – builds everything using the stage 1 compiler, not just up to `std` - - `./x.py build --stage 2` – builds everything with the stage 2 compiler including + - `./x build --stage 2` – builds everything with the stage 2 compiler including `rustdoc` - Running tests (see the [section on running tests](../tests/running.html) for more details): - - `./x.py test library/std` – runs the unit tests and integration tests from `std` - - `./x.py test tests/ui` – runs the `ui` test suite - - `./x.py test tests/ui/const-generics` - runs all the tests in - the `const-generics/` subdirectory of the `ui` test suite - - `./x.py test tests/ui/const-generics/const-types.rs` - runs - the single test `const-types.rs` from the `ui` test suite + - `./x test library/std` – runs the unit tests and integration tests from `std` + - `./x test tests/ui` – runs the `ui` test suite + - `./x test tests/ui/const-generics` - runs all the tests in + the `const-generics/` subdirectory of the `ui` test suite + - `./x test tests/ui/const-generics/const-types.rs` - runs + the single test `const-types.rs` from the `ui` test suite ### Cleaning out build directories @@ -287,8 +356,10 @@ you should file a bug as to what is going wrong. If you do need to clean everything up then you only need to run one command! ```bash -./x.py clean +./x clean ``` `rm -rf build` works too, but then you have to rebuild LLVM, which can take a long time even on fast computers. + +[^1]: issue[#1707](https://github.com/rust-lang/rustc-dev-guide/issues/1707) diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index 629445be6..83973f2c9 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -10,7 +10,7 @@ relevant to your desired goal. For very new targets, you may need to use a different fork of LLVM than what is currently shipped with Rust. In that case, navigate to -the `src/llvm-project` git submodule (you might need to run `./x.py +the `src/llvm-project` git submodule (you might need to run `./x check` at least once so the submodule is updated), check out the appropriate commit for your fork, then commit that new submodule reference in the main Rust repository. @@ -135,7 +135,7 @@ cross-compile `rustc`: ``` DESTDIR=/path/to/install/in \ -./x.py install -i --stage 1 --host aarch64-apple-darwin.json --target aarch64-apple-darwin \ +./x install -i --stage 1 --host aarch64-apple-darwin.json --target aarch64-apple-darwin \ compiler/rustc library/std ``` diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index 3dc2ea934..c511c7c81 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -20,7 +20,7 @@ recommend trying to build on a Raspberry Pi! We recommend the following. * 2+ cores. Having more cores really helps. 10 or 20 or more is not too many! Beefier machines will lead to much faster builds. If your machine is not very -powerful, a common strategy is to only use `./x.py check` on your local machine +powerful, a common strategy is to only use `./x check` on your local machine and let the CI build test your changes when you push to a PR branch. Building the compiler takes more than half an hour on my moderately powerful diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 9dcc795f2..0da3f60cf 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -10,14 +10,14 @@ to make your life easier. CI will automatically fail your build if it doesn't pass `tidy`, our internal tool for ensuring code quality. If you'd like, you can install a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) -that will automatically run `./x.py test tidy` on each push, to ensure -your code is up to par. If the hook fails then run `./x.py test tidy --bless` +that will automatically run `./x test tidy` on each push, to ensure +your code is up to par. If the hook fails then run `./x test tidy --bless` and commit the changes. If you decide later that the pre-push behavior is undesirable, you can delete the `pre-push` file in `.git/hooks`. A prebuilt git hook lives at [`src/etc/pre-push.sh`](https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh) which can be copied into your `.git/hooks` folder as `pre-push` (without the `.sh` extension!). -You can also install the hook as a step of running `./x.py setup`! +You can also install the hook as a step of running `./x setup`! ## Configuring `rust-analyzer` for `rustc` @@ -26,22 +26,19 @@ You can also install the hook as a step of running `./x.py setup`! `rust-analyzer` can help you check and format your code whenever you save a file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands, but you can override these commands to use more adapted versions -of these tools when hacking on `rustc`. For example, `x.py setup vscode` will prompt +of these tools when hacking on `rustc`. For example, `x setup vscode` will prompt you to create a `.vscode/settings.json` file which will configure Visual Studio code. -This will ask `rust-analyzer` to use `./x.py check` to check the sources, and the +This will ask `rust-analyzer` to use `./x check` to check the sources, and the stage 0 rustfmt to format them. The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_settings.json`]. -If you have enough free disk space and you would like to be able to run `x.py` commands while +If you have enough free disk space and you would like to be able to run `x` commands while rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the -`overrideCommand` to avoid x.py locking. - -If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a -`.vim/coc-settings.json` and copy the settings from [`src/etc/rust_analyzer_settings.json`]. +`overrideCommand` to avoid x locking. [`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json -If running `./x.py check` on save is inconvenient, in VS Code you can use a [Build +If running `./x check` on save is inconvenient, in VS Code you can use a [Build Task] instead: ```JSON @@ -50,8 +47,8 @@ Task] instead: "version": "2.0.0", "tasks": [ { - "label": "./x.py check", - "command": "./x.py check", + "label": "./x check", + "command": "./x check", "type": "shell", "problemMatcher": "$rustc", "presentation": { "clear": true }, @@ -73,13 +70,13 @@ Rust-Analyzer to already be configured with Neovim. Steps for this can be [found here](https://rust-analyzer.github.io/manual.html#nvim-lsp). 1. First install the plugin. This can be done by following the steps in the README. -2. Run `x.py setup`, which will have a prompt for it to create a `.vscode/settings.json` file. -`neoconf` is able to read and update Rust-Analyzer settings automatically when the project is -opened when this file is detected. +2. Run `x setup`, which will have a prompt for it to create a `.vscode/settings.json` file. + `neoconf` is able to read and update Rust-Analyzer settings automatically when the project is + opened when this file is detected. If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a `.vim/coc-settings.json` and copy the settings from -[this file](https://github.com/rust-lang/rust/blob/master/src/etc/vscode_settings.json). +[this file](https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json). Another way is without a plugin, and creating your own logic in your configuration. To do this you must translate the JSON to Lua yourself. The translation is 1:1 and fairly straight-forward. It @@ -94,11 +91,11 @@ follow the same instructions as above. ## Check, check, and check again -When doing simple refactorings, it can be useful to run `./x.py check` +When doing simple refactorings, it can be useful to run `./x check` continuously. If you set up `rust-analyzer` as described above, this will be done for you every time you save a file. Here you are just checking that the compiler can **build**, but often that is all you need (e.g., when renaming a -method). You can then run `./x.py build` when you actually need to +method). You can then run `./x build` when you actually need to run tests. In fact, it is sometimes useful to put off tests even when you are not @@ -141,11 +138,11 @@ directories you have [setup a worktree for]. You may need to use the pinned nightly version from `src/stage0.json`, but often the normal `nightly` channel will work. -**Note** see [the section on vscode] for how to configure it with this real rustfmt `x.py` uses, +**Note** see [the section on vscode] for how to configure it with this real rustfmt `x` uses, and [the section on rustup] for how to setup `rustup` toolchain for your bootstrapped compiler **Note** This does _not_ allow you to build `rustc` with cargo directly. You -still have to use `x.py` to work on the compiler or standard library, this just +still have to use `x` to work on the compiler or standard library, this just lets you use `cargo fmt`. [installing a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust @@ -166,13 +163,13 @@ don't work (but that is easily detected and fixed). The sequence of commands you want is as follows: -- Initial build: `./x.py build library` +- Initial build: `./x build library` - As [documented previously], this will build a functional stage1 compiler as part of running all stage0 commands (which include building a `std` compatible with the stage1 compiler) as well as the first few steps of the "stage 1 actions" up to "stage1 (sysroot stage1) builds std". -- Subsequent builds: `./x.py build library --keep-stage 1` +- Subsequent builds: `./x build library --keep-stage 1` - Note that we added the `--keep-stage 1` flag here [documented previously]: ./how-to-build-and-run.md#building-the-compiler @@ -194,8 +191,8 @@ rebuild. That ought to fix the problem. You can also use `--keep-stage 1` when running tests. Something like this: -- Initial test run: `./x.py test tests/ui` -- Subsequent test run: `./x.py test tests/ui --keep-stage 1` +- Initial test run: `./x test tests/ui` +- Subsequent test run: `./x test tests/ui --keep-stage 1` ## Using incremental compilation @@ -203,7 +200,7 @@ You can further enable the `--incremental` flag to save additional time in subsequent rebuilds: ```bash -./x.py test tests/ui --incremental --test-args issue-1234 +./x test tests/ui --incremental --test-args issue-1234 ``` If you don't want to include the flag with every command, you can @@ -348,4 +345,4 @@ Zsh support will also be included once issues with [`clap_complete`](https://cra You can use `source ./src/etc/completions/x.py.` 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 +Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion. diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md index e356f415d..786c831ee 100644 --- a/src/doc/rustc-dev-guide/src/closure.md +++ b/src/doc/rustc-dev-guide/src/closure.md @@ -115,10 +115,10 @@ Let's start with defining a term that we will be using quite a bit in the rest o *upvar*. An **upvar** is a variable that is local to the function where the closure is defined. So, in the above examples, **x** will be an upvar to the closure. They are also sometimes referred to as the *free variables* meaning they are not bound to the context of the closure. -[`compiler/rustc_middle/src/ty/query/mod.rs`][upvars] defines a query called *upvars_mentioned* +[`compiler/rustc_passes/src/upvars.rs`][upvars] defines a query called *upvars_mentioned* for this purpose. -[upvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_query_impl/queries/struct.upvars_mentioned.html +[upvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_passes/upvars/index.html Other than lazy invocation, one other thing that distinguishes a closure from a normal function is that it can use the upvars. It borrows these upvars from its surrounding diff --git a/src/doc/rustc-dev-guide/src/compiler-src.md b/src/doc/rustc-dev-guide/src/compiler-src.md index 9c7d0bb2e..6090c6787 100644 --- a/src/doc/rustc-dev-guide/src/compiler-src.md +++ b/src/doc/rustc-dev-guide/src/compiler-src.md @@ -195,11 +195,8 @@ These include: run a lot of tests on a lot of platforms. - [`src/doc`]: Various documentation, including submodules for a few books. - [`src/etc`]: Miscellaneous utilities. -- [`src/tools/rustc-workspace-hack`], and others: Various workarounds to make - cargo work with bootstrapping. - And more... [`src/ci`]: https://github.com/rust-lang/rust/tree/master/src/ci [`src/doc`]: https://github.com/rust-lang/rust/tree/master/src/doc [`src/etc`]: https://github.com/rust-lang/rust/tree/master/src/etc -[`src/tools/rustc-workspace-hack`]: https://github.com/rust-lang/rust/tree/master/src/tools/rustc-workspace-hack diff --git a/src/doc/rustc-dev-guide/src/constants.md b/src/doc/rustc-dev-guide/src/constants.md index 91d21bd32..56d01cc79 100644 --- a/src/doc/rustc-dev-guide/src/constants.md +++ b/src/doc/rustc-dev-guide/src/constants.md @@ -77,6 +77,6 @@ the constant doesn't use them in any way. This can cause [some interesting errors][pcg-unused-substs] and breaks some already stable code. [`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html -[`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.ConstKind.html +[`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.ConstKind.html [`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html [pcg-unused-substs]: https://github.com/rust-lang/project-const-generics/issues/33 diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index d6037c7f1..d6b9fc84d 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -2,7 +2,7 @@ -## Bug Reports +## Bug reports While bugs are unfortunate, they're a reality in software. We can't fix what we don't know about, so please report liberally. If you're not sure if something @@ -16,8 +16,7 @@ please follow our [instructions for reporting security vulnerabilities][vuln]**. If you're using the nightly channel, please check if the bug exists in the latest toolchain before filing your bug. It might be fixed already. -If you have the chance, before reporting a bug, please [search existing -issues](https://github.com/rust-lang/rust/issues?q=is%3Aissue), +If you have the chance, before reporting a bug, please [search existing issues], as it's possible that someone else has already reported your error. This doesn't always work, and sometimes it's hard to know what to search for, so consider this extra credit. We won't mind if you accidentally file a duplicate report. @@ -33,22 +32,22 @@ Opening an issue is as easy as following [this link](https://github.com/rust-lang/rust/issues/new/choose) and filling out the fields in the appropriate provided template. -## Bug Fixes or "Normal" code changes +## Bug fixes or "normal" code changes -For most PRs, no special procedures are needed. You can just [open a PR][prs], and it +For most PRs, no special procedures are needed. You can just [open a PR], and it will be reviewed, approved, and merged. This includes most bug fixes, refactorings, and other user-invisible changes. The next few sections talk about exceptions to this rule. -Also, note that it is perfectly acceptable to open WIP PRs or GitHub [Draft -PRs][draft]. Some people prefer to do this so they can get feedback along the +Also, note that it is perfectly acceptable to open WIP PRs or GitHub [Draft PRs]. +Some people prefer to do this so they can get feedback along the way or share their code with a collaborator. Others do this so they can utilize -the CI to build and test their PR (e.g. if you are developing on a laptop). +the CI to build and test their PR (e.g. when developing on a slow machine). -[prs]: #pull-requests -[draft]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ +[open a PR]: #pull-requests +[Draft PRs]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ -## New Features +## New features Rust has strong backwards-compatibility guarantees. Thus, new features can't just be implemented directly in stable Rust. Instead, we have 3 release @@ -63,13 +62,11 @@ channels: stable, beta, and nightly. See [this chapter on implementing new features](./implementing_new_features.md) for more information. -### Breaking Changes +### Breaking changes -Breaking changes have a [dedicated section][breaking-changes] in the dev-guide. +Breaking changes have a [dedicated section][Breaking Changes] in the dev-guide. -[breaking-changes]: ./bug-fix-procedure.md - -### Major Changes +### Major changes The compiler team has a special process for large changes, whether or not they cause breakage. This process is called a Major Change Proposal (MCP). MCP is a @@ -80,12 +77,12 @@ Example of things that might require MCPs include major refactorings, changes to important types, or important changes to how the compiler does something, or smaller user-facing changes. -**When in doubt, ask on [zulip][z]. It would be a shame to put a lot of work +**When in doubt, ask on [zulip]. It would be a shame to put a lot of work into a PR that ends up not getting merged!** [See this document][mcpinfo] for more info on MCPs. [mcpinfo]: https://forge.rust-lang.org/compiler/mcp.html -[z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler +[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler ### Performance @@ -95,19 +92,19 @@ few years into [gradually improving it][perfdash]. [perfdash]: https://perf.rust-lang.org/dashboard.html If you suspect that your change may cause a performance regression (or -improvement), you can request a "perf run" (your reviewer may also request one +improvement), you can request a "perf run" (and your reviewer may also request one before approving). This is yet another bot that will compile a collection of benchmarks on a compiler with your changes. The numbers are reported [here][perf], and you can see a comparison of your changes against the latest master. -For an introduction to the performance of Rust code in general -which would also be useful in rustc development, see [The Rust Performance Book]. +> For an introduction to the performance of Rust code in general +> which would also be useful in rustc development, see [The Rust Performance Book]. [perf]: https://perf.rust-lang.org [The Rust Performance Book]: https://nnethercote.github.io/perf-book/ -## Pull Requests +## Pull requests Pull requests (or PRs for short) are the primary mechanism we use to change Rust. GitHub itself has some [great documentation][about-pull-requests] on using the @@ -135,15 +132,15 @@ to the end of the pull request description, and [@rustbot] will assign them instead of a random person. This is entirely optional. You can also assign a random reviewer from a specific team by writing `r? rust-lang/groupname`. -So if you were making a diagnostics change, then you could get a reviewer from the diagnostics -team by adding: +As an example, +if you were making a diagnostics change, +then you could get a reviewer from the diagnostics team by adding: r? rust-lang/diagnostics -For a full list of possible `groupname` check the `adhoc_groups` section at the -[triagebot.toml config file](https://github.com/rust-lang/rust/blob/master/triagebot.toml) -or the list of teams in the [rust-lang teams -database](https://github.com/rust-lang/team/tree/master/teams). +For a full list of possible `groupname`s, +check the `adhoc_groups` section at the [triagebot.toml config file], +or the list of teams in the [rust-lang teams database]. ### Waiting for reviews @@ -175,22 +172,21 @@ Zulip ([#t-release/triage]). They have knowledge of when to ping, who might be on vacation, etc. The reviewer may request some changes using the GitHub code review interface. -They may also request special procedures (such as a [crater] run; [see -below][break]) for some PRs. +They may also request special procedures for some PRs. +See [Crater] and [Breaking Changes] chapters for some examples of such procedures. [r?]: https://github.com/rust-lang/rust/pull/78133#issuecomment-712692371 [#t-release/triage]: https://rust-lang.zulipchat.com/#narrow/stream/242269-t-release.2Ftriage -[break]: #breaking-changes +[Crater]: tests/crater.md + ### CI -In addition to being reviewed by a human, pull requests are automatically tested +In addition to being reviewed by a human, pull requests are automatically tested, thanks to continuous integration (CI). Basically, every time you open and update a pull request, CI builds the compiler and tests it against the -[compiler test suite][rctd], and also performs other tests such as checking that +[compiler test suite], and also performs other tests such as checking that your pull request is in compliance with Rust's style guidelines. -[rctd]: tests/intro.md - Running continuous integration tests allows PR authors to catch mistakes early without going through a first review cycle, and also helps reviewers stay aware of the status of a particular pull request. @@ -198,7 +194,7 @@ of the status of a particular pull request. Rust has plenty of CI capacity, and you should never have to worry about wasting computational resources each time you push a change. It is also perfectly fine (and even encouraged!) to use the CI to test your changes if it can help your -productivity. In particular, we don't recommend running the full `./x.py test` suite locally, +productivity. In particular, we don't recommend running the full `./x test` suite locally, since it takes a very long time to execute. ### r+ @@ -209,7 +205,7 @@ on the pull request with an `r+`. It will look something like this: @bors r+ This tells [@bors], our lovable integration bot, that your pull request has -been approved. The PR then enters the [merge queue][merge-queue], where [@bors] +been approved. The PR then enters the [merge queue], where [@bors] will run *all* the tests on *every* platform we support. If it all works out, [@bors] will merge your code into `master` and close the pull request. @@ -226,25 +222,23 @@ Be patient; this can take a while and the queue can sometimes be long. PRs are n [@rustbot]: https://github.com/rustbot [@bors]: https://github.com/bors -[merge-queue]: https://bors.rust-lang.org/queue/rust ### Opening a PR You are now ready to file a pull request? Great! Here are a few points you should be aware of. -All pull requests should be filed against the `master` branch, except in very -particular scenarios. Unless you know for sure that you should target another -branch, `master` will be the right choice (it's also the default). +All pull requests should be filed against the `master` branch, +unless you know for sure that you should target a different branch. Make sure your pull request is in compliance with Rust's style guidelines by running - $ ./x.py test tidy --bless + $ ./x test tidy --bless We recommend to make this check before every pull request (and every new commit -in a pull request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) -before every push to make sure you never forget to make this check. The -CI will also run tidy and will fail if tidy fails. +in a pull request); you can add [git hooks] +before every push to make sure you never forget to make this check. +The CI will also run tidy and will fail if tidy fails. Rust follows a _no merge-commit policy_, meaning, when you encounter merge conflicts you are expected to always rebase instead of merging. E.g. always use @@ -268,11 +262,11 @@ the issue in question. [labeling]: ./rustbot.md#issue-relabeling [closing-keywords]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue -## External Dependencies +## External dependencies This section has moved to ["Using External Repositories"](./external-repos.md). -## Writing Documentation +## Writing documentation Documentation improvements are very welcome. The source of `doc.rust-lang.org` is located in [`src/doc`] in the tree, and standard API documentation is generated @@ -282,13 +276,9 @@ function in the same way as other pull requests. [`src/doc`]: https://github.com/rust-lang/rust/tree/master/src/doc [std-root]: https://github.com/rust-lang/rust/blob/master/library/std/src/lib.rs#L1 -To find documentation-related issues, sort by the [A-docs label][adocs]. - -[adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs - -You can find documentation style guidelines in [RFC 1574][rfc1574]. +To find documentation-related issues, sort by the [A-docs label]. -[rfc1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text +You can find documentation style guidelines in [RFC 1574]. To build the standard library documentation, use `x doc --stage 0 library --open`. To build the documentation for a book (e.g. the unstable book), use `x doc src/doc/unstable-book.` @@ -302,22 +292,23 @@ The CSS might be messed up, but you can verify that the HTML is right. ### Contributing to rustc-dev-guide -Contributions to the [rustc-dev-guide][rdg] are always welcome, and can be made directly at +Contributions to the [rustc-dev-guide] are always welcome, and can be made directly at [the rust-lang/rustc-dev-guide repo][rdgrepo]. The issue tracker in that repo is also a great way to find things that need doing. There are issues for beginners and advanced compiler devs alike! Just a few things to keep in mind: -- Please limit line length to 100 characters. This is enforced by CI, and you can run the checks - locally with `ci/lengthcheck.sh`. +- Please limit line length to 100 characters. + This is enforced by CI, + and you can run the checks locally with `ci/lengthcheck.sh`. - When contributing text to the guide, please contextualize the information with some time period and/or a reason so that the reader knows how much to trust or mistrust the information. Aim to provide a reasonable amount of context, possibly including but not limited to: - - A reason for why the data may be out of date other than "change", as change is a constant across - the project. + - A reason for why the data may be out of date other than "change", + as change is a constant across the project. - The date the comment was added, e.g. instead of writing _"Currently, ..."_ or _"As of now, ..."_, @@ -358,19 +349,15 @@ Just a few things to keep in mind: subsections) it might benefit from having a Table of Contents at the beginning, which you can auto-generate by including the `` marker. -[rdg]: https://rustc-dev-guide.rust-lang.org/ -[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide - -## Issue Triage +## Issue triage -Sometimes, an issue will stay open, even though the bug has been fixed. And -sometimes, the original bug may go stale because something has changed in the -meantime. +Sometimes, an issue will stay open, even though the bug has been fixed. +And sometimes, the original bug may go stale because something has changed in the meantime. -It can be helpful to go through older bug reports and make sure that they are -still valid. Load up an older issue, double check that it's still true, and -leave a comment letting us know if it is or is not. The [least recently -updated sort][lru] is good for finding issues like this. +It can be helpful to go through older bug reports and make sure that they are still valid. +Load up an older issue, double check that it's still true, +and leave a comment letting us know if it is or is not. +The [least recently updated sort][lru] is good for finding issues like this. [Thanks to `@rustbot`][rustbot], anyone can help triage issues by adding appropriate labels to issues that haven't been triaged yet: @@ -466,8 +453,19 @@ This is used for [RFCs], issues, and pull requests. [rfcbot]: https://github.com/anp/rfcbot-rs/ [RFCs]: https://github.com/rust-lang/rfcs -## Helpful Links and Information - -This section has moved to the ["About this guide"][more-links] chapter. - -[more-links]: ./about-this-guide.md#other-places-to-find-information +## Helpful links and information + +This section has moved to the ["About this guide"] chapter. + +["About this guide"]: about-this-guide.md#other-places-to-find-information +[search existing issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue +[Breaking Changes]: bug-fix-procedure.md +[triagebot.toml config file]: https://github.com/rust-lang/rust/blob/HEAD/triagebot.toml +[rust-lang teams database]: https://github.com/rust-lang/team/tree/HEAD/teams +[compiler test suite]: tests/intro.md +[merge queue]: https://bors.rust-lang.org/queue/rust +[git hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks +[A-docs label]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs +[RFC 1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ +[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide diff --git a/src/doc/rustc-dev-guide/src/conventions.md b/src/doc/rustc-dev-guide/src/conventions.md index 521aeb4a5..1c963c669 100644 --- a/src/doc/rustc-dev-guide/src/conventions.md +++ b/src/doc/rustc-dev-guide/src/conventions.md @@ -13,11 +13,11 @@ However, for now we don't use stable `rustfmt`; we use a pinned version with a special config, so this may result in different style from normal [`rustfmt`]. Therefore, formatting this repository using `cargo fmt` is not recommended. -Instead, formatting should be done using `./x.py fmt`. It's a good habit to run -`./x.py fmt` before every commit, as this reduces conflicts later. +Instead, formatting should be done using `./x fmt`. It's a good habit to run +`./x fmt` before every commit, as this reduces conflicts later. Formatting is checked by the `tidy` script. It runs automatically when you do -`./x.py test` and can be run in isolation with `./x.py fmt --check`. +`./x test` and can be run in isolation with `./x fmt --check`. If you want to use format-on-save in your editor, the pinned version of `rustfmt` is built under `build//stage0/bin/rustfmt`. You'll have to @@ -126,7 +126,7 @@ dramatically (versus adding to it) in a later commit, that **Format liberally.** While only the final commit of a PR must be correctly formatted, it is both easier to review and less noisy to format each commit -individually using `./x.py fmt`. +individually using `./x fmt`. **No merges.** We do not allow merge commits into our history, other than those by bors. If you get a merge conflict, rebase instead via a diff --git a/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md b/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md index 932b23b92..ac629934e 100644 --- a/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md +++ b/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md @@ -133,8 +133,7 @@ or `symbols`. Rust has support for embedding Natvis files for crates outside of the standard libraries by using the `#[debugger_visualizer]` attribute. For more details on how to embed debugger visualizers, -please refer to the `#[debugger_visualizer]` attribute in -[the unstable book](https://doc.rust-lang.org/unstable-book/language-features/debugger-visualizer.html). +please refer to the section on the [`debugger_visualizer` attribute]. ## DWARF and `rustc` @@ -352,3 +351,4 @@ but may have to add some mode to let the compiler understand some extensions. [symbol records]: https://llvm.org/docs/PDB/CodeViewSymbols.html [type records]: https://llvm.org/docs/PDB/CodeViewTypes.html [Windows Debugging Tools]: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/ +[`debugger_visualizer` attribute]: https://doc.rust-lang.org/nightly/reference/attributes/debugger.html#the-debugger_visualizer-attribute diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index daaffba7b..9f4245f28 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -507,6 +507,83 @@ module. [rlint]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/index.html +### When do lints run? + +Different lints will run at different times based on what information the lint +needs to do its job. Some lints get grouped into *passes* where the lints +within a pass are processed together via a single visitor. Some of the passes +are: + +- Pre-expansion pass: Works on [AST nodes] before [macro expansion]. This + should generally be avoided. + - Example: [`keyword_idents`] checks for identifiers that will become + keywords in future editions, but is sensitive to identifiers used in + macros. + +- Early lint pass: Works on [AST nodes] after [macro expansion] and name + resolution, just before [HIR lowering]. These lints are for purely + syntactical lints. + - Example: The [`unsued_parens`] lint checks for parenthesized-expressions + in situations where they are not needed, like an `if` condition. + +- Late lint pass: Works on [HIR nodes], towards the end of [analysis] (after + borrow checking, etc.). These lints have full type information available. + Most lints are late. + - Example: The [`invalid_value`] lint (which checks for obviously invalid + uninitialized values) is a late lint because it needs type information to + figure out whether a type allows being left uninitialized. + +- MIR pass: Works on [MIR nodes]. This isn't quite the same as other passes; + lints that work on MIR nodes have their own methods for running. + - Example: The [`arithmetic_overflow`] lint is emitted when it detects a + constant value that may overflow. + +Most lints work well via the pass systems, and they have a fairly +straightforward interface and easy way to integrate (mostly just implementing +a specific `check` function). However, some lints are easier to write when +they live on a specific code path anywhere in the compiler. For example, the +[`unused_mut`] lint is implemented in the borrow checker as it requires some +information and state in the borrow checker. + +Some of these inline lints fire before the linting system is ready. Those +lints will be *buffered* where they are held until later phases of the +compiler when the linting system is ready. See [Linting early in the +compiler](#linting-early-in-the-compiler). + + +[AST nodes]: the-parser.md +[HIR lowering]: lowering.md +[HIR nodes]: hir.md +[MIR nodes]: mir/index.md +[macro expansion]: macro-expansion.md +[analysis]: part-4-intro.md +[`keyword_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#keyword-idents +[`unsued_parens`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-parens +[`invalid_value`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#invalid-value +[`arithmetic_overflow`]: https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#arithmetic-overflow +[`unused_mut`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-mut + +### Lint definition terms + +Lints are managed via the [`LintStore`][LintStore] and get registered in +various ways. The following terms refer to the different classes of lints +generally based on how they are registered. + +- *Built-in* lints are defined inside the compiler source. +- *Driver-registered* lints are registered when the compiler driver is created + by an external driver. This is the mechanism used by Clippy, for example. +- *Plugin* lints are registered by the [deprecated plugin system]. +- *Tool* lints are lints with a path prefix like `clippy::` or `rustdoc::`. +- *Internal* lints are the `rustc::` scoped tool lints that only run on the + rustc source tree itself and are defined in the compiler source like a + regular built-in lint. + +More information about lint registration can be found in the [LintStore] +chapter. + +[deprecated plugin system]: https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html +[LintStore]: diagnostics/lintstore.md + ### Declaring a lint The built-in compiler lints are defined in the [`rustc_lint`][builtin] diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index 790d74dcf..6d698e3f3 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -70,7 +70,7 @@ Diagnostics are more than just their primary message, they often include labels, notes, help messages and suggestions, all of which can also be specified on a `Diagnostic`. -`#[label]`, `#[help]` and `#[note]` can all be applied to fields which have the +`#[label]`, `#[help]`, `#[warning]` and `#[note]` can all be applied to fields which have the type `Span`. Applying any of these attributes will create the corresponding subdiagnostic with that `Span`. These attributes will look for their diagnostic message in a Fluent attribute attached to the primary Fluent @@ -87,11 +87,11 @@ Other types have special behavior when used in a `Diagnostic` derive: - Any attribute applied to a `Vec` will be repeated for each element of the vector. -`#[help]` and `#[note]` can also be applied to the struct itself, in which case +`#[help]`, `#[warning]` and `#[note]` can also be applied to the struct itself, in which case they work exactly like when applied to fields except the subdiagnostic won't have a `Span`. These attributes can also be applied to fields of type `()` for the same effect, which when combined with the `Option` type can be used to -represent optional `#[note]`/`#[help]` subdiagnostics. +represent optional `#[note]`/`#[help]`/`#[warning]` subdiagnostics. Suggestions can be emitted using one of four field attributes: @@ -161,14 +161,14 @@ following attributes: - `code = "..."` (_Optional_) - Specifies the error code. - `#[note]` or `#[note(slug)]` (_Optional_) - - _Applied to struct or `Span`/`()` fields._ + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a note subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. - Defaults to equivalent of `.note`. - If applied to a `Span` field, creates a spanned note. - `#[help]` or `#[help(slug)]` (_Optional_) - - _Applied to struct or `Span`/`()` fields._ + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a help subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. @@ -180,8 +180,8 @@ following attributes: - Value is a path to an item in `rustc_errors::fluent` for the note's message. - Defaults to equivalent of `.label`. -- `#[warn_]` or `#[warn_(slug)]` (_Optional_) - - _Applied to `Span` fields._ +- `#[warning]` or `#[warning(slug)]` (_Optional_) + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a warning subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. @@ -253,6 +253,7 @@ attribute applied to the struct or each variant, one of: - `#[label(..)]` for defining a label - `#[note(..)]` for defining a note - `#[help(..)]` for defining a help +- `#[warning(..)]` for defining a warning - `#[suggestion{,_hidden,_short,_verbose}(..)]` for defining a suggestion All of the above must provide a slug as the first positional argument (a path @@ -333,7 +334,7 @@ diagnostic struct. ### Reference `#[derive(Subdiagnostic)]` supports the following attributes: -- `#[label(slug)]`, `#[help(slug)]` or `#[note(slug)]` +- `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]` - _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._ - _Mandatory_ - Defines the type to be representing a label, help or note. diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md index 2dbdb53fe..7cdf5ebca 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md @@ -37,7 +37,7 @@ To create a new error, you first need to find the next available code. You can find it with `tidy`: ``` -./x.py test tidy +./x test tidy ``` This will invoke the tidy script, which generally checks that your code obeys diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md index e3ccec7d7..a42a15484 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md @@ -86,10 +86,10 @@ excellent examples of translating messages into different locales and the information that needs to be provided by the code to do so. ### Compile-time validation and typed identifiers -rustc's Fluent resources for the default locale (`en-US`) are in the -[`compiler/rustc_error_messages/locales/en-US`] directory. Currently, each crate -which defines translatable diagnostics has its own Fluent resource, such as -`parser.ftl` or `typeck.ftl`. +Currently, each crate which defines translatable diagnostics has its own +Fluent resource in a file named `messages.ftl`, such as +[`compiler/rustc_borrowck/messages.ftl`] and +[`compiler/rustc_parse/messages.ftl`]. rustc's `fluent_messages` macro performs compile-time validation of Fluent resources and generates code to make it easier to refer to Fluent messages in @@ -240,5 +240,6 @@ won't fail. Bundle loading can fail if a requested locale is missing, Fluent files are malformed, or a message is duplicated in multiple resources. [Fluent]: https://projectfluent.org -[`compiler/rustc_error_messages/locales/en-US`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_error_messages/locales/en-US +[`compiler/rustc_borrowck/messages.ftl`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_borrowck/messages.ftl +[`compiler/rustc_parse/messages.ftl`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_parse/messages.ftl [`rustc_error_messages::DiagnosticMessage`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_error_messages/enum.DiagnosticMessage.html diff --git a/src/doc/rustc-dev-guide/src/early-late-bound.md b/src/doc/rustc-dev-guide/src/early-late-bound.md index 29b2136b4..8fb856742 100644 --- a/src/doc/rustc-dev-guide/src/early-late-bound.md +++ b/src/doc/rustc-dev-guide/src/early-late-bound.md @@ -1,107 +1,199 @@ -# Early and Late Bound Variables +# Early and Late Bound Parameter Definitions -In Rust, item definitions (like `fn`) can often have generic parameters, which -are always [_universally_ quantified][quant]. That is, if you have a function -like +Understanding this page likely requires a rudimentary understanding of higher ranked +trait bounds/`for<'a>`and also what types such as `dyn for<'a> Trait<'a>` and +`for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html) +on HRTB may be useful for understanding this syntax. The meaning of `for<'a> fn(&'a u32)` +is incredibly similar to the meaning of `T: for<'a> Trait<'a>`. +If you are looking for information on the `RegionKind` variants `ReLateBound` and `ReEarlyBound` +you should look at the section on [bound vars and params](./bound-vars-and-params.md). This section +discusses what makes generic parameters on functions and closures late/early bound. Not the general +concept of bound vars and generic parameters which `RegionKind` has named somewhat confusingly +with this topic. + +## What does it mean for parameters to be early or late bound + +All function definitions conceptually have a ZST (this is represented by `TyKind::FnDef` in rustc). +The only generics on this ZST are the early bound parameters of the function definition. e.g. ```rust -fn foo(x: T) { } +fn foo<'a>(_: &'a u32) {} + +fn main() { + let b = foo; + // ^ `b` has type `FnDef(foo, [])` (no substs because `'a` is late bound) + assert!(std::mem::size_of_val(&b) == 0); +} ``` -this function is defined "for all T" (not "for some specific T", which would be -[_existentially_ quantified][quant]). +In order to call `b` the late bound parameters do need to be provided, these are inferred at the +call site instead of when we refer to `foo`. +```rust +fn main() { + let b = foo; + let a: &'static u32 = &10; + foo(a); + // the lifetime argument for `'a` on `foo` is inferred at the callsite + // the generic parameter `'a` on `foo` is inferred to `'static` here +} +``` + +Because late bound parameters are not part of the `FnDef`'s substs this allows us to prove trait +bounds such as `F: for<'a> Fn(&'a u32)` where `F` is `foo`'s `FnDef`. e.g. +```rust +fn foo_early<'a, T: Trait<'a>>(_: &'a u32, _: T) {} +fn foo_late<'a, T>(_: &'a u32, _: T) {} + +fn accepts_hr_func Fn(&'a u32, u32)>(_: F) {} + +fn main() { + // doesnt work, the substituted bound is `for<'a> FnDef<'?0>: Fn(&'a u32, u32)` + // `foo_early` only implements `for<'a> FnDef<'a>: Fn(&'a u32, u32)`- the lifetime + // of the borrow in the function argument must be the same as the lifetime + // on the `FnDef`. + accepts_hr_func(foo_early); + + // works, the substituted bound is `for<'a> FnDef: Fn(&'a u32, u32)` + accepts_hr_func(foo_late); +} + +// the builtin `Fn` impls for `foo_early` and `foo_late` look something like: +// `foo_early` +impl<'a, T: Trait<'a>> Fn(&'a u32, T) for FooEarlyFnDef<'a, T> { ... } +// `foo_late` +impl<'a, T> Fn(&'a u32, T) for FooLateFnDef { ... } + +``` + +Early bound parameters are present on the `FnDef`. Late bound generic parameters are not present +on the `FnDef` but are instead constrained by the builtin `Fn*` impl. + +The same distinction applies to closures. Instead of `FnDef` we are talking about the anonymous +closure type. Closures are [currently unsound](https://github.com/rust-lang/rust/issues/84366) in +ways that are closely related to the distinction between early/late bound +parameters (more on this later) + +The early/late boundness of generic parameters is only relevent for the desugaring of +functions/closures into types with builtin `Fn*` impls. It does not make sense to talk about +in other contexts. + +The `generics_of` query in rustc only contains early bound parameters. In this way it acts more +like `generics_of(my_func)` is the generics for the FnDef than the generics provided to the function +body although it's not clear to the author of this section if this was the actual justification for +making `generics_of` behave this way. -[quant]: ./appendix/background.md#quantified +## What parameters are currently late bound -While Rust *items* can be quantified over types, lifetimes, and constants, the -types of values in Rust are only ever quantified over lifetimes. So you can -have a type like `for<'a> fn(&'a u32)`, which represents a function pointer -that takes a reference with any lifetime, or `for<'a> dyn Trait<'a>`, which is -a `dyn` trait for a trait implemented for any lifetime; but we have no type -like `for fn(T)`, which would be a function that takes a value of *any type* -as a parameter. This is a consequence of monomorphization -- to support a value -of type `for fn(T)`, we would need a single function pointer that can be -used for a parameter of any type, but in Rust we generate customized code for -each parameter type. +Below are the current requirements for determining if a generic parameter is late bound. It is worth +keeping in mind that these are not necessarily set in stone and it is almost certainly possible to +be more flexible. -One consequence of this asymmetry is a weird split in how we represent some -generic types: _early-_ and _late-_ bound parameters. -Basically, if we cannot represent a type (e.g. a universally quantified type), -we have to bind it _early_ so that the unrepresentable type is never around. +### Must be a lifetime parameter -Consider the following example: +Rust can't support types such as `for dyn Trait` or `for fn(T)`, this is a +fundamental limitation of the language as we are required to monomorphize type/const +parameters and cannot do so behind dynamic dispatch. (technically we could probably +support `for dyn MarkerTrait` as there is nothing to monomorphize) -```rust,ignore -fn foo<'a, 'b, T>(x: &'a u32, y: &'b T) where T: 'b { ... } +Not being able to support `for dyn Trait` resulted in making all type and const +parameters early bound. Only lifetime parameters can be late bound. + +### Must not appear in the where clauses + +In order for a generic parameter to be late bound it must not appear in any where clauses. +This is currently an incredibly simplistic check that causes lifetimes to be early bound even +if the where clause they appear in are always true, or implied by well formedness of function +arguments. e.g. +```rust +fn foo1<'a: 'a>(_: &'a u32) {} +// ^^ early bound parameter because it's in a `'a: 'a` clause +// even though the bound obviously holds all the time +fn foo2<'a, T: Trait<'a>(a: T, b: &'a u32) {} +// ^^ early bound parameter because it's used in the `T: Trait<'a>` clause +fn foo3<'a, T: 'a>(_: &'a T) {} +// ^^ early bound parameter because it's used in the `T: 'a` clause +// even though that bound is implied by wellformedness of `&'a T` +fn foo4<'a, 'b: 'a>(_: Inv<&'a ()>, _: Inv<&'b ()>) {} +// ^^ ^^ ^^^ note: +// ^^ ^^ `Inv` stands for `Invariant` and is used to +// ^^ ^^ make the the type parameter invariant. This +// ^^ ^^ is necessary for demonstration purposes as +// ^^ ^^ `for<'a, 'b> fn(&'a (), &'b ())` and +// ^^ ^^ `for<'a> fn(&'a u32, &'a u32)` are subtypes- +// ^^ ^^ of eachother which makes the bound trivially +// ^^ ^^ satisfiable when making the fnptr. `Inv` +// ^^ ^^ disables this subtyping. +// ^^ ^^ +// ^^^^^^ both early bound parameters because they are present in the +// `'b: 'a` clause ``` -We cannot treat `'a`, `'b`, and `T` in the same way. Types in Rust can't have -`for { .. }`, only `for<'a> {...}`, so whenever you reference `foo` the type -you get back can't be `for<'a, 'b, T> fn(&'a u32, y: &'b T)`. Instead, the `T` -must be substituted early. In particular, you have: +The reason for this requirement is that we cannot represent the `T: Trait<'a>` or `'a: 'b` clauses +on a function pointer. `for<'a, 'b> fn(Inv<&'a ()>, Inv<&'b ()>)` is not a valid function pointer to +represent`foo4` as it would allow calling the function without `'b: 'a` holding. -```rust,ignore -let x = foo; // T, 'b have to be substituted here -x(...); // 'a substituted here, at the point of call -x(...); // 'a substituted here with a different value +### Must be constrained by where clauses or function argument types + +The builtin impls of the `Fn*` traits for closures and `FnDef`s cannot not have any unconstrained +parameters. For example the following impl is illegal: +```rust +impl<'a> Trait for u32 { type Assoc = &'a u32; } +``` +We must not end up with a similar impl for the `Fn*` traits e.g. +```rust +impl<'a> Fn<()> for FnDef { type Assoc = &'a u32 } ``` -## Early-bound parameters +Violating this rule can trivially lead to unsoundness as seen in [#84366](https://github.com/rust-lang/rust/issues/84366). +Additionally if we ever support late bound type params then an impl like: +```rust +impl Fn<()> for FnDef { type Assoc = T; } +``` +would break the compiler in various ways. -Early-bound parameters in rustc are identified by an index, stored in the -[`ParamTy`] struct for types or the [`EarlyBoundRegion`] struct for lifetimes. -The index counts from the outermost declaration in scope. This means that as you -add more binders inside, the index doesn't change. +In order to ensure that everything functions correctly, we do not allow generic parameters to +be late bound if it would result in a builtin impl that does not constrain all of the generic +parameters on the builtin impl. Making a generic parameter be early bound trivially makes it be +constrained by the builtin impl as it ends up on the self type. -For example, +Because of the requirement that late bound parameters must not appear in where clauses, checking +this is simpler than the rules for checking impl headers constrain all the parameters on the impl. +We only have to ensure that all late bound parameters appear at least once in the function argument +types outside of an alias (e.g. an associated type). -```rust,ignore -trait Foo { - type Bar = (Self, T, U); -} +The requirement that they not indirectly be in the substs of an alias for it to count is the +same as why the follow code is forbidden: +```rust +impl OtherTrait for ::Assoc { type Assoc = T } ``` +There is no guarantee that `::Assoc` will normalize to different types for every +instantiation of `T`. If we were to allow this impl we could get overlapping impls and the +same is true of the builtin `Fn*` impls. + +## Making more generic parameters late bound + +It is generally considered desirable for more parameters to be late bound as it makes +the builtin `Fn*` impls more flexible. Right now many of the requirements for making +a parameter late bound are overly restrictive as they are tied to what we can currently +(or can ever) do with fn ptrs. + +It would be theoretically possible to support late bound params in `where`-clauses in the +language by introducing implication types which would allow us to express types such as: +`for<'a, 'b: 'a> fn(Inv<&'a u32>, Inv<&'b u32>)` which would ensure `'b: 'a` is upheld when +calling the function pointer. + +It would also be theoretically possible to support it by making the coercion to a fn ptr +instantiate the parameter with an infer var while still allowing the FnDef to not have the +generic parameter present as trait impls are perfectly capable of representing the where clauses +on the function on the impl itself. This would also allow us to support late bound type/const +vars allowing bounds like `F: for Fn(T)` to hold. + +It is almost somewhat unclear if we can change the `Fn` traits to be structured differently +so that we never have to make a parameter early bound just to make the builtin impl have all +generics be constrained. Of all the possible causes of a generic parameter being early bound +this seems the most difficult to remove. + +Whether these would be good ideas to implement is a separate question- they are only brought +up to illustrate that the current rules are not necessarily set in stone and a result of +"its the only way of doing this". -Here, the type `(Self, T, U)` would be `($0, $1, $2)`, where `$N` means a -[`ParamTy`] with the index of `N`. - -In rustc, the [`Generics`] structure carries this information. So the -[`Generics`] for `Bar` above would be just like for `U` and would indicate the -'parent' generics of `Foo`, which declares `Self` and `T`. You can read more -in [this chapter](./generics.md). - -[`ParamTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamTy.html -[`EarlyBoundRegion`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.EarlyBoundRegion.html -[`Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html - -## Late-bound parameters - -Late-bound parameters in `rustc` are handled quite differently (they are also -specialized to lifetimes since, right now, only late-bound lifetimes are -supported, though with GATs that has to change). We indicate their potential -presence by a [`Binder`] type. The [`Binder`] doesn't know how many variables -there are at that binding level. This can only be determined by walking the -type itself and collecting them. So a type like `for<'a, 'b> ('a, 'b)` would be -`for (^0.a, ^0.b)`. Here, we just write `for` because we don't know the names -of the things bound within. - -Moreover, a reference to a late-bound lifetime is written `^0.a`: - -- The `0` is the index; it identifies that this lifetime is bound in the - innermost binder (the `for`). -- The `a` is the "name"; late-bound lifetimes in rustc are identified by a - "name" -- the [`BoundRegionKind`] enum. This enum can contain a - [`DefId`][defid] or it might have various "anonymous" numbered names. The - latter arise from types like `fn(&u32, &u32)`, which are equivalent to - something like `for<'a, 'b> fn(&'a u32, &'b u32)`, but the names of those - lifetimes must be generated. - -This setup of not knowing the full set of variables at a binding level has some -advantages and some disadvantages. The disadvantage is that you must walk the -type to find out what is bound at the given level and so forth. The advantage -is primarily that, when constructing types from Rust syntax, if we encounter -anonymous regions like in `fn(&u32)`, we just create a fresh index and don't have -to update the binder. - -[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html -[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html -[defid]: ./hir.html#identifiers-in-the-hir diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md index 9e9a83ea6..8ad4fea1f 100644 --- a/src/doc/rustc-dev-guide/src/feature-gates.md +++ b/src/doc/rustc-dev-guide/src/feature-gates.md @@ -3,44 +3,16 @@ This chapter is intended to provide basic help for adding, removing, and modifying feature gates. +Note that this is specific to *language* feature gates; *library* feature gates use [a different +mechanism][libs-gate]. -## Adding a feature gate - -See ["Stability in code"] for help with adding a new feature; this section just -covers how to add the feature gate *declaration*. - -First, add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block. - -Then, add a feature gate declaration to `rustc_feature/src/active.rs` in the active -`declare_features` block: - -```rust,ignore -/// description of feature -(active, $feature_name, "$current_nightly_version", Some($tracking_issue_number), $edition) -``` +[libs-gate]: ./stability.md -where `$edition` has the type `Option`, and is typically -just `None`. - -For example: - -```rust,ignore -/// Allows defining identifiers beyond ASCII. -(active, non_ascii_idents, "1.0.0", Some(55467), None), -``` - -Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` lint] -by setting their type to `incomplete`: - -```rust,ignore -/// Allows unsized rvalues at arguments and parameters. -(incomplete, unsized_locals, "1.30.0", Some(48055), None), -``` +## Adding a feature gate -When added, the current version should be the one for the current nightly. -Once the feature is moved to `accepted.rs`, the version is changed to that -nightly version. +See ["Stability in code"][adding] in the "Implementing new features" section for instructions. +[adding]: ./implementing_new_features.md#stability-in-code ## Removing a feature gate @@ -109,5 +81,4 @@ updating the declaration! ["Stability in code"]: ./implementing_new_features.md#stability-in-code -[`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features ["Updating the feature-gate listing"]: ./stabilization_guide.md#updating-the-feature-gate-listing diff --git a/src/doc/rustc-dev-guide/src/fuzzing.md b/src/doc/rustc-dev-guide/src/fuzzing.md index 3fb1add01..869fc2f71 100644 --- a/src/doc/rustc-dev-guide/src/fuzzing.md +++ b/src/doc/rustc-dev-guide/src/fuzzing.md @@ -36,7 +36,7 @@ project, please read this guide before reporting fuzzer-generated bugs! If you're not sure whether or not an ICE is a duplicate of one that's already been reported, please go ahead and report it and link to issues you think might be related. In general, ICEs on the same line but with different *query stacks* -are usually distinct bugs. For example, [#109020][#109202] and [#109129][#109129] +are usually distinct bugs. For example, [#109020][#109020] and [#109129][#109129] had similar error messages: ``` @@ -100,7 +100,7 @@ to avoid introducing syntax, type-, and borrow-checking errors while using these tools, post both the complete and minimized test cases. Generally, *syntax-aware* tools give the best results in the least amount of time. [`treereduce-rust`][treereduce] and [picireny][picireny] are syntax-aware. -`halfempty` is not, but is generally a high-quality tool. +[`halfempty`][halfempty] is not, but is generally a high-quality tool. [halfempty]: https://github.com/googleprojectzero/halfempty [picireny]: https://github.com/renatahodovan/picireny @@ -146,4 +146,4 @@ ICEs that require debug assertions to reproduce should be tagged [glacier]: https://github.com/rust-lang/glacier [fuzz-rustc]: https://github.com/dwrensha/fuzz-rustc [icemaker]: https://github.com/matthiaskrgr/icemaker/ -[tree-splicer]: https://github.com/langston-barrett/tree-splicer/ \ No newline at end of file +[tree-splicer]: https://github.com/langston-barrett/tree-splicer/ diff --git a/src/doc/rustc-dev-guide/src/generic_arguments.md b/src/doc/rustc-dev-guide/src/generic_arguments.md index c9911acf5..6e09e8620 100644 --- a/src/doc/rustc-dev-guide/src/generic_arguments.md +++ b/src/doc/rustc-dev-guide/src/generic_arguments.md @@ -1,28 +1,28 @@ # Generic arguments -A `ty::subst::GenericArg<'tcx>` represents some entity in the type system: a type +A `ty::GenericArg<'tcx>` represents some entity in the type system: a type (`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). -`GenericArg` is used to perform substitutions of generic parameters for concrete +`GenericArg` is used to perform instantiation of generic parameters to concrete arguments, such as when calling a function with generic parameters explicitly -with type arguments. Substitutions are represented using the -[`Subst` type](#subst) as described below. +with type arguments. Instantiations are represented using the +[`GenericArgs` type](#genericargs) as described below. -## `Subst` -`ty::subst::Subst<'tcx>` is intuitively simply a slice of `GenericArg<'tcx>`s, -acting as an ordered list of substitutions from generic parameters to +## `GenericArgs` +`ty::GenericArgs<'tcx>` is intuitively simply a slice of `GenericArg<'tcx>`s, +acting as an ordered list of generic parameters instantiated to concrete arguments (such as types, lifetimes and consts). For example, given a `HashMap` with two type parameters, `K` and `V`, an instantiation of the parameters, for example `HashMap`, would be -represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. +represented by `&'tcx [tcx.types.i32, tcx.types.u32]`. -`Subst` provides various convenience methods to instantiate substitutions +`GenericArgs` provides various convenience methods to instantiate generic arguments given item definitions, which should generally be used rather than explicitly -constructing such substitution slices. +instantiating such slices. ## `GenericArg` The actual `GenericArg` struct is optimised for space, storing the type, lifetime or const as an interned pointer containing a tag identifying its kind (in the -lowest 2 bits). Unless you are working with the `Subst` implementation +lowest 2 bits). Unless you are working with the `GenericArgs` implementation specifically, you should generally not have to deal with `GenericArg` and instead make use of the safe [`GenericArgKind`](#genericargkind) abstraction. @@ -30,7 +30,7 @@ make use of the safe [`GenericArgKind`](#genericargkind) abstraction. As `GenericArg` itself is not type-safe, the `GenericArgKind` enum provides a more convenient and safe interface for dealing with generic arguments. An `GenericArgKind` can be converted to a raw `GenericArg` using `GenericArg::from()` -(or simply `.into()` when the context is clear). As mentioned earlier, substitution +(or simply `.into()` when the context is clear). As mentioned earlier, instantiation lists store raw `GenericArg`s, so before dealing with them, it is preferable to convert them to `GenericArgKind`s first. This is done by calling the `.unpack()` method. @@ -44,7 +44,7 @@ fn deal_with_generic_arg<'tcx>(generic_arg: GenericArg<'tcx>) -> GenericArg<'tcx GenericArgKind::Lifetime(lt) => { /* ... */ } GenericArgKind::Const(ct) => { /* ... */ } }; - // Pack the `GenericArgKind` to store it in a substitution list. + // Pack the `GenericArgKind` to store it in a generic args list. new_generic_arg.into() } ``` diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index 297873d98..80c3d3793 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -57,7 +57,7 @@ even if you can't figure out who to ping. Another way to find experts for a given part of the compiler is to see who has made recent commits. For example, to find people who have recently worked on name resolution since the 1.68.2 release, you could run `git shortlog -n 1.68.2.. compiler/rustc_resolve/`. Ignore any commits starting with -"Rollup merge" or commits by `@bors` (see [CI contribution prodcedures](./contributing.md#ci) for +"Rollup merge" or commits by `@bors` (see [CI contribution procedures](./contributing.md#ci) for more information about these commits). [map]: https://github.com/rust-lang/compiler-team/blob/master/content/experts/map.toml @@ -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+-label%3AS-blocked+ +[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%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+ [Triage]: ./contributing.md#issue-triage ### Recurring work diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index 34f2f101e..6c5c64685 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -10,7 +10,7 @@ can be incorporated into the compiler. The goal of this page is to cover some of the more common questions and problems new contributors face. Although some Git basics will be covered here, -if you find that this is still a little too fast for you, it might make sense +if you find that this is still a little too fast for you, it might make sense to first read some introductions to Git, such as the Beginner and Getting started sections of [this tutorial from Atlassian][atlassian-git]. GitHub also provides [documentation] and [guides] for beginners, or you can consult the @@ -139,7 +139,7 @@ You might also notice conflicts in the web UI: ![conflict in src/tools/cargo](./img/submodule-conflicts.png) The most common cause is that you rebased after a change and ran `git add .` without first running -`x.py` to update the submodules. Alternatively, you might have run `cargo fmt` instead of `x fmt` +`x` to update the submodules. Alternatively, you might have run `cargo fmt` instead of `x fmt` and modified files in a submodule, then committed the changes. To fix it, do the following things: @@ -167,7 +167,7 @@ error: cannot rebase: You have unstaged changes. error: Please commit or stash them. ``` -(See https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F#_the_three_states for the difference between the two.) +(See for the difference between the two.) This means you have made changes since the last time you made a commit. To be able to rebase, either commit your changes, or make a temporary commit called a "stash" to have them still not be commited @@ -178,7 +178,7 @@ will prevent the "cannot rebase" error in nearly all cases: git config --global rebase.autostash true ``` -See https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning for more info about stashing. +See for more info about stashing. ### I see 'Untracked Files: src/stdarch'? @@ -239,31 +239,13 @@ no changes added to commit (use "git add" and/or "git commit -a") ``` These changes are not changes to files: they are changes to submodules (more on this -[later](#git-submodules)). To get rid of those, run `./x.py --help`, which will automatically update +[later](#git-submodules)). To get rid of those, run `./x --help`, which will automatically update the submodules. Some submodules are not actually needed; for example, `src/llvm-project` doesn't need to be checked out if you're using `download-ci-llvm`. To avoid having to keep fetching its history, you can use `git submodule deinit -f src/llvm-project`, which will also avoid it showing as modified again. -Note that, as of Aug 2022, -there is a [bug][#77620] if you use worktrees, -submodules, and `x.py` in a commit hook. -If you run into an error like the following, -it's not anything you did wrong: - -``` -error: failed to read `/home/jyn/rustc-worktree/src/tools/cargo/Cargo.toml` - -Caused by: - No such file or directory (os error 2) -``` - -There is a workaround in [the issue][#77620-workaround]. - -[#77620]: https://github.com/rust-lang/rust/issues/77620 -[#77620-workaround]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229 - ## Rebasing and Conflicts When you edit your code locally, you are making changes to the version of @@ -314,7 +296,7 @@ Generally, resolving the conflict consists of two steps: First, fix the particular conflict. Edit the file to make the changes you want and remove the `<<<<<<<`, `=======` and `>>>>>>>` lines in the process. Second, check the surrounding code. If there was a conflict, its likely there are some logical -errors lying around too! It's a good idea to run `x.py check` here to make sure +errors lying around too! It's a good idea to run `x check` here to make sure there are no glaring errors. Once you're all done fixing the conflicts, you need to stage the files that had @@ -461,7 +443,7 @@ that merge commits in PRs are not accepted. As a result, if you are running course, this is not always true; if your merge will just be a fast-forward, like the merges that `git pull` usually performs, then no merge commit is created and you have nothing to worry about. Running `git config merge.ff only` -(this will apply the config to the local repo). +(this will apply the config to the local repo) once will ensure that all the merges you perform are of this type, so that you cannot make a mistake. @@ -558,7 +540,7 @@ commit, which doesn't change unless modified manually. If you use `git checkout in the `llvm-project` directory and go back to the `rust` directory, you can stage this change like any other, e.g. by running `git add src/llvm-project`. (Note that if you *don't* stage the change to commit, then you run the risk that running -`x.py` will just undo your change by switching back to the previous commit when +`x` will just undo your change by switching back to the previous commit when it automatically "updates" the submodules.) This version selection is usually done by the maintainers of the project, and diff --git a/src/doc/rustc-dev-guide/src/identifiers.md b/src/doc/rustc-dev-guide/src/identifiers.md index 09e85c019..c7e32d04c 100644 --- a/src/doc/rustc-dev-guide/src/identifiers.md +++ b/src/doc/rustc-dev-guide/src/identifiers.md @@ -70,7 +70,7 @@ See the [HIR chapter][hir-map] for more detailed information. - [`Local`] identifies a local variable in a function. Its associated data is in [`LocalDecl`], which can be retrieved by indexing into [`Body.local_decls`]. -- [`Field`] identifies a struct's, union's, or enum variant's field. It is used +- [`FieldIdx`] identifies a struct's, union's, or enum variant's field. It is used as a "projection" in [`Place`]. - [`SourceScope`] identifies a name scope in the original source code. Used for @@ -96,7 +96,7 @@ See the [HIR chapter][hir-map] for more detailed information. [`Local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Local.html [`LocalDecl`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.LocalDecl.html [`Body.local_decls`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Body.html#structfield.local_decls -[`Field`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Field.html +[`FieldIdx`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_abi/struct.FieldIdx.html [`Place`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Place.html [`SourceScope`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.SourceScope.html [`SourceScopeData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.SourceScopeData.html diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index 946637d29..01508889f 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -1,4 +1,4 @@ -# Implementing new features +# Implementing new language features @@ -6,6 +6,11 @@ When you want to implement a new significant feature in the compiler, you need to go through this process to make sure everything goes smoothly. +**NOTE: this section is for *language* features, not *library* features, +which use [a different process].** + +[a different process]: ./stability.md + ## The @rfcbot FCP process When the change is small and uncontroversial, then it can be done @@ -91,31 +96,16 @@ by being unstable and unchanged for a year. To keep track of the status of an unstable feature, the experience we get while using it on nightly, and of the concerns that block its stabilization, every feature-gate -needs a tracking issue. - -General discussions about the feature should be done on -the tracking issue. +needs a tracking issue. General discussions about the feature should be done on the tracking issue. For features that have an RFC, you should use the RFC's tracking issue for the feature. For other features, you'll have to make a tracking issue for that feature. The issue title should be "Tracking issue -for YOUR FEATURE". - -For tracking issues for features (as opposed to future-compat -warnings), I don't think the description has to contain -anything specific. Generally we put the list of items required -for stabilization in a checklist, e.g., +for YOUR FEATURE". Use the ["Tracking Issue" issue template][template]. -```txt -**Steps:** - -- [ ] Implement the RFC. (CC @rust-lang/compiler -- can anyone write - up mentoring instructions?) -- [ ] Adjust the documentation. ([See instructions on rustc-dev-guide.](stabilization_guide.md#documentation-prs)) -- [ ] Stabilize the feature. ([See instructions on rustc-dev-guide.](stabilization_guide.md#stabilization-pr)) -``` +[template]: https://github.com/rust-lang/rust/issues/new?template=tracking_issue.md ## Stability in code @@ -128,14 +118,48 @@ a new unstable feature: The tracking issue should be labeled with at least `C-tracking-issue`. For a language feature, a label `F-feature_name` should be added as well. -2. Pick a name for the feature gate (for RFCs, use the name +1. Pick a name for the feature gate (for RFCs, use the name in the RFC). -3. Add a feature gate declaration to `rustc_feature/src/active.rs` in the active - `declare_features` block, and add the feature gate keyword to - `rustc_span/src/symbol.rs`. See [here][add-feature-gate] for detailed instructions. +1. Add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block. + +1. Add a feature gate declaration to `rustc_feature/src/active.rs` in the active + `declare_features` block. + + ```rust ignore + /// description of feature + (active, $feature_name, "CURRENT_RUSTC_VERSION", Some($tracking_issue_number), $edition) + ``` + + where `$edition` has the type `Option`, and is typically just `None`. If you haven't yet + opened a tracking issue (e.g. because you want initial feedback on whether the feature is likely + to be accepted), you can temporarily use `None` - but make sure to update it before the PR is + merged! + + For example: + + ```rust ignore + /// Allows defining identifiers beyond ASCII. + (active, non_ascii_idents, "CURRENT_RUSTC_VERSION", Some(55467), None), + ``` + + Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` + lint] + by setting their type to `incomplete`: + + [`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features + + ```rust ignore + /// Allows unsized rvalues at arguments and parameters. + (incomplete, unsized_locals, "CURRENT_RUSTC_VERSION", Some(48055), None), + ``` + + To avoid [semantic merge conflicts], please use `CURRENT_RUSTC_VERSION` instead of `1.70` or + another explicit version number. + + [semantic merge conflicts]: https://bors.tech/essay/2017/02/02/pitch/ -4. Prevent usage of the new feature unless the feature gate is set. +1. Prevent usage of the new feature unless the feature gate is set. You can check it in most places in the compiler using the expression `tcx.features().$feature_name` (or `sess.features_untracked().$feature_name` if the @@ -151,18 +175,18 @@ a new unstable feature: and then finally feature-gate all the spans in [`rustc_ast_passes::feature_gate::check_crate`]. -5. Add a test to ensure the feature cannot be used without - a feature gate, by creating `feature-gate-$feature_name.rs` - and `feature-gate-$feature_name.stderr` files under the - directory where the other tests for your feature reside. +1. Add a test to ensure the feature cannot be used without + a feature gate, by creating `tests/ui/feature-gates/feature-gate-$feature_name.rs`. + You can generate the corresponding `.stderr` file by running `./x test +tests/ui/feature-gates/ --bless`. -6. Add a section to the unstable book, in +1. Add a section to the unstable book, in `src/doc/unstable-book/src/language-features/$feature_name.md`. -7. Write a lot of tests for the new feature. +1. Write a lot of tests for the new feature, preferably in `tests/ui/$feature_name/`. PRs without tests will not be accepted! -8. Get your PR reviewed and land it. You have now successfully +1. Get your PR reviewed and land it. You have now successfully implemented a feature in Rust! [`GatedSpans`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.GatedSpans.html @@ -172,5 +196,5 @@ a new unstable feature: [value the stability of Rust]: https://github.com/rust-lang/rfcs/blob/master/text/1122-language-semver.md [stability in code]: #stability-in-code [here]: ./stabilization_guide.md -[tracking issue]: #tracking-issue +[tracking issue]: #tracking-issues [add-feature-gate]: ./feature-gates.md#adding-a-feature-gate diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index 8cd765011..2b1677ef4 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -199,7 +199,7 @@ statements is only implemented for LLVM, at this time. [backend-lowering-mir]: backend/lowering-mir.md [codegen-statement]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_statement [codegen-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_coverage -[function-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/coverageinfo/map/struct.FunctionCoverage.html +[function-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/map_data/struct.FunctionCoverage.html [instrprof-increment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/trait.BuilderMethods.html#tymethod.instrprof_increment ### Coverage Map Generation @@ -279,8 +279,8 @@ Coverage instrumentation in the MIR is validated by a `mir-opt` test: More complete testing of end-to-end coverage instrumentation and reports are done in the `run-make-fulldeps` tests, with sample Rust programs (to be -instrumented) in the [`coverage`][coverage-test-samples] directory, and the -actual tests and expected results in [`coverage-reports`]. +instrumented) in the [`tests/run-coverage`] directory, +together with the actual tests and expected results. Finally, the [`coverage-llvmir`] test compares compiles a simple Rust program with `-C instrument-coverage` and compares the compiled program's LLVM IR to @@ -292,13 +292,12 @@ Expected results for both the `mir-opt` tests and the `coverage*` tests under `run-make-fulldeps` can be refreshed by running: ```shell -$ ./x.py test mir-opt --bless -$ ./x.py test tests/run-make-fulldeps/coverage --bless +$ ./x test mir-opt --bless +$ ./x test tests/run-make-fulldeps/coverage --bless ``` [mir-opt-test]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs -[coverage-test-samples]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage -[`coverage-reports`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-reports +[`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage [spanview-debugging]: compiler-debugging.md#viewing-spanview-output [`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-llvmir @@ -466,7 +465,7 @@ function--[`bcb_from_bb()`][bcb-from-bb]--to look up a `BasicCoverageBlock` from [graph-traits]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/index.html#traits [mir-dev-guide]: mir/index.md [compute-basic-coverage-blocks]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.compute_basic_coverage_blocks -[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/struct.SimplifyCfg.html +[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/enum.SimplifyCfg.html [rust-lang/rust#78544]: https://github.com/rust-lang/rust/issues/78544 [mir-debugging]: mir/debugging.md [bcb-from-bb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.bcb_from_bb diff --git a/src/doc/rustc-dev-guide/src/macro-expansion.md b/src/doc/rustc-dev-guide/src/macro-expansion.md index 7f50f7f89..f3883223d 100644 --- a/src/doc/rustc-dev-guide/src/macro-expansion.md +++ b/src/doc/rustc-dev-guide/src/macro-expansion.md @@ -48,7 +48,7 @@ iteration, this represents a compile error. Here is the [algorithm][original]: [fef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.MacroExpander.html#method.fully_expand_fragment [original]: https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049 -1. Initialize an `queue` of unresolved macros. +1. Initialize a `queue` of unresolved macros. 2. Repeat until `queue` is empty (or we make no progress, which is an error): 1. [Resolve](./name-resolution.md) imports in our partially built crate as much as possible. diff --git a/src/doc/rustc-dev-guide/src/mir/optimizations.md b/src/doc/rustc-dev-guide/src/mir/optimizations.md index 293d2fe91..16cf2035b 100644 --- a/src/doc/rustc-dev-guide/src/mir/optimizations.md +++ b/src/doc/rustc-dev-guide/src/mir/optimizations.md @@ -34,7 +34,7 @@ optimizes it, and returns the improved MIR. `println!`, `format!`, etc. generate a lot of MIR that can make it harder to understand what the optimization does to the test. -2. Run `./x.py test --bless tests/mir-opt/.rs` to generate a MIR +2. Run `./x test --bless tests/mir-opt/.rs` to generate a MIR dump. Read [this README][mir-opt-test-readme] for instructions on how to dump things. @@ -45,16 +45,16 @@ optimizes it, and returns the improved MIR. 4. Implement a new optimization in [`compiler/rustc_mir_transform/src`]. The fastest and easiest way to do this is to - 1. pick a small optimization (such as [`no_landing_pads`]) and copy it + 1. pick a small optimization (such as [`remove_storage_markers`]) and copy it to a new file, 2. add your optimization to one of the lists in the [`run_optimization_passes()`] function, 3. and then start modifying the copied optimization. -5. Rerun `./x.py test --bless tests/mir-opt/.rs` to regenerate the +5. Rerun `./x test --bless tests/mir-opt/.rs` to regenerate the MIR dumps. Look at the diffs to see if they are what you expect. -6. Run `./x.py test tests/ui` to see if your optimization broke anything. +6. Run `./x test tests/ui` to see if your optimization broke anything. 7. If there are issues with your optimization, experiment with it a bit and repeat steps 5 and 6. @@ -72,8 +72,7 @@ If you have any questions along the way, feel free to ask in [mir-opt-test-readme]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/README.md [`compiler/rustc_mir_transform/src`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src - -[`no_landing_pads`]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_transform/src/no_landing_pads.rs +[`remove_storage_markers`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_mir_transform/src/remove_storage_markers.rs [`run_optimization_passes()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/fn.run_optimization_passes.html ## Defining optimization passes diff --git a/src/doc/rustc-dev-guide/src/mir/visitor.md b/src/doc/rustc-dev-guide/src/mir/visitor.md index 17186fe75..c0c703a6b 100644 --- a/src/doc/rustc-dev-guide/src/mir/visitor.md +++ b/src/doc/rustc-dev-guide/src/mir/visitor.md @@ -23,7 +23,7 @@ struct MyVisitor<...> { and you then implement the `Visitor` or `MutVisitor` trait for that type: ```rust,ignore -impl<'tcx> MutVisitor<'tcx> for NoLandingPads { +impl<'tcx> MutVisitor<'tcx> for MyVisitor { fn visit_foo(&mut self, ...) { ... self.super_foo(...); diff --git a/src/doc/rustc-dev-guide/src/name-resolution.md b/src/doc/rustc-dev-guide/src/name-resolution.md index 93c2a3eb7..fbeef19ff 100644 --- a/src/doc/rustc-dev-guide/src/name-resolution.md +++ b/src/doc/rustc-dev-guide/src/name-resolution.md @@ -117,7 +117,7 @@ fn do_something(val: T) { // <- New rib in both types and values (1) }; // End of (3) // `val` is accessible, `helper` variable shadows `helper` function fn helper() { // <- New rib in both types and values (4) - // `val` is not accessible here, (4) is not transparent for locals) + // `val` is not accessible here, (4) is not transparent for locals // `T` is not accessible here } // End of (4) let val = T::default(); // New rib (5) diff --git a/src/doc/rustc-dev-guide/src/notification-groups/about.md b/src/doc/rustc-dev-guide/src/notification-groups/about.md index a85c4a505..1307a50fc 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/about.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/about.md @@ -42,7 +42,7 @@ particularly those of **middle priority**: ## Joining a notification group -To join an notification group, you just have to open a PR adding your +To join a notification group, you just have to open a PR adding your Github username to the appropriate file in the Rust team repository. See the "example PRs" below to get a precise idea and to identify the file to edit. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md b/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md index 2e7b1766c..707334304 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md @@ -39,9 +39,9 @@ are a few: * The [rust-reduce](https://github.com/jethrogb/rust-reduce) tool can try to reduce code automatically. - * The [C-reduce](https://embed.cs.utah.edu/creduce/) tool also works + * The [C-reduce](https://github.com/csmith-project/creduce) tool also works on Rust code, though it requires that you start from a single - file. (XXX link to some post explaining how to do it?) + file. (A post explaining how to do it can be found [here](https://insaneinside.net/2017/09/12/whole-crate-bug-reduction-with-creduce.html).) * pnkfelix's [Rust Bug Minimization Patterns] blog post * This post focuses on "heavy bore" techniques, where you are starting with a large, complex cargo project that you wish to diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index de06c742b..797f4d8e2 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -286,7 +286,7 @@ of a crate.][passes] Then the codegen backend invokes the for that function and then creates codegen units. This kind of split will need to remain to ensure that unreachable functions still have their errors emitted. -[passes]: https://github.com/rust-lang/rust/blob/45ebd5808afd3df7ba842797c0fcd4447ddf30fb/src/librustc_interface/passes.rs#L824 +[passes]: https://github.com/rust-lang/rust/blob/e69c7306e2be08939d95f14229e3f96566fb206c/compiler/rustc_interface/src/passes.rs#L791 Moreover, the compiler wasn't originally built to use a query system; the query system has been retrofitted into the compiler, so parts of it are not query-fied diff --git a/src/doc/rustc-dev-guide/src/parallel-rustc.md b/src/doc/rustc-dev-guide/src/parallel-rustc.md index e7cbbd7ee..9942f751a 100644 --- a/src/doc/rustc-dev-guide/src/parallel-rustc.md +++ b/src/doc/rustc-dev-guide/src/parallel-rustc.md @@ -44,7 +44,6 @@ are implemented differently depending on whether `parallel-compiler` is true. | MappedWriteGuard | parking_lot::MappedRwLockWriteGuard | std::cell::RefMut | | LockGuard | parking_lot::MutexGuard | std::cell::RefMut | | MappedLockGuard | parking_lot::MappedMutexGuard | std::cell::RefMut | -| MetadataRef | [`OwningRef, [u8]>`][OwningRef] | [`OwningRef, [u8]>`][OwningRef] | - These thread-safe data structures interspersed during compilation can cause a lot of lock contention, which actually degrades performance as the @@ -164,4 +163,3 @@ are a bit out of date): [parallel-rustdoc]: https://github.com/rust-lang/rust/issues/82741 [Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html [Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html -[OwningRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/owning_ref/index.html diff --git a/src/doc/rustc-dev-guide/src/part-2-intro.md b/src/doc/rustc-dev-guide/src/part-2-intro.md index 5ea4d7b6b..aecab562b 100644 --- a/src/doc/rustc-dev-guide/src/part-2-intro.md +++ b/src/doc/rustc-dev-guide/src/part-2-intro.md @@ -1,4 +1,4 @@ -# Part 2: High-Level Compiler Architecture +# High-Level Compiler Architecture The remaining parts of this guide discuss how the compiler works. They go through everything from high-level structure of the compiler to how each stage diff --git a/src/doc/rustc-dev-guide/src/part-3-intro.md b/src/doc/rustc-dev-guide/src/part-3-intro.md index c10080632..59a1eeba7 100644 --- a/src/doc/rustc-dev-guide/src/part-3-intro.md +++ b/src/doc/rustc-dev-guide/src/part-3-intro.md @@ -1,4 +1,4 @@ -# Part 3: Source Code Representation +# Source Code Representation This part describes the process of taking raw source code from the user and transforming it into various forms that the compiler can work with easily. diff --git a/src/doc/rustc-dev-guide/src/part-4-intro.md b/src/doc/rustc-dev-guide/src/part-4-intro.md index 00a74f308..6a8433164 100644 --- a/src/doc/rustc-dev-guide/src/part-4-intro.md +++ b/src/doc/rustc-dev-guide/src/part-4-intro.md @@ -1,4 +1,4 @@ -# Part 4: Analysis +# Analysis This part discusses the many analyses that the compiler uses to check various properties of the code and to inform later stages. Typically, this is what people diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index e1666e237..df987e00a 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -19,7 +19,7 @@ Depending on what you're trying to measure, there are several different approach - If you want a nice visual representation of the compile times of your crate graph, you can use [cargo's `--timings` flag](https://doc.rust-lang.org/nightly/cargo/reference/timings.html), e.g. `cargo build --timings`. - You can use this flag on the compiler itself with `CARGOFLAGS="--timings" ./x.py build` + You can use this flag on the compiler itself with `CARGOFLAGS="--timings" ./x build` - If you want to profile memory usage, you can use various tools depending on what operating system you are using. @@ -41,11 +41,11 @@ extension in LLVM bitcode format. Example usage: ``` cargo install cargo-llvm-lines -# On a normal crate you could now run `cargo llvm-lines`, but `x.py` isn't normal :P +# On a normal crate you could now run `cargo llvm-lines`, but `x` isn't normal :P # Do a clean before every run, to not mix in the results from previous runs. -./x.py clean -env RUSTFLAGS=-Csave-temps ./x.py build --stage 0 compiler/rustc +./x clean +env RUSTFLAGS=-Csave-temps ./x build --stage 0 compiler/rustc # Single crate, e.g., rustc_middle. (Relies on the glob support of your shell.) # Convert unoptimized LLVM bitcode into a human readable LLVM assembly accepted by cargo-llvm-lines. @@ -85,7 +85,7 @@ Example output for the compiler: 326903 (0.7%) 642 (0.0%) rustc_query_system::query::plumbing::try_execute_query ``` -Since this doesn't seem to work with incremental compilation or `./x.py check`, +Since this doesn't seem to work with incremental compilation or `./x check`, you will be compiling rustc _a lot_. I recommend changing a few settings in `config.toml` to make it bearable: ``` diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_perf.md index c9bd88ecd..469e237b9 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_perf.md @@ -10,7 +10,7 @@ This is a guide for how to profile rustc with [perf](https://perf.wiki.kernel.or - `debuginfo-level = 1` - enables line debuginfo - `jemalloc = false` - lets you do memory use profiling with valgrind - leave everything else the defaults -- Run `./x.py build` to get a full build +- Run `./x build` to get a full build - Make a rustup toolchain pointing to that result - see [the "build and run" section for instructions][b-a-r] @@ -282,7 +282,7 @@ Tree What happens with `--tree-callees` is that - we find each sample matching the regular expression -- we look at the code that is occurs *after* the regex match and try +- we look at the code that occurs *after* the regex match and try to build up a call tree The `--tree-min-percent 3` option says "only show me things that take diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md index e7cf9418c..a800c5717 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md @@ -47,11 +47,11 @@ we'll need to build a stage 1 compiler and then a stage 2 compiler ourselves. To do this, make sure you have set `debuginfo-level = 1` in your `config.toml` file. This tells rustc to generate debug information which includes stack frames when bootstrapping. -Now you can build the stage 1 compiler: `python x.py build --stage 1 -i library` or however +Now you can build the stage 1 compiler: `x build --stage 1 -i library` or however else you want to build the stage 1 compiler. Now that the stage 1 compiler is built, we can record the stage 2 build. Go back to WPR, click the -"start" button and build the stage 2 compiler (e.g., `python x build --stage=2 -i library`). +"start" button and build the stage 2 compiler (e.g., `x build --stage=2 -i library`). When this process finishes, stop the recording. Click the Save button and once that process is complete, click the "Open in WPA" button which diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md index 5dbffac8d..782c5b4b3 100644 --- a/src/doc/rustc-dev-guide/src/query.md +++ b/src/doc/rustc-dev-guide/src/query.md @@ -103,7 +103,7 @@ When the tcx is created, it is given the providers by its creator using the [`Providers`][providers_struct] struct. This struct is generated by the macros here, but it is basically a big list of function pointers: -[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/query/struct.Providers.html +[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/struct.Providers.html ```rust,ignore struct Providers { diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md new file mode 100644 index 000000000..2ad9494e8 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md @@ -0,0 +1,419 @@ +# Return Position Impl Trait In Trait + +Return-position impl trait in trait (RPITIT) is conceptually (and as of +[#112988], literally) sugar that turns RPITs in trait methods into +generic associated types (GATs) without the user having to define that +GAT either on the trait side or impl side. + +RPITIT was originally implemented in [#101224], which added support for +async fn in trait (AFIT), since the implementation for RPITIT came for +free as a part of implementing AFIT which had been RFC'd previously. It +was then RFC'd independently in [RFC 3425], which was recently approved +by T-lang. + +## How does it work? + +This doc is ordered mostly via the compilation pipeline. AST -> HIR -> +astconv -> typeck. + +### AST and HIR + +AST -> HIR lowering for RPITITs is almost the same as lowering RPITs. We +still lower them as +[`hir::ItemKind::OpaqueTy`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.OpaqueTy.html). +The two differences are that: + +We record `in_trait` for the opaque. This will signify that the opaque +is an RPITIT for astconv, diagnostics that deal with HIR, etc. + +We record `lifetime_mapping`s for the opaque type, described below. + +#### Aside: Opaque lifetime duplication + +*All opaques* (not just RPITITs) end up duplicating their captured +lifetimes into new lifetime parameters local to the opaque. The main +reason we do this is because RPITs need to be able to "reify"[^1] any +captured late-bound arguments, or make them into early-bound ones. This +is so they can be used as substs for the opaque, and later to +instantiate hidden types. Since we don't know which lifetimes are early- +or late-bound during AST lowering, we just do this for all lifetimes. + +[^1]: This is compiler-errors terminology, I'm not claiming it's accurate :^) + +The main addition for RPITITs is that during lowering we track the +relationship between the captured lifetimes and the corresponding +duplicated lifetimes in an additional field, +[`OpaqueTy::lifetime_mapping`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.OpaqueTy.html#structfield.lifetime_mapping). +We use this lifetime mapping later on in `predicates_of` to install +bounds that enforce equality between these duplicated lifetimes and +their source lifetimes in order to properly typecheck these GATs, which +will be discussed below. + +##### note: + +It may be better if we were able to lower without duplicates and for +that I think we would need to stop distinguishing between early and late +bound lifetimes. So we would need a solution like [Account for +late-bound lifetimes in generics +#103448](https://github.com/rust-lang/rust/pull/103448) and then also a +PR similar to [Inherit function lifetimes for impl-trait +#103449](https://github.com/rust-lang/rust/pull/103449). + +### Astconv + +The main change to astconv is that we lower `hir::TyKind::OpaqueDef` for +an RPITIT to a projection instead of an opaque, using a newly +synthesized def-id for a new associated type in the trait. We'll +describe how exactly we get this def-id in the next section. + +This means that any time we call `ast_ty_to_ty` on the RPITIT, we end up +getting a projection back instead of an opaque. This projection can then +be normalized to the right value -- either the original opaque if we're +in the trait, or the inferred type of the RPITIT if we're in an impl. + +#### Lowering to synthetic associated types + +Using query feeding, we synthesize new associated types on both the +trait side and impl side for RPITITs that show up in methods. + +##### Lowering RPITITs in traits + +When `tcx.associated_item_def_ids(trait_def_id)` is called on a trait to +gather all of the trait's associated types, the query previously just +returned the def-ids of the HIR items that are children of the trait. +After [#112988], additionally, for each method in the trait, we add the +def-ids returned by +`tcx.associated_types_for_impl_traits_in_associated_fn(trait_method_def_id)`, +which walks through each trait method, gathers any RPITITs that show up +in the signature, and then calls +`associated_type_for_impl_trait_in_trait` for each RPITIT, which +synthesizes a new associated type. + +##### Lowering RPITITs in impls + +Similarly, along with the impl's HIR items, for each impl method, we +additionally add all of the +`associated_types_for_impl_traits_in_associated_fn` for the impl method. +This calls `associated_type_for_impl_trait_in_impl`, which will +synthesize an associated type definition for each RPITIT that comes from +the corresponding trait method. + +#### Synthesizing new associated types + +We use query feeding +([`TyCtxtAt::create_def`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/plumbing/struct.TyCtxtAt.html#method.create_def)) +to synthesize a new def-id for the synthetic GATs for each RPITIT. + +Locally, most of rustc's queries match on the HIR of an item to compute +their values. Since the RPITIT doesn't really have HIR associated with +it, or at least not HIR that corresponds to an associated type, we must +compute many queries eagerly and +[feed](https://github.com/rust-lang/rust/pull/104940) them, like +`opt_def_kind`, `associated_item`, `visibility`, and`defaultness`. + +The values for most of these queries is obvious, since the RPITIT +conceptually inherits most of its information from the parent function +(e.g. `visibility`), or because it's trivially knowable because it's an +associated type (`opt_def_kind`). + +Some other queries are more involved, or cannot be feeded, and we +document the interesting ones of those below: + +##### `generics_of` for the trait + +The GAT for an RPITIT conceptually inherits the same generics as the +RPIT it comes from. However, instead of having the method as the +generics' parent, the trait is the parent. + +Currently we get away with taking the RPIT's generics and method +generics and flattening them both into a new generics list, preserving +the def-id of each of the parameters. (This may cause issues with +def-ids having the wrong parents, but in the worst case this will cause +diagnostics issues. If this ends up being an issue, we can synthesize +new def-ids for generic params whose parent is the GAT.) + +
+ An illustrated example + +```rust +trait Foo { + fn method<'early: 'early, 'late, T>() -> impl Sized + Captures<'early, 'late>; +} +``` + +Would desugar to... +```rust +trait Foo { + // vvvvvvvvv method's generics + // vvvvvvvvvvvvvvvvvvvvvvvv opaque's generics + type Gat<'early, T, 'early_duplicated, 'late>: Sized + Captures<'early_duplicated, 'late>; + + fn method<'early: 'early, 'late, T>() -> Self::Gat<'early, T, 'early, 'late>; +} +``` +
+ +##### `generics_of` for the impl + +The generics for an impl's GAT are a bit more interesting. They are +composed of RPITIT's own generics (from the trait definition), appended +onto the impl's methods generics. This has the same issue as above, +where the generics for the GAT have parameters whose def-ids have the +wrong parent, but this should only cause issues in diagnostics. + +We could fix this similarly if we were to synthesize new generics +def-ids, but this can be done later in a forwards-compatible way, +perhaps by a interested new contributor. + +##### `opt_rpitit_info` + +Some queries rely on computing information that would result in cycles +if we were to feed them eagerly, like `explicit_predicates_of`. +Therefore we defer to the `predicates_of` provider to return the right +value for our RPITIT's GAT. We do this by detecting early on in the +query if the associated type is synthetic by using +[`opt_rpitit_info`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.opt_rpitit_info), +which returns `Some` if the associated type is synthetic. + +Then, during a query like `explicit_predicates_of`, we can detect if an +associated type is synthetic like: + +```rust +fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ... { + if let Some(rpitit_info) = tcx.opt_rpitit_info(def_id) { + // Do something special for RPITITs... + return ...; + } + + // The regular computation which relies on access to the HIR of `def_id`. +} +``` + +##### `explicit_predicates_of` + +RPITITs begin by copying the predicates of the method that defined it, +both on the trait and impl side. + +Additionally, we install "bidirectional outlives" predicates. +Specifically, we add region-outlives predicates in both directions for +each captured early-bound lifetime that constrains it to be equal to the +duplicated early-bound lifetime that results from lowering. This is best +illustrated in an example: + +```rust +trait Foo<'a> { + fn bar() -> impl Sized + 'a; +} + +// Desugars into... + +trait Foo<'a> { + type Gat<'a_duplicated>: Sized + 'a + where + 'a: 'a_duplicated, + 'a_duplicated: 'a; + //~^ Specifically, we should be able to assume that the + // duplicated `'a_duplicated` lifetime always stays in + // sync with the `'a` lifetime. + + fn bar() -> Self::Gat<'a>; +} +``` + +##### `assumed_wf_types` + +The GATs in both the trait and impl inherit the `assumed_wf_types` of +the trait method that defines the RPITIT. This is to make sure that the +following code is well formed when lowered. + +```rust +trait Foo { + fn iter<'a, T>(x: &'a [T]) -> impl Iterator; +} + +// which is lowered to... + +trait FooDesugared { + type Iter<'a, T>: Iterator; + //~^ assumed wf: `&'a [T]` + // Without assumed wf types, the GAT would not be well-formed on its own. + + fn iter<'a, T>(x: &'a [T]) -> Self::Iter<'a, T>; +} +``` + +Because `assumed_wf_types` is only defined for local def ids, in order +to properly implement `assumed_wf_types` for impls of foreign traits +with RPITs, we need to encode the assumed wf types of RPITITs in an +extern query +[`assumed_wf_types_for_rpitit`](https://github.com/rust-lang/rust/blob/a17c7968b727d8413801961fc4e89869b6ab00d3/compiler/rustc_ty_utils/src/implied_bounds.rs#L14). + +### Typechecking + +#### The RPITIT inference algorithm + +The RPITIT inference algorithm is implemented in +[`collect_return_position_impl_trait_in_trait_tys`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.collect_return_position_impl_trait_in_trait_tys.html). + +**High-level:** Given a impl method and a trait method, we take the +trait method and instantiate each RPITIT in the signature with an infer +var. We then equate this trait method signature with the impl method +signature, and process all obligations that fall out in order to infer +the type of all of the RPITITs in the method. + +The method is also responsible for making sure that the hidden types for +each RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that +if we infer `impl Trait = Foo`, that `Foo: Trait` holds. + +
+ An example... + +```rust +#![feature(return_position_impl_trait_in_trait)] + +use std::ops::Deref; + +trait Foo { + fn bar() -> impl Deref; + // ^- RPITIT ?0 ^- RPITIT ?1 +} + +impl Foo for () { + fn bar() -> Box { Box::new(String::new()) } +} +``` + +We end up with the trait signature that looks like `fn() -> ?0`, and +nested obligations `?0: Deref`, `?1: Sized`. The impl +signature is `fn() -> Box`. + +Equating these signatures gives us `?0 = Box`, which then after +processing the obligation `Box: Deref` gives us `?1 += String`, and the other obligation `String: Sized` evaluates to true. + +By the end of the algorithm, we end up with a mapping between associated +type def-ids to concrete types inferred from the signature. We can then +use this mapping to implement `type_of` for the synthetic associated +types in the impl, since this mapping describes the type that should +come after the `=` in `type Assoc = ...` for each RPITIT. +
+ +#### Default trait body + +Type-checking a default trait body, like: + +```rust +trait Foo { + fn bar() -> impl Sized { + 1i32 + } +} +``` + +requires one interesting hack. We need to install a projection predicate +into the param-env of `Foo::bar` allowing us to assume that the RPITIT's +GAT normalizes to the RPITIT's opaque type. This relies on the +observation that a trait method and RPITIT's GAT will always be "in +sync". That is, one will only ever be overridden if the other one is as +well. + +Compare this to a similar desugaring of the code above, which would fail +because we cannot rely on this same assumption: + +```rust +#![feature(impl_trait_in_assoc_type)] +#![feature(associated_type_defaults)] + +trait Foo { + type RPITIT = impl Sized; + + fn bar() -> Self::RPITIT { + 01i32 + } +} +``` + +Failing because a down-stream impl could theoretically provide an +implementation for `RPITIT` without providing an implementation of +`foo`: + +```text +error[E0308]: mismatched types +--> src/lib.rs:8:9 + | +5 | type RPITIT = impl Sized; + | ------------------------- associated type defaults can't be assumed inside the trait defining them +6 | +7 | fn bar() -> Self::RPITIT { + | ------------ expected `::RPITIT` because of return type +8 | 01i32 + | ^^^^^ expected associated type, found `i32` + | + = note: expected associated type `::RPITIT` + found type `i32` +``` + +#### Well-formedness checking + +We check well-formedness of RPITITs just like regular associated types. + +Since we added lifetime bounds in `predicates_of` that link the +duplicated early-bound lifetimes to their original lifetimes, and we +implemented `assumed_wf_types` which inherits the WF types of the method +from which the RPITIT originates ([#113704]), we have no issues +WF-checking the GAT as if it were a regular GAT. + +### What's broken, what's weird, etc. + +##### Specialization is super busted + +The "default trait methods" described above does not interact well with +specialization, because we only install those projection bounds in trait +default methods, and not in impl methods. Given that specialization is +already pretty busted, I won't go into detail, but it's currently a bug +tracked in: + * `tests/ui/impl-trait/in-trait/specialization-broken.rs` + +##### Projections don't have variances + +This code fails because projections don't have variances: +```rust +#![feature(return_position_impl_trait_in_trait)] + +trait Foo { + // Note that the RPITIT below does *not* capture `'lt`. + fn bar<'lt: 'lt>() -> impl Eq; +} + +fn test<'a, 'b, T: Foo>() -> bool { + ::bar::<'a>() == ::bar::<'b>() + //~^ ERROR + // (requires that `'a == 'b`) +} +``` + +This is because we can't relate `::Rpitit<'a>` and `::Rpitit<'b>`, even if they don't capture their lifetime. If we were +using regular opaque types, this would work, because they would be +bivariant in that lifetime parameter: +```rust +#![feature(return_position_impl_trait_in_trait)] + +fn bar<'lt: 'lt>() -> impl Eq { + () +} + +fn test<'a, 'b>() -> bool { + bar::<'a>() == bar::<'b>() +} +``` + +This is probably okay though, since RPITITs will likely have their +captures behavior changed to capture all in-scope lifetimes anyways. +This could also be relaxed later in a forwards-compatible way if we were +to consider variances of RPITITs when relating projections. + +[#112988]: https://github.com/rust-lang/rust/pull/112988 +[RFC 3425]: https://github.com/rust-lang/rfcs/pull/3425 +[#101224]: https://github.com/rust-lang/rust/pull/101224 +[#113704]: https://github.com/rust-lang/rust/pull/113704 diff --git a/src/doc/rustc-dev-guide/src/rustc-driver.md b/src/doc/rustc-dev-guide/src/rustc-driver.md index 192811da1..bae98c746 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver.md @@ -32,7 +32,7 @@ as well as allowing some custom code run after different phases of the compilati [cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html -[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html +[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html [i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-example.rs [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index d58c2d280..e78c4bb25 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -173,6 +173,8 @@ running the Markdown parser. There's also a function in here (`find_testable_code`) that specifically scans for Rust code blocks so the test-runner code can find all the doctests in the crate. +[Askama]: https://docs.rs/askama/latest/askama/ + ### From soup to nuts (alternate title: ["An unbroken thread that stretches from those first `Cell`s @@ -279,7 +281,7 @@ server. To test these features locally, you can run a local HTTP server, like this: ```bash -$ ./x.py doc library +$ ./x doc library # The documentation has been generated into `build/[YOUR ARCH]/doc`. $ python3 -m http.server -d build/[YOUR ARCH]/doc ``` diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index cbe5e8b1f..02da8be81 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -41,24 +41,24 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) ## Cheat sheet -* Run `./x.py setup tools` before getting started. This will configure `x.py` +* Run `./x setup tools` before getting started. This will configure `x` with nice settings for developing rustdoc and other tools, including downloading a copy of rustc rather than building it. -* Use `./x.py check src/tools/rustdoc` to quickly check for compile errors. -* Use `./x.py build` to make a usable +* Use `./x check src/tools/rustdoc` to quickly check for compile errors. +* Use `./x build` to make a usable rustdoc you can run on other projects. * Add `library/test` to be able to use `rustdoc --test`. * Run `rustup toolchain link stage2 build/host/stage2` to add a custom toolchain called `stage2` to your rustup environment. After running that, `cargo +stage2 doc` in any directory will build with your locally-compiled rustdoc. -* Use `./x.py doc library` to use this rustdoc to generate the +* Use `./x doc library` to use this rustdoc to generate the standard library docs. * The completed docs will be available in `build/host/doc` (under `core`, `alloc`, and `std`). * If you want to copy those docs to a webserver, copy all of `build/host/doc`, since that's where the CSS, JS, fonts, and landing page are. -* Use `./x.py test tests/rustdoc*` to run the tests using a stage1 +* Use `./x test tests/rustdoc*` to run the tests using a stage1 rustdoc. * See [Rustdoc internals] for more information about tests. diff --git a/src/doc/rustc-dev-guide/src/salsa.md b/src/doc/rustc-dev-guide/src/salsa.md index 66f9d7479..47442ae14 100644 --- a/src/doc/rustc-dev-guide/src/salsa.md +++ b/src/doc/rustc-dev-guide/src/salsa.md @@ -148,9 +148,9 @@ this one depends on by specifying them as supertraits, as seen in the following example: ```rust,ignore -/// This query group is going to contain queries that depend on derived values a +/// This query group is going to contain queries that depend on derived values. A /// query group can access another query group's queries by specifying the -/// dependency as a super trait query groups can be stacked as much as needed using +/// dependency as a super trait. Query groups can be stacked as much as needed using /// that pattern. #[salsa::query_group(ParserStorage)] pub trait Parser: Inputs { @@ -168,7 +168,7 @@ belongs to, in addition to the other keys. ```rust,ignore ///This is going to be the definition of the `ast` query in the `Parser` trait. ///So, when the query `ast` is invoked, and it needs to be recomputed, Salsa is going to call this function -///and it's is going to give it the database as `impl Parser`. +///and it's going to give it the database as `impl Parser`. ///The function doesn't need to be aware of all the queries of all the query groups fn ast(db: &impl Parser, name: String) -> String { //! Note, `impl Parser` is used here but `dyn Parser` works just as well diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 21b07ec99..27d40a11a 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -98,7 +98,7 @@ To enable a sanitizer on a new target which is already supported by LLVM: 2. [Build the runtime for the target and include it in the libdir.][sanitizer-targets] 3. [Teach compiletest that your target now supports the sanitizer.][compiletest-definition] Tests marked with `needs-sanitizer-*` should now run on the target. -4. Run tests `./x.py test --force-rerun tests/ui/sanitize/` to verify. +4. Run tests `./x test --force-rerun tests/ui/sanitize/` to verify. 5. [--enable-sanitizers in the CI configuration][ci-configuration] to build and distribute the sanitizer runtime as part of the release process. diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md index 691d21bc2..78b065311 100644 --- a/src/doc/rustc-dev-guide/src/serialization.md +++ b/src/doc/rustc-dev-guide/src/serialization.md @@ -109,7 +109,7 @@ and `Encodable`. only allow decoding by [`rustc_metadata::rmeta::encoder::EncodeContext`] and [`rustc_metadata::rmeta::decoder::DecodeContext`]. These are used for types that contain `rustc_metadata::rmeta::Lazy`. -- `TyEncodable` and `TyDecoder` generate implementation that apply to any +- `TyEncodable` and `TyDecodable` generate implementation that apply to any `TyEncoder` or `TyDecoder`. These should be used for types that are only serialized in crate metadata and/or the incremental cache, which is most serializable types in `rustc_middle`. @@ -130,7 +130,7 @@ some deserialization needs to be deferred from the initial loading of metadata. The [`LazyValue`] type wraps the (relative) offset in the crate metadata where a `T` has been serialized. There are also some variants, [`LazyArray`] and [`LazyTable`]. -The `Lazy<[T]>` and `LazyTable` type provide some functionality over +The `Lazy<[T]>` and `LazyTable` types provide some functionality over `Lazy>` and `Lazy>`: - It's possible to encode a `LazyArray` directly from an iterator, without diff --git a/src/doc/rustc-dev-guide/src/solve/normalization.md b/src/doc/rustc-dev-guide/src/solve/normalization.md new file mode 100644 index 000000000..653c976a4 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/solve/normalization.md @@ -0,0 +1,80 @@ +# Normalization in the new solver + +With the new solver we've made some fairly significant changes to normalization when compared +to the existing implementation. + +We now differentiate between "shallow normalization" and "deep normalization". +"Shallow normalization" normalizes a type until it is no-longer a potentially normalizeable alias; +it does not recurse into the type. "deep normalization" replaces all normalizeable aliases in a +type with its underlying type. + +The old trait solver currently always deeply normalizes via `Projection` obligations. +This is the only way to normalize in the old solver. By replacing projections with a new +inference variable and then emitting `Projection(::Assoc, ?new_infer)` the old +solver successfully deeply normalizes even in the case of ambiguity. This approach does not +work for projections referencing bound variables. + +## Inside of the trait solver + +Normalization in the new solver exclusively happens via `Projection`[^0] goals. +This only succeeds by first normalizing the alias by one level and then equating +it with the expected type. This differs from [the behavior of projection clauses] +which can also be proven by successfully equating the projection without normalizating. +This means that `Projection`[^0] goals must only be used in places where we +*have to normalize* to make progress. To normalize `::Assoc`, we first create +a fresh inference variable `?normalized` and then prove +`Projection(::Assoc, ?normalized)`[^0]. `?normalized` is then constrained to +the underlying type. + +Inside of the trait solver we never deeply normalize. we only apply shallow normalization +in [`assemble_candidates_after_normalizing_self_ty`] and inside for [`AliasRelate`] +goals for the [`normalizes-to` candidates]. + +## Outside of the trait solver + +The core type system - relating types and trait solving - will not need deep +normalization with the new solver. There are still some areas which depend on it. +For these areas there is the function `At::deeply_normalize`. Without additional +trait solver support deep normalization does not always work in case of ambiguity. +Luckily deep normalization is currently only necessary in places where there is no ambiguity. +`At::deeply_normalize` immediately fails if there's ambiguity. + +If we only care about the outermost layer of types, we instead use +`At::structurally_normalize` or `FnCtxt::(try_)structurally_resolve_type`. +Unlike `At::deeply_normalize`, shallow normalization is also used in cases where we +have to handle ambiguity. `At::structurally_normalize` normalizes until the self type +is either rigid or an inference variable and we're stuck with ambiguity. This means +that the self type may not be fully normalized after `At::structurally_normalize` was called. + +Because this may result in behavior changes depending on how the trait solver handles +ambiguity, it is safer to also require full normalization there. This happens in +`FnCtxt::structurally_resolve_type` which always emits a hard error if the self type ends +up as an inference variable. There are some existing places which have a fallback for +inference variables instead. These places use `try_structurally_resolve_type` instead. + +## Why deep normalization with ambiguity is hard + +Fully correct deep normalization is very challenging, especially with the new solver +given that we do not want to deeply normalize inside of the solver. Mostly deeply normalizing +but sometimes failing to do so is bound to cause very hard to minimize and understand bugs. +If possible, avoiding any reliance on deep normalization entirely therefore feels preferable. + +If the solver itself does not deeply normalize, any inference constraints returned by the +solver would require normalization. Handling this correctly is ugly. This also means that +we change goals we provide to the trait solver by "normalizing away" some projections. + +The way we (mostly) guarantee deep normalization with the old solver is by eagerly replacing +the projection with an inference variable and emitting a nested `Projection` goal. This works +as `Projection` goals in the old solver deeply normalize. Unless we add another `PredicateKind` +for deep normalization to the new solver we cannot emulate this behavior. This does not work +for projections with bound variables, sometimes leaving them unnormalized. An approach which +also supports projections with bound variables will be even more involved. + + +[`assemble_candidates_after_normalizing_self_ty`]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L330-L378 +[`AliasRelate`]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/alias_relate.rs#L16-L102 +[`normalizes-to` candidates]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/alias_relate.rs#L105-L151 +[the behavior of projection clauses]: https://github.com/rust-lang/trait-system-refactor-initiative/issues/1 +[normalize-via-infer]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L350-L358 + +[^0]: TODO: currently refactoring this to use `NormalizesTo` predicates instead. \ No newline at end of file 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 b0cd9af6c..c3089f4a8 100644 --- a/src/doc/rustc-dev-guide/src/solve/trait-solving.md +++ b/src/doc/rustc-dev-guide/src/solve/trait-solving.md @@ -97,7 +97,7 @@ all free regions during codegen we must not rely on them during typeck. A notewo 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 +This is fine for codegen, as we treat all erased regions as equal. We can however lose equality information from HIR to MIR typeck. ### 7. Removing ambiguity makes strictly more things compile @@ -111,8 +111,8 @@ Two types being equal in the type system must mean that they have the same `Type [solve]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/index.html -[`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/struct.Goal.html +[`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/struct.Goal.html [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html [`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/struct.Candidate.html [`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/enum.CandidateSource.html -[`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/type.CanonicalResponse.html +[`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/type.CanonicalResponse.html diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index 85c75fadb..bf82d8517 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -1,12 +1,12 @@ # Stability attributes - - This section is about the stability attributes and schemes that allow stable APIs to use unstable APIs internally in the rustc standard library. -For instructions on stabilizing a language feature see [Stabilizing -Features](./stabilization_guide.md). +**NOTE**: this section is for *library* features, not *language* features. For instructions on +stabilizing a language feature see [Stabilizing Features](./stabilization_guide.md). + + ## unstable diff --git a/src/doc/rustc-dev-guide/src/stabilization_guide.md b/src/doc/rustc-dev-guide/src/stabilization_guide.md index 0ac19293b..001ed25a5 100644 --- a/src/doc/rustc-dev-guide/src/stabilization_guide.md +++ b/src/doc/rustc-dev-guide/src/stabilization_guide.md @@ -1,6 +1,6 @@ # Request for stabilization -**NOTE**: this page is about stabilizing language features. +**NOTE**: this page is about stabilizing *language* features. For stabilizing *library* features, see [Stabilizing a library feature]. [Stabilizing a library feature]: ./stability.md#stabilizing-a-library-feature diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index 632614539..fc0c4937e 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -84,7 +84,7 @@ The next step is to create the expected output from the compiler. This can be done with the `--bless` option: ```sh -./x.py test tests/ui/async-await/await-without-async.rs --bless +./x test tests/ui/async-await/await-without-async.rs --bless ``` This will build the compiler (if it hasn't already been built), compile the @@ -118,7 +118,7 @@ annotations](ui.md#error-annotations) section). Save that, and run the test again: ```sh -./x.py test tests/ui/async-await/await-without-async.rs +./x test tests/ui/async-await/await-without-async.rs ``` It should now pass, yay! @@ -166,7 +166,7 @@ The final step before posting a PR is to check if you have affected anything els Running the UI suite is usually a good start: ```sh -./x.py test tests/ui +./x test tests/ui ``` If other tests start failing, you may need to investigate what has changed diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index cca4973cb..bfdc2a45a 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -6,7 +6,7 @@ When a Pull Request is opened on GitHub, [GitHub Actions] will automatically launch a build that will run all tests on some configurations (x86_64-gnu-llvm-13 linux, x86_64-gnu-tools linux, and mingw-check linux). -In essence, each runs `./x.py test` with various different options. +In essence, each runs `./x test` with various different options. The integration bot [bors] is used for coordinating merges to the master branch. When a PR is approved, it goes into a [queue] where merges are tested one at a @@ -54,8 +54,8 @@ the other jobs. The comment at the top of `ci.yml` will tell you to run this command: ```sh -./x.py run src/tools/expand-yaml-anchors -```` +./x run src/tools/expand-yaml-anchors +``` This will generate the true [`.github/workflows/ci.yml`] which is what GitHub Actions uses. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index d4730c5b4..86ebe3a49 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -330,7 +330,7 @@ set a baseline for optimizations: The test should be annotated with `// EMIT_MIR` comments that specify files that will contain the expected MIR output. -You can use `x.py test --bless` to create the initial expected files. +You can use `x test --bless` to create the initial expected files. There are several forms the `EMIT_MIR` comment can take: @@ -380,7 +380,7 @@ There is a [`tools.mk`] Makefile which you can include which provides a bunch of utilities to make it easier to run commands and compare outputs. Take a look at some of the other tests for some examples on how to get started. -[`tools.mk`]: https://github.com/rust-lang/rust/blob/master/tests/run-make-fulldeps/tools.mk +[`tools.mk`]: https://github.com/rust-lang/rust/blob/master/tests/run-make/tools.mk [`tests/run-make`]: https://github.com/rust-lang/rust/tree/master/tests/run-make @@ -452,7 +452,7 @@ compiler, and `no-prefer-dynamic` is needed to tell compiletest to not use `prefer-dynamic` which is not compatible with proc-macros. The `#![crate_type]` attribute is needed to specify the correct crate-type. -Then in your test, you can build with with `aux-build`: +Then in your test, you can build with `aux-build`: ```rust,ignore // aux-build: my-proc-macro.rs @@ -503,10 +503,9 @@ currently only apply to the test as a whole, not to particular revisions. The only headers that are intended to really work when customized to a revision are error patterns and compiler flags. - ## Compare modes -Compiletest can be run in different modes, called *compare modes*, which can +Compiletest can be run in different modes, called _compare modes_, which can be used to compare the behavior of all tests with different compiler flags enabled. This can help highlight what differences might appear with certain flags, and @@ -516,7 +515,7 @@ To run the tests in a different mode, you need to pass the `--compare-mode` CLI flag: ```bash -./x.py test tests/ui --compare-mode=chalk +./x test tests/ui --compare-mode=chalk ``` The possible compare modes are: @@ -537,5 +536,5 @@ following settings: enabling split-DWARF. Note that compare modes are separate to [revisions](#revisions). -All revisions are tested when running `./x.py test tests/ui`, however +All revisions are tested when running `./x test tests/ui`, however compare-modes must be manually run individually via the `--compare-mode` flag. diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md index 0d9e0a492..31e3825f5 100644 --- a/src/doc/rustc-dev-guide/src/tests/docker.md +++ b/src/doc/rustc-dev-guide/src/tests/docker.md @@ -21,7 +21,7 @@ directory. From there, you can run `../src/ci/run.sh` which will run the build as defined by the image. Alternatively, you can run individual commands to do specific tasks. For -example, you can run `python3 ../x.py test tests/ui` to just run UI tests. +example, you can run `../x test tests/ui` to just run UI tests. Note that there is some configuration in the [`src/ci/run.sh`] script that you may need to recreate. Particularly, set `submodules = false` in your `config.toml` so that it doesn't attempt to modify the read-only directory. diff --git a/src/doc/rustc-dev-guide/src/tests/headers.md b/src/doc/rustc-dev-guide/src/tests/headers.md index 682c96b44..f066dbbb5 100644 --- a/src/doc/rustc-dev-guide/src/tests/headers.md +++ b/src/doc/rustc-dev-guide/src/tests/headers.md @@ -28,7 +28,7 @@ Header commands can be standalone (like `// run-pass`) or take a value (like ## Header commands The following is a list of header commands. -Commands are linked to sections the describe the command in more detail if available. +Commands are linked to sections that describe the command in more detail if available. This list may not be exhaustive. Header commands can generally be found by browsing the `TestProps` structure found in [`header.rs`] from the compiletest source. @@ -70,7 +70,6 @@ found in [`header.rs`] from the compiletest source. * `min-llvm-versionX` * `min-system-llvm-version` * `ignore-llvm-version` - * `ignore-llvm-version` * [Environment variable headers](#environment-variable-headers) * `rustc-env` * `exec-env` @@ -145,7 +144,7 @@ The following header commands will check rustc build settings and target setting (AddressSanitizer, hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or ThreadSanitizer respectively) * `needs-run-enabled` — ignores if it is a test that gets executed, and - running has been disabled. Running tests can be disabled with the `x.py test + running has been disabled. Running tests can be disabled with the `x test --run=never` flag, or running on fuchsia. * `needs-unwind` — ignores if the target does not support unwinding * `needs-rust-lld` — ignores if the rust lld support is not enabled diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index adc5d58ec..647d1fbea 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -3,14 +3,14 @@ The Rust project runs a wide variety of different tests, orchestrated by -the build system (`./x.py test`). +the build system (`./x test`). This section gives a brief overview of the different testing tools. Subsequent chapters dive into [running tests](running.md) and [adding new tests](adding.md). ## Kinds of tests There are several kinds of tests to exercise things in the Rust distribution. -Almost all of them are driven by `./x.py test`, with some exceptions noted below. +Almost all of them are driven by `./x test`, with some exceptions noted below. ### Compiletest @@ -19,7 +19,7 @@ It supports running different styles of tests, called *test suites*. The tests are all located in the [`tests`] directory. The [Compiletest chapter][compiletest] goes into detail on how to use this tool. -> Example: `./x.py test tests/ui` +> Example: `./x test tests/ui` [compiletest]: compiletest.md [`tests`]: https://github.com/rust-lang/rust/tree/master/tests @@ -29,23 +29,23 @@ The [Compiletest chapter][compiletest] goes into detail on how to use this tool. The standard library and many of the compiler packages include typical Rust `#[test]` unit tests, integration tests, and documentation tests. You can pass a path to `x.py` to almost any package in the `library` or `compiler` directory, -and `x.py` will essentially run `cargo test` on that package. +and `x` will essentially run `cargo test` on that package. Examples: -| Command | Description | -|---------|-------------| -| `./x.py test library/std` | Runs tests on `std` only | -| `./x.py test library/core` | Runs tests on `core` only | -| `./x.py test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | +| Command | Description | +| ----------------------------------------- | ------------------------------------- | +| `./x test library/std` | Runs tests on `std` only | +| `./x test library/core` | Runs tests on `core` only | +| `./x test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | The standard library relies very heavily on documentation tests to cover its functionality. However, unit tests and integration tests can also be used as needed. Almost all of the compiler packages have doctests disabled. -The standard library and compiler always place all unit tests in a separate `tests` file -(this is enforced in [tidy][tidy-unit-tests]). -This approach ensures that when the test file is changed, the crate does not need to be recompiled. +All standard library and compiler unit tests are placed in separate `tests` file +(which is enforced in [tidy][tidy-unit-tests]). +This ensures that when the test file is changed, the crate does not need to be recompiled. For example: ```rust,ignore @@ -53,12 +53,11 @@ For example: mod tests; ``` -If it wasn't done this way, and the tests were placed in the same file as the source, -then changing or adding a test would cause the crate you are working on to be recompiled. -If you were working on something like `core`, -then that would require recompiling the entire standard library, and the entirety of `rustc`. +If it wasn't done this way, +and you were working on something like `core`, +that would require recompiling the entire standard library, and the entirety of `rustc`. -`./x.py test` includes some CLI options for controlling the behavior with these tests: +`./x test` includes some CLI options for controlling the behavior with these tests: * `--doc` — Only runs documentation tests in the package. * `--no-doc` — Run all tests *except* documentation tests. @@ -71,7 +70,7 @@ Tidy is a custom tool used for validating source code style and formatting conve such as rejecting long lines. There is more information in the [section on coding conventions](../conventions.md#formatting). -> Example: `./x.py test tidy` +> Example: `./x test tidy` ### Formatting @@ -80,28 +79,28 @@ The formatting check is automatically run by the Tidy tool mentioned above. Examples: -| Command | Description | -|---------|-------------| -| `./x.py fmt --check` | Checks formatting and exits with an error if formatting is needed. | -| `./x.py fmt` | Runs rustfmt across the entire codebase. | -| `./x.py test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | +| Command | Description | +| ----------------------- | ------------------------------------------------------------------ | +| `./x fmt --check` | Checks formatting and exits with an error if formatting is needed. | +| `./x fmt` | Runs rustfmt across the entire codebase. | +| `./x test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | ### Book documentation tests All of the books that are published have their own tests, primarily for validating that the Rust code examples pass. Under the hood, these are essentially using `rustdoc --test` on the markdown files. -The tests can be run by passing a path to a book to `./x.py test`. +The tests can be run by passing a path to a book to `./x test`. -> Example: `./x.py test src/doc/book` +> Example: `./x test src/doc/book` ### Documentation link checker Links across all documentation is validated with a link checker tool. -> Example: `./x.py test src/tools/linkchecker` +> Example: `./x test src/tools/linkchecker` -> Example: `./x.py test linkchecker` +> Example: `./x test linkchecker` This requires building all of the documentation, which might take a while. @@ -110,7 +109,7 @@ This requires building all of the documentation, which might take a while. `distcheck` verifies that the source distribution tarball created by the build system will unpack, build, and run all tests. -> Example: `./x.py test distcheck` +> Example: `./x test distcheck` ### Tool tests @@ -119,9 +118,9 @@ This includes things such as cargo, clippy, rustfmt, miri, bootstrap (testing the Rust build system itself), etc. Most of the tools are located in the [`src/tools`] directory. -To run the tool's tests, just pass its path to `./x.py test`. +To run the tool's tests, just pass its path to `./x test`. -> Example: `./x.py test src/tools/cargo` +> Example: `./x test src/tools/cargo` Usually these tools involve running `cargo test` within the tool's directory. @@ -139,7 +138,7 @@ More information can be found in the [toolstate documentation]. (such as `servo`, `ripgrep`, `tokei`, etc.). This ensures there aren't any significant regressions. -> Example: `./x.py test src/tools/cargotest` +> Example: `./x test src/tools/cargotest` ### Crater diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 0a3de6f8b..71fb82b68 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -2,11 +2,11 @@ -You can run the tests using `x.py`. The most basic command – which +You can run the tests using `x`. The most basic command – which you will almost never want to use! – is as follows: ```bash -./x.py test +./x test ``` This will build the stage 1 compiler and then run the whole test @@ -37,7 +37,7 @@ modifying rustc to see if things are generally working correctly would be the following: ```bash -./x.py test tests/ui +./x test tests/ui ``` This will run the `ui` test suite. Of course, the choice @@ -46,32 +46,32 @@ doing. For example, if you are hacking on debuginfo, you may be better off with the debuginfo test suite: ```bash -./x.py test tests/debuginfo +./x test tests/debuginfo ``` If you only need to test a specific subdirectory of tests for any -given test suite, you can pass that directory to `./x.py test`: +given test suite, you can pass that directory to `./x test`: ```bash -./x.py test tests/ui/const-generics +./x test tests/ui/const-generics ``` Likewise, you can test a single file by passing its path: ```bash -./x.py test tests/ui/const-generics/const-test.rs +./x test tests/ui/const-generics/const-test.rs ``` ### Run only the tidy script ```bash -./x.py test tidy +./x test tidy ``` ### Run tests on the standard library ```bash -./x.py test --stage 0 library/std +./x test --stage 0 library/std ``` Note that this only runs tests on `std`; if you want to test `core` or other crates, @@ -80,13 +80,13 @@ you have to specify those explicitly. ### Run the tidy script and tests on the standard library ```bash -./x.py test --stage 0 tidy library/std +./x test --stage 0 tidy library/std ``` ### Run tests on the standard library using a stage 1 compiler ```bash -./x.py test --stage 1 library/std +./x test --stage 1 library/std ``` By listing which test suites you want to run you avoid having to run @@ -99,7 +99,7 @@ there are some limitations. ### Run all tests using a stage 2 compiler ```bash -./x.py test --stage 2 +./x test --stage 2 ``` You almost never need to do this; CI will run these tests for you. @@ -108,13 +108,13 @@ You almost never need to do this; CI will run these tests for you. You may want to run unit tests on a specific file with following: ```bash -./x.py test compiler/rustc_data_structures/src/thin_vec/tests.rs +./x test compiler/rustc_data_structures/src/thin_vec/tests.rs ``` But unfortunately, it's impossible. You should invoke following instead: ```bash -./x.py test compiler/rustc_data_structures/ --test-args thin_vec +./x test compiler/rustc_data_structures/ --test-args thin_vec ``` ## Running an individual test @@ -122,10 +122,10 @@ But unfortunately, it's impossible. You should invoke following instead: Another common thing that people want to do is to run an **individual test**, often the test they are trying to fix. As mentioned earlier, you may pass the full file path to achieve this, or alternatively one -may invoke `x.py` with the `--test-args` option: +may invoke `x` with the `--test-args` option: ```bash -./x.py test tests/ui --test-args issue-1234 +./x test tests/ui --test-args issue-1234 ``` Under the hood, the test runner invokes the standard Rust test runner @@ -133,6 +133,15 @@ Under the hood, the test runner invokes the standard Rust test runner filtering for tests that include "issue-1234" in the name. (Thus `--test-args` is a good way to run a collection of related tests.) +## Passing arguments to `rustc` when running tests + +It can sometimes be useful to run some tests with specific compiler arguments, +without using `RUSTFLAGS` (during development of unstable features, with `-Z` +flags, for example). + +This can be done with `./x test`'s `--rustc-args` option, to pass additional +arguments to the compiler when building the tests. + ## Editing and updating the reference files If you have changed the compiler's output intentionally, or you are @@ -140,7 +149,7 @@ making a new test, you can pass `--bless` to the test subcommand. E.g. if some tests in `tests/ui` are failing, you can run ```text -./x.py test tests/ui --bless +./x test tests/ui --bless ``` to automatically adjust the `.stderr`, `.stdout` or `.fixed` files of @@ -168,7 +177,7 @@ exists in the test file. For example, you can run all the tests in `tests/ui` as `check-pass`: ```bash -./x.py test tests/ui --pass check +./x test tests/ui --pass check ``` By passing `--pass $mode`, you can reduce the testing time. For each @@ -184,7 +193,7 @@ mode, a test `foo.rs` will first look for expected output in The following will run the UI test suite in Polonius mode: ```bash -./x.py test tests/ui --compare-mode=polonius +./x test tests/ui --compare-mode=polonius ``` See [Compare modes](compiletest.md#compare-modes) for more details. @@ -217,7 +226,7 @@ execution* so be careful where it is used. To do this, first build `remote-test-server` for the remote machine, e.g. for RISC-V ```sh -./x.py build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu +./x build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu ``` The binary will be created at @@ -247,11 +256,11 @@ pong ``` To run tests using the remote runner, set the `TEST_DEVICE_ADDR` environment -variable then use `x.py` as usual. For example, to run `ui` tests for a RISC-V +variable then use `x` as usual. For example, to run `ui` tests for a RISC-V machine with the IP address `1.2.3.4` use ```sh export TEST_DEVICE_ADDR="1.2.3.4:12345" -./x.py test tests/ui --target riscv64gc-unknown-linux-gnu +./x test tests/ui --target riscv64gc-unknown-linux-gnu ``` If `remote-test-server` was run with the verbose flag, output on the test machine @@ -273,7 +282,7 @@ run "/tmp/work/test1018/a" [...] ``` -Tests are built on the machine running `x.py` not on the remote machine. Tests +Tests are built on the machine running `x` not on the remote machine. Tests which fail to build unexpectedly (or `ui` tests producing incorrect build output) may fail without ever running on the remote machine. diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index d94d8cc4e..1f899f586 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -88,7 +88,7 @@ check for output files: 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 +UI tests run with `-Zdeduplicate-diagnostics=no` flag which disables rustc's built-in diagnostic deduplication mechanism. This means you may see some duplicate messages in the output. This helps illuminate situations where duplicate diagnostics are being @@ -390,7 +390,7 @@ Tests with the `*-pass` headers can be overridden with the `--pass` command-line option: ```sh -./x.py test tests/ui --pass check +./x test tests/ui --pass check ``` The `--pass` option only affects UI tests. @@ -485,7 +485,7 @@ Then, it applies the suggestion and compares against `.fixed` (they must match). Finally, the fixed source is compiled, and this compilation is required to succeed. Usually when creating a rustfix test you will generate the `.fixed` file -automatically with the `x.py test --bless` option. +automatically with the `x test --bless` option. The `run-rustfix` header will cause *all* suggestions to be applied, even if they are not [`MachineApplicable`](../diagnostics.md#suggestions). @@ -515,7 +515,7 @@ If in the rare case you encounter a test that has different behavior, you can run something like the following to generate the alternate stderr file: ```sh -./x.py test tests/ui --compare-mode=polonius --bless +./x test tests/ui --compare-mode=polonius --bless ``` Currently none of the compare modes are checked in CI for UI tests. diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 84cb1296f..5e22f10e4 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -163,7 +163,7 @@ Depending on the feature/change/bug fix/improvement, implementation may be relatively-straightforward or it may be a major undertaking. You can always ask for help or mentorship from more experienced compiler devs. Also, you don't have to be the one to implement your feature; but keep in mind that if you -don't it might be a while before someone else does. +don't, it might be a while before someone else does. For the `?` macro feature, I needed to go understand the relevant parts of macro expansion in the compiler. Personally, I find that [improving the diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml index cea6033ed..167aece0e 100644 --- a/src/doc/rustc/book.toml +++ b/src/doc/rustc/book.toml @@ -6,3 +6,9 @@ title = "The rustc book" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc" edit-url-template = "https://github.com/rust-lang/rust/edit/master/src/doc/rustc/{path}" + +[output.html.search] +use-boolean-and = true + +[output.html.playground] +runnable = false diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index f8af26326..94605e2a2 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -28,21 +28,28 @@ - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) - [\*-android and \*-androideabi](platform-support/android.md) - [\*-linux-ohos](platform-support/openharmony.md) + - [aarch64-unknown-teeos](platform-support/aarch64-unknown-teeos.md) - [\*-esp-espidf](platform-support/esp-idf.md) - [\*-unknown-fuchsia](platform-support/fuchsia.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) + - [csky-unknown-linux-gnuabiv2](platform-support/csky-unknown-linux-gnuabiv2.md) - [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md) - [loongarch\*-unknown-none\*](platform-support/loongarch-none.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md) - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md) + - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md) - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) + - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) + - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) + - [*-unknown-hermit](platform-support/hermit.md) - [\*-unknown-netbsd\*](platform-support/netbsd.md) - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) + - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md) - [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) @@ -55,4 +62,6 @@ - [Instrumentation-based Code Coverage](instrument-coverage.md) - [Linker-plugin-based LTO](linker-plugin-lto.md) - [Exploit Mitigations](exploit-mitigations.md) +- [Symbol Mangling](symbol-mangling/index.md) + - [v0 Symbol Format](symbol-mangling/v0.md) - [Contributing to `rustc`](contributing.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 8de638dde..f882a31de 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -569,20 +569,22 @@ for the purpose of generating object code and linking. Supported values for this option are: -* `v0` — The "v0" mangling scheme. The specific format is not specified at - this time. +* `v0` — The "v0" mangling scheme. The default, if not specified, will use a compiler-chosen default which may change in the future. +See the [Symbol Mangling] chapter for details on symbol mangling and the mangling format. + [name mangling]: https://en.wikipedia.org/wiki/Name_mangling +[Symbol Mangling]: ../symbol-mangling/index.md ## target-cpu 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 -and the default target CPU for the current buid target. +and the default target CPU for the current build target. Each target has a default base CPU. Special values include: * `native` can be passed to use the processor of the host machine. diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index d2a25e612..68b70a4f3 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -101,7 +101,7 @@ target | notes `x86_64-unknown-freebsd` | 64-bit FreeBSD `x86_64-unknown-illumos` | illumos `x86_64-unknown-linux-musl` | 64-bit Linux with MUSL -`x86_64-unknown-netbsd` | NetBSD/amd64 +[`x86_64-unknown-netbsd`](platform-support/netbsd.md) | NetBSD/amd64 ## Tier 2 @@ -128,7 +128,7 @@ target | std | notes `aarch64-apple-ios` | ✓ | ARM64 iOS [`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64 `aarch64-fuchsia` | ✓ | Alias for `aarch64-unknown-fuchsia` -`aarch64-unknown-fuchsia` | ✓ | ARM64 Fuchsia +[`aarch64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | ARM64 Fuchsia [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat `aarch64-unknown-none` | * | Bare ARM64, hardfloat @@ -159,7 +159,7 @@ target | std | notes `mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL `mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL `mipsel-unknown-linux-musl` | ✓ | MIPS (LE) Linux with MUSL -`nvptx64-nvidia-cuda` | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] +[`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] `riscv32i-unknown-none-elf` | * | Bare RISC-V (RV32I ISA) `riscv32imac-unknown-none-elf` | * | Bare RISC-V (RV32IMAC ISA) `riscv32imc-unknown-none-elf` | * | Bare RISC-V (RV32IMC ISA) @@ -176,13 +176,15 @@ target | std | notes `thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline `thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat +[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+ `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI +[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` -`x86_64-unknown-fuchsia` | ✓ | 64-bit Fuchsia +[`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android `x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) @@ -220,9 +222,10 @@ target | std | host | notes [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [`aarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARM64 OpenHarmony | +[`aarch64-unknown-teeos`](platform-support/aarch64-unknown-teeos.md) | ? | | ARM64 TEEOS | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD -`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore +[`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD @@ -257,6 +260,7 @@ target | std | host | notes `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) +`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux(little endian) `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS | @@ -277,10 +281,10 @@ target | std | host | notes [`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX) `mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc `mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat -`mipsisa32r6-unknown-linux-gnu` | ? | | -`mipsisa32r6el-unknown-linux-gnu` | ? | | -`mipsisa64r6-unknown-linux-gnuabi64` | ? | | -`mipsisa64r6el-unknown-linux-gnuabi64` | ? | | +[`mipsisa32r6-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Big Endian +[`mipsisa32r6el-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Little Endian +[`mipsisa64r6-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ? | | 64-bit MIPS Release 6 Big Endian +[`mipsisa64r6el-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ✓ | ✓ | 64-bit MIPS Release 6 Little Endian `msp430-none-elf` | * | | 16-bit MSP430 microcontrollers `powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux `powerpc-unknown-linux-musl` | ? | | @@ -302,11 +306,13 @@ target | std | host | notes [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF +[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit `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) -[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ? | RISC-V NetBSD +[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 +[`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 @@ -324,14 +330,16 @@ target | std | host | notes [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support `x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos +[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku -`x86_64-unknown-hermit` | ✓ | | HermitCore +[`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit `x86_64-unknown-l4re-uclibc` | ? | | +[`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | x86_64 OpenHarmony | [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD `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) +[`x86_64h-apple-darwin`](platform-support/x86_64h-apple-darwin.md) | ✓ | ✓ | 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/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md new file mode 100644 index 000000000..8bc938134 --- /dev/null +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md @@ -0,0 +1,100 @@ +# `aarch64-unknown-teeos` + +**Tier: 3** + +Target for the TEEOS operating system. + +TEEOS is a mini os run in TrustZone, for trusted/security apps. The kernel of TEEOS is HongMeng/ChCore micro kernel. The libc for TEEOS is a part of musl. +It's very small that there is no RwLock, no network, no stdin, and no file system for apps in TEEOS. + +Some abbreviation: +| Abbreviation | The full text | Description | +| ---- | ---- | ---- | +| TEE | Trusted Execution Environment | ARM TrustZone divides the system into two worlds/modes -- the secure world/mode and the normal world/mode. TEE is in the secure world/mode. | +| REE | Rich Execution Environment | The normal world. for example, Linux for Android phone is in REE side. | +| TA | Trusted Application | The app run in TEE side system. | +| CA | Client Application | The progress run in REE side system. | + +TEEOS is open source in progress. [MORE about](https://gitee.com/opentrustee-group) + +## Target maintainers + +- Petrochenkov Vadim +- Sword-Destiny + +## Setup +We use OpenHarmony SDK for TEEOS. + +The OpenHarmony SDK doesn't currently support Rust compilation directly, so +some setup is required. + +First, you must obtain the OpenHarmony SDK from [this page](https://gitee.com/openharmony/docs/tree/master/en/release-notes). +Select the version of OpenHarmony you are developing for and download the "Public SDK package for the standard system". + +Create the following shell scripts that wrap Clang from the OpenHarmony SDK: + +`aarch64-unknown-teeos-clang.sh` + +```sh +#!/bin/sh +exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ + --target aarch64-linux-gnu \ + "$@" +``` + +`aarch64-unknown-teeos-clang++.sh` + +```sh +#!/bin/sh +exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ + --target aarch64-linux-gnu \ + "$@" +``` + +## Building the target + +To build a rust toolchain, create a `config.toml` with the following contents: + +```toml +profile = "compiler" +changelog-seen = 2 + +[build] +sanitizers = true +profiler = true +target = ["x86_64-unknown-linux-gnu", "aarch64-unknown-teeos"] +submodules = false +compiler-docs = false +extended = true + +[install] +bindir = "bin" +libdir = "lib" + +[target.aarch64-unknown-teeos] +cc = "/path/to/scripts/aarch64-unknown-teeos-clang.sh" +cxx = "/path/to/scripts/aarch64-unknown-teeos-clang.sh" +linker = "/path/to/scripts/aarch64-unknown-teeos-clang.sh" +ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" +ranlib = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ranlib" +llvm-config = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-config" +``` + +## 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. + +You will need to configure the linker to use in `~/.cargo/config`: +```toml +[target.aarch64-unknown-teeos] +linker = "/path/to/aarch64-unknown-teeos-clang.sh" +``` + +## Testing + +Running the Rust testsuite is not possible now. + +More information about how to test CA/TA. [See here](https://gitee.com/openharmony-sig/tee_tee_dev_kit/tree/master/docs) diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md index e351cfaf8..4ef74295e 100644 --- a/src/doc/rustc/src/platform-support/android.md +++ b/src/doc/rustc/src/platform-support/android.md @@ -39,6 +39,8 @@ edition of the [Android NDK]. Supported Android targets are: * thumbv7neon-linux-androideabi * x86_64-linux-android +The riscv64-linux-android target is supported as a Tier 3 target. + [Android NDK]: https://developer.android.com/ndk/downloads A list of all supported targets can be found diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md new file mode 100644 index 000000000..e73598be0 --- /dev/null +++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md @@ -0,0 +1,70 @@ +# `csky-unknown-linux-gnuabiv2` + +**Tier: 3** + +This target supports [C-SKY](https://github.com/c-sky) CPUs with `abi` v2 and `glibc`. + +https://c-sky.github.io/ +https://gitlab.com/c-sky/ + +## Target maintainers + +* [@Dirreke](https://github.com/Dirreke) + +## Requirements + + +## Building the target + +### Get a C toolchain + +Compiling rust for this target has been tested on `x86_64` linux hosts. Other host types have not been tested, but may work, if you can find a suitable cross compilation toolchain for them. + +If you don't already have a suitable toolchain, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource/1356021/1619528643136/csky-linux-gnuabiv2-tools-x86_64-glibc-linux-4.9.56-20210423.tar.gz), and unpack it into a directory. + +### Configure rust + +The target can be built by enabling it for a `rustc` build, by placing the following in `config.toml`: + +```toml +[build] +target = ["x86_64-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2"] +stage = 2 + +[target.csky-unknown-linux-gnuabiv2] +# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN +cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc" + +### Build + +```sh +# in rust dir +./x.py build --stage 2 +``` + +## Building and Running Rust programs + +To test cross-compiled binaries on a `x86_64` system, you can use the `qemu-cskyv2`. This avoids having a full emulated ARM system by doing dynamic binary translation and dynamic system call translation. It lets you run CSKY programs directly on your `x86_64` kernel. It's very convenient! + +To use: + +* Install `qemu-cskyv2` (If you don't already have a qemu, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1689324918932/xuantie-qemu-x86_64-Ubuntu-18.04-20230714-0202.tar.gz"), and unpack it into a directory.) +* Link your built toolchain via: + * `rustup toolchain link stage2 ${RUST}/build/x86_64-unknown-linux-gnu/stage2` +* Create a test program + +```sh +cargo new hello_world +cd hello_world +``` + +* Build and run + +```sh +CARGO_TARGET_CSKY_UNKNOWN_LINUX_GNUABIV2_RUNNER=${QEMU_PATH}/bin/qemu-cskyv2 -L ${TOOLCHAIN_PATH}/csky-linux-gnuabiv2/libc \ +CARGO_TARGET_CSKY_UNKNOWN_LINUX_GNUABIV2_LINKER=${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc \ +RUSTFLAGS="-C target-features=+crt-static" \ +cargo +stage2 run --target csky-unknown-linux-gnuabiv2 +``` + +Attention: The dynamic-linked program may nor be run by `qemu-cskyv2` but can be run on the target. diff --git a/src/doc/rustc/src/platform-support/hermit.md b/src/doc/rustc/src/platform-support/hermit.md new file mode 100644 index 000000000..146079e36 --- /dev/null +++ b/src/doc/rustc/src/platform-support/hermit.md @@ -0,0 +1,75 @@ +# `*-unknown-hermit` + +**Tier: 3** + +The [Hermit] unikernel target allows compiling your applications into self-contained, specialized unikernel images that can be run in small virtual machines. + +[Hermit]: https://github.com/hermitcore + +Target triplets available so far: + +- `x86_64-unknown-hermit` +- `aarch64-unknown-hermit` +- `riscv64gc-unknown-hermit` + +## Target maintainers + +- Stefan Lankes ([@stlankes](https://github.com/stlankes)) +- Martin Kröning ([@mkroening](https://github.com/mkroening)) + +## Requirements + +These targets only support cross-compilation. +The targets do support std. + +When building binaries for this target, the Hermit unikernel is built from scratch. +The application developer themselves specializes the target and sets corresponding expectations. + +The Hermit targets follow Linux's `extern "C"` calling convention. + +Hermit binaries have the ELF format. + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`. +To run the Hermit build scripts, you also have to enable your host target. +The build scripts rely on `llvm-tools` and binaries are linked using `rust-lld`, so those have to be enabled as well. + +```toml +[build] +build-stage = 1 +target = [ + "", + "x86_64-unknown-hermit", + "aarch64-unknown-hermit", + "riscv64gc-unknown-hermit", +] + +[rust] +lld = true +llvm-tools = true +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for these targets. +To compile for these targets, you will either need to build Rust with the targets enabled +(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar. + +Building Rust programs can be done by following the tutorial in our starter application [rusty-demo]. + +[rusty-demo]: https://github.com/hermitcore/rusty-demo + +## Testing + +The targets support running binaries in the form of self-contained unikernel images. +These images can be chainloaded by Hermit's [loader] or hypervisor ([Uhyve]). +QEMU can be used to boot Hermit binaries using the loader on any architecture. +The targets do not support running the Rust test suite. + +[loader]: https://github.com/hermitcore/rusty-loader +[Uhyve]: https://github.com/hermitcore/uhyve + +## Cross-compilation toolchains and C code + +The targets do not yet support C code and Rust code at the same time. diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md index 17e85590f..e8f55b8bf 100644 --- a/src/doc/rustc/src/platform-support/loongarch-linux.md +++ b/src/doc/rustc/src/platform-support/loongarch-linux.md @@ -71,7 +71,7 @@ CXX_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux- AR_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc-ar \ CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_LINKER=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \ # SET TARGET SYSTEM LIBRARY PATH -CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRAY_PATH" \ +CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRARY_PATH" \ cargo run --target loongarch64-unknown-linux-gnu --release ``` Tested on x86 architecture, other architectures not tested. diff --git a/src/doc/rustc/src/platform-support/mips-release-6.md b/src/doc/rustc/src/platform-support/mips-release-6.md new file mode 100644 index 000000000..3f1912fc6 --- /dev/null +++ b/src/doc/rustc/src/platform-support/mips-release-6.md @@ -0,0 +1,181 @@ +# mipsisa\*r6\*-unknown-linux-gnu\* + +**Tier: 3** + +[MIPS Release 6](https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00083-2B-MIPS64INT-AFP-06.01.pdf), or simply MIPS R6, is the latest iteration of the MIPS instruction set architecture (ISA). + +MIPS R6 is experimental in nature, as there is not yet real hardware. However, Qemu emulation is available and we have two Linux distros maintained for development and evaluation purposes. This documentation describes the Rust support for MIPS R6 targets under `mipsisa*r6*-unknown-linux-gnu*`. + +The target name follow this format: `--`, where `` specifies the CPU family/model, `` specifies the vendor and `` the operating system name. The `` denotes the base ABI (32/n32/64/o64). + +| ABI suffix | Description | +|------------|------------------------------------| +| abi64 | Uses the 64-bit (64) ABI | +| abin32 | Uses the n32 ABI | +| N/A | Uses the (assumed) 32-bit (32) ABI | + +## Target Maintainers + +- [Xuan Chen](https://github.com/chenx97) +- [Walter Ji](https://github.com/709924470) +- [Xinhui Yang](https://github.com/Cyanoxygen) +- [Lain Yang](https://github.com/Fearyncess) + +## Requirements + +### C/C++ Toolchain + +A GNU toolchain for one of the MIPS R6 target is required. [AOSC OS](https://aosc.io/) provides working native and cross-compiling build environments. You may also supply your own a toolchain consisting of recent versions of GCC and Binutils. + +### Target libraries + +A minimum set of libraries is required to perform dynamic linking: + +- GNU glibc +- OpenSSL +- Zlib +- Linux API Headers + +This set of libraries should be installed to make up minimal target sysroot. + +For AOSC OS, You may install such a sysroot with the following commands: + +```sh +cd /tmp + +# linux+api, glibc, and file system structure are included in the toolchain. +sudo apt install gcc+cross-mips64r6el binutils+cross-mips64r6el + +# Download and extract required libraries. +wget https://repo.aosc.io/debs/pool/stable/main/z/zlib_1.2.13-0_mips64r6el.deb -O zlib.deb +wget https://repo.aosc.io/debs/pool/stable/main/o/openssl_1.1.1q-1_mips64r6el.deb -O openssl.deb + +# Extract them to your desired location. +for i in zlib openssl ; do + sudo dpkg-deb -vx $i.deb /var/ab/cross-root/mips64r6el +done + +# Workaround a possible ld bug when using -Wl,-Bdynamic. +sudo sed -i 's|/usr|=/usr|g' /var/ab/cross-root/mips64r6el/usr/lib/libc.so +``` + +For other distros, you may build them manually. + +## Building + +The following procedure outlines the build process for the MIPS64 R6 target with 64-bit (64) ABI (`mipsisa64r6el-unknown-linux-gnuabi64`). + +### Prerequisite: Disable debuginfo + +A LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this: + +```toml +[rust] +debug = false +debug-info-level = 0 +``` + +### Prerequisite: Enable rustix's libc backend + +The crate `rustix` may try to link itself against MIPS R2 assembly, resulting in linkage error. To avoid this, you may force `rustix` to use its fallback `libc` backend by setting relevant `RUSTFLAGS`: + +```sh +export RUSTFLAGS="--cfg rustix_use_libc" +``` + +This will trigger warnings during build, as `-D warnings` is enabled by default. Disable `-D warnings` by editing `config.toml` to append the following: + +```toml +[rust] +deny-warnings = false +``` + +### Prerequisite: Supplying OpenSSL + +As a Tier 3 target, `openssl_sys` lacks the vendored OpenSSL library for this target. You will need to provide a prebuilt OpenSSL library to link `cargo`. Since we have a pre-configured sysroot, we can point to it directly: + +```sh +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_NO_VENDOR=y +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_DIR="/var/ab/cross-root/mips64r6el/usr" +``` + +On Debian, you may need to provide library path and include path separately: + +```sh +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_NO_VENDOR=y +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_LIB_DIR="/usr/lib/mipsisa64r6el-linux-gnuabi64/" +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_INCLUDE_DIR="/usr/include" +``` + +### Launching `x.py` + +```toml +[build] +target = ["mipsisa64r6el-unknown-linux-gnuabi64"] +``` + +Make sure that `mipsisa64r6el-unknown-linux-gnuabi64-gcc` is available from your executable search path (`$PATH`). + +Alternatively, you can specify the directories to all necessary toolchain executables in `config.toml`: + +```toml +[target.mipsisa64r6el-unknown-linux-gnuabi64] +# Adjust the paths below to point to your toolchain installation prefix. +cc = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-gcc" +cxx = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-g++" +ar = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-gcc-ar" +ranlib = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-ranlib" +linker = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-gcc" +``` + +Or, you can specify your cross compiler toolchain with an environment variable: + +```sh +export CROSS_COMPILE="/opt/abcross/mips64r6el/bin/mipsisa64r6el-aosc-linux-gnuabi64-" +``` + +Finally, launch the build script: + +```sh +./x.py build +``` + +### Tips + +- Avoid setting `cargo-native-static` to `false`, as this will result in a redundant artifact error while building clippy: + ```text + 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: + + the following dependencies have different features: + syn 2.0.8 (registry+https://github.com/rust-lang/crates.io-index) + `clippy-driver` additionally enabled features {"full"} at ... + `cargo` additionally enabled features {} at ... + + 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 + thread 'main' panicked at 'tools should not compile multiple copies of the same crate', tool.rs:250:13 + note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + ``` + +## Building Rust programs + +To build Rust programs for MIPS R6 targets, for instance, the `mipsisa64r6el-unknown-linux-gnuabi64` target: + +```bash +cargo build --target mipsisa64r6el-unknown-linux-gnuabi64 +``` + +## Testing + +To test a cross-compiled binary on your build system, install the Qemu user emulator that support the MIPS R6 architecture (`qemu-user-mipsel` or `qemu-user-mips64el`). GCC runtime libraries (`libgcc_s`) for the target architecture should be present in target sysroot to run the program. + +```sh +env \ + CARGO_TARGET_MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_LINKER="/opt/abcross/mips64r6el/bin/mipsisa64r6el-aosc-linux-gnuabi64-gcc" \ + CARGO_TARGET_MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_RUNNER="qemu-mips64el-static -L /var/ab/cross-root/mips64r6el" \ + cargo run --release \ + --target mipsisa64r6el-unknown-linux-gnuabi64 +``` + +## Tips for building Rust programs for MIPS R6 + +- Until we finalize a fix, please make sure the aforementioned workarounds for `rustix` crate and LLVM are always applied. This can be achieved by setting the relevant environment variables, and editing `Cargo.toml` before building. diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md index 23f4488de..3891d6d31 100644 --- a/src/doc/rustc/src/platform-support/netbsd.md +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -86,7 +86,7 @@ The Rust testsuite could presumably be run natively. For the systems where the maintainer can build natively, the rust compiler itself is re-built natively. This involves the rust compiler -being re-built with the newly self-built rust compiler, so excercises +being re-built with the newly self-built rust compiler, so exercises the result quite extensively. Additionally, for some systems we build `librsvg`, and for the more diff --git a/src/doc/rustc/src/platform-support/openharmony.md b/src/doc/rustc/src/platform-support/openharmony.md index a8dcc6443..89539f388 100644 --- a/src/doc/rustc/src/platform-support/openharmony.md +++ b/src/doc/rustc/src/platform-support/openharmony.md @@ -71,6 +71,28 @@ exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ "$@" ``` +`x86_64-unknown-linux-ohos-clang.sh` + +```sh +#!/bin/sh +exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ + -target x86_64-linux-ohos \ + --sysroot=/path/to/ohos-sdk/linux/native/sysroot \ + -D__MUSL__ \ + "$@" +``` + +`x86_64-unknown-linux-ohos-clang++.sh` + +```sh +#!/bin/sh +exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ + -target x86_64-linux-ohos \ + --sysroot=/path/to/ohos-sdk/linux/native/sysroot \ + -D__MUSL__ \ + "$@" +``` + Future versions of the OpenHarmony SDK will avoid the need for this process. ## Building the target @@ -98,6 +120,13 @@ cxx = "/path/to/armv7-unknown-linux-ohos-clang++.sh" ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" ranlib = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ranlib" linker = "/path/to/armv7-unknown-linux-ohos-clang.sh" + +[target.x86_64-unknown-linux-ohos] +cc = "/path/to/x86_64-unknown-linux-ohos-clang.sh" +cxx = "/path/to/x86_64-unknown-linux-ohos-clang++.sh" +ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" +ranlib = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ranlib" +linker = "/path/to/x86_64-unknown-linux-ohos-clang.sh" ``` ## Building Rust programs @@ -116,6 +145,10 @@ linker = "/path/to/aarch64-unknown-linux-ohos-clang.sh" [target.armv7-unknown-linux-ohos] ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" linker = "/path/to/armv7-unknown-linux-ohos-clang.sh" + +[target.x86_64-unknown-linux-ohos] +ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" +linker = "/path/to/x86_64-unknown-linux-ohos-clang.sh" ``` ## Testing diff --git a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md new file mode 100644 index 000000000..f579b1fb8 --- /dev/null +++ b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md @@ -0,0 +1,188 @@ +# `sparc-unknown-none-elf` + +**Tier: 3** + +Rust for bare-metal 32-bit SPARC V7 and V8 systems, e.g. the Gaisler LEON3. + +| Target | Descriptions | +| ---------------------- | ----------------------------------------- | +| sparc-unknown-none-elf | SPARC V7 32-bit (freestanding, hardfloat) | + +## Target maintainers + +- Jonathan Pallant, , https://ferrous-systems.com + +## Requirements + +This target is cross-compiled. There is no support for `std`. There is no +default allocator, but it's possible to use `alloc` by supplying an allocator. + +By default, code generated with this target should run on any `SPARC` hardware; +enabling additional target features may raise this baseline. + +- `-Ctarget-cpu=v8` adds the extra SPARC V8 instructions. + +- `-Ctarget-cpu=leon3` adds the SPARC V8 instructions and sets up scheduling to + suit the Gaisler Leon3. + +Functions marked `extern "C"` use the [standard SPARC architecture calling +convention](https://sparc.org/technical-documents/). + +This target generates ELF binaries. Any alternate formats or special +considerations for binary layout will require linker options or linker scripts. + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `config.toml`: + +```toml +[build] +build-stage = 1 +host = [""] +target = ["", "sparc-unknown-none-elf"] +``` + +Replace `` with `x86_64-unknown-linux-gnu` or whatever +else is appropriate for your host machine. + +## Building Rust programs + +To build with this target, pass it to the `--target` argument, like: + +```console +cargo build --target sparc-unknown-none-elf +``` + +This target uses GCC as a linker, and so you will need an appropriate GCC +compatible `sparc-unknown-none` toolchain. The default linker binary is +`sparc-elf-gcc`, but you can override this in your project configuration, as +follows: + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-custom-elf-gcc" +``` + +## Testing + +As `sparc-unknown-none-elf` supports a variety of different environments and does +not support `std`, this target does not support running the Rust test suite. + +## Cross-compilation toolchains and C code + +This target was initially tested using [BCC2] from Gaisler, along with the TSIM +Leon3 processor simulator. Both [BCC2] GCC and [BCC2] Clang have been shown to +work. To work with these tools, your project configuration should contain +something like: + +[BCC2]: https://www.gaisler.com/index.php/downloads/compilers + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-gaisler-elf-gcc" +runner = "tsim-leon3" + +[build] +target = ["sparc-unknown-none-elf"] +rustflags = "-Ctarget-cpu=leon3" +``` + +With this configuration, running `cargo run` will compile your code for the +SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3` +simulator. The `libcore` was pre-compiled as part of the `rustc` compilation +process using the SPARC V7 baseline, but if you are using a nightly toolchain +you can use the +[`-Z build-std=core`](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std) +option to rebuild `libcore` from source. This may be useful if you want to +compile it for SPARC V8 and take advantage of the extra instructions. + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-gaisler-elf-gcc" +runner = "tsim-leon3" + +[build] +target = ["sparc-unknown-none-elf"] +rustflags = "-Ctarget-cpu=leon3" + +[unstable] +build-std = ["core"] +``` + +Either way, once the simulator is running, simply enter the command `run` to +start the code executing in the simulator. + +The default C toolchain libraries are linked in, so with the Gaisler [BCC2] +toolchain, and using its default Leon3 BSP, you can use call the C `putchar` +function and friends to output to the simulator console. The default linker +script is also appropriate for the Leon3 simulator, so no linker script is +required. + +Here's a complete example using the above config file: + +```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions) +#![no_std] +#![no_main] + +extern "C" { + fn putchar(ch: i32); + fn _exit(code: i32) -> !; +} + +#[no_mangle] +extern "C" fn main() -> i32 { + let message = "Hello, this is Rust!"; + for b in message.bytes() { + unsafe { + putchar(b as i32); + } + } + 0 +} + +#[panic_handler] +fn panic(_panic: &core::panic::PanicInfo) -> ! { + unsafe { + _exit(1); + } +} +``` + +```console +$ cargo run --target=sparc-unknown-none-elf + Compiling sparc-demo-rust v0.1.0 (/work/sparc-demo-rust) + Finished dev [unoptimized + debuginfo] target(s) in 3.44s + Running `tsim-leon3 target/sparc-unknown-none-elf/debug/sparc-demo-rust` + + TSIM3 LEON3 SPARC simulator, version 3.1.9 (evaluation version) + + Copyright (C) 2023, Frontgrade Gaisler - all rights reserved. + This software may only be used with a valid license. + For latest updates, go to https://www.gaisler.com/ + Comments or bug-reports to support@gaisler.com + + This TSIM evaluation version will expire 2023-11-28 + +Number of CPUs: 2 +system frequency: 50.000 MHz +icache: 1 * 4 KiB, 16 bytes/line (4 KiB total) +dcache: 1 * 4 KiB, 16 bytes/line (4 KiB total) +Allocated 8192 KiB SRAM memory, in 1 bank at 0x40000000 +Allocated 32 MiB SDRAM memory, in 1 bank at 0x60000000 +Allocated 8192 KiB ROM memory at 0x00000000 +section: .text, addr: 0x40000000, size: 20528 bytes +section: .rodata, addr: 0x40005030, size: 128 bytes +section: .data, addr: 0x400050b0, size: 1176 bytes +read 347 symbols + +tsim> run + Initializing and starting from 0x40000000 +Hello, this is Rust! + + Program exited normally on CPU 0. +tsim> +``` diff --git a/src/doc/rustc/src/platform-support/unikraft-linux-musl.md b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md new file mode 100644 index 000000000..90fa18b98 --- /dev/null +++ b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md @@ -0,0 +1,67 @@ +# `*-unikraft-linux-musl` + +**Tier: 3** + +Targets for the [Unikraft] Unikernel Development Kit (with musl). + +[Unikraft]: https://unikraft.org/ + +Target triplets available so far: + +- `x86_64-unikraft-linux-musl` + +## Target maintainers + +- Martin Kröning ([@mkroening](https://github.com/mkroening)) + +## Requirements + +These targets only support cross-compilation. +The targets do support std. + +Unikraft pretends to behave exactly like Linux. +How much of that functionality is available depends on the individual unikernel configuration. +For example, the basic Unikraft + musl config does not support `poll` or networking out of the box. +That functionality requires enabling [`LIBPOSIX_EVENT`] or [lwIP] respectively. + +[`LIBPOSIX_EVENT`]: https://github.com/unikraft/unikraft/blob/RELEASE-0.13.1/lib/posix-event/Config.uk +[lwIP]: https://github.com/unikraft/lib-lwip + +The Unikraft targets follow Linux's `extern "C"` calling convention. + +For these targets, `rustc` does not perform the final linking step. +Instead, the Unikraft build system will produce the final Unikernel image for the selected platform (e.g., KVM, Linux user space, and Xen). + +## Building the targets + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: + +```toml +[build] +build-stage = 1 +target = [ "x86_64-unikraft-linux-musl" ] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for these targets. +To compile for these targets, you will either need to build Rust with the targets enabled +(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar. + +Linking requires a [KraftKit] shim. +See [unikraft/kraftkit#612] for more information. + +[KraftKit]: https://github.com/unikraft/kraftkit +[unikraft/kraftkit#612]: https://github.com/unikraft/kraftkit/issues/612 + +## Testing + +The targets do support running binaries in the form of unikernel images. +How the unikernel image is run depends on the specific platform (e.g., KVM, Linux user space, and Xen). +The targets do not support running the Rust test suite. + +## Cross-compilation toolchains and C code + +The targets do support C code. +To build compatible C code, you have to use the same compiler and flags as does the Unikraft build system for your specific configuration. +The easiest way to achieve that, is to build the C code with the Unikraft build system when building your unikernel image. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md new file mode 100644 index 000000000..23b999248 --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md @@ -0,0 +1,148 @@ +# `wasm32-wasi-preview1-threads` + +**Tier: 2** + +The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an +experimental target. This target is an extension to `wasm32-wasi-preview1` target, +originally known as `wasm32-wasi`. It extends the original target with a +standardized set of syscalls that are intended to empower WebAssembly binaries with +native multi threading capabilities. + +[wasi-threads]: https://github.com/WebAssembly/wasi-threads +[threads]: https://github.com/WebAssembly/threads + + +## Target maintainers + +- Georgii Rylov, https://github.com/g0djan +- Alex Crichton, https://github.com/alexcrichton +- Andrew Brown, https://github.com/abrown +- Marcin Kolny, https://github.com/loganek + +## Requirements + +This target is cross-compiled. The target supports `std` fully. + +The Rust target definition here is interesting in a few ways. We want to +serve two use cases here with this target: +* First, we want Rust usage of the target to be as hassle-free as possible, + ideally avoiding the need to configure and install a local wasm32-wasi-preview1-threads + toolchain. +* Second, one of the primary use cases of LLVM's new wasm backend and the + wasm support in LLD is that any compiled language can interoperate with + any other. The `wasm32-wasi-preview1-threads` target is the first with a viable C + standard library and sysroot common definition, so we want Rust and C/C++ + code to interoperate when compiled to `wasm32-unknown-unknown`. + + +You'll note, however, that the two goals above are somewhat at odds with one +another. To attempt to solve both use cases in one go we define a target +that (ab)uses the `crt-static` target feature to indicate which one you're +in. +### No interop with C required +By default the `crt-static` target feature is enabled, and when enabled +this means that the bundled version of `libc.a` found in `liblibc.rlib` +is used. This isn't intended really for interoperation with a C because it +may be the case that Rust's bundled C library is incompatible with a +foreign-compiled C library. In this use case, though, we use `rust-lld` and +some copied crt startup object files to ensure that you can download the +wasi target for Rust and you're off to the races, no further configuration +necessary. +All in all, by default, no external dependencies are required. You can +compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, +reliably interoperate with C code in this mode (yet). +### Interop with C required +For the second goal we repurpose the `target-feature` flag, meaning that +you'll need to do a few things to have C/Rust code interoperate. +1. All Rust code needs to be compiled with `-C target-feature=-crt-static`, + indicating that the bundled C standard library in the Rust sysroot will + not be used. +2. If you're using rustc to build a linked artifact then you'll need to + specify `-C linker` to a `clang` binary that supports + `wasm32-wasi-preview1-threads` and is configured with the `wasm32-wasi-preview1-threads` sysroot. This + will cause Rust code to be linked against the libc.a that the specified + `clang` provides. +3. If you're building a staticlib and integrating Rust code elsewhere, then + compiling with `-C target-feature=-crt-static` is all you need to do. + +All in all, by default, no external dependencies are required. You can +compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, +reliably interoperate with C code in this mode (yet). + + +Also note that at this time the `wasm32-wasi-preview1-threads` target assumes the +presence of other merged wasm proposals such as (with their LLVM feature flags): + +* [Bulk memory] - `+bulk-memory` +* Mutable imported globals - `+mutable-globals` +* Atomics - `+atomics` + +[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md + +LLVM 16 is required for this target. The reason is related to linker flags: prior to LLVM 16, --import-memory and --export-memory were not allowed together. The reason both are needed is an artifact of how WASI currently does things; see https://github.com/WebAssembly/WASI/issues/502 for more details. + +The target intends to match the corresponding Clang target for its `"C"` ABI. + +> **Note**: due to the relatively early-days nature of this target when working +> with this target you may encounter LLVM bugs. If an assertion hit or a bug is +> found it's recommended to open an issue either with rust-lang/rust or ideally +> with LLVM itself. + +## Platform requirements + +The runtime should support the same set of APIs as any other supported wasi target for interacting with the host environment through the WASI standard. The runtime also should have implemetation of [wasi-threads proposal](https://github.com/WebAssembly/wasi-threads). + +This target is not a stable target. This means that there are a few engines +which implement the `wasi-threads` feature and if they do they're likely behind a +flag, for example: + +* Wasmtime - `--wasm-features=threads --wasi-modules=experimental-wasi-threads` +* [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime) - needs to be built with WAMR_BUILD_LIB_WASI_THREADS=1 + +## Building the target + +Users need to install or built wasi-sdk since release 20.0 +https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-20 +and specify path to *wasi-root* `.cargo/config.toml` + +```toml +[target.wasm32-wasi-preview1-threads] +wasi-root = ".../wasi-libc/sysroot" +``` + +After that users can build this by adding it to the `target` list in +`config.toml`, or with `-Zbuild-std`. + +## Building Rust programs + +From Rust Nightly 1.71.1 (2023-08-03) on the artifacts are shipped pre-compiled: + +```text +rustup target add wasm32-wasi-preview1-threads --toolchain nightly +``` + +Rust programs can be built for that target: + +```text +rustc --target wasm32-wasi-preview1-threads your-code.rs +``` + +## Cross-compilation + +This target can be cross-compiled from any hosts. + +## Testing + +Currently testing is not well supported for `wasm32-wasi-preview1-threads` and the +Rust project doesn't run any tests for this target. However the UI testsuite can be run +manually following this instructions: + +0. Ensure [wamr](https://github.com/bytecodealliance/wasm-micro-runtime), [wasmtime](https://github.com/bytecodealliance/wasmtime) +or another engine that supports `wasi-threads` is installed and can be found in the `$PATH` env variable. +1. Clone master branch. +2. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1. +3. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests. +4. Checkout branch with your changes. +5. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1. +6. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests. +7. For both lists of failed tests run `cat list | sort > sorted_list` and compare it with `diff sorted_list1 sorted_list2`. diff --git a/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md b/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md index 1a6f7bb83..0fe9d4eda 100644 --- a/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md +++ b/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md @@ -20,7 +20,7 @@ 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 +targeted 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 @@ -49,7 +49,7 @@ suite seems to work. 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 +Targeting it from non-Apple hosts is difficult, but no more so than targeting `x86_64-apple-darwin`. When compiling C code for this target, either the "`x86_64h-apple-macosx*`" LLVM diff --git a/src/doc/rustc/src/symbol-mangling/index.md b/src/doc/rustc/src/symbol-mangling/index.md new file mode 100644 index 000000000..be58f2b41 --- /dev/null +++ b/src/doc/rustc/src/symbol-mangling/index.md @@ -0,0 +1,52 @@ +# Symbol Mangling + +[Symbol name mangling] is used by `rustc` to encode a unique name for symbols that are used during code generation. +The encoded names are used by the linker to associate the name with the thing it refers to. + +The method for mangling the names can be controlled with the [`-C symbol-mangling-version`] option. + +[Symbol name mangling]: https://en.wikipedia.org/wiki/Name_mangling +[`-C symbol-mangling-version`]: ../codegen-options/index.md#symbol-mangling-version + +## Per-item control + +The [`#[no_mangle]` attribute][reference-no_mangle] can be used on items to disable name mangling on that item. + +The [`#[export_name]`attribute][reference-export_name] can be used to specify the exact name that will be used for a function or static. + +Items listed in an [`extern` block][reference-extern-block] use the identifier of the item without mangling to refer to the item. +The [`#[link_name]` attribute][reference-link_name] can be used to change that name. + + + +[reference-no_mangle]: ../../reference/abi.html#the-no_mangle-attribute +[reference-export_name]: ../../reference/abi.html#the-export_name-attribute +[reference-link_name]: ../../reference/items/external-blocks.html#the-link_name-attribute +[reference-extern-block]: ../../reference/items/external-blocks.html + +## Decoding + +The encoded names may need to be decoded in some situations. +For example, debuggers and other tooling may need to demangle the name so that it is more readable to the user. +Recent versions of `gdb` and `lldb` have built-in support for demangling Rust identifiers. +In situations where you need to do your own demangling, the [`rustc-demangle`] crate can be used to programmatically demangle names. +[`rustfilt`] is a CLI tool which can demangle names. + +An example of running rustfilt: + +```text +$ rustfilt _RNvCskwGfYPst2Cb_3foo16example_function +foo::example_function +``` + +[`rustc-demangle`]: https://crates.io/crates/rustc-demangle +[`rustfilt`]: https://crates.io/crates/rustfilt + +## Mangling versions + +`rustc` supports different mangling versions which encode the names in different ways. +The legacy version (which is currently the default) is not described here. +The "v0" mangling scheme addresses several limitations of the legacy format, +and is described in the [v0 Symbol Format](v0.md) chapter. diff --git a/src/doc/rustc/src/symbol-mangling/v0.md b/src/doc/rustc/src/symbol-mangling/v0.md new file mode 100644 index 000000000..61f747fac --- /dev/null +++ b/src/doc/rustc/src/symbol-mangling/v0.md @@ -0,0 +1,1222 @@ +# v0 Symbol Format + +The v0 mangling format was introduced in [RFC 2603]. +It has the following properties: + +- It provides an unambiguous string encoding for everything that can end up in a binary's symbol table. +- It encodes information about generic parameters in a reversible way. +- The mangled symbols are *decodable* such that the demangled form should be easily identifiable as some concrete instance of e.g. a polymorphic function. +- It has a consistent definition that does not rely on pretty-printing certain language constructs. +- Symbols can be restricted to only consist of the characters `A-Z`, `a-z`, `0-9`, and `_`. + This helps ensure that it is platform-independent, + where other characters might have special meaning in some context (e.g. `.` for MSVC `DEF` files). + Unicode symbols are optionally supported. +- It tries to stay efficient, avoiding unnecessarily long names, + and avoiding computationally expensive operations to demangle. + +The v0 format is not intended to be compatible with other mangling schemes (such as C++). + +The v0 format is not presented as a stable ABI for Rust. +This format is currently intended to be well-defined enough that a demangler can produce a reasonable human-readable form of the symbol. +There are several implementation-defined portions that result in it not being possible to entirely predict how a given Rust entity will be encoded. + +The sections below define the encoding of a v0 symbol. +There is no standardized demangled form of the symbols, +though suggestions are provided for how to demangle a symbol. +Implementers may choose to demangle in different ways. + +## Extensions + +This format may be extended in the future to add new tags as Rust is extended with new language items. +To be forward compatible, demanglers should gracefully handle symbols that have encodings where it encounters a tag character not described in this document. +For example, they may fall back to displaying the mangled symbol. +The format may be extended anywhere there is a tag character, such as the [type] rule. +The meaning of existing tags and encodings will not be changed. + +## Grammar notation + +The format of an encoded symbol is illustrated as a context free grammar in an extended BNF-like syntax. +A consolidated summary can be found in the [Symbol grammar summary][summary]. + +| Name | Syntax | Example | Description | +|------|--------|---------|-------------| +| Rule | → | A → *B* *C* | A production. | +| Concatenation | whitespace | A → *B* *C* *D* | Individual elements in sequence left-to-right. | +| Alternative | \| | A → *B* \| *C* | Matches either one or the other. | +| Grouping | () | A → *B* (*C* \| *D*) *E* | Groups multiple elements as one. | +| Repetition | {} | A → {*B*} | Repeats the enclosed zero or more times. | +| Option | opt | A → *B*opt *C* | An optional element. | +| Literal | `monospace` | A → `G` | A terminal matching the exact characters case-sensitive. | + +## Symbol name +[symbol-name]: #symbol-name + +> symbol-name → `_R` *[decimal-number]*opt *[path]* *[instantiating-crate]*opt *[vendor-specific-suffix]*opt + +A mangled symbol starts with the two characters `_R` which is a prefix to identify the symbol as a Rust symbol. +The prefix can optionally be followed by a *[decimal-number]* which specifies the encoding version. +This number is currently not used, and is never present in the current encoding. +Following that is a *[path]* which encodes the path to an entity. +The path is followed by an optional *[instantiating-crate]* which helps to disambiguate entities which may be instantiated multiple times in separate crates. +The final part is an optional *[vendor-specific-suffix]*. + +> **Recommended Demangling** +> +> A *symbol-name* should be displayed as the *[path]*. +> The *[instantiating-crate]* and the *[vendor-specific-suffix]* usually need not be displayed. + +> Example: +> ```rust +> std::path::PathBuf::new(); +> ``` +> +> The symbol for `PathBuf::new` in crate `mycrate` is: +> +> ```text +> _RNvMsr_NtCs3ssYzQotkvD_3std4pathNtB5_7PathBuf3newCs15kBYyAo9fc_7mycrate +> ├┘└───────────────────────┬──────────────────────┘└──────────┬─────────┘ +> │ │ │ +> │ │ └── instantiating-crate path "mycrate" +> │ └───────────────────────────────────── path to std::path::PathBuf::new +> └─────────────────────────────────────────────────────────────── `_R` symbol prefix +> ``` +> +> Recommended demangling: `::new` + +## Symbol path +[path]: #symbol-path + +> path → \ +>       *[crate-root]* \ +>    | *[inherent-impl]* \ +>    | *[trait-impl]* \ +>    | *[trait-definition]* \ +>    | *[nested-path]* \ +>    | *[generic-args]* \ +>    | *[backref]* + +A *path* represents a variant of a [Rust path][reference-paths] to some entity. +In addition to typical Rust path segments using identifiers, +it uses extra elements to represent unnameable entities (like an `impl`) or generic arguments for monomorphized items. + +The initial tag character can be used to determine which kind of path it represents: + +| Tag | Rule | Description | +|-----|------|-------------| +| `C` | *[crate-root]* | The root of a crate path. | +| `M` | *[inherent-impl]* | An inherent implementation. | +| `X` | *[trait-impl]* | A trait implementation. | +| `Y` | *[trait-definition]* | A trait definition. | +| `N` | *[nested-path]* | A nested path. | +| `I` | *[generic-args]* | Generic arguments. | +| `B` | *[backref]* | A back reference. | + +### Path: Crate root +[crate-root]: #path-crate-root + +> crate-root → `C` *[identifier]* + +A *crate-root* indicates a path referring to the root of a crate's module tree. +It consists of the character `C` followed by the crate name as an *[identifier]*. + +The crate name is the name as seen from the defining crate. +Since Rust supports linking multiple crates with the same name, +the *[disambiguator]* is used to make the name unique across the crate graph. + +> **Recommended Demangling** +> +> A *crate-root* can be displayed as the identifier such as `mycrate`. +> +> Usually the disambiguator in the identifier need not be displayed, +> but as an alternate form the disambiguator can be shown in hex such as +> `mycrate[ca63f166dbe9294]`. + +> Example: +> ```rust +> fn example() {} +> ``` +> +> The symbol for `example` in crate `mycrate` is: +> +> ```text +> _RNvCs15kBYyAo9fc_7mycrate7example +> │└────┬─────┘││└──┬──┘ +> │ │ ││ │ +> │ │ ││ └── crate-root identifier "mycrate" +> │ │ │└────── length 7 of "mycrate" +> │ │ └─────── end of base-62-number +> │ └────────────── disambiguator for crate-root "mycrate" 0xca63f166dbe9293 + 1 +> └──────────────────── crate-root +> ``` +> +> Recommended demangling: `mycrate::example` + +### Path: Inherent impl +[inherent-impl]: #path-inherent-impl + +> inherent-impl → `M` *[impl-path]* *[type]* + +An *inherent-impl* indicates a path to an [inherent implementation][reference-inherent-impl]. +It consists of the character `M` followed by an *[impl-path]*, which uniquely identifies the impl block the item is defined in. +Following that is a *[type]* representing the `Self` type of the impl. + +> **Recommended Demangling** +> +> An *inherent-impl* can be displayed as a qualified path segment to the *[type]* within angled brackets. +> The *[impl-path]* usually need not be displayed. + +> Example: +> ```rust +> struct Example; +> impl Example { +> fn foo() {} +> } +> ``` +> +> The symbol for `foo` in the impl for `Example` is: +> +> ```text +> _RNvMs_Cs4Cv8Wi1oAIB_7mycrateNtB4_7Example3foo +> │├┘└─────────┬──────────┘└────┬──────┘ +> ││ │ │ +> ││ │ └── Self type "Example" +> ││ └─────────────────── path to the impl's parent "mycrate" +> │└─────────────────────────────── disambiguator 1 +> └──────────────────────────────── inherent-impl +> ``` +> +> Recommended demangling: `::foo` + +### Path: Trait impl +[trait-impl]: #path-trait-impl + +> trait-impl → `X` *[impl-path]* *[type]* *[path]* + +A *trait-impl* indicates a path to a [trait implementation][reference-trait-impl]. +It consists of the character `X` followed by an *[impl-path]* to the impl's parent followed by the *[type]* representing the `Self` type of the impl followed by a *[path]* to the trait. + +> **Recommended Demangling** +> +> A *trait-impl* can be displayed as a qualified path segment using the `<` *type* `as` *path* `>` syntax. +> The *[impl-path]* usually need not be displayed. + +> Example: +> ```rust +> struct Example; +> trait Trait { +> fn foo(); +> } +> impl Trait for Example { +> fn foo() {} +> } +> ``` +> +> The symbol for `foo` in the trait impl for `Example` is: +> +> ```text +> _RNvXCs15kBYyAo9fc_7mycrateNtB2_7ExampleNtB2_5Trait3foo +> │└─────────┬──────────┘└─────┬─────┘└────┬────┘ +> │ │ │ │ +> │ │ │ └── path to the trait "Trait" +> │ │ └────────────── Self type "Example" +> │ └──────────────────────────────── path to the impl's parent "mycrate" +> └─────────────────────────────────────────── trait-impl +> ``` +> +> Recommended demangling: `::foo` + +### Path: Impl +[impl-path]: #path-impl + +> impl-path → *[disambiguator]*opt *[path]* + +An *impl-path* is a path used for *[inherent-impl]* and *[trait-impl]* to indicate the path to parent of an [implementation][reference-implementations]. +It consists of an optional *[disambiguator]* followed by a *[path]*. +The *[path]* is the path to the parent that contains the impl. +The *[disambiguator]* can be used to distinguish between multiple impls within the same parent. + +> **Recommended Demangling** +> +> An *impl-path* usually need not be displayed (unless the location of the impl is desired). + +> Example: +> ```rust +> struct Example; +> impl Example { +> fn foo() {} +> } +> impl Example { +> fn bar() {} +> } +> ``` +> +> The symbol for `foo` in the impl for `Example` is: +> +> ```text +> _RNvMCs7qp2U7fqm6G_7mycrateNtB2_7Example3foo +> └─────────┬──────────┘ +> │ +> └── path to the impl's parent crate-root "mycrate" +> ``` +> +> The symbol for `bar` is similar, though it has a disambiguator to indicate it is in a different impl block. +> +> ```text +> _RNvMs_Cs7qp2U7fqm6G_7mycrateNtB4_7Example3bar +> ├┘└─────────┬──────────┘ +> │ │ +> │ └── path to the impl's parent crate-root "mycrate" +> └────────────── disambiguator 1 +> ``` +> +> Recommended demangling: +> * `foo`: `::foo` +> * `bar`: `::bar` + +### Path: Trait definition +[trait-definition]: #path-trait-definition + +> trait-definition → `Y` *[type]* *[path]* + +A *trait-definition* is a path to a [trait definition][reference-traits]. +It consists of the character `Y` followed by the *[type]* which is the `Self` type of the referrer, followed by the *[path]* to the trait definition. + +> **Recommended Demangling** +> +> A *trait-definition* can be displayed as a qualified path segment using the `<` *type* `as` *path* `>` syntax. + +> Example: +> ```rust +> trait Trait { +> fn example() {} +> } +> struct Example; +> impl Trait for Example {} +> ``` +> +> The symbol for `example` in the trait `Trait` implemented for `Example` is: +> +> ```text +> _RNvYNtCs15kBYyAo9fc_7mycrate7ExampleNtB4_5Trait7exampleB4_ +> │└──────────────┬───────────────┘└────┬────┘ +> │ │ │ +> │ │ └── path to the trait "Trait" +> │ └──────────────────────── path to the implementing type "mycrate::Example" +> └──────────────────────────────────────── trait-definition +> ``` +> +> Recommended demangling: `::example` + +### Path: Nested path +[nested-path]: #path-nested-path + +> nested-path → `N` *[namespace]* *[path]* *[identifier]* + +A *nested-path* is a path representing an optionally named entity. +It consists of the character `N` followed by a *[namespace]* indicating the namespace of the entity, +followed by a *[path]* which is a path representing the parent of the entity, +followed by an *[identifier]* of the entity. + +The identifier of the entity may have a length of 0 when the entity is not named. +For example, entities like closures, tuple-like struct constructors, and anonymous constants may not have a name. +The identifier may still have a disambiguator unless the disambiguator is 0. + +> **Recommended Demangling** +> +> A *nested-path* can be displayed by first displaying the *[path]* followed by a `::` separator followed by the *[identifier]*. +> If the *[identifier]* is empty, then the separating `::` should not be displayed. +> +> If a *[namespace]* is specified, then extra context may be added such as: \ +> *[path]* `::{` *[namespace]* (`:` *[identifier]*)opt `#` *disambiguator*as base-10 number `}` +> +> Here the namespace `C` may be printed as `closure` and `S` as `shim`. +> Others may be printed by their character tag. +> The `:` *name* portion may be skipped if the name is empty. +> +> The *[disambiguator]* in the *[identifier]* may be displayed if a *[namespace]* is specified. +> In other situations, it is usually not necessary to display the *[disambiguator]*. +> If it is displayed, it is recommended to place it in brackets, for example `[284a76a8b41a7fd3]`. +> If the *[disambiguator]* is not present, then its value is 0 and it can always be omitted from display. + +> Example: +> ```rust +> fn main() { +> let x = || {}; +> let y = || {}; +> x(); +> y(); +> } +> ``` +> +> The symbol for the closure `x` in crate `mycrate` is: +> +> ```text +> _RNCNvCsgStHSCytQ6I_7mycrate4main0B3_ +> ││└─────────────┬─────────────┘│ +> ││ │ │ +> ││ │ └── identifier with length 0 +> ││ └───────────────── path to "mycrate::main" +> │└──────────────────────────────── closure namespace +> └───────────────────────────────── nested-path +> ``` +> +> The symbol for the closure `y` is similar, with a disambiguator: +> +> ```text +> _RNCNvCsgStHSCytQ6I_7mycrate4mains_0B3_ +> ││ +> │└── base-62-number 0 +> └─── disambiguator 1 (base-62-number+1) +> ``` +> +> Recommended demangling: +> * `x`: `mycrate::main::{closure#0}` +> * `y`: `mycrate::main::{closure#1}` + +### Path: Generic arguments +[generic-args]: #path-generic-arguments +[generic-arg]: #path-generic-arguments + +> generic-args → `I` *[path]* {*[generic-arg]*} `E` +> +> generic-arg → \ +>       *[lifetime]* \ +>    | *[type]* \ +>    | `K` *[const]* + +A *generic-args* is a path representing a list of generic arguments. +It consists of the character `I` followed by a *[path]* to the defining entity, followed by zero or more [generic-arg]s terminated by the character `E`. + +Each *[generic-arg]* is either a *[lifetime]* (starting with the character `L`), a *[type]*, or the character `K` followed by a *[const]* representing a const argument. + +> **Recommended Demangling** +> +> A *generic-args* may be printed as: *[path]* `::`opt `<` comma-separated list of args `>` +> The `::` separator may be elided for type paths (similar to Rust's rules). + +> > Example: +> ```rust +> fn main() { +> example([123]); +> } +> +> fn example(x: [T; N]) {} +> ``` +> +> The symbol for the function `example` is: +> +> ```text +> _RINvCsgStHSCytQ6I_7mycrate7examplelKj1_EB2_ +> │└──────────────┬───────────────┘││││││ +> │ │ │││││└── end of generic-args +> │ │ ││││└─── end of const-data +> │ │ │││└──── const value `1` +> │ │ ││└───── const type `usize` +> │ │ │└────── const generic +> │ │ └─────── generic type i32 +> │ └──────────────────────── path to "mycrate::example" +> └──────────────────────────────────────── generic-args +> ``` +> +> Recommended demangling: `mycrate::example::` + +### Namespace +[namespace]: #namespace + +> namespace → *[lower]* | *[upper]* + +A *namespace* is used to segregate names into separate logical groups, allowing identical names to otherwise avoid collisions. +It consists of a single character of an upper or lowercase ASCII letter. +Lowercase letters are reserved for implementation-internal disambiguation categories (and demanglers should never show them). +Uppercase letters are used for special namespaces which demanglers may display in a special way. + +Uppercase namespaces are: + +* `C` — A closure. +* `S` — A shim. Shims are added by the compiler in some situations where an intermediate is needed. + For example, a `fn()` pointer to a function with the [`#[track_caller]` attribute][reference-track_caller] needs a shim to deal with the implicit caller location. + +> **Recommended Demangling** +> +> See *[nested-path]* for recommended demangling. + +## Identifier +[identifier]: #identifier +[undisambiguated-identifier]: #identifier +[bytes]: #identifier + +> identifier → *[disambiguator]*opt *[undisambiguated-identifier]* +> +> undisambiguated-identifier → `u`opt *[decimal-number]* `_`opt *[bytes]* +> +> bytes → {*UTF-8 bytes*} + +An *identifier* is a named label used in a *[path]* to refer to an entity. +It consists of an optional *[disambiguator]* followed by an *[undisambiguated-identifier]*. + +The disambiguator is used to disambiguate identical identifiers that should not otherwise be considered the same. +For example, closures have no name, so the disambiguator is the only differentiating element between two different closures in the same parent path. + +The undisambiguated-identifier starts with an optional `u` character, +which indicates that the identifier is encoded in [Punycode][Punycode identifiers]. +The next part is a *[decimal-number]* which indicates the length of the *bytes*. + +Following the identifier size is an optional `_` character which is used to separate the length value from the identifier itself. +The `_` is mandatory if the *bytes* starts with a decimal digit or `_` in order to keep it unambiguous where the *decimal-number* ends and the *bytes* starts. + +*bytes* is the identifier itself encoded in UTF-8. + +> **Recommended Demangling** +> +> The display of an *identifier* can depend on its context. +> If it is Punycode-encoded, then it may first be decoded before being displayed. +> +> The *[disambiguator]* may or may not be displayed; see recommendations for rules that use *identifier*. + +### Punycode identifiers +[Punycode identifiers]: #punycode-identifiers + +Because some environments are restricted to ASCII alphanumerics and `_`, +Rust's [Unicode identifiers][reference-identifiers] may be encoded using a modified version of [Punycode]. + +For example, the function: + +```rust +mod gödel { + mod escher { + fn bach() {} + } +} +``` + +would be mangled as: + +```text +_RNvNtNtCsgOH4LzxkuMq_7mycrateu8gdel_5qa6escher4bach + ││└───┬──┘ + ││ │ + ││ └── gdel_5qa translates to gödel + │└─────── 8 is the length + └──────── `u` indicates it is a Unicode identifier +``` + +Standard Punycode generates strings of the form `([[:ascii:]]+-)?[[:alnum:]]+`. +This is problematic because the `-` character +(which is used to separate the ASCII part from the base-36 encoding) +is not in the supported character set for symbols. +For this reason, `-` characters in the Punycode encoding are replaced with `_`. + +Here are some examples: + +| Original | Punycode | Punycode + Encoding | +|-----------------|-----------------|---------------------| +| føø | f-5gaa | f_5gaa | +| α_ω | _-ylb7e | __ylb7e | +| 铁锈 | n84amf | n84amf | +| 🤦 | fq9h | fq9h | +| ρυστ | 2xaedc | 2xaedc | + +> Note: It is up to the compiler to decide whether or not to encode identifiers using Punycode or not. +> Some platforms may have native support for UTF-8 symbols, +> and the compiler may decide to use the UTF-8 encoding directly. +> Demanglers should be prepared to support either form. + +[Punycode]: https://tools.ietf.org/html/rfc3492 + +## Disambiguator +[disambiguator]: #disambiguator + +> disambiguator → `s` *[base-62-number]* + +A *disambiguator* is used in various parts of a symbol *[path]* to uniquely identify path elements that would otherwise be identical but should not be considered the same. +It starts with the character `s` and is followed by a *[base-62-number]*. + +If the *disambiguator* is not specified, then its value can be assumed to be zero. +Otherwise, when demangling, the value 1 should be added to the *[base-62-number]* +(thus a *base-62-number* of zero encoded as `_` has a value of 1). +This allows disambiguators that are encoded sequentially to use minimal bytes. + +> **Recommended Demangling** +> +> The *disambiguator* may or may not be displayed; see recommendations for rules that use *disambiguator*. + +## Lifetime +[lifetime]: #lifetime + +> lifetime → `L` *[base-62-number]* + +A *lifetime* is used to encode an anonymous (numbered) lifetime, either erased or [higher-ranked](#binder). +It starts with the character `L` and is followed by a *[base-62-number]*. +Index 0 is always erased. +Indices starting from 1 refer (as de Bruijn indices) to a higher-ranked lifetime bound by one of the enclosing [binder]s. + +> **Recommended Demangling** +> +> A *lifetime* may be displayed like a Rust lifetime using a single quote. +> +> Index 0 should be displayed as `'_`. +> Index 0 should not be displayed for lifetimes in a *[ref-type]*, *[mut-ref-type]*, or *[dyn-trait-type]*. +> +> A lifetime can be displayed by converting the De Bruijn index to a De Bruijn level +> (level = number of bound lifetimes - index) and selecting a unique name for each level. +> For example, starting with single lowercase letters such as `'a` for level 0. +> Levels over 25 may consider printing the numeric lifetime as in `'_123`. +> See *[binder]* for more on lifetime indexes and ordering. + +> Example: +> ```rust +> fn main() { +> example::(); +> } +> +> pub fn example() {} +> ``` +> +> The symbol for the function `example` is: +> +> ```text +> _RINvCs7qp2U7fqm6G_7mycrate7exampleFG0_RL1_hRL0_tEuEB2_ +> │└┬┘│└┬┘││└┬┘││ +> │ │ │ │ ││ │ │└── end of input types +> │ │ │ │ ││ │ └─── type u16 +> │ │ │ │ ││ └───── lifetime #1 'b +> │ │ │ │ │└─────── reference type +> │ │ │ │ └──────── type u8 +> │ │ │ └────────── lifetime #2 'a +> │ │ └──────────── reference type +> │ └────────────── binder with 2 lifetimes +> └──────────────── function type +> ``` +> +> Recommended demangling: `mycrate::example:: fn(&'a u8, &'b u16)>` + +## Const +[const]: #const +[const-data]: #const +[hex-digit]: #const + +> const → \ +>       *[type]* *[const-data]* \ +>    | `p` \ +>    | *[backref]* +> +> const-data → `n`opt {*[hex-digit]*} `_` +> +> [hex-digit] → *[digit]* | `a` | `b` | `c` | `d` | `e` | `f` + +A *const* is used to encode a const value used in generics and types. +It has the following forms: + +* A constant value encoded as a *[type]* which represents the type of the constant and *[const-data]* which is the constant value, followed by `_` to terminate the *const*. +* The character `p` which represents a [placeholder]. +* A *[backref]* to a previously encoded *const* of the same value. + +The encoding of the *const-data* depends on the type: + +* `bool` — The value `false` is encoded as `0_`, the value true is encoded as `1_`. +* `char` — The Unicode scalar value of the character is encoded in hexadecimal. +* Unsigned integers — The value is encoded in hexadecimal. +* Signed integers — The character `n` is a prefix to indicate that it is negative, + followed by the absolute value encoded in hexadecimal. + +> **Recommended Demangling** +> +> A *const* may be displayed by the const value depending on the type. +> +> The `p` placeholder should be displayed as the `_` character. +> +> For specific types: +> * `b` (bool) — Display as `true` or `false`. +> * `c` (char) — Display the character in as a Rust character (such as `'A'` or `'\n'`). +> * integers — Display the integer (either in decimal or hex). + +> Example: +> ```rust +> fn main() { +> example::<0x12345678>(); +> } +> +> pub fn example() {} +> ``` +> +> The symbol for function `example` is: +> +> ```text +> _RINvCs7qp2U7fqm6G_7mycrate7exampleKy12345678_EB2_ +> ││└───┬───┘ +> ││ │ +> ││ └── const-data 0x12345678 +> │└─────── const type u64 +> └──────── const generic arg +> ``` +> +> Recommended demangling: `mycrate::example::<305419896>` + +### Placeholders +[placeholder]: #placeholders + +A *placeholder* may occur in circumstances where a type or const value is not relevant. + +> Example: +> ```rust +> pub struct Example([T; N]); +> +> impl Example { +> pub fn foo() -> &'static () { +> static EXAMPLE_STATIC: () = (); +> &EXAMPLE_STATIC +> } +> } +> ``` +> +> In this example, the static `EXAMPLE_STATIC` would not be monomorphized by the type or const parameters `T` and `N`. +> Those will use the placeholder for those generic arguments. +> Its symbol is: +> +> ```text +> _RNvNvMCsd9PVOYlP1UU_7mycrateINtB4_7ExamplepKpE3foo14EXAMPLE_STATIC +> │ │││ +> │ ││└── const placeholder +> │ │└─── const generic argument +> │ └──── type placeholder +> └────────────────── generic-args +> ``` +> +> Recommended demangling: `>::foo::EXAMPLE_STATIC` + + +## Type +[type]: #type +[basic-type]: #basic-type +[array-type]: #array-type +[slice-type]: #slice-type +[tuple-type]: #tuple-type +[ref-type]: #ref-type +[mut-ref-type]: #mut-ref-type +[const-ptr-type]: #const-ptr-type +[mut-ptr-type]: #mut-ptr-type +[fn-type]: #fn-type +[dyn-trait-type]: #dyn-trait-type + +> type → \ +>       *[basic-type]* \ +>    | *[array-type]* \ +>    | *[slice-type]* \ +>    | *[tuple-type]* \ +>    | *[ref-type]* \ +>    | *[mut-ref-type]* \ +>    | *[const-ptr-type]* \ +>    | *[mut-ptr-type]* \ +>    | *[fn-type]* \ +>    | *[dyn-trait-type]* \ +>    | *[path]* \ +>    | *[backref]* + +A *type* represents a Rust [type][reference-types]. +The initial character can be used to distinguish which type is encoded. +The type encodings based on the initial tag character are: + +* A *basic-type* is encoded as a single character: + * `a` — `i8` + * `b` — `bool` + * `c` — `char` + * `d` — `f64` + * `e` — `str` + * `f` — `f32` + * `h` — `u8` + * `i` — `isize` + * `j` — `usize` + * `l` — `i32` + * `m` — `u32` + * `n` — `i128` + * `o` — `u128` + * `s` — `i16` + * `t` — `u16` + * `u` — unit `()` + * `v` — variadic `...` + * `x` — `i64` + * `y` — `u64` + * `z` — `!` + * `p` — [placeholder] `_` + +* `A` — An [array][reference-array] `[T; N]`. + + > array-type → `A` *[type]* *[const]* + + The tag `A` is followed by the *[type]* of the array followed by a *[const]* for the array size. + +* `S` — A [slice][reference-slice] `[T]`. + + > slice-type → `S` *[type]* + + The tag `S` is followed by the *[type]* of the slice. + +* `T` — A [tuple][reference-tuple] `(T1, T2, T3, ...)`. + + > tuple-type → `T` {*[type]*} `E` + + The tag `T` is followed by one or more [type]s indicating the type of each field, followed by a terminating `E` character. + + Note that a zero-length tuple (unit) is encoded with the `u` *[basic-type]*. + +* `R` — A [reference][reference-shared-reference] `&T`. + + > ref-type → `R` *[lifetime]*opt *[type]* + + The tag `R` is followed by an optional *[lifetime]* followed by the *[type]* of the reference. + The lifetime is not included if it has been erased. + +* `Q` — A [mutable reference][reference-mutable-reference] `&mut T`. + + > mut-ref-type → `Q` *[lifetime]*opt *[type]* + + The tag `Q` is followed by an optional *[lifetime]* followed by the *[type]* of the mutable reference. + The lifetime is not included if it has been erased. + +* `P` — A [constant raw pointer][reference-raw-pointer] `*const T`. + + The tag `P` is followed by the *[type]* of the pointer. + + > const-ptr-type → `P` *[type]* + +* `O` — A [mutable raw pointer][reference-raw-pointer] `*mut T`. + + > mut-ptr-type → `O` *[type]* + + The tag `O` is followed by the *[type]* of the pointer. + +* `F` — A [function pointer][reference-fn-pointer] `fn(…) -> …`. + + > fn-type → `F` *[fn-sig]* + > + > fn-sig → *[binder]*opt `U`opt (`K` *[abi]*)opt {*[type]*} `E` *[type]* + > + > abi → \ + >       `C` \ + >    | *[undisambiguated-identifier]* + + The tag `F` is followed by a *[fn-sig]* of the function signature. + A *fn-sig* is the signature for a function pointer. + + It starts with an optional *[binder]* which represents the higher-ranked trait bounds (`for<…>`). + + Following that is an optional `U` character which is present for an `unsafe` function. + + Following that is an optional `K` character which indicates that an *[abi]* is specified. + If the ABI is not specified, it is assumed to be the `"Rust"` ABI. + + The *[abi]* can be the letter `C` to indicate it is the `"C"` ABI. + Otherwise it is an *[undisambiguated-identifier]* of the ABI string with dashes converted to underscores. + + Following that is zero or more [type]s which indicate the input parameters of the function. + + Following that is the character `E` and then the *[type]* of the return value. + +[fn-sig]: #fn-sig +[abi]: #abi + +* `D` — A [trait object][reference-trait-object] `dyn Trait + Send + 'a`. + + > dyn-trait-type → `D` *[dyn-bounds]* *[lifetime]* + > + > dyn-bounds → *[binder]*opt {*[dyn-trait]*} `E` + > + > dyn-trait → *[path]* {*[dyn-trait-assoc-binding]*} + > + > dyn-trait-assoc-binding → `p` *[undisambiguated-identifier]* *[type]* + + The tag `D` is followed by a *[dyn-bounds]* which encodes the trait bounds, + followed by a *[lifetime]* of the trait object lifetime bound. + + A *dyn-bounds* starts with an optional *[binder]* which represents the higher-ranked trait bounds (`for<…>`). + Following that is a sequence of *[dyn-trait]* terminated by the character `E`. + + Each *[dyn-trait]* represents a trait bound, which consists of a *[path]* to the trait followed by zero or more *[dyn-trait-assoc-binding]* which list the associated types. + + Each *[dyn-trait-assoc-binding]* consists of a character `p` followed a *[undisambiguated-identifier]* representing the associated binding name, and finally a *[type]*. + +[dyn-bounds]: #dyn-bounds +[dyn-trait]: #dyn-trait +[dyn-trait-assoc-binding]: #dyn-trait-assoc-binding + + +* A *[path]* to a named type. + +* A *[backref]* to refer to a previously encoded type. + +> **Recommended Demangling** +> +> A *[type]* may be displayed as the type it represents, using typical Rust syntax to represent the type. + +> Example: +> ```rust +> fn main() { +> example::<[u16; 8]>(); +> } +> +> pub fn example() {} +> ``` +> +> The symbol for function `example` is: +> +> ```text +> _RINvCs7qp2U7fqm6G_7mycrate7exampleAtj8_EB2_ +> │││├┘│ +> ││││ └─── end of generic args +> │││└───── const data 8 +> ││└────── const type usize +> │└─────── array element type u16 +> └──────── array type +> ``` +> +> Recommended demangling: `mycrate::example::<[u16; 8]>` + +## Binder +[binder]: #binder + +> binder → `G` *[base-62-number]* + +A *binder* represents the number of [higher-ranked trait bound][reference-hrtb] lifetimes to bind. +It consists of the character `G` followed by a *[base-62-number]*. +The value 1 should be added to the *[base-62-number]* when decoding +(such that the *base-62-number* encoding of `_` is interpreted as having 1 binder). + +A *lifetime* rule can then refer to these numbered lifetimes. +The lowest indices represent the innermost lifetimes. +The number of bound lifetimes is the value of *[base-62-number]* plus one. + +For example, in `for<'a, 'b> fn(for<'c> fn (...))`, any [lifetime]s in `...` +(but not inside more binders) will observe the indices 1, 2, and 3 to refer to `'c`, `'b`, and `'a`, respectively. + +> **Recommended Demangling** +> +> A *binder* may be printed using `for<…>` syntax listing the lifetimes as recommended in *[lifetime]*. +> See *[lifetime]* for an example. + +## Backref +[backref]: #backref + +> backref → `B` *[base-62-number]* + +A *backref* is used to refer to a previous part of the mangled symbol. +This provides a simple form of compression to reduce the length of the mangled symbol. +This can help reduce the amount of work and resources needed by the compiler, linker, and loader. + +It consists of the character `B` followed by a *[base-62-number]*. +The number indicates the 0-based offset in bytes starting from just after the `_R` prefix of the symbol. +The *backref* represents the corresponding element starting at that position. + +backrefs always refer to a position before the *backref* itself. + +The *backref* compression relies on the fact that all substitutable symbol elements have a self-terminating mangled form. +Given the start position of the encoded node, the grammar guarantees that it is always unambiguous where the node ends. +This is ensured by not allowing optional or repeating elements at the end of substitutable productions. + +> **Recommended Demangling** +> +> A *backref* should be demangled by rendering the element that it points to. +> Care should be considered when handling deeply nested backrefs to avoid using too much stack. + +> Example: +> ```rust +> fn main() { +> example::(); +> } +> +> struct Example; +> +> pub fn example() {} +> ``` +> +> The symbol for function `example` is: +> +> ```text +> _RINvCs7qp2U7fqm6G_7mycrate7exampleNtB2_7ExampleBw_EB2_ +> │├┘ │├┘ │├┘ +> ││ ││ ││ +> ││ ││ │└── backref to offset 3 (crate-root) +> ││ ││ └─── backref for instantiating-crate path +> ││ │└────── backref to offset 33 (path to Example) +> ││ └─────── backref for second generic-arg +> │└───────────────── backref to offset 3 (crate-root) +> └────────────────── backref for first generic-arg (first segment of Example path) +> ``` +> +> Recommended demangling: `mycrate::example::` + +## Instantiating crate +[instantiating-crate]: #instantiating-crate + +> instantiating-crate → *[path]* + +The *instantiating-crate* is an optional element of the *[symbol-name]* which can be used to indicate which crate is instantiating the symbol. +It consists of a single *[path]*. + +This helps differentiate symbols that would otherwise be identical, +for example the monomorphization of a function from an external crate may result in a duplicate if another crate is also instantiating the same generic function with the same types. + +In practice, the instantiating crate is also often the crate where the symbol is defined, +so it is usually encoded as a *[backref]* to the *[crate-root]* encoded elsewhere in the symbol. + +> **Recommended Demangling** +> +> The *instantiating-crate* usually need not be displayed. + +> Example: +> ```rust +> std::path::Path::new("example"); +> ``` +> +> The symbol for `Path::new::` instantiated from the `mycrate` crate is: +> +> ```text +> _RINvMsY_NtCseXNvpPnDBDp_3std4pathNtB6_4Path3neweECs7qp2U7fqm6G_7mycrate +> └──┬───┘ +> │ +> └── instantiating crate identifier `mycrate` +> ``` +> +> Recommended demangling: `::new::` + +## Vendor-specific suffix +[vendor-specific-suffix]: #vendor-specific-suffix +[suffix]: #vendor-specific-suffix + +> vendor-specific-suffix → (`.` | `$`) *[suffix]* +> +> suffix → {*byte*} + +The *vendor-specific-suffix* is an optional element at the end of the *[symbol-name]*. +It consists of either a `.` or `$` character followed by zero or more bytes. +There are no restrictions on the characters following the period or dollar sign. + +This suffix is added as needed by the implementation. +One example where this can happen is when locally unique names need to become globally unique. +LLVM can append a `.llvm.` suffix during LTO to ensure a unique name, +and `$` can be used for thread-local data on Mach-O. +In these situations it's generally fine to ignore the suffix; +the suffixed name has the same semantics as the original. + +> **Recommended Demangling** +> +> The *vendor-specific-suffix* usually need not be displayed. + +> Example: +> ```rust +> # use std::cell::RefCell; +> thread_local! { +> pub static EXAMPLE: RefCell = RefCell::new(1); +> } +> ``` +> +> The symbol for `EXAMPLE` on macOS may have the following for thread-local data: +> +> ```text +> _RNvNvNvCs7qp2U7fqm6G_7mycrate7EXAMPLE7___getit5___KEY$tlv$init +> └───┬───┘ +> │ +> └── vendor-specific-suffix +> ``` +> +> Recommended demangling: `mycrate::EXAMPLE::__getit::__KEY` + +## Common rules +[decimal-number]: #common-rules +[digit]: #common-rules +[non-zero-digit]: #common-rules +[lower]: #common-rules +[upper]: #common-rules + +> [decimal-number] → \ +>       `0` \ +>    | *[non-zero-digit]* {*[digit]*} +> +> [non-zero-digit] → `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | `9` \ +> [digit] → `0` | *[non-zero-digit]* +> +> [lower] → `a` |`b` |`c` |`d` |`e` |`f` |`g` |`h` |`i` |`j` |`k` |`l` |`m` |`n` |`o` |`p` |`q` |`r` |`s` |`t` |`u` |`v` |`w` |`x` |`y` |`z` +> +> [upper] → `A` | `B` | `C` | `D` | `E` | `F` | `G` | `H` | `I` | `J` | `K` | `L` | `M` | `N` | `O` | `P` | `Q` | `R` | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` + +A *decimal-number* is encoded as one or more [digit]s indicating a numeric value in decimal. + +The value zero is encoded as a single byte `0`. +Beware that there are situations where `0` may be followed by another digit that should not be decoded as part of the decimal-number. +For example, a zero-length *[identifier]* within a *[nested-path]* which is in turn inside another *[nested-path]* will result in two identifiers in a row, where the first one only has the encoding of `0`. + +A *digit* is an ASCII number. + +A *lower* and *upper* is an ASCII lower and uppercase letter respectively. + +## base-62-number +[base-62-number]: #base-62-number + +> [base-62-number] → { *[digit]* | *[lower]* | *[upper]* } `_` + +A *base-62-number* is an encoding of a numeric value. +It uses ASCII numbers and lowercase and uppercase letters. +The value is terminated with the `_` character. +If the value is 0, then the encoding is the `_` character without any digits. +Otherwise, one is subtracted from the value, and it is encoded with the mapping: + +* `0`-`9` maps to 0-9 +* `a`-`z` maps to 10 to 35 +* `A`-`Z` maps to 36 to 61 + +The number is repeatedly divided by 62 (with integer division round towards zero) +to choose the next character in the sequence. +The remainder of each division is used in the mapping to choose the next character. +This is repeated until the number is 0. +The final sequence of characters is then reversed. + +Decoding is a similar process in reverse. + +Examples: + +| Value | Encoding | +|-------|----------| +| 0 | `_` | +| 1 | `0_` | +| 11 | `a_` | +| 62 | `Z_` | +| 63 | `10_` | +| 1000 | `g7_` | + +## Symbol grammar summary +[summary]: #symbol-grammar-summary + +The following is a summary of all of the productions of the symbol grammar. + +> [symbol-name] → `_R` *[decimal-number]*opt *[path]* *[instantiating-crate]*opt *[vendor-specific-suffix]*opt +> +> [path] → \ +>       *[crate-root]* \ +>    | *[inherent-impl]* \ +>    | *[trait-impl]* \ +>    | *[trait-definition]* \ +>    | *[nested-path]* \ +>    | *[generic-args]* \ +>    | *[backref]* +> +> [crate-root] → `C` *[identifier]* \ +> [inherent-impl] → `M` *[impl-path]* *[type]* \ +> [trait-impl] → `X` *[impl-path]* *[type]* *[path]* \ +> [trait-definition] → `Y` *[type]* *[path]* \ +> [nested-path] → `N` *[namespace]* *[path]* *[identifier]* \ +> [generic-args] → `I` *[path]* {*[generic-arg]*} `E` +> +> [identifier] → *[disambiguator]*opt *[undisambiguated-identifier]* \ +> [undisambiguated-identifier] → `u`opt *[decimal-number]* `_`opt *[bytes]* \ +> [bytes] → {*UTF-8 bytes*} +> +> [disambiguator] → `s` *[base-62-number]* +> +> [impl-path] → *[disambiguator]*opt *[path]* +> +> [type] → \ +>       *[basic-type]* \ +>    | *[array-type]* \ +>    | *[slice-type]* \ +>    | *[tuple-type]* \ +>    | *[ref-type]* \ +>    | *[mut-ref-type]* \ +>    | *[const-ptr-type]* \ +>    | *[mut-ptr-type]* \ +>    | *[fn-type]* \ +>    | *[dyn-trait-type]* \ +>    | *[path]* \ +>    | *[backref]* +> +> [basic-type] → *[lower]* \ +> [array-type] → `A` *[type]* *[const]* \ +> [slice-type] → `S` *[type]* \ +> [tuple-type] → `T` {*[type]*} `E` \ +> [ref-type] → `R` *[lifetime]*opt *[type]* \ +> [mut-ref-type] → `Q` *[lifetime]*opt *[type]* \ +> [const-ptr-type] → `P` *[type]* \ +> [mut-ptr-type] → `O` *[type]* \ +> [fn-type] → `F` *[fn-sig]* \ +> [dyn-trait-type] → `D` *[dyn-bounds]* *[lifetime]* +> +> [namespace] → *[lower]* | *[upper]* +> +> [generic-arg] → \ +>       *[lifetime]* \ +>    | *[type]* \ +>    | `K` *[const]* +> +> [lifetime] → `L` *[base-62-number]* +> +> [const] → \ +>       *[type]* *[const-data]* \ +>    | `p` \ +>    | *[backref]* +> +> [const-data] → `n`opt {*[hex-digit]*} `_` +> +> [hex-digit] → *[digit]* | `a` | `b` | `c` | `d` | `e` | `f` +> +> [fn-sig] → *[binder]*opt `U`opt (`K` *[abi]*)opt {*[type]*} `E` *[type]* +> +> [abi] → \ +>       `C` \ +>    | *[undisambiguated-identifier]* +> +> [dyn-bounds] → *[binder]*opt {*[dyn-trait]*} `E` \ +> [dyn-trait] → *[path]* {*[dyn-trait-assoc-binding]*} \ +> [dyn-trait-assoc-binding] → `p` *[undisambiguated-identifier]* *[type]* +> +> [binder] → `G` *[base-62-number]* +> +> [backref] → `B` *[base-62-number]* +> +> [instantiating-crate] → *[path]* +> +> [vendor-specific-suffix] → (`.` | `$`) *[suffix]* \ +> [suffix] → {*byte*} +> +> [decimal-number] → \ +>       `0` \ +>    | *[non-zero-digit]* {*[digit]*} +> +> [base-62-number] → { *[digit]* | *[lower]* | *[upper]* } `_` +> +> [non-zero-digit] → `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | `9` \ +> [digit] → `0` | *[non-zero-digit]* \ +> [lower] → `a` |`b` |`c` |`d` |`e` |`f` |`g` |`h` |`i` |`j` |`k` |`l` |`m` |`n` |`o` |`p` |`q` |`r` |`s` |`t` |`u` |`v` |`w` |`x` |`y` |`z` \ +> [upper] → `A` | `B` | `C` | `D` | `E` | `F` | `G` | `H` | `I` | `J` | `K` | `L` | `M` | `N` | `O` | `P` | `Q` | `R` | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` + +## Encoding of Rust entities + +The following are guidelines for how Rust entities are encoded in a symbol. +The compiler has some latitude in how an entity is encoded as long as the symbol is unambiguous. + +* Named functions, methods, and statics shall be represented by a *[path]* production. + +* Paths should be rooted at the inner-most entity that can act as a path root. + Roots can be crate-ids, inherent impls, trait impls, and (for items within default methods) trait definitions. + +* The compiler is free to choose disambiguation indices and namespace tags from + the reserved ranges as long as it ascertains identifier unambiguity. + +* Generic arguments that are equal to the default should not be encoded in order to save space. + + +[RFC 2603]: https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html +[reference-array]: ../../reference/types/array.html +[reference-fn-pointer]: ../../reference/types/function-pointer.html +[reference-hrtb]: ../../reference/trait-bounds.html#higher-ranked-trait-bounds +[reference-identifiers]: ../../reference/identifiers.html +[reference-implementations]: ../../reference/items/implementations.html +[reference-inherent-impl]: ../../reference/items/implementations.html#inherent-implementations +[reference-mutable-reference]: ../../reference/types/pointer.html#mutable-references-mut +[reference-paths]: ../../reference/paths.html +[reference-raw-pointer]: ../../reference/types/pointer.html#raw-pointers-const-and-mut +[reference-shared-reference]: ../../reference/types/pointer.html#shared-references- +[reference-slice]: ../../reference/types/slice.html +[reference-track_caller]: ../../reference/attributes/codegen.html#the-track_caller-attribute +[reference-trait-impl]: ../../reference/items/implementations.html#trait-implementations +[reference-trait-object]: ../../reference/types/trait-object.html +[reference-traits]: ../../reference/items/traits.html +[reference-tuple]: ../../reference/types/tuple.html +[reference-types]: ../../reference/types.html diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index fd57b0796..f15e6e451 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -412,3 +412,37 @@ help: if you meant to use a literal backtick, escape it warning: 1 warning emitted ``` + +## `redundant_explicit_links` + +This lint is **warned by default**. It detects explicit links that are same +as computed automatic links. +This usually means the explicit links is removeable. For example: + +```rust +#![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default. + +/// add takes 2 [`usize`](usize) and performs addition +/// on them, then returns result. +pub fn add(left: usize, right: usize) -> usize { + left + right +} +``` + +Which will give: + +```text +error: redundant explicit rustdoc link + --> src/lib.rs:3:27 + | +3 | /// add takes 2 [`usize`](usize) and performs addition + | ^^^^^ + | + = note: Explicit link does not affect the original link +note: the lint level is defined here + --> src/lib.rs:1:9 + | +1 | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: Remove explicit link instead +``` diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 013b93e01..f69156b7c 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -200,6 +200,7 @@ To do so, the `#[doc(keyword = "...")]` attribute is used. Example: ```rust #![feature(rustdoc_internals)] +#![allow(internal_features)] /// Some documentation about the keyword. #[doc(keyword = "keyword")] diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md index 7a444d77c..7179ee0cf 100644 --- a/src/doc/rustdoc/src/what-is-rustdoc.md +++ b/src/doc/rustdoc/src/what-is-rustdoc.md @@ -37,7 +37,7 @@ top, with no contents. ## Configuring rustdoc There are two problems with this: first, why does it -think that our package is named "lib"? Second, why does it not have any +think that our crate is named "lib"? Second, why does it not have any contents? The first problem is due to `rustdoc` trying to be helpful; like `rustc`, diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md index b8aa64ba1..f4d759673 100644 --- a/src/doc/style-guide/src/README.md +++ b/src/doc/style-guide/src/README.md @@ -36,11 +36,10 @@ options. ### Indentation and line width -* Use spaces, not tabs. -* Each level of indentation must be four spaces (that is, all indentation - outside of string literals and comments must be a multiple of four). -* The maximum width for a line is 100 characters. -* A tool may choose to make some of these configurable. +- Use spaces, not tabs. +- Each level of indentation must be 4 spaces (that is, all indentation + outside of string literals and comments must be a multiple of 4). +- The maximum width for a line is 100 characters. #### Block indent @@ -63,7 +62,8 @@ example) and less rightward drift. ### Trailing commas -Lists should have a trailing comma when followed by a newline: +In comma-separated lists of any kind, use a trailing comma when followed by a +newline: ```rust function_call( @@ -99,13 +99,13 @@ fn bar() {} fn baz() {} ``` -Formatting tools may wish to make the bounds on blank lines configurable. - ### [Module-level items](items.md) + ### [Statements](statements.md) + ### [Expressions](expressions.md) -### [Types](types.md) +### [Types](types.md) ### Comments @@ -114,17 +114,17 @@ formatter might skip formatting of comments. Prefer line comments (`//`) to block comments (`/* ... */`). -When using line comments there should be a single space after the opening sigil. +When using line comments, put a single space after the opening sigil. -When using single-line block comments there should be a single space after the -opening sigil and before the closing sigil. Multi-line block comments should -have a newline after the opening sigil and before the closing sigil. +When using single-line block comments, put a single space after the opening +sigil and before the closing sigil. For multi-line block comments, put a +newline after the opening sigil, and a newline before the closing sigil. -Prefer to put a comment on its own line. Where a comment follows code, there -should be a single space before it. Where a block comment is inline, there -should be surrounding whitespace as if it were an identifier or keyword. There -should be no trailing whitespace after a comment or at the end of any line in a -multi-line comment. Examples: +Prefer to put a comment on its own line. Where a comment follows code, put a +single space before it. Where a block comment appears inline, use surrounding +whitespace as if it were an identifier or keyword. Do not include trailing +whitespace after a comment or at the end of any line in a multi-line comment. +Examples: ```rust // A comment on an item. @@ -173,7 +173,7 @@ Prefer line comments (`///`) to block comments (`/** ... */`). Prefer outer doc comments (`///` or `/** ... */`), only use inner doc comments (`//!` and `/*! ... */`) to write module-level or crate-level documentation. -Doc comments should come before attributes. +Put doc comments before attributes. ### Attributes @@ -198,18 +198,20 @@ struct CRepr { } ``` -For attributes with an equal sign, there should be a single space before and -after the `=`, e.g., `#[foo = 42]`. +For attributes with an equal sign, put a single space before and after the `=`, +e.g., `#[foo = 42]`. There must only be a single `derive` attribute. Note for tool authors: if combining multiple `derive` attributes into a single attribute, the ordering of -the derived names should be preserved. E.g., `#[derive(bar)] #[derive(foo)] -struct Baz;` should be formatted to `#[derive(bar, foo)] struct Baz;`. +the derived names must generally be preserved for correctness: +`#[derive(Foo)] #[derive(Bar)] struct Baz;` must be formatted to +`#[derive(Foo, Bar)] struct Baz;`. ### *small* items -In many places in this guide we specify that a formatter may format an item -differently if it is *small*, for example struct literals: +In many places in this guide we specify formatting that depends on a code +construct being *small*. For example, single-line vs multi-line struct +literals: ```rust // Normal formatting @@ -218,7 +220,7 @@ Foo { f2: another_expression(), } -// *small* formatting +// "small" formatting Foo { f1, f2 } ``` @@ -231,10 +233,6 @@ complexity of an item (for example, that all components must be simple names, not more complex sub-expressions). For more discussion on suitable heuristics, see [this issue](https://github.com/rust-lang-nursery/fmt-rfcs/issues/47). -Tools should give the user an option to ignore such heuristics and always use -the normal formatting. - - ## [Non-formatting conventions](advice.md) ## [Cargo.toml conventions](cargo.md) diff --git a/src/doc/style-guide/src/SUMMARY.md b/src/doc/style-guide/src/SUMMARY.md index 606485bfb..64540c399 100644 --- a/src/doc/style-guide/src/SUMMARY.md +++ b/src/doc/style-guide/src/SUMMARY.md @@ -9,4 +9,5 @@ - [Other style advice](advice.md) - [`Cargo.toml` conventions](cargo.md) - [Guiding principles and rationale](principles.md) +- [Rust style editions](editions.md) - [Nightly-only syntax](nightly.md) diff --git a/src/doc/style-guide/src/advice.md b/src/doc/style-guide/src/advice.md index 9a617be50..65cf8cb6e 100644 --- a/src/doc/style-guide/src/advice.md +++ b/src/doc/style-guide/src/advice.md @@ -18,16 +18,16 @@ if y { ## Names - * Types shall be `UpperCamelCase`, - * Enum variants shall be `UpperCamelCase`, - * Struct fields shall be `snake_case`, - * Function and method names shall be `snake_case`, - * Local variables shall be `snake_case`, - * Macro names shall be `snake_case`, - * Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`. - * When a name is forbidden because it is a reserved word (such as `crate`), - either use a raw identifier (`r#crate`) or use a trailing underscore - (`crate_`). Don't misspell the word (`krate`). +- Types shall be `UpperCamelCase`, +- Enum variants shall be `UpperCamelCase`, +- Struct fields shall be `snake_case`, +- Function and method names shall be `snake_case`, +- Local variables shall be `snake_case`, +- Macro names shall be `snake_case`, +- Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`. +- When a name is forbidden because it is a reserved word (such as `crate`), + either use a raw identifier (`r#crate`) or use a trailing underscore + (`crate_`). Don't misspell the word (`krate`). ### Modules diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md new file mode 100644 index 000000000..5c67a185b --- /dev/null +++ b/src/doc/style-guide/src/editions.md @@ -0,0 +1,46 @@ +# Rust style editions + +The default Rust style evolves over time, as Rust does. However, to avoid +breaking established code style, and CI jobs checking code style, changes to +the default Rust style only appear in *style editions*. + +Code written in a given +[Rust edition](https://doc.rust-lang.org/edition-guide/) +uses the corresponding Rust style edition by default. To make it easier to +migrate code style separately from the semantic changes between Rust editions, +formatting tools such as `rustfmt` allow updating the style edition separately +from the Rust edition. + +The current version of the style guide describes the latest Rust style edition. +Each distinct past style will have a corresponding archived version of the +style guide. + +Note that archived versions of the style guide do not document formatting for +newer Rust constructs that did not exist at the time that version of the style +guide was archived. However, each style edition will still format all +constructs valid in that Rust edition, with the style of newer constructs +coming from the first subsequent style edition providing formatting rules for +that construct (without any of the systematic/global changes from that style +edition). + +Not all Rust editions have corresponding changes to the Rust style. For +instance, Rust 2015, Rust 2018, and Rust 2021 all use the same style edition. + +## Rust 2024 style edition + +This style guide describes the Rust 2024 style edition. The Rust 2024 style +edition is currently nightly-only and may change before the release of Rust +2024. + +For a full history of changes in the Rust 2024 style edition, see the git +history of the style guide. Notable changes in the Rust 2024 style edition +include: + +- Miscellaneous `rustfmt` bugfixes. + +## Rust 2015/2018/2021 style edition + +The archived version of the style guide at + +describes the style edition corresponding to Rust 2015, Rust 2018, and Rust +2021. diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 143161da6..32c604f9f 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -1,11 +1,14 @@ -## Expressions +# Expressions -### Blocks +## Blocks -A block expression should have a newline after the initial `{` and before the -terminal `}`. Any qualifier before the block (e.g., `unsafe`) should always be -on the same line as the opening brace, and separated with a single space. The -contents of the block should be block indented: +A block expression must have a newline after the initial `{` and before the +terminal `}`, unless it qualifies to be written as a single line based on +another style rule. + +A keyword before the block (such as `unsafe` or `async`) must be on the same +line as the opening brace, with a single space between the keyword and the +opening brace. Indent the contents of the block. ```rust fn block_as_stmt() { @@ -40,7 +43,7 @@ fn unsafe_block_as_stmt() { } ``` -If a block has an attribute, it should be on its own line: +If a block has an attribute, put it on its own line before the block: ```rust fn block_as_stmt() { @@ -54,18 +57,18 @@ fn block_as_stmt() { } ``` -Avoid writing comments on the same line as the braces. +Avoid writing comments on the same lines as either of the braces. -An empty block should be written as `{}`. +Write an empty block as `{}`. -A block may be written on a single line if: +Write a block on a single line if: -* it is either used in expression position (not statement position) or is an - unsafe block in statement position -* contains a single-line expression and no statements -* contains no comments +- it is either used in expression position (not statement position) or is an + unsafe block in statement position, +- it contains a single-line expression and no statements, and +- it contains no comments -A single line block should have spaces after the opening brace and before the +For a single-line block, put spaces after the opening brace and before the closing brace. Examples: @@ -113,18 +116,17 @@ fn main() { } ``` - -### Closures +## Closures Don't put any extra spaces before the first `|` (unless the closure is prefixed -by `move`); put a space between the second `|` and the expression of the -closure. Between the `|`s, you should use function definition syntax, however, -elide types where possible. +by a keyword such as `move`); put a space between the second `|` and the +expression of the closure. Between the `|`s, use function definition syntax, +but elide types where possible. Use closures without the enclosing `{}`, if possible. Add the `{}` when you have -a return type, when there are statements, there are comments in the body, or the -body expression spans multiple lines and is a control-flow expression. If using -braces, follow the rules above for blocks. Examples: +a return type, when there are statements, when there are comments inside the +closure, or when the body expression is a control-flow expression that spans +multiple lines. If using braces, follow the rules above for blocks. Examples: ```rust |arg1, arg2| expr @@ -152,16 +154,16 @@ move |arg1: i32, arg2: i32| -> i32 { } ``` +## Struct literals -### Struct literals +If a struct literal is *small*, format it on a single line, and do not use a +trailing comma. If not, split it across multiple lines, with each field on its +own block-indented line, and use a trailing comma. -If a struct literal is *small* it may be formatted on a single line. If not, -each field should be on it's own, block-indented line. There should be a -trailing comma in the multi-line form only. There should be a space after the -colon only. +For each `field: value` entry, put a space after the colon only. -There should be a space before the opening brace. In the single-line form there -should be spaces after the opening brace and before the closing brace. +Put a space before the opening brace. In the single-line form, put spaces after +the opening brace and before the closing brace. ```rust Foo { field1, field2: 0 } @@ -172,19 +174,24 @@ let f = Foo { ``` Functional record update syntax is treated like a field, but it must never have -a trailing comma. There should be no space after `..`. +a trailing comma. Do not put a space after `..`. +```rust let f = Foo { field1, ..an_expr }; +``` +## Tuple literals -### Tuple literals +Use a single-line form where possible. Do not put spaces between the opening +parenthesis and the first element, or between the last element and the closing +parenthesis. Separate elements with a comma followed by a space. -Use a single-line form where possible. There should not be spaces around the -parentheses. Where a single-line form is not possible, each element of the tuple -should be on its own block-indented line and there should be a trailing comma. +Where a single-line form is not possible, write the tuple across +multiple lines, with each element of the tuple on its own block-indented line, +and use a trailing comma. ```rust (a, b, c) @@ -195,17 +202,24 @@ let x = ( ); ``` +## Tuple struct literals -### Tuple struct literals +Do not put space between the identifier and the opening parenthesis. Otherwise, +follow the rules for tuple literals: -There should be no space between the identifier and the opening parenthesis. -Otherwise, follow the rules for tuple literals, e.g., `Foo(a, b)`. +```rust +Foo(a, b, c) +let x = Foo( + a_long_expr, + another_very_long_expr, +); +``` -### Enum literals +## Enum literals Follow the formatting rules for the various struct literals. Prefer using the -name of the enum as a qualifying name, unless the enum is in the prelude. E.g., +name of the enum as a qualifying name, unless the enum is in the prelude: ```rust Foo::Bar(a, b) @@ -216,27 +230,31 @@ Foo::Baz { Ok(an_expr) ``` +## Array literals -### Array literals +Write small array literals on a single line. Do not put spaces between the opening +square bracket and the first element, or between the last element and the closing +square bracket. Separate elements with a comma followed by a space. -For simple array literals, avoid line breaking, no spaces around square -brackets, contents of the array should be separated by commas and spaces. If -using the repeating initialiser, there should be a space after the semicolon -only. Apply the same rules if using the `vec!` or similar macros (always use -square brackets here). Examples: +If using the repeating initializer, put a space after the semicolon +only. + +Apply the same rules if using `vec!` or similar array-like macros; always use +square brackets with such macros. Examples: ```rust fn main() { - [1, 2, 3]; - vec![a, b, c, d]; + let x = [1, 2, 3]; + let y = vec![a, b, c, d]; let a = [42; 10]; } ``` -If a line must be broken, prefer breaking only after the `;`, if possible. -Otherwise, follow the rules below for function calls. In any case, the contents -of the initialiser should be block indented and there should be line breaks -after the opening bracket and before the closing bracket: +For arrays that have to be broken across lines, if using the repeating +initializer, break after the `;`, not before. Otherwise, follow the rules below +for function calls. In any case, block-indent the contents of the initializer, +and put line breaks after the opening square bracket and before the closing +square bracket: ```rust fn main() { @@ -252,14 +270,14 @@ fn main() { } ``` +## Array accesses, indexing, and slicing -### Array accesses, indexing, and slicing. - -No spaces around the square brackets, avoid breaking lines if possible, never -break a line between the target expression and the opening bracket. If the -indexing expression covers multiple lines, then it should be block indented and -there should be newlines after the opening brackets and before the closing -bracket. However, this should be avoided where possible. +Don't put spaces around the square brackets. Avoid breaking lines if possible. +Never break a line between the target expression and the opening square +bracket. If the indexing expression must be broken onto a subsequent line, or +spans multiple lines itself, then block-indent the indexing expression, and put +newlines after the opening square bracket and before the closing square +bracket: Examples: @@ -275,13 +293,13 @@ fn main() { } ``` -### Unary operations +## Unary operations Do not include a space between a unary op and its operand (i.e., `!x`, not `! x`). However, there must be a space after `&mut`. Avoid line-breaking between a unary operator and its operand. -### Binary operations +## Binary operations Do include spaces around binary ops (i.e., `x + 1`, not `x+1`) (including `=` and other assignment operators such as `+=` or `*=`). @@ -291,7 +309,7 @@ if you have `t: &T`, and `u: U`, prefer `*t op u` to `t op &u`. In general, within expressions, prefer dereferencing to taking references, unless necessary (e.g. to avoid an unnecessarily expensive operation). -Use parentheses liberally, do not necessarily elide them due to precedence. +Use parentheses liberally; do not necessarily elide them due to precedence. Tools should not automatically insert or remove parentheses. Do not use spaces to indicate precedence. @@ -310,7 +328,7 @@ foo_bar Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather than at other binary operators. -### Control flow +## Control flow Do not include extraneous parentheses for `if` and `while` expressions. @@ -329,7 +347,7 @@ if (true) { Do include extraneous parentheses if it makes an arithmetic or logic expression easier to understand (`(x * 15) + (y * 20)` is fine) -### Function calls +## Function calls Do not put a space between the function name, and the opening parenthesis. @@ -339,7 +357,7 @@ Do put a space between an argument, and the comma which precedes it. Prefer not to break a line in the callee expression. -#### Single-line calls +### Single-line calls Do not put a space between the function name and open paren, between the open paren and the first argument, or between the last argument and the close paren. @@ -350,13 +368,13 @@ Do not put a comma after the last argument. foo(x, y, z) ``` -#### Multi-line calls +### Multi-line calls If the function call is not *small*, it would otherwise over-run the max width, -or any argument or the callee is multi-line, then the call should be formatted -across multiple lines. In this case, each argument should be on it's own block- -indented line, there should be a newline after the opening parenthesis and -before the closing parenthesis, and there should be a trailing comma. E.g., +or any argument or the callee is multi-line, then format the call across +multiple lines. In this case, put each argument on its own block-indented line, +break after the opening parenthesis and before the closing parenthesis, +and use a trailing comma: ```rust a_function_call( @@ -365,8 +383,7 @@ a_function_call( ) ``` - -### Method calls +## Method calls Follow the function rules for calling. @@ -376,20 +393,20 @@ Do not put any spaces around the `.`. x.foo().bar().baz(x, y, z); ``` +## Macro uses -### Macro uses - -Macros which can be parsed like other constructs should be formatted like those +If a macro can be parsed like other constructs, format it like those constructs. For example, a macro use `foo!(a, b, c)` can be parsed like a -function call (ignoring the `!`), therefore it should be formatted following the -rules for function calls. +function call (ignoring the `!`), so format it using the rules for function +calls. -#### Special case macros +### Special case macros -Macros which take a format string and where all other arguments are *small* may -be formatted with arguments before and after the format string on a single line -and the format string on its own line, rather than putting each argument on its -own line. For example, +For macros which take a format string, if all other arguments are *small*, +format the arguments before the format string on a single line if they fit, and +format the arguments after the format string on a single line if they fit, with +the format string on its own line. If the arguments are not small or do not +fit, put each on its own line as with a function. For example: ```rust println!( @@ -404,8 +421,7 @@ assert_eq!( ); ``` - -### Casts (`as`) +## Casts (`as`) Put spaces before and after `as`: @@ -413,16 +429,15 @@ Put spaces before and after `as`: let cstr = "Hi\0" as *const str as *const [u8] as *const std::os::raw::c_char; ``` +## Chains of fields and method calls -### Chains of fields and method calls - -A chain is a sequence of field accesses and/or method calls. A chain may also -include the try operator ('?'). E.g., `a.b.c().d` or `foo?.bar().baz?`. +A chain is a sequence of field accesses, method calls, and/or uses of the try +operator `?`. E.g., `a.b.c().d` or `foo?.bar().baz?`. -Prefer formatting on one line if possible, and the chain is *small*. If -formatting on multiple lines, each field access or method call in the chain -should be on its own line with the line-break before the `.` and after any `?`. -Each line should be block-indented. E.g., +Format the chain on one line if it is "small" and otherwise possible to do so. +If formatting on multiple lines, put each field access or method call in the +chain on its own line, with the line-break before the `.` and after any `?`. +Block-indent each subsequent line: ```rust let foo = bar @@ -431,13 +446,16 @@ let foo = bar ``` If the length of the last line of the first element plus its indentation is -less than or equal to the indentation of the second line (and there is space), -then combine the first and second lines, e.g., +less than or equal to the indentation of the second line, then combine the +first and second lines if they fit. Apply this rule recursively. ```rust x.baz? .qux() +x.y.z + .qux() + let foo = x .baz? .qux(); @@ -449,14 +467,13 @@ foo( .qux(); ``` -#### Multi-line elements +### Multi-line elements -If any element in a chain is formatted across multiple lines, then that element -and any later elements must be on their own line. Earlier elements may be kept -on a single line. E.g., +If any element in a chain is formatted across multiple lines, put that element +and any later elements on their own lines. ```rust -a.b.c()?.d +a.b.c()? .foo( an_expr, another_expr, @@ -485,18 +502,18 @@ self.pre_comment.as_ref().map_or( ) ``` -### Control flow expressions +## Control flow expressions This section covers `if`, `if let`, `loop`, `while`, `while let`, and `for` expressions. -The keyword, any initial clauses, and the opening brace of the block should be -on a single line. The usual rules for [block formatting](#blocks) should be -applied to the block. +Put the keyword, any initial clauses, and the opening brace of the block all on +a single line, if they fit. Apply the usual rules for [block +formatting](#blocks) to the block. -If there is an `else` component, then the closing brace, `else`, any following -clause, and the opening brace should all be on the same line. There should be a -single space before and after the `else` keyword. For example: +If there is an `else` component, then put the closing brace, `else`, any +following clause, and the opening brace all on the same line, with a single +space before and after the `else` keyword: ```rust if ... { @@ -514,10 +531,10 @@ if let ... { } ``` -If the control line needs to be broken, then prefer to break before the `=` in -`* let` expressions and before `in` in a `for` expression; the following line -should be block indented. If the control line is broken for any reason, then the -opening brace should be on its own line and not indented. Examples: +If the control line needs to be broken, prefer to break before the `=` in `* +let` expressions and before `in` in a `for` expression; block-indent the +following line. If the control line is broken for any reason, put the opening +brace on its own line, not indented. Examples: ```rust while let Some(foo) @@ -540,10 +557,10 @@ if a_long_expression } ``` -Where the initial clause is multi-lined and ends with one or more closing -parentheses, square brackets, or braces, and there is nothing else on that line, -and that line is not indented beyond the indent on the first line of the control -flow expression, then the opening brace of the block should be put on the same +Where the initial clause spans multiple lines and ends with one or more closing +parentheses, square brackets, or braces, and there is nothing else on that +line, and that line is not indented beyond the indent on the first line of the +control flow expression, then put the opening brace of the block on the same line with a preceding space. For example: ```rust @@ -556,12 +573,11 @@ if !self.config.file_lines().intersects( } ``` +### Single line `if else` -#### Single line `if else` - -Formatters may place an `if else` or `if let else` on a single line if it occurs -in expression context (i.e., is not a standalone statement), it contains a -single `else` clause, and is *small*. For example: +Put an `if else` or `if let else` on a single line if it occurs in expression +context (i.e., is not a standalone statement), it contains a single `else` +clause, and is *small*: ```rust let y = if x { 0 } else { 1 }; @@ -580,12 +596,11 @@ if x { } ``` +## Match -### Match - -Prefer not to line-break inside the discriminant expression. There must always -be a line break after the opening brace and before the closing brace. The match -arms must be block indented once: +Prefer not to line-break inside the discriminant expression. Always break after +the opening brace and before the closing brace. Block-indent the match arms +once: ```rust match foo { @@ -599,7 +614,7 @@ let x = match foo.bar.baz() { Use a trailing comma for a match arm if and only if not using a block. -Never start a match arm pattern with `|`, e.g., +Never start a match arm pattern with `|`: ```rust match foo { @@ -609,14 +624,13 @@ match foo { | a_very_long_pattern | another_pattern | yet_another_pattern - | a_forth_pattern => { + | a_fourth_pattern => { ... } } ``` -Prefer - +Prefer: ```rust match foo { @@ -624,7 +638,7 @@ match foo { a_very_long_pattern | another_pattern | yet_another_pattern - | a_forth_pattern => { + | a_fourth_pattern => { ... } } @@ -634,11 +648,12 @@ Avoid splitting the left-hand side (before the `=>`) of a match arm where possible. If the right-hand side of the match arm is kept on the same line, never use a block (unless the block is empty). -If the right-hand side consists of multiple statements or has line comments or -the start of the line cannot be fit on the same line as the left-hand side, use -a block. +If the right-hand side consists of multiple statements, or has line comments, +or the start of the line does not fit on the same line as the left-hand side, +use a block. Do not flatten a right-hand side block containing a single macro call +because its expanded form could contain a trailing semicolon. -The body of a block arm should be block indented once. +Block-indent the body of a block arm. Examples: @@ -659,12 +674,16 @@ match foo { bar => {} // Trailing comma on last item. foo => bar, + baz => qux!(), + lorem => { + ipsum!() + } } ``` If the body is a single expression with no line comments and not a control flow -expression, then it may be started on the same line as the right-hand side. If -not, then it must be in a block. Example, +expression, start it on the same line as the left-hand side. If not, then it +must be in a block. Example: ```rust match foo { @@ -686,10 +705,10 @@ match foo { } ``` -#### Line-breaking +### Line-breaking -Where it is possible to use a block form on the right-hand side and avoid -breaking the left-hand side, do that. E.g. +If using a block form on the right-hand side of a match arm makes it possible +to avoid breaking on the left-hand side, do that: ```rust // Assuming the following line does not fit in the max width @@ -721,7 +740,7 @@ body on a new line: If required to break the pattern, put each clause of the pattern on its own line with no additional indent, breaking before the `|`. If there is an `if` -clause, then you must use the above form: +clause, use the above form: ```rust a_very_long_pattern @@ -741,7 +760,7 @@ clause, then you must use the above form: ``` If the pattern is multi-line, and the last line is less wide than the indent, do -not put the `if` clause on a newline. E.g., +not put the `if` clause on a new line. E.g., ```rust Token::Dimension { @@ -754,8 +773,8 @@ not put the `if` clause on a newline. E.g., ``` If every clause in a pattern is *small*, but the whole pattern does not fit on -one line, then the pattern may be formatted across multiple lines with as many -clauses per line as possible. Again break before a `|`: +one line, then format the pattern across multiple lines with as many clauses +per line as possible. Again, break before a `|`: ```rust foo | bar | baz @@ -780,12 +799,11 @@ small_no_tuple: E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not. - -### Combinable expressions +## Combinable expressions Where a function call has a single argument, and that argument is formatted -across multiple-lines, the outer call may be formatted as if it were a single- -line call. The same combining behaviour may be applied to any similar +across multiple-lines, format the outer call as if it were a single-line call, +if the result fits. Apply the same combining behaviour to any similar expressions which have multi-line, block-indented lists of sub-expressions delimited by parentheses (e.g., macros or tuple struct literals). E.g., @@ -803,15 +821,24 @@ foo(|param| { action(); foo(param) }) + +let x = combinable([ + an_expr, + another_expr, +]); + +let arr = [combinable( + an_expr, + another_expr, +)]; ``` -Such behaviour should extend recursively, however, tools may choose to limit the -depth of nesting. +Apply this behavior recursively. -Only where the multi-line sub-expression is a closure with an explicit block, -this combining behaviour may be used where there are other arguments, as long as -all the arguments and the first line of the closure fit on the first line, the -closure is the last argument, and there is only one closure argument: +For a function with multiple arguments, if the last argument is a multi-line +closure with an explicit block, there are no other closure arguments, and all +the arguments and the first line of the closure fit on the first line, use the +same combining behavior: ```rust foo(first_arg, x, |param| { @@ -820,34 +847,30 @@ foo(first_arg, x, |param| { }) ``` - -### Ranges +## Ranges Do not put spaces in ranges, e.g., `0..10`, `x..=y`, `..x.len()`, `foo..`. When writing a range with both upper and lower bounds, if the line must be -broken, break before the range operator and block indent the second line: +broken within the range, break before the range operator and block indent the +second line: ```rust a_long_expression ..another_long_expression ``` -For the sake of indicating precedence, we recommend that if either bound is a -compound expression, then use parentheses around it, e.g., `..(x + 1)`, -`(x.f)..(x.f.len())`, or `0..(x - 10)`. +For the sake of indicating precedence, if either bound is a compound +expression, use parentheses around it, e.g., `..(x + 1)`, `(x.f)..(x.f.len())`, +or `0..(x - 10)`. - -### Hexadecimal literals +## Hexadecimal literals Hexadecimal literals may use upper- or lower-case letters, but they must not be mixed within the same literal. Projects should use the same case for all literals, but we do not make a recommendation for either lower- or upper-case. -Tools should have an option to convert mixed case literals to upper-case, and -may have an option to convert all literals to either lower- or upper-case. - ## Patterns -Patterns should be formatted like their corresponding expressions. See the -section on `match` for additional formatting for patterns in match arms. +Format patterns like their corresponding expressions. See the section on +`match` for additional formatting for patterns in match arms. diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index 1e0e60248..a6d941f6d 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -1,4 +1,4 @@ -## Items +# Items Items consist of the set of things permitted at the top level of a module. However, Rust also allows some items to appear within some other types of @@ -9,19 +9,17 @@ an item appears at module level or within another item. alphabetically. `use` statements, and module *declarations* (`mod foo;`, not `mod { ... }`) -must come before other items. We recommend that imports come before module -declarations; if imports and modules are separated, then they should be ordered -alphabetically. When sorting, `self` and `super` must come before any other -names. Module declarations should not be moved if they are annotated with -`#[macro_use]`, since that may be semantics changing. +must come before other items. Put imports before module declarations. Sort each +alphabetically, except that `self` and `super` must come before any other +names. -Tools should make the above ordering optional. +Don't automatically move module declarations annotated with `#[macro_use]`, +since that might change semantics. - -### Function definitions +## Function definitions In Rust, people often find functions by searching for `fn [function-name]`, so -the formatting of function definitions shold enable this. +the formatting of function definitions must enable this. The proper ordering and spacing is: @@ -48,14 +46,13 @@ fn foo( Note the trailing comma on the last argument. - -### Tuples and tuple structs +## Tuples and tuple structs Write the type list as you would a parameter list to a function. Build a tuple or tuple struct as you would call a function. -#### Single-line +### Single-line ```rust struct Bar(Type1, Type2); @@ -64,7 +61,7 @@ let x = Bar(11, 22); let y = (11, 22, 33); ``` -### Enums +## Enums In the declaration, put each variant on its own line, block indented. @@ -83,9 +80,9 @@ enum FooBar { } ``` -If a struct variant is [*small*](index.html#small-items), it may be formatted on -one line. In this case, do not use a trailing comma for the field list, but do -put spaces around each brace: +If a struct variant is [*small*](index.html#small-items), format it on one +line. In this case, do not use a trailing comma for the field list, but do put +spaces around each brace: ```rust enum FooBar { @@ -94,12 +91,11 @@ enum FooBar { ``` In an enum with multiple struct variants, if any struct variant is written on -multiple lines, then the multi-line formatting should be used for all struct -variants. However, such a situation might be an indication that you should -factor out the fields of the variant into their own struct. - +multiple lines, use the multi-line formatting for all struct variants. However, +such a situation might be an indication that you should factor out the fields +of the variant into their own struct. -### Structs and Unions +## Structs and Unions Struct names follow on the same line as the `struct` keyword, with the opening brace on the same line when it fits within the right margin. All struct fields @@ -140,12 +136,11 @@ union Foo { } ``` +## Tuple structs -### Tuple structs - -Put the whole struct on one line if possible. Types in the parentheses should be -separated by a comma and space with no trailing comma. No spaces around the -parentheses or semicolon: +Put the whole struct on one line if possible. Separate types within the +parentheses using a comma and space. Don't use a trailing comma for a +single-line tuple struct. Don't put spaces around the parentheses or semicolon: ```rust pub struct Foo(String, u8); @@ -154,9 +149,11 @@ pub struct Foo(String, u8); Prefer unit structs to empty tuple structs (these only exist to simplify code generation), e.g., `struct Foo;` rather than `struct Foo();`. -For more than a few fields, prefer a proper struct with named fields. Given -this, a tuple struct should always fit on one line. If it does not, block format -the fields with a field on each line and a trailing comma: +For more than a few fields (in particular if the tuple struct does not fit on +one line), prefer a proper struct with named fields. + +For a multi-line tuple struct, block-format the fields with a field on each +line and a trailing comma: ```rust pub struct Foo( @@ -165,12 +162,11 @@ pub struct Foo( ); ``` +## Traits -### Traits - -Trait items should be block-indented. If there are no items, the trait may be -formatted on a single line. Otherwise there should be line-breaks after the -opening brace and before the closing brace: +Use block-indent for trait items. If there are no items, format the trait (including its `{}`) +on a single line. Otherwise, break after the opening brace and before +the closing brace: ```rust trait Foo {} @@ -180,8 +176,8 @@ pub trait Bar { } ``` -If the trait has bounds, there should be a space after the colon but not before -and before and after each `+`, e.g., +If the trait has bounds, put a space after the colon but not before, +and put spaces around each `+`, e.g., ```rust trait Foo: Debug + Bar {} @@ -204,12 +200,11 @@ pub trait IndexRanges: } ``` +## Impls -### Impls - -Impl items should be block indented. If there are no items, the impl may be -formatted on a single line. Otherwise there should be line-breaks after the -opening brace and before the closing brace: +Use block-indent for impl items. If there are no items, format the impl +(including its `{}`) on a single line. Otherwise, break after the opening brace +and before the closing brace: ```rust impl Foo {} @@ -231,15 +226,13 @@ impl Bar } ``` - -### Extern crate +## Extern crate `extern crate foo;` Use spaces around keywords, no spaces around the semicolon. - -### Modules +## Modules ```rust mod foo { @@ -253,7 +246,7 @@ mod foo; Use spaces around keywords and before the opening brace, no spaces around the semicolon. -### macro\_rules! +## `macro_rules!` Use `{}` for the full definition of the macro. @@ -262,17 +255,16 @@ macro_rules! foo { } ``` - -### Generics +## Generics Prefer to put a generics clause on one line. Break other parts of an item declaration rather than line-breaking a generics clause. If a generics clause is -large enough to require line-breaking, you should prefer to use a `where` clause -instead. +large enough to require line-breaking, prefer a `where` clause instead. -Do not put spaces before or after `<` nor before `>`. Only put a space after `>` -if it is followed by a word or opening brace, not an opening parenthesis. There -should be a space after each comma and no trailing comma. +Do not put spaces before or after `<` nor before `>`. Only put a space after +`>` if it is followed by a word or opening brace, not an opening parenthesis. +Put a space after each comma. Do not use a trailing comma for a single-line +generics clause. ```rust fn foo(x: Vec, y: Vec) ... @@ -280,10 +272,9 @@ fn foo(x: Vec, y: Vec) ... impl SomeType { ... ``` -If the generics clause must be formatted across multiple lines, each parameter -should have its own block-indented line, there should be newlines after the -opening bracket and before the closing bracket, and the should be a trailing -comma. +If the generics clause must be formatted across multiple lines, put each +parameter on its own block-indented line, break after the opening `<` and +before the closing `>`, and use a trailing comma. ```rust fn foo< @@ -292,8 +283,7 @@ fn foo< >(x: Vec, y: Vec) ... ``` -If an associated type is bound in a generic type, then there should be spaces on -either side of the `=`: +If an associated type is bound in a generic type, put spaces around the `=`: ```rust > @@ -301,17 +291,18 @@ either side of the `=`: Prefer to use single-letter names for generic parameters. - -### `where` clauses +## `where` clauses These rules apply for `where` clauses on any item. -A `where` clause may immediately follow a closing bracket of any kind. -Otherwise, it must start a new line, with no indent. Each component of a `where` -clause must be on its own line and be block indented. There should be a trailing +If immediately following a closing bracket of any kind, write the keyword +`where` on the same line, with a space before it. + +Otherwise, put `where` on a new line at the same indentation level. Put each +component of a `where` clause on its own line, block-indented. Use a trailing comma, unless the clause is terminated with a semicolon. If the `where` clause -is followed by a block (or assignment), the block should be started on a new -line. Examples: +is followed by a block (or assignment), start that block on a new line. +Examples: ```rust fn function(args) @@ -355,12 +346,12 @@ where = Bar; ``` -If a `where` clause is very short, we recommend using an inline bound on the -type parameter. - +If a `where` clause is very short, prefer using an inline bound on the type +parameter. -If a component of a `where` clause is long, it may be broken before `+` and -further block indented. Each bound should go on its own line. E.g., +If a component of a `where` clause does not fit and contains `+`, break it +before each `+` and block-indent the continuation lines. Put each bound on its +own line. E.g., ```rust impl IndexRanges for T @@ -369,40 +360,14 @@ where + Index, Output = Self::Output> + Index, Output = Self::Output> + Index, Output = Self::Output> - + Index, Output = Self::Output> + Index + + Index, Output = Self::Output> + + Index, ``` -#### Option - `where_single_line` +## Type aliases -`where_single_line` is `false` by default. If `true`, then a where clause with -exactly one component may be formatted on a single line if the rest of the -item's signature is also kept on one line. In this case, there is no need for a -trailing comma and if followed by a block, no need for a newline before the -block. E.g., - -```rust -// May be single-lined. -fn foo(args) -> ReturnType -where T: Bound { - body -} - -// Must be multi-lined. -fn foo( - args -) -> ReturnType -where - T: Bound, -{ - body -} -``` - - -### Type aliases - -Type aliases should generally be kept on one line. If necessary to break the -line, do so after the `=`; the right-hand-side should be block indented: +Keep type aliases on one line when they fit. If necessary to break the line, do +so after the `=`, and block-indent the right-hand side: ```rust pub type Foo = Bar; @@ -424,29 +389,24 @@ where = AnEvenLongerType>; ``` +## Associated types -### Associated types - -Associated types should follow the guidelines above for type aliases. Where an -associated type has a bound, there should be a space after the colon but not -before: +Format associated types like type aliases. Where an associated type has a +bound, put a space after the colon but not before: ```rust pub type Foo: Bar; ``` +## extern items -### extern items - -When writing extern items (such as `extern "C" fn`), always be explicit about -the ABI. For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or +When writing extern items (such as `extern "C" fn`), always specify the ABI. +For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or `extern "C" { ... }`. +## Imports (`use` statements) -### Imports (`use` statements) - -If an import can be formatted on one line, do so. There should be no spaces -around braces. +Format imports on one line where possible. Don't put spaces around braces. ```rust use a::b::c; @@ -454,18 +414,16 @@ use a::b::d::*; use a::b::{foo, bar, baz}; ``` - -#### Large list imports +### Large list imports Prefer to use multiple imports rather than a multi-line import. However, tools -should not split imports by default (they may offer this as an option). +should not split imports by default. If an import does require multiple lines (either because a list of single names does not fit within the max width, or because of the rules for nested imports below), then break after the opening brace and before the closing brace, use a trailing comma, and block indent the names. - ```rust // Prefer foo::{long, list, of, imports}; @@ -478,8 +436,7 @@ foo::{ }; ``` - -#### Ordering of imports +### Ordering of imports A *group* of imports is a set of imports on the same or sequential lines. One or more blank lines or other items (e.g., a function) separate groups of imports. @@ -487,7 +444,6 @@ more blank lines or other items (e.g., a function) separate groups of imports. Within a group of imports, imports must be sorted ASCIIbetically (uppercase before lowercase). Groups of imports must not be merged or re-ordered. - E.g., input: ```rust @@ -511,29 +467,25 @@ use b; Because of `macro_use`, attributes must also start a new group and prevent re-ordering. -#### Ordering list import +### Ordering list import Names in a list import must be sorted ASCIIbetically, but with `self` and `super` first, and groups and glob imports last. This applies recursively. For example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g., `use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`. +### Normalisation -#### Normalisation - -Tools must make the following normalisations: - -* `use a::self;` -> `use a;` -* `use a::{};` -> (nothing) -* `use a::{b};` -> `use a::b;` +Tools must make the following normalisations, recursively: -And must apply these recursively. +- `use a::self;` -> `use a;` +- `use a::{};` -> (nothing) +- `use a::{b};` -> `use a::b;` Tools must not otherwise merge or un-merge import lists or adjust glob imports (without an explicit option). - -#### Nested imports +### Nested imports If there are any nested imports in a list import, then use the multi-line form, even if the import fits on one line. Each nested import must be on its own line, @@ -549,8 +501,7 @@ use a::b::{ }; ``` - -#### Merging/un-merging imports +### Merging/un-merging imports An example: diff --git a/src/doc/style-guide/src/nightly.md b/src/doc/style-guide/src/nightly.md index 031811b0e..66e7fa3c9 100644 --- a/src/doc/style-guide/src/nightly.md +++ b/src/doc/style-guide/src/nightly.md @@ -1,3 +1,5 @@ +# Nightly + This chapter documents style and formatting for nightly-only syntax. The rest of the style guide documents style for stable Rust syntax; nightly syntax only appears in this chapter. Each section here includes the name of the feature gate, so that searches (e.g. `git grep`) for a nightly feature in the Rust repository also turn up the style guide section. Style and formatting for nightly-only syntax should be removed from this chapter and integrated into the appropriate sections of the style guide at the time of stabilization. diff --git a/src/doc/style-guide/src/principles.md b/src/doc/style-guide/src/principles.md index d548693e3..ce57c649a 100644 --- a/src/doc/style-guide/src/principles.md +++ b/src/doc/style-guide/src/principles.md @@ -3,27 +3,27 @@ When deciding on style guidelines, the style team follows these guiding principles (in rough priority order): -* readability - - scan-ability - - avoiding misleading formatting - - 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 - plain-text contexts +- readability + - scan-ability + - avoiding misleading formatting + - 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 + plain-text contexts -* aesthetics - - sense of 'beauty' - - consistent with other languages/tools +- aesthetics + - sense of 'beauty' + - consistent with other languages/tools -* specifics - - compatibility with version control practices - preserving diffs, - merge-friendliness, etc. - - preventing rightward drift - - minimising vertical space +- specifics + - compatibility with version control practices - preserving diffs, + merge-friendliness, etc. + - preventing rightward drift + - minimising vertical space -* application - - ease of manual application - - ease of implementation (in `rustfmt`, and in other tools/editors/code generators) - - internal consistency - - simplicity of formatting rules +- application + - ease of manual application + - ease of implementation (in `rustfmt`, and in other tools/editors/code generators) + - internal consistency + - simplicity of formatting rules diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md index a5cd6da10..6f322b3d6 100644 --- a/src/doc/style-guide/src/statements.md +++ b/src/doc/style-guide/src/statements.md @@ -1,9 +1,9 @@ -## Statements +# Statements -### Let statements +## Let statements -There should be spaces after the `:` and on both sides of the `=` (if they are -present). No space before the semicolon. +Put a space after the `:` and on both sides of the `=` (if they are present). +Don't put a space before the semicolon. ```rust // A comment. @@ -14,20 +14,19 @@ let pattern: Type; let pattern = expr; ``` -If possible the declaration should be formatted on a single line. If this is not -possible, then try splitting after the `=`, if the declaration can fit on two -lines. The expression should be block indented. +If possible, format the declaration on a single line. If not possible, then try +splitting after the `=`, if the declaration fits on two lines. Block-indent the +expression. ```rust let pattern: Type = expr; ``` -If the first line does not fit on a single line, then split after the colon, -using block indentation. If the type covers multiple lines, even after line- -breaking after the `:`, then the first line may be placed on the same line as -the `:`, subject to the [combining rules](https://github.com/rust-lang-nursery/fmt-rfcs/issues/61) (WIP). - +If the first line still does not fit on a single line, split after the `:`, and +use block indentation. If the type requires multiple lines, even after +line-breaking after the `:`, then place the first line on the same line as the +`:`, subject to the [combining rules](expressions.html#combinable-expressions). ```rust let pattern: @@ -51,12 +50,12 @@ let (abcd, ``` If the expression covers multiple lines, if the first line of the expression -fits in the remaining space, it stays on the same line as the `=`, the rest of the -expression is not indented. If the first line does not fit, then it should start -on the next lines, and should be block indented. If the expression is a block -and the type or pattern cover multiple lines, then the opening brace should be -on a new line and not indented (this provides separation for the interior of the -block from the type), otherwise the opening brace follows the `=`. +fits in the remaining space, it stays on the same line as the `=`, and the rest +of the expression is not further indented. If the first line does not fit, then +put the expression on subsequent lines, block indented. If the expression is a +block and the type or pattern cover multiple lines, put the opening brace on a +new line and not indented (this provides separation for the interior of the +block from the type); otherwise, the opening brace follows the `=`. Examples: @@ -101,15 +100,15 @@ let Foo { ); ``` -#### else blocks (let-else statements) +### else blocks (let-else statements) A let statement can contain an `else` component, making it a let-else statement. In this case, always apply the same formatting rules to the components preceding the `else` block (i.e. the `let pattern: Type = initializer_expr` portion) as described [for other let statements](#let-statements). -The entire let-else statement may be formatted on a single line if all the -following are true: +Format the entire let-else statement on a single line if all the following are +true: * the entire statement is *short* * the `else` block contains only a single-line expression and no statements @@ -120,9 +119,6 @@ following are true: let Some(1) = opt else { return }; ``` -Formatters may allow users to configure the value of the threshold -used to determine whether a let-else statement is *short*. - Otherwise, the let-else statement requires some line breaks. If breaking a let-else statement across multiple lines, never break between the @@ -157,9 +153,9 @@ before the `else`. }; ``` -If the initializer expression is multi-line, the `else` keyword and opening -brace of the block (i.e. `else {`) should be put on the same line as the end of -the initializer expression, with a space between them, if and only if all the +If the initializer expression is multi-line, put the `else` keyword and opening +brace of the block (i.e. `else {`) on the same line as the end of the +initializer expression, with a space between them, if and only if all the following are true: * The initializer expression ends with one or more closing @@ -182,9 +178,9 @@ let Some(x) = y.foo( } ``` -Otherwise, the `else` keyword and opening brace should be placed on the next -line after the end of the initializer expression, and the `else` keyword should -have the same indentation level as the `let` keyword. +Otherwise, put the `else` keyword and opening brace on the next line after the +end of the initializer expression, with the `else` keyword at the same +indentation level as the `let` keyword. For example: @@ -234,28 +230,27 @@ fn main() { } ``` -### Macros in statement position +## Macros in statement position -A macro use in statement position should use parentheses or square brackets as -delimiters and should be terminated with a semicolon. There should be no spaces -between the name, `!`, the delimiters, or the `;`. +For a macro use in statement position, use parentheses or square brackets as +delimiters, and terminate it with a semicolon. Do not put spaces around the +name, `!`, the delimiters, or the `;`. ```rust // A comment. a_macro!(...); ``` +## Expressions in statement position -### Expressions in statement position - -There should be no space between the expression and the semicolon. +Do not put space between the expression and the semicolon. ``` ; ``` -All expressions in statement position should be terminated with a semicolon, -unless they end with a block or are used as the value for a block. +Terminate all expressions in statement position with a semicolon, unless they +end with a block or are used as the value for a block. E.g., diff --git a/src/doc/style-guide/src/types.md b/src/doc/style-guide/src/types.md index ae456ef21..b7921c891 100644 --- a/src/doc/style-guide/src/types.md +++ b/src/doc/style-guide/src/types.md @@ -1,23 +1,22 @@ -## Types and Bounds +# Types and Bounds -### Single line formatting +## Single line formatting -* `[T]` no spaces -* `[T; expr]`, e.g., `[u32; 42]`, `[Vec; 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 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) -* ` as SomeTrait>::Foo::Bar` or `Foo::Bar` or `::Foo::Bar` (no spaces around `::` or angle brackets, single spaces around `as`) -* `Foo::Bar` (spaces after commas, no trailing comma, no spaces around angle brackets) -* `T + T + T` (single spaces between types, and `+`). -* `impl T + T + T` (single spaces between keyword, types, and `+`). +- `[T]` no spaces +- `[T; expr]`, e.g., `[u32; 42]`, `[Vec; 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 keywords and sigils, and after commas, no trailing commas, no spaces around brackets) +- `!` gets 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) +- ` as SomeTrait>::Foo::Bar` or `Foo::Bar` or `::Foo::Bar` (no spaces around `::` or angle brackets, single spaces around `as`) +- `Foo::Bar` (spaces after commas, no trailing comma, no spaces around angle brackets) +- `T + T + T` (single spaces between types, and `+`). +- `impl T + T + T` (single spaces between keyword, types, and `+`). -Parentheses used in types should not be surrounded by whitespace, e.g., `(Foo)` +Do not put space around parentheses used in types, e.g., `(Foo)` - -### Line breaks +## Line breaks Avoid breaking lines in types where possible. Prefer breaking at outermost scope, e.g., prefer @@ -37,13 +36,17 @@ Foo> ``` -`[T; expr]` may be broken after the `;` if necessary. +If a type requires line-breaks in order to fit, this section outlines where to +break such types if necessary. + +Break `[T; expr]` after the `;` if necessary. -Function types may be broken following the rules for function declarations. +Break function types following the rules for function declarations. -Generic types may be broken following the rules for generics. +Break generic types following the rules for generics. -Types with `+` may be broken after any `+` using block indent and breaking before the `+`. When breaking such a type, all `+`s should be line broken, e.g., +Break types with `+` by breaking before the `+` and block-indenting the +subsequent lines. When breaking such a type, break before *every* `+`: ```rust impl Clone diff --git a/src/doc/unstable-book/src/compiler-flags/no-parallel-llvm.md b/src/doc/unstable-book/src/compiler-flags/no-parallel-llvm.md new file mode 100644 index 000000000..f19ba16b6 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/no-parallel-llvm.md @@ -0,0 +1,8 @@ +# `no-parallel-llvm` + +--------------------- + +This flag disables parallelization of codegen and linking, while otherwise preserving +behavior with regard to codegen units and LTO. + +This flag is not useful for regular users, but it can be useful for debugging the backend. Codegen issues commonly only manifest under specific circumstances, e.g. if multiple codegen units are used and ThinLTO is enabled. Serialization of these threaded configurations makes the use of LLVM debugging facilities easier, by avoiding the interleaving of output. diff --git a/src/doc/unstable-book/src/compiler-flags/path-options.md b/src/doc/unstable-book/src/compiler-flags/path-options.md new file mode 100644 index 000000000..0786ef1f1 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/path-options.md @@ -0,0 +1,11 @@ +# `--print` Options + +The behavior of the `--print` flag can be modified by optionally be specifying a filepath +for each requested information kind, in the format `--print KIND=PATH`, just like for +`--emit`. When a path is specified, information will be written there instead of to stdout. + +This is unstable feature, so you have to provide `-Zunstable-options` to enable it. + +## Examples + +`rustc main.rs -Z unstable-options --print cfg=cfgs.txt` diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md index ce894ce6a..2dd1f6f8e 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md +++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md @@ -1,4 +1,4 @@ -# `profile-sample-use +# `profile-sample-use` --- diff --git a/src/doc/unstable-book/src/language-features/abi-thiscall.md b/src/doc/unstable-book/src/language-features/abi-thiscall.md deleted file mode 100644 index 73bc6eacf..000000000 --- a/src/doc/unstable-book/src/language-features/abi-thiscall.md +++ /dev/null @@ -1,12 +0,0 @@ -# `abi_thiscall` - -The tracking issue for this feature is: [#42202] - -[#42202]: https://github.com/rust-lang/rust/issues/42202 - ------------------------- - -The MSVC ABI on x86 Windows uses the `thiscall` calling convention for C++ -instance methods by default; it is identical to the usual (C) calling -convention on x86 Windows except that the first parameter of the method, -the `this` pointer, is passed in the ECX register. 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 c634dc50d..968c9bb4e 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,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - AVR - MSP430 - M68k +- CSKY - s390x ## Register classes @@ -46,6 +47,8 @@ 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` | +| CSKY | `reg` | `r[0-31]` | `r` | +| CSKY | `freg` | `f[0-31]` | `f` | | s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | | s390x | `freg` | `f[0-15]` | `f` | @@ -79,6 +82,8 @@ 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` | +| CSKY | `reg` | None | `i8`, `i16`, `i32` | +| CSKY | `freg` | None | `f32`, | | s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | @@ -102,6 +107,17 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `a5` | `bp` | | M68k | `a6` | `fp` | | M68k | `a7` | `sp`, `usp`, `ssp`, `isp` | +| CSKY | `r[0-3]` | `a[0-3]` | +| CSKY | `r[4-11]` | `l[0-7]` | +| CSKY | `r[12-13]` | `t[0-1]` | +| CSKY | `r14` | `sp` | +| CSKY | `r15` | `lr` | +| CSKY | `r[16-17]` | `l[8-9]` | +| CSKY | `r[18-25]` | `t[2-9]` | +| CSKY | `r28` | `rgb` | +| CSKY | `r29` | `rtb` | +| CSKY | `r30` | `svbr` | +| CSKY | `r31` | `tls` | > **Notes**: > - TI does not mandate a frame pointer for MSP430, but toolchains are allowed @@ -123,6 +139,13 @@ 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. | +| CSKY | `r7`, `r28` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r8` | Used internally by LLVM for the frame pointer. | +| CSKY | `r14` | Used internally by LLVM for the stack pointer. | +| CSKY | `r15` | This is the link register. | +| CSKY | `r[26-30]` | Reserved by its ABI. | +| CSKY | `r31` | This is the TLS register. | + ## Template modifiers @@ -139,6 +162,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `freg` | None | `0` | None | | s390x | `reg` | None | `%r0` | None | | s390x | `freg` | None | `%f0` | None | +| CSKY | `reg` | None | `r0` | None | +| CSKY | `freg` | None | `f0` | None | # Flags covered by `preserves_flags` diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md index ea9bace6d..8fa8f567d 100644 --- a/src/doc/unstable-book/src/language-features/intrinsics.md +++ b/src/doc/unstable-book/src/language-features/intrinsics.md @@ -17,6 +17,7 @@ via a declaration like ```rust #![feature(intrinsics)] +#![allow(internal_features)] # fn main() {} extern "rust-intrinsic" { diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index f4bc18bc7..9e20662ff 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -9,25 +9,60 @@ functionality that isn't hard-coded into the language, but is implemented in libraries, with a special marker to tell the compiler it exists. The marker is the attribute `#[lang = "..."]` and there are various different values of `...`, i.e. various different 'lang -items'. +items'. Most of them can only be defined once. -For example, `Box` pointers require a lang item for allocation. -A freestanding program that uses the `Box` -sugar for dynamic allocations via `malloc` and `free`: +Lang items are loaded lazily by the compiler; e.g. if one never uses `Box` +then there is no need to define a function for `exchange_malloc`. +`rustc` will emit an error when an item is needed but not found in the current +crate or any that it depends on. + +Some features provided by lang items: + +- overloadable operators via traits: the traits corresponding to the + `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all + marked with lang items; those specific four are `eq`, `partial_ord`, + `deref`/`deref_mut`, and `add` respectively. +- panicking: the `panic` and `panic_impl` lang items, among others. +- stack unwinding: the lang item `eh_personality` is a function used by the + failure mechanisms of the compiler. This is often mapped to GCC's personality + function (see the [`std` implementation][personality] for more information), + but programs which don't trigger a panic can be assured that this function is + never called. Additionally, a `eh_catch_typeinfo` static is needed for certain + targets which implement Rust panics on top of C++ exceptions. +- the traits in `core::marker` used to indicate types of + various kinds; e.g. lang items `sized`, `sync` and `copy`. +- memory allocation, see below. + +Most lang items are defined by `core`, but if you're trying to build +an executable without the `std` crate, you might run into the need +for lang item definitions. + +[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/personality/gcc.rs + +## Example: Implementing a `Box` + +`Box` pointers require two lang items: one for the type itself and one for +allocation. A freestanding program that uses the `Box` sugar for dynamic +allocations via `malloc` and `free`: ```rust,ignore (libc-is-finicky) -#![feature(lang_items, start, libc, core_intrinsics, rustc_private, rustc_attrs)] +#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] +#![allow(internal_features)] #![no_std] + +extern crate libc; +extern crate unwind; + +use core::ffi::c_void; use core::intrinsics; use core::panic::PanicInfo; use core::ptr::NonNull; -extern crate libc; - +pub struct Global; // the global allocator struct Unique(NonNull); #[lang = "owned_box"] -pub struct Box(Unique); +pub struct Box(Unique, A); impl Box { pub fn new(x: T) -> Self { @@ -36,24 +71,26 @@ impl Box { } } +impl Drop for Box { + fn drop(&mut self) { + unsafe { + libc::free(self.0.0.as_ptr() as *mut c_void); + } + } +} + #[lang = "exchange_malloc"] unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as libc::size_t) as *mut u8; + let p = libc::malloc(size) as *mut u8; // Check if `malloc` failed: - if p as usize == 0 { + if p.is_null() { intrinsics::abort(); } p } -impl Drop for Box { - fn drop(&mut self) { - libc::free(self.0.0.0 as *mut libc::c_void) - } -} - #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { let _x = Box::new(1); @@ -61,245 +98,18 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { 0 } -#[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_impl"] extern fn rust_begin_panic(_info: &PanicInfo) -> ! { intrinsics::abort() } -#[no_mangle] pub extern fn rust_eh_register_frames () {} -#[no_mangle] pub extern fn rust_eh_unregister_frames () {} -``` - -Note the use of `abort`: the `exchange_malloc` lang item is assumed to -return a valid pointer, and so needs to do the check internally. - -Other features provided by lang items include: - -- overloadable operators via traits: the traits corresponding to the - `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all - marked with lang items; those specific four are `eq`, `ord`, - `deref`, and `add` respectively. -- stack unwinding and general failure; the `eh_personality`, - `panic` and `panic_bounds_check` lang items. -- the traits in `std::marker` used to indicate types of - various kinds; lang items `send`, `sync` and `copy`. -- the marker types and variance indicators found in - `std::marker`; lang items `covariant_type`, - `contravariant_lifetime`, etc. - -Lang items are loaded lazily by the compiler; e.g. if one never uses -`Box` then there is no need to define a function for `exchange_malloc`. -`rustc` will emit an error when an item is needed -but not found in the current crate or any that it depends on. - -Most lang items are defined by `libcore`, but if you're trying to build -an executable without the standard library, you'll run into the need -for lang items. The rest of this page focuses on this use-case, even though -lang items are a bit broader than that. - -### Using libc - -In order to build a `#[no_std]` executable we will need libc as a dependency. -We can specify this using our `Cargo.toml` file: - -```toml -[dependencies] -libc = { version = "0.2.14", default-features = false } -``` - -Note that the default features have been disabled. This is a critical step - -**the default features of libc include the standard library and so must be -disabled.** - -### Writing an executable without stdlib - -Controlling the entry point is possible in two ways: the `#[start]` attribute, -or overriding the default shim for the C `main` function with your own. - -The function marked `#[start]` is passed the command line parameters -in the same format as C: - -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. #[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} +fn rust_eh_personality() {} -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} +#[panic_handler] +fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } ``` -To override the compiler-inserted `main` shim, one has to disable it -with `#![no_main]` and then create the appropriate symbol with the -correct ABI and the correct name, which requires overriding the -compiler's name mangling too: - -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -#![no_main] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` - -In many cases, you may need to manually link to the `compiler_builtins` crate -when building a `no_std` binary. You may observe this via linker error messages -such as "```undefined reference to `__rust_probestack'```". - -## More about the language items - -The compiler currently makes a few assumptions about symbols which are -available in the executable to call. Normally these functions are provided by -the standard library, but without it you must define your own. These symbols -are called "language items", and they each have an internal name, and then a -signature that an implementation must conform to. - -The first of these functions, `rust_eh_personality`, is used by the failure -mechanisms of the compiler. This is often mapped to GCC's personality function -(see the [libstd implementation][unwind] for more information), but crates -which do not trigger a panic can be assured that this function is never -called. The language item's name is `eh_personality`. - -[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs - -The second function, `rust_begin_panic`, is also used by the failure mechanisms of the -compiler. When a panic happens, this controls the message that's displayed on -the screen. While the language item's name is `panic_impl`, the symbol name is -`rust_begin_panic`. - -Finally, a `eh_catch_typeinfo` static is needed for certain targets which -implement Rust panics on top of C++ exceptions. +Note the use of `abort`: the `exchange_malloc` lang item is assumed to +return a valid pointer, and so needs to do the check internally. ## List of all language items -This is a list of all language items in Rust along with where they are located in -the source code. +An up-to-date list of all language items can be found [here] in the compiler code. -- Primitives - - `i8`: `libcore/num/mod.rs` - - `i16`: `libcore/num/mod.rs` - - `i32`: `libcore/num/mod.rs` - - `i64`: `libcore/num/mod.rs` - - `i128`: `libcore/num/mod.rs` - - `isize`: `libcore/num/mod.rs` - - `u8`: `libcore/num/mod.rs` - - `u16`: `libcore/num/mod.rs` - - `u32`: `libcore/num/mod.rs` - - `u64`: `libcore/num/mod.rs` - - `u128`: `libcore/num/mod.rs` - - `usize`: `libcore/num/mod.rs` - - `f32`: `libstd/f32.rs` - - `f64`: `libstd/f64.rs` - - `char`: `libcore/char.rs` - - `slice`: `liballoc/slice.rs` - - `str`: `liballoc/str.rs` - - `const_ptr`: `libcore/ptr.rs` - - `mut_ptr`: `libcore/ptr.rs` - - `unsafe_cell`: `libcore/cell.rs` -- Runtime - - `start`: `libstd/rt.rs` - - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) - - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) - - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) - - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) - - `panic`: `libcore/panicking.rs` - - `panic_bounds_check`: `libcore/panicking.rs` - - `panic_impl`: `libcore/panicking.rs` - - `panic_impl`: `libstd/panicking.rs` -- Allocations - - `owned_box`: `liballoc/boxed.rs` - - `exchange_malloc`: `liballoc/heap.rs` -- Operands - - `not`: `libcore/ops/bit.rs` - - `bitand`: `libcore/ops/bit.rs` - - `bitor`: `libcore/ops/bit.rs` - - `bitxor`: `libcore/ops/bit.rs` - - `shl`: `libcore/ops/bit.rs` - - `shr`: `libcore/ops/bit.rs` - - `bitand_assign`: `libcore/ops/bit.rs` - - `bitor_assign`: `libcore/ops/bit.rs` - - `bitxor_assign`: `libcore/ops/bit.rs` - - `shl_assign`: `libcore/ops/bit.rs` - - `shr_assign`: `libcore/ops/bit.rs` - - `deref`: `libcore/ops/deref.rs` - - `deref_mut`: `libcore/ops/deref.rs` - - `index`: `libcore/ops/index.rs` - - `index_mut`: `libcore/ops/index.rs` - - `add`: `libcore/ops/arith.rs` - - `sub`: `libcore/ops/arith.rs` - - `mul`: `libcore/ops/arith.rs` - - `div`: `libcore/ops/arith.rs` - - `rem`: `libcore/ops/arith.rs` - - `neg`: `libcore/ops/arith.rs` - - `add_assign`: `libcore/ops/arith.rs` - - `sub_assign`: `libcore/ops/arith.rs` - - `mul_assign`: `libcore/ops/arith.rs` - - `div_assign`: `libcore/ops/arith.rs` - - `rem_assign`: `libcore/ops/arith.rs` - - `eq`: `libcore/cmp.rs` - - `ord`: `libcore/cmp.rs` -- Functions - - `fn`: `libcore/ops/function.rs` - - `fn_mut`: `libcore/ops/function.rs` - - `fn_once`: `libcore/ops/function.rs` - - `generator_state`: `libcore/ops/generator.rs` - - `generator`: `libcore/ops/generator.rs` -- Other - - `coerce_unsized`: `libcore/ops/unsize.rs` - - `drop`: `libcore/ops/drop.rs` - - `drop_in_place`: `libcore/ptr.rs` - - `clone`: `libcore/clone.rs` - - `copy`: `libcore/marker.rs` - - `send`: `libcore/marker.rs` - - `sized`: `libcore/marker.rs` - - `unsize`: `libcore/marker.rs` - - `sync`: `libcore/marker.rs` - - `phantom_data`: `libcore/marker.rs` - - `discriminant_kind`: `libcore/marker.rs` - - `freeze`: `libcore/marker.rs` - - `debug_trait`: `libcore/fmt/mod.rs` - - `non_zero`: `libcore/nonzero.rs` - - `arc`: `liballoc/sync.rs` - - `rc`: `liballoc/rc.rs` +[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs diff --git a/src/doc/unstable-book/src/language-features/start.md b/src/doc/unstable-book/src/language-features/start.md new file mode 100644 index 000000000..09e4875a2 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/start.md @@ -0,0 +1,59 @@ +# `start` + +The tracking issue for this feature is: [#29633] + +[#29633]: https://github.com/rust-lang/rust/issues/29633 + +------------------------ + +Allows you to mark a function as the entry point of the executable, which is +necessary in `#![no_std]` environments. + +The function marked `#[start]` is passed the command line parameters in the same +format as the C main function (aside from the integer types being used). +It has to be non-generic and have the following signature: + +```rust,ignore (only-for-syntax-highlight) +# let _: +fn(isize, *const *const u8) -> isize +# ; +``` + +This feature should not be confused with the `start` *lang item* which is +defined by the `std` crate and is written `#[lang = "start"]`. + +## Usage together with the `std` crate + +`#[start]` can be used in combination with the `std` crate, in which case the +normal `main` function (which would get called from the `std` crate) won't be +used as an entry point. +The initialization code in `std` will be skipped this way. + +Example: + +```rust +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +``` + +Unwinding the stack past the `#[start]` function is currently considered +Undefined Behavior (for any unwinding implementation): + +```rust,ignore (UB) +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + std::panic::catch_unwind(|| { + panic!(); // panic safely gets caught or safely aborts execution + }); + + panic!(); // UB! + + 0 +} +``` diff --git a/src/doc/unstable-book/src/library-features/default-free-fn.md b/src/doc/unstable-book/src/library-features/default-free-fn.md deleted file mode 100644 index bafc9ac4d..000000000 --- a/src/doc/unstable-book/src/library-features/default-free-fn.md +++ /dev/null @@ -1,47 +0,0 @@ -# `default_free_fn` - -The tracking issue for this feature is: [#73014] - -[#73014]: https://github.com/rust-lang/rust/issues/73014 - ------------------------- - -Adds a free `default()` function to the `std::default` module. This function -just forwards to [`Default::default()`], but may remove repetition of the word -"default" from the call site. - -[`Default::default()`]: ../../std/default/trait.Default.html#tymethod.default - -Here is an example: - -```rust -#![feature(default_free_fn)] -use std::default::default; - -#[derive(Default)] -struct AppConfig { - foo: FooConfig, - bar: BarConfig, -} - -#[derive(Default)] -struct FooConfig { - foo: i32, -} - -#[derive(Default)] -struct BarConfig { - bar: f32, - baz: u8, -} - -fn main() { - let options = AppConfig { - foo: default(), - bar: BarConfig { - bar: 10.1, - ..default() - }, - }; -} -``` diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 9f65f1eee..151c4120d 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -4,6 +4,7 @@ complete -c x.py -n "__fish_use_subcommand" -l build -d 'build target of the sta 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 skip -d 'build paths to skip' -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 @@ -18,7 +19,7 @@ complete -c x.py -n "__fish_use_subcommand" -l llvm-skip-rebuild -d 'whether reb 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -26,7 +27,6 @@ complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include 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' @@ -48,6 +48,7 @@ complete -c x.py -n "__fish_seen_subcommand_from build" -l build -d 'build targe 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 skip -d 'build paths to skip' -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 @@ -62,7 +63,7 @@ complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-skip-rebuild -d 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -70,7 +71,6 @@ complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths 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)" @@ -78,6 +78,7 @@ complete -c x.py -n "__fish_seen_subcommand_from check" -l build -d 'build targe 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 skip -d 'build paths to skip' -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 @@ -92,7 +93,7 @@ complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-skip-rebuild -d 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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)' @@ -101,7 +102,6 @@ complete -c x.py -n "__fish_seen_subcommand_from check" -l include-default-paths 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 @@ -113,6 +113,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clippy" -l build -d 'build targ 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 skip -d 'build paths to skip' -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 @@ -127,7 +128,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-skip-rebuild -d 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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)' @@ -136,7 +137,6 @@ complete -c x.py -n "__fish_seen_subcommand_from clippy" -l include-default-path 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)" @@ -144,6 +144,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fix" -l build -d 'build target 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 skip -d 'build paths to skip' -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 @@ -158,7 +159,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-skip-rebuild -d 'w 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -166,7 +167,6 @@ complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths - 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)" @@ -174,6 +174,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fmt" -l build -d 'build target 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 skip -d 'build paths to skip' -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 @@ -188,7 +189,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-skip-rebuild -d 'w 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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)' @@ -197,7 +198,6 @@ complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths - 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)" @@ -205,6 +205,7 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l build -d 'build target 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 skip -d 'build paths to skip' -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 @@ -219,7 +220,7 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-skip-rebuild -d 'w 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -229,11 +230,11 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l include-default-paths - 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 skip -d 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times' -r -F 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 extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -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 @@ -257,7 +258,7 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-skip-rebuild -d ' 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -272,7 +273,6 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -l include-default-paths 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 @@ -281,6 +281,7 @@ complete -c x.py -n "__fish_seen_subcommand_from bench" -l build -d 'build targe 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 skip -d 'build paths to skip' -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 @@ -295,7 +296,7 @@ complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-skip-rebuild -d 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -303,17 +304,17 @@ complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths 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 stage -d 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used' -r complete -c x.py -n "__fish_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 skip -d 'build paths to skip' -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)" @@ -325,16 +326,15 @@ complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-skip-rebuild -d 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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" -l all -d 'Clean the entire build directory (not used by default)' 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)" @@ -342,6 +342,7 @@ complete -c x.py -n "__fish_seen_subcommand_from dist" -l build -d 'build target 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 skip -d 'build paths to skip' -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 @@ -356,7 +357,7 @@ complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-skip-rebuild -d ' 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -364,7 +365,6 @@ complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths 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)" @@ -372,6 +372,7 @@ complete -c x.py -n "__fish_seen_subcommand_from install" -l build -d 'build tar 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 skip -d 'build paths to skip' -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 @@ -386,7 +387,7 @@ complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-skip-rebuild - 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -394,7 +395,6 @@ complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-pat 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 @@ -403,6 +403,7 @@ complete -c x.py -n "__fish_seen_subcommand_from run" -l build -d 'build target 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 skip -d 'build paths to skip' -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 @@ -417,7 +418,7 @@ complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-skip-rebuild -d 'w 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -425,7 +426,6 @@ complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths - 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)" @@ -433,6 +433,7 @@ complete -c x.py -n "__fish_seen_subcommand_from setup" -l build -d 'build targe 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 skip -d 'build paths to skip' -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 @@ -447,7 +448,7 @@ complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-skip-rebuild -d 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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' @@ -455,7 +456,6 @@ complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths 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)" @@ -463,6 +463,7 @@ complete -c x.py -n "__fish_seen_subcommand_from suggest" -l build -d 'build tar 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 skip -d 'build paths to skip' -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 @@ -477,7 +478,7 @@ complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-skip-rebuild - 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 reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r 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)' @@ -486,5 +487,4 @@ complete -c x.py -n "__fish_seen_subcommand_from suggest" -l include-default-pat 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 index 569c18655..cafb8eed1 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -27,6 +27,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -42,7 +43,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -52,7 +53,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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') @@ -78,6 +78,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -93,7 +94,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -103,7 +104,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -115,6 +115,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -130,7 +131,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--all-targets', 'all-targets', [CompletionResultType]::ParameterName, 'Check all targets') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -141,7 +142,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -157,6 +157,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -172,7 +173,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--fix', 'fix', [CompletionResultType]::ParameterName, 'fix') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -183,7 +184,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -195,6 +195,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -210,7 +211,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -220,7 +221,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -232,6 +232,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -247,7 +248,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -258,7 +259,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -270,6 +270,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -285,7 +286,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--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') @@ -297,7 +298,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -306,6 +306,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--extra-checks', 'extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)') [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') @@ -330,7 +331,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--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') @@ -347,7 +348,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -360,6 +360,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -375,7 +376,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -385,21 +386,21 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--stage', 'stage', [CompletionResultType]::ParameterName, 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used') [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') [CompletionResult]::new('--build', '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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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') @@ -412,9 +413,9 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') - [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'all') + [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'Clean the entire build directory (not used by default)') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -423,7 +424,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -435,6 +435,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -450,7 +451,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -460,7 +461,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -472,6 +472,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -487,7 +488,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -497,7 +498,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -510,6 +510,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -525,7 +526,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -535,7 +536,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -547,6 +547,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -562,7 +563,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -572,7 +573,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 @@ -584,6 +584,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip') [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.)') @@ -599,7 +600,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml') [CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'run suggested tests') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -610,7 +611,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [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 diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 322afdb28..3c57e71bd 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -61,7 +61,7 @@ _x.py() { 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" + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --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 @@ -91,6 +91,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -151,7 +155,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -167,7 +171,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -201,6 +205,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -261,7 +269,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -277,7 +285,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -307,6 +315,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -367,7 +379,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -383,7 +395,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -413,6 +425,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -473,7 +489,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -489,12 +505,16 @@ _x.py() { 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]..." + opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --stage) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) COMPREPLY=($(compgen -f "${cur}")) return 0 @@ -519,6 +539,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -527,10 +551,6 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --stage) - COMPREPLY=("${cur}") - return 0 - ;; --keep-stage) COMPREPLY=("${cur}") return 0 @@ -579,7 +599,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -595,7 +615,7 @@ _x.py() { 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]..." + opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --skip --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -641,6 +661,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -701,7 +725,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -717,7 +741,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -747,6 +771,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -807,7 +835,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -823,7 +851,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -853,6 +881,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -913,7 +945,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -929,7 +961,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -959,6 +991,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -1019,7 +1055,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -1035,7 +1071,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --skip --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1065,6 +1101,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -1125,7 +1165,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -1141,7 +1181,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1171,6 +1211,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -1231,7 +1275,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -1247,7 +1291,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1281,6 +1325,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -1341,7 +1389,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -1357,7 +1405,7 @@ _x.py() { 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 [|hook|vscode|link] [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [|hook|vscode|link] [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1387,6 +1435,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -1447,7 +1499,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -1463,7 +1515,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1493,6 +1545,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --skip) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --rustc-error-format) COMPREPLY=("${cur}") return 0 @@ -1553,7 +1609,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; @@ -1569,7 +1625,7 @@ _x.py() { 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]..." + opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --extra-checks --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 --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1587,6 +1643,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --extra-checks) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --compare-mode) COMPREPLY=($(compgen -f "${cur}")) return 0 @@ -1683,7 +1743,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --llvm-bolt-profile-use) + --reproducible-artifact) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 5ab1874e9..2e0f83219 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -274,6 +274,8 @@ def get_commands(template): args = shlex.split(args) except UnicodeEncodeError: args = [arg.decode('utf-8') for arg in shlex.split(args.encode('utf-8'))] + except Exception as exc: + raise Exception("line {}: {}".format(lineno + 1, exc)) from None yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1, context=line) diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index c4ad98ec1..00c17d833 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -66,7 +66,10 @@ dyn pointees. Rc<[T]> and Arc<[T]> are handled separately altogether so we can actually show - the slice values. + the slice values. These visualizers have a second wildcard `foo<slice2$<*>, *>` + which accounts for the allocator parameter. This isn't needed for the other visualizers since + their inner `*` eats the type parameter but since the slice ones match part of the type params + it is necessary for them. --> @@ -84,7 +87,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -114,7 +117,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -143,7 +146,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -172,7 +175,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json index d9c4645f0..6e5e2c350 100644 --- a/src/etc/rust_analyzer_settings.json +++ b/src/etc/rust_analyzer_settings.json @@ -31,5 +31,8 @@ "--json-output" ], "rust-analyzer.cargo.sysrootSrc": "./library", - "rust-analyzer.rustc.source": "./Cargo.toml" + "rust-analyzer.rustc.source": "./Cargo.toml", + "rust-analyzer.cargo.extraEnv": { + "RUSTC_BOOTSTRAP": "1" + } } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 92bae5516..a06f31a93 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -46,7 +46,7 @@ where let tcx = self.cx.tcx; 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); + debug!("get_auto_trait_impl_for({trait_ref:?}): already generated, aborting"); return None; } @@ -137,10 +137,10 @@ where pub(crate) fn get_auto_trait_impls(&mut self, item_def_id: DefId) -> Vec { let tcx = self.cx.tcx; let param_env = tcx.param_env(item_def_id); - let ty = tcx.type_of(item_def_id).subst_identity(); + let ty = tcx.type_of(item_def_id).instantiate_identity(); let f = auto_trait::AutoTraitFinder::new(tcx); - debug!("get_auto_trait_impls({:?})", ty); + debug!("get_auto_trait_impls({ty:?})"); let auto_traits: Vec<_> = self.cx.auto_traits.to_vec(); let mut auto_traits: Vec = auto_traits .into_iter() @@ -163,9 +163,9 @@ where fn get_lifetime(region: Region<'_>, names_map: &FxHashMap) -> Lifetime { region_name(region) .map(|name| { - names_map.get(&name).unwrap_or_else(|| { - panic!("Missing lifetime with name {:?} for {:?}", name.as_str(), region) - }) + names_map + .get(&name) + .unwrap_or_else(|| panic!("Missing lifetime with name {name:?} for {region:?}")) }) .unwrap_or(&Lifetime::statik()) .clone() @@ -372,7 +372,7 @@ where let output = output.as_ref().cloned().map(Box::new); if old_output.is_some() && old_output != output { - panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, output); + panic!("Output mismatch for {ty:?} {old_output:?} {output:?}"); } let new_params = GenericArgs::Parenthesized { inputs: old_input, output }; @@ -462,7 +462,7 @@ where ); let mut generic_params = raw_generics.params; - debug!("param_env_to_generics({:?}): generic_params={:?}", item_def_id, generic_params); + debug!("param_env_to_generics({item_def_id:?}): generic_params={generic_params:?}"); let mut has_sized = FxHashSet::default(); let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); @@ -623,7 +623,7 @@ where // loop ty_to_traits.entry(ty.clone()).or_default().insert(trait_.clone()); } - _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id), + _ => panic!("Unexpected LHS {lhs:?} for {item_def_id:?}"), } } }; @@ -710,7 +710,7 @@ where /// involved (impls rarely have more than a few bounds) means that it /// shouldn't matter in practice. fn unstable_debug_sort(&self, vec: &mut [T]) { - vec.sort_by_cached_key(|x| format!("{:?}", x)) + vec.sort_by_cached_key(|x| format!("{x:?}")) } fn is_fn_trait(&self, path: &Path) -> bool { diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index a36041588..dad2aa406 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -17,7 +17,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { let param_env = cx.tcx.param_env(item_def_id); let ty = cx.tcx.type_of(item_def_id); - trace!("get_blanket_impls({:?})", ty); + 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_reachable(cx.tcx, trait_def_id) @@ -38,18 +38,22 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { continue; } let infcx = cx.tcx.infer_ctxt().build(); - let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id); - let impl_ty = ty.subst(infcx.tcx, substs); - let param_env = EarlyBinder::bind(param_env).subst(infcx.tcx, substs); + let args = infcx.fresh_args_for_item(DUMMY_SP, item_def_id); + let impl_ty = ty.instantiate(infcx.tcx, args); + let param_env = EarlyBinder::bind(param_env).instantiate(infcx.tcx, args); - let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); - let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs); + let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = trait_ref.instantiate(infcx.tcx, impl_args); // Require the type the impl is implemented on to match // our type, and ignore the impl if there was a mismatch. - let Ok(eq_result) = infcx.at(&traits::ObligationCause::dummy(), param_env).eq(DefineOpaqueTypes::No, impl_trait_ref.self_ty(), impl_ty) else { - continue - }; + let Ok(eq_result) = infcx.at(&traits::ObligationCause::dummy(), param_env).eq( + DefineOpaqueTypes::No, + impl_trait_ref.self_ty(), + impl_ty, + ) else { + continue; + }; let InferOk { value: (), obligations } = eq_result; // FIXME(eddyb) ignoring `obligations` might cause false positives. drop(obligations); @@ -63,12 +67,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { let predicates = cx .tcx .predicates_of(impl_def_id) - .instantiate(cx.tcx, impl_substs) + .instantiate(cx.tcx, impl_args) .predicates .into_iter() .chain(Some(ty::Binder::dummy(impl_trait_ref).to_predicate(infcx.tcx))); for predicate in predicates { - debug!("testing predicate {:?}", predicate); + debug!("testing predicate {predicate:?}"); let obligation = traits::Obligation::new( infcx.tcx, traits::ObligationCause::dummy(), @@ -104,11 +108,11 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { // the post-inference `trait_ref`, as it's more accurate. trait_: Some(clean_trait_ref_with_bindings( cx, - ty::Binder::dummy(trait_ref.subst_identity()), + ty::Binder::dummy(trait_ref.instantiate_identity()), ThinVec::new(), )), for_: clean_middle_ty( - ty::Binder::dummy(ty.subst_identity()), + ty::Binder::dummy(ty.instantiate_identity()), cx, None, None, @@ -117,11 +121,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .tcx .associated_items(impl_def_id) .in_definition_order() - .map(|x| clean_middle_assoc_item(x, cx)) + .filter(|item| !item.is_impl_trait_in_trait()) + .map(|item| clean_middle_assoc_item(item, cx)) .collect::>(), polarity: ty::ImplPolarity::Positive, kind: ImplKind::Blanket(Box::new(clean_middle_ty( - ty::Binder::dummy(trait_ref.subst_identity().self_ty()), + ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()), cx, None, None, diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 5177cffe6..ab5aec12f 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -434,9 +434,9 @@ impl<'a> fmt::Display for Display<'a> { } if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { if self.1.is_html() { - write!(fmt, "{}", feat)?; + write!(fmt, "{feat}")?; } else { - write!(fmt, "`{}`", feat)?; + write!(fmt, "`{feat}`")?; } } else { write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; @@ -471,9 +471,9 @@ impl<'a> fmt::Display for Display<'a> { } if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { if self.1.is_html() { - write!(fmt, "{}", feat)?; + write!(fmt, "{feat}")?; } else { - write!(fmt, "`{}`", feat)?; + write!(fmt, "`{feat}`")?; } } else { write_with_opt_paren(fmt, !sub_cfg.is_simple(), Display(sub_cfg, self.1))?; @@ -519,8 +519,11 @@ impl<'a> fmt::Display for Display<'a> { "asmjs" => "JavaScript", "loongarch64" => "LoongArch LA64", "m68k" => "M68k", + "csky" => "CSKY", "mips" => "MIPS", + "mips32r6" => "MIPS Release 6", "mips64" => "MIPS-64", + "mips64r6" => "MIPS-64 Release 6", "msp430" => "MSP430", "powerpc" => "PowerPC", "powerpc64" => "PowerPC-64", @@ -549,21 +552,21 @@ impl<'a> fmt::Display for Display<'a> { "sgx" => "SGX", _ => "", }, - (sym::target_endian, Some(endian)) => return write!(fmt, "{}-endian", endian), - (sym::target_pointer_width, Some(bits)) => return write!(fmt, "{}-bit", bits), + (sym::target_endian, Some(endian)) => return write!(fmt, "{endian}-endian"), + (sym::target_pointer_width, Some(bits)) => return write!(fmt, "{bits}-bit"), (sym::target_feature, Some(feat)) => match self.1 { Format::LongHtml => { - return write!(fmt, "target feature {}", feat); + return write!(fmt, "target feature {feat}"); } - Format::LongPlain => return write!(fmt, "target feature `{}`", feat), - Format::ShortHtml => return write!(fmt, "{}", feat), + Format::LongPlain => return write!(fmt, "target feature `{feat}`"), + Format::ShortHtml => return write!(fmt, "{feat}"), }, (sym::feature, Some(feat)) => match self.1 { Format::LongHtml => { - return write!(fmt, "crate feature {}", feat); + return write!(fmt, "crate feature {feat}"); } - Format::LongPlain => return write!(fmt, "crate feature `{}`", feat), - Format::ShortHtml => return write!(fmt, "{}", feat), + Format::LongPlain => return write!(fmt, "crate feature `{feat}`"), + Format::ShortHtml => return write!(fmt, "{feat}"), }, _ => "", }; @@ -578,12 +581,12 @@ impl<'a> fmt::Display for Display<'a> { Escape(v.as_str()) ) } else { - write!(fmt, r#"`{}="{}"`"#, name, v) + write!(fmt, r#"`{name}="{v}"`"#) } } else if self.1.is_html() { write!(fmt, "{}", Escape(name.as_str())) } else { - write!(fmt, "`{}`", name) + write!(fmt, "`{name}`") } } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 870cfa930..cac211307 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -9,9 +9,10 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId}; +use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId}; use rustc_hir::Mutability; use rustc_metadata::creader::{CStore, LoadedMacro}; +use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; @@ -49,7 +50,7 @@ pub(crate) fn try_inline( } let mut ret = Vec::new(); - debug!("attrs={:?}", attrs); + debug!("attrs={attrs:?}"); let attrs_without_docs = attrs.map(|(attrs, def_id)| { (attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::>(), def_id) @@ -78,7 +79,7 @@ pub(crate) fn try_inline( build_impls(cx, did, attrs_without_docs, &mut ret); clean::UnionItem(build_union(cx, did)) } - Res::Def(DefKind::TyAlias, did) => { + Res::Def(DefKind::TyAlias { .. }, did) => { record_extern_fqn(cx, did, ItemType::Typedef); build_impls(cx, did, attrs_without_docs, &mut ret); clean::TypedefItem(build_type_alias(cx, did)) @@ -137,9 +138,10 @@ pub(crate) fn try_inline( pub(crate) fn try_inline_glob( cx: &mut DocContext<'_>, res: Res, - current_mod: LocalDefId, + current_mod: LocalModDefId, visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, + import: &hir::Item<'_>, ) -> Option> { let did = res.opt_def_id()?; if did.is_local() { @@ -152,12 +154,20 @@ 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_local(current_mod) + .module_children_local(current_mod.to_local_def_id()) .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)); + let attrs = cx.tcx.hir().attrs(import.hir_id()); + let mut items = build_module_items( + cx, + did, + visited, + inlined_names, + Some(&reexports), + Some((attrs, Some(import.owner_id.def_id.to_def_id()))), + ); items.retain(|item| { if let Some(name) = item.name { // If an item with the same type and name already exists, @@ -190,7 +200,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT let fqn = if let ItemType::Macro = kind { // Check to see if it is a macro 2.0 or built-in macro if matches!( - CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.sess()), + CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.tcx), LoadedMacro::MacroDef(def, _) if matches!(&def.kind, ast::ItemKind::MacroDef(ast_def) if !ast_def.macro_rules) @@ -215,6 +225,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean .tcx .associated_items(did) .in_definition_order() + .filter(|item| !item.is_impl_trait_in_trait()) .map(|item| clean_middle_assoc_item(item, cx)) .collect(); @@ -226,7 +237,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean } fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box { - let sig = cx.tcx.fn_sig(did).subst_identity(); + let sig = cx.tcx.fn_sig(did).instantiate_identity(); let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var { ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => { @@ -279,7 +290,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union { fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box { let predicates = cx.tcx.explicit_predicates_of(did); let type_ = clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(did).subst_identity()), + ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity()), cx, Some(did), None, @@ -314,9 +325,8 @@ pub(crate) fn build_impls( // * https://github.com/rust-lang/rust/pull/99917 — where the feature got used // * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { - use rustc_middle::ty::fast_reject::SimplifiedType::*; let type_ = - if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) }; + if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; for &did in tcx.incoherent_impls(type_) { build_impl(cx, did, attrs, ret); } @@ -391,7 +401,7 @@ pub(crate) fn build_impl( let for_ = match &impl_item { Some(impl_) => clean_ty(impl_.self_ty, cx), None => clean_middle_ty( - ty::Binder::dummy(tcx.type_of(did).subst_identity()), + ty::Binder::dummy(tcx.type_of(did).instantiate_identity()), cx, Some(did), None, @@ -459,6 +469,7 @@ pub(crate) fn build_impl( None => ( tcx.associated_items(did) .in_definition_order() + .filter(|item| !item.is_impl_trait_in_trait()) .filter(|item| { // If this is a trait impl, filter out associated items whose corresponding item // in the associated trait is marked `doc(hidden)`. @@ -473,7 +484,7 @@ pub(crate) fn build_impl( associated_trait.def_id, ) .unwrap(); // corresponding associated item has to exist - !tcx.is_doc_hidden(trait_item.def_id) + document_hidden || !tcx.is_doc_hidden(trait_item.def_id) } else { item.visibility(tcx).is_public() } @@ -496,7 +507,7 @@ pub(crate) fn build_impl( let mut stack: Vec<&Type> = vec![&for_]; if let Some(did) = trait_.as_ref().map(|t| t.def_id()) { - if tcx.is_doc_hidden(did) { + if !document_hidden && tcx.is_doc_hidden(did) { return; } } @@ -505,7 +516,7 @@ pub(crate) fn build_impl( } while let Some(ty) = stack.pop() { - if let Some(did) = ty.def_id(&cx.cache) && tcx.is_doc_hidden(did) { + if let Some(did) = ty.def_id(&cx.cache) && !document_hidden && tcx.is_doc_hidden(did) { return; } if let Some(generics) = ty.generics() { @@ -518,7 +529,7 @@ pub(crate) fn build_impl( } let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs); - trace!("merged_attrs={:?}", merged_attrs); + trace!("merged_attrs={merged_attrs:?}"); trace!( "build_impl: impl {:?} for {:?}", @@ -547,7 +558,7 @@ pub(crate) fn build_impl( } fn build_module(cx: &mut DocContext<'_>, did: DefId, visited: &mut DefIdSet) -> clean::Module { - let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None); + let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None, None); let span = clean::Span::new(cx.tcx.def_span(did)); clean::Module { items, span } @@ -559,6 +570,7 @@ fn build_module_items( visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, allowed_def_ids: Option<&DefIdSet>, + attrs: Option<(&[ast::Attribute], Option)>, ) -> Vec { let mut items = Vec::new(); @@ -613,7 +625,7 @@ fn build_module_items( cfg: None, inline_stmt_id: None, }); - } else if let Some(i) = try_inline(cx, res, item.ident.name, None, visited) { + } else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) { items.extend(i) } } @@ -632,13 +644,18 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String { } fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant { + let mut generics = + clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id)); + clean::simplify::move_bounds_to_generic_parameters(&mut generics); + clean::Constant { type_: clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()), + ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()), cx, Some(def_id), None, ), + generics: Box::new(generics), kind: clean::ConstantKind::Extern { def_id }, } } @@ -646,7 +663,7 @@ fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant { fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static { clean::Static { type_: clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(did).subst_identity()), + ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity()), cx, Some(did), None, @@ -663,7 +680,7 @@ fn build_macro( import_def_id: Option, macro_kind: MacroKind, ) -> clean::ItemKind { - match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) { + match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) { LoadedMacro::MacroDef(item_def, _) => match macro_kind { MacroKind::Bang => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { @@ -764,7 +781,7 @@ pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) { cx.active_extern_traits.insert(did); } - debug!("record_extern_trait: {:?}", did); + debug!("record_extern_trait: {did:?}"); let trait_ = build_external_trait(cx, did); cx.external_traits.borrow_mut().insert(did, trait_); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8ad1ed095..c9a05460b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -24,7 +24,6 @@ use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, AdtKind, EarlyBinder, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -54,7 +53,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< let mut inserted = FxHashSet::default(); items.extend(doc.foreigns.iter().map(|(item, renamed)| { let item = clean_maybe_renamed_foreign_item(cx, item, *renamed); - if let Some(name) = item.name && !item.is_doc_hidden() { + if let Some(name) = item.name && (cx.render_options.document_hidden || !item.is_doc_hidden()) { inserted.insert((item.type_(), name)); } item @@ -64,7 +63,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< return None; } let item = clean_doc_module(x, cx); - if item.is_doc_hidden() { + if !cx.render_options.document_hidden && item.is_doc_hidden() { // Hidden modules are stripped at a later stage. // If a hidden module has the same name as a visible one, we want // to keep both of them around. @@ -85,12 +84,25 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< } let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id); for item in &v { - if let Some(name) = item.name && !item.is_doc_hidden() { + if let Some(name) = item.name && (cx.render_options.document_hidden || !item.is_doc_hidden()) { inserted.insert((item.type_(), name)); } } v })); + items.extend(doc.inlined_foreigns.iter().flat_map(|((_, renamed), (res, local_import_id))| { + let Some(def_id) = res.opt_def_id() else { return Vec::new() }; + let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id)); + let import = cx.tcx.hir().expect_item(*local_import_id); + match import.kind { + hir::ItemKind::Use(path, kind) => { + let hir::UsePath { segments, span, .. } = *path; + let path = hir::Path { segments, res: *res, span }; + clean_use_statement_inner(import, name, &path, kind, cx, &mut Default::default()) + } + _ => unreachable!(), + } + })); items.extend(doc.items.values().flat_map(|(item, renamed, _)| { // Now we actually lower the imports, skipping everything else. if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind { @@ -120,25 +132,31 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< }); let kind = ModuleItem(Module { items, span }); - generate_item_with_correct_attrs(cx, kind, doc.def_id, doc.name, doc.import_id, doc.renamed) + generate_item_with_correct_attrs( + cx, + kind, + doc.def_id.to_def_id(), + doc.name, + doc.import_id, + doc.renamed, + ) } fn generate_item_with_correct_attrs( cx: &mut DocContext<'_>, kind: ItemKind, - local_def_id: LocalDefId, + def_id: DefId, name: Symbol, import_id: Option, renamed: Option, ) -> 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); + let mut attrs = get_all_import_attributes(cx, import_id, def_id, is_inline); add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None); attrs } else { @@ -197,11 +215,11 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>( ) -> Path { let kind = cx.tcx.def_kind(trait_ref.def_id()).into(); if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { - span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind); + span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {kind:?}"); } inline::record_extern_fqn(cx, trait_ref.def_id(), kind); let path = - external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs)); + external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.args)); debug!(?trait_ref); @@ -239,7 +257,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> | rbv::ResolvedArg::Free(_, node_id), ) = def { - if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() { + if let Some(lt) = cx.args.get(&node_id).and_then(|p| p.as_lt()).cloned() { return lt; } } @@ -250,11 +268,12 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'t let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id(); Constant { type_: clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()), + ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()), cx, Some(def_id), None, ), + generics: Box::new(Generics::default()), kind: ConstantKind::Anonymous { body: constant.value.body }, } } @@ -266,6 +285,7 @@ pub(crate) fn clean_middle_const<'tcx>( // FIXME: instead of storing the stringified expression, store `self` directly instead. Constant { type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None), + generics: Box::new(Generics::default()), kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() }, } } @@ -284,7 +304,7 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option { - debug!("cannot clean region {:?}", region); + debug!("cannot clean region {region:?}"); None } } @@ -350,9 +370,8 @@ fn clean_poly_trait_predicate<'tcx>( cx: &mut DocContext<'tcx>, ) -> Option { // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. - if pred.skip_binder().constness == ty::BoundConstness::ConstIfConst - && Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() - { + // FIXME(effects) check constness + if Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() { return None; } @@ -442,7 +461,7 @@ fn clean_projection<'tcx>( let bounds = cx .tcx .explicit_item_bounds(ty.skip_binder().def_id) - .subst_iter_copied(cx.tcx, ty.skip_binder().substs) + .iter_instantiated_copied(cx.tcx, ty.skip_binder().args) .map(|(pred, _)| pred) .collect::>(); return clean_middle_opaque_bounds(cx, bounds); @@ -481,9 +500,9 @@ fn projection_to_path_segment<'tcx>( PathSegment { name: item.name, args: GenericArgs::AngleBracketed { - args: substs_to_args( + args: ty_args_to_args( cx, - ty.map_bound(|ty| &ty.substs[generics.parent_count..]), + ty.map_bound(|ty| &ty.args[generics.parent_count..]), false, None, ) @@ -504,7 +523,7 @@ fn clean_generic_param_def<'tcx>( ty::GenericParamDefKind::Type { has_default, synthetic, .. } => { let default = if has_default { Some(clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(def.def_id).subst_identity()), + ty::Binder::dummy(cx.tcx.type_of(def.def_id).instantiate_identity()), cx, Some(def.def_id), None, @@ -538,7 +557,7 @@ fn clean_generic_param_def<'tcx>( )), default: match has_default { true => Some(Box::new( - cx.tcx.const_param_default(def.def_id).subst_identity().to_string(), + cx.tcx.const_param_default(def.def_id).instantiate_identity().to_string(), )), false => None, }, @@ -786,10 +805,10 @@ fn clean_ty_generics<'tcx>( let where_predicates = preds .predicates .iter() - .flat_map(|(p, _)| { + .flat_map(|(pred, _)| { let mut projection = None; let param_idx = (|| { - let bound_p = p.kind(); + let bound_p = pred.kind(); match bound_p.skip_binder() { ty::ClauseKind::Trait(pred) => { if let ty::Param(param) = pred.self_ty().kind() { @@ -814,33 +833,26 @@ fn clean_ty_generics<'tcx>( })(); if let Some(param_idx) = param_idx - && let Some(b) = impl_trait.get_mut(¶m_idx.into()) + && let Some(bounds) = impl_trait.get_mut(¶m_idx.into()) { - let p: WherePredicate = clean_predicate(*p, cx)?; + let pred = clean_predicate(*pred, cx)?; - b.extend( - p.get_bounds() + bounds.extend( + pred.get_bounds() .into_iter() .flatten() .cloned() - .filter(|b| !b.is_sized_bound(cx)), ); - let proj = projection.map(|p| { - ( - clean_projection(p.map_bound(|p| p.projection_ty), cx, None), - p.map_bound(|p| p.term), - ) - }); - if let Some(((_, trait_did, name), rhs)) = proj - .as_ref() - .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs))) + if let Some(proj) = projection + && let lhs = clean_projection(proj.map_bound(|p| p.projection_ty), cx, None) + && let Some((_, trait_did, name)) = lhs.projection() { impl_trait_proj.entry(param_idx).or_default().push(( trait_did, name, - *rhs, - p.get_bound_params() + proj.map_bound(|p| p.term), + pred.get_bound_params() .into_iter() .flatten() .cloned() @@ -851,13 +863,32 @@ fn clean_ty_generics<'tcx>( return None; } - Some(p) + Some(pred) }) .collect::>(); for (param, mut bounds) in impl_trait { + let mut has_sized = false; + bounds.retain(|b| { + if b.is_sized_bound(cx) { + has_sized = true; + false + } else { + true + } + }); + if !has_sized { + bounds.push(GenericBound::maybe_sized(cx)); + } + // Move trait bounds to the front. - bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..))); + bounds.sort_by_key(|b| !b.is_trait_bound()); + + // Add back a `Sized` bound if there are no *trait* bounds remaining (incl. `?Sized`). + // Since all potential trait bounds are at the front we can just check the first bound. + if bounds.first().map_or(true, |b| !b.is_trait_bound()) { + bounds.insert(0, GenericBound::sized(cx)); + } let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() }; if let Some(proj) = impl_trait_proj.remove(&idx) { @@ -879,7 +910,7 @@ fn clean_ty_generics<'tcx>( // implicit `Sized` bound unless removed with `?Sized`. // However, in the list of where-predicates below, `Sized` appears like a // normal bound: It's either present (the type is sized) or - // absent (the type is unsized) but never *maybe* (i.e. `?Sized`). + // absent (the type might be unsized) but never *maybe* (i.e. `?Sized`). // // This is unsuitable for rendering. // Thus, as a first step remove all `Sized` bounds that should be implicit. @@ -890,8 +921,8 @@ fn clean_ty_generics<'tcx>( let mut sized_params = FxHashSet::default(); where_predicates.retain(|pred| { if let WherePredicate::BoundPredicate { ty: Generic(g), bounds, .. } = pred - && *g != kw::SelfUpper - && bounds.iter().any(|b| b.is_sized_bound(cx)) + && *g != kw::SelfUpper + && bounds.iter().any(|b| b.is_sized_bound(cx)) { sized_params.insert(*g); false @@ -1158,11 +1189,18 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let local_did = trait_item.owner_id.to_def_id(); cx.with_param_env(local_did, |cx| { let inner = match trait_item.kind { - hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem( - clean_ty(ty, cx), - ConstantKind::Local { def_id: local_did, body: default }, - ), - hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)), + hir::TraitItemKind::Const(ty, Some(default)) => { + let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); + AssocConstItem( + Box::new(generics), + clean_ty(ty, cx), + ConstantKind::Local { def_id: local_did, body: default }, + ) + } + hir::TraitItemKind::Const(ty, None) => { + let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); + TyAssocConstItem(Box::new(generics), clean_ty(ty, cx)) + } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body)); MethodItem(m, None) @@ -1207,8 +1245,9 @@ pub(crate) fn clean_impl_item<'tcx>( cx.with_param_env(local_did, |cx| { let inner = match impl_.kind { hir::ImplItemKind::Const(ty, expr) => { + let generics = clean_generics(impl_.generics, cx); let default = ConstantKind::Local { def_id: local_did, body: expr }; - AssocConstItem(clean_ty(ty, cx), default) + AssocConstItem(Box::new(generics), clean_ty(ty, cx), default) } hir::ImplItemKind::Fn(ref sig, body) => { let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body)); @@ -1243,24 +1282,31 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( let kind = match assoc_item.kind { ty::AssocKind::Const => { let ty = clean_middle_ty( - ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()), + ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()), cx, Some(assoc_item.def_id), None, ); + let mut generics = Box::new(clean_ty_generics( + cx, + tcx.generics_of(assoc_item.def_id), + tcx.explicit_predicates_of(assoc_item.def_id), + )); + simplify::move_bounds_to_generic_parameters(&mut generics); + let provided = match assoc_item.container { ty::ImplContainer => true, ty::TraitContainer => tcx.defaultness(assoc_item.def_id).has_value(), }; if provided { - AssocConstItem(ty, ConstantKind::Extern { def_id: assoc_item.def_id }) + AssocConstItem(generics, ty, ConstantKind::Extern { def_id: assoc_item.def_id }) } else { - TyAssocConstItem(ty) + TyAssocConstItem(generics, ty) } } ty::AssocKind::Fn => { - let sig = tcx.fn_sig(assoc_item.def_id).subst_identity(); + let sig = tcx.fn_sig(assoc_item.def_id).instantiate_identity(); let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var { ty::BoundVariableKind::Region(ty::BrNamed(_, name)) @@ -1283,7 +1329,9 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( if assoc_item.fn_has_self_parameter { let self_ty = match assoc_item.container { - ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)).subst_identity(), + ty::ImplContainer => { + tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity() + } ty::TraitContainer => tcx.types.self_param, }; let self_arg_ty = sig.input(0).skip_binder(); @@ -1339,7 +1387,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; if let ty::TraitContainer = assoc_item.container { let bounds = - tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied(); + tcx.explicit_item_bounds(assoc_item.def_id).instantiate_identity_iter_copied(); predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); } let mut generics = clean_ty_generics( @@ -1347,34 +1395,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( tcx.generics_of(assoc_item.def_id), ty::GenericPredicates { parent: None, predicates }, ); - // Move bounds that are (likely) directly attached to the parameters of the - // (generic) associated type from the where clause to the respective parameter. - // There is no guarantee that this is what the user actually wrote but we have - // no way of knowing. - let mut where_predicates = ThinVec::new(); - for mut pred in generics.where_predicates { - if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred - && let Some(GenericParamDef { - kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, - .. - }) = generics.params.iter_mut().find(|param| ¶m.name == arg) - { - param_bounds.append(bounds); - } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred - && let Some(GenericParamDef { - kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, - .. - }) = generics.params.iter_mut().find(|param| ¶m.name == arg) - { - param_bounds.extend(bounds.drain(..).map(|bound| match bound { - GenericBound::Outlives(lifetime) => lifetime, - _ => unreachable!(), - })); - } else { - where_predicates.push(pred); - } - } - generics.where_predicates = where_predicates; + simplify::move_bounds_to_generic_parameters(&mut generics); if let ty::TraitContainer = assoc_item.container { // Move bounds that are (likely) directly attached to the associated type @@ -1442,7 +1463,9 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( AssocTypeItem( Box::new(Typedef { type_: clean_middle_ty( - ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()), + ty::Binder::dummy( + tcx.type_of(assoc_item.def_id).instantiate_identity(), + ), cx, Some(assoc_item.def_id), None, @@ -1459,7 +1482,9 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( AssocTypeItem( Box::new(Typedef { type_: clean_middle_ty( - ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()), + ty::Binder::dummy( + tcx.type_of(assoc_item.def_id).instantiate_identity(), + ), cx, Some(assoc_item.def_id), None, @@ -1478,14 +1503,127 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx) } +fn first_non_private_clean_path<'tcx>( + cx: &mut DocContext<'tcx>, + path: &hir::Path<'tcx>, + new_path_segments: &'tcx [hir::PathSegment<'tcx>], + new_path_span: rustc_span::Span, +) -> Path { + let new_hir_path = + hir::Path { segments: new_path_segments, res: path.res, span: new_path_span }; + let mut new_clean_path = clean_path(&new_hir_path, cx); + // In here we need to play with the path data one last time to provide it the + // missing `args` and `res` of the final `Path` we get, which, since it comes + // from a re-export, doesn't have the generics that were originally there, so + // we add them by hand. + if let Some(path_last) = path.segments.last().as_ref() + && let Some(new_path_last) = new_clean_path.segments[..].last_mut() + && let Some(path_last_args) = path_last.args.as_ref() + && path_last.args.is_some() + { + assert!(new_path_last.args.is_empty()); + new_path_last.args = clean_generic_args(path_last_args, cx); + } + new_clean_path +} + +/// The goal of this function is to return the first `Path` which is not private (ie not private +/// or `doc(hidden)`). If it's not possible, it'll return the "end type". +/// +/// If the path is not a re-export or is public, it'll return `None`. +fn first_non_private<'tcx>( + cx: &mut DocContext<'tcx>, + hir_id: hir::HirId, + path: &hir::Path<'tcx>, +) -> Option { + let target_def_id = path.res.opt_def_id()?; + let (parent_def_id, ident) = match &path.segments[..] { + [] => return None, + // Relative paths are available in the same scope as the owner. + [leaf] => (cx.tcx.local_parent(hir_id.owner.def_id), leaf.ident), + // So are self paths. + [parent, leaf] if parent.ident.name == kw::SelfLower => { + (cx.tcx.local_parent(hir_id.owner.def_id), leaf.ident) + } + // Crate paths are not. We start from the crate root. + [parent, leaf] if matches!(parent.ident.name, kw::Crate | kw::PathRoot) => { + (LOCAL_CRATE.as_def_id().as_local()?, leaf.ident) + } + [parent, leaf] if parent.ident.name == kw::Super => { + let parent_mod = cx.tcx.parent_module(hir_id); + if let Some(super_parent) = cx.tcx.opt_local_parent(parent_mod.to_local_def_id()) { + (super_parent, leaf.ident) + } else { + // If we can't find the parent of the parent, then the parent is already the crate. + (LOCAL_CRATE.as_def_id().as_local()?, leaf.ident) + } + } + // Absolute paths are not. We start from the parent of the item. + [.., parent, leaf] => (parent.res.opt_def_id()?.as_local()?, leaf.ident), + }; + let hir = cx.tcx.hir(); + // First we try to get the `DefId` of the item. + for child in + cx.tcx.module_children_local(parent_def_id).iter().filter(move |c| c.ident == ident) + { + if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = child.res { + continue; + } + + if let Some(def_id) = child.res.opt_def_id() && target_def_id == def_id { + let mut last_path_res = None; + 'reexps: for reexp in child.reexport_chain.iter() { + if let Some(use_def_id) = reexp.id() && + let Some(local_use_def_id) = use_def_id.as_local() && + let Some(hir::Node::Item(item)) = hir.find_by_def_id(local_use_def_id) && + !item.ident.name.is_empty() && + let hir::ItemKind::Use(path, _) = item.kind + { + for res in &path.res { + if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { + continue; + } + if (cx.render_options.document_hidden || + !cx.tcx.is_doc_hidden(use_def_id)) && + // We never check for "cx.render_options.document_private" + // because if a re-export is not fully public, it's never + // documented. + cx.tcx.local_visibility(local_use_def_id).is_public() { + break 'reexps; + } + last_path_res = Some((path, res)); + continue 'reexps; + } + } + } + if !child.reexport_chain.is_empty() { + // So in here, we use the data we gathered from iterating the reexports. If + // `last_path_res` is set, it can mean two things: + // + // 1. We found a public reexport. + // 2. We didn't find a public reexport so it's the "end type" path. + if let Some((new_path, _)) = last_path_res { + return Some(first_non_private_clean_path(cx, path, new_path.segments, new_path.span)); + } + // If `last_path_res` is `None`, it can mean two things: + // + // 1. The re-export is public, no need to change anything, just use the path as is. + // 2. Nothing was found, so let's just return the original path. + return None; + } + } + } + None +} + fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type { - let hir::Ty { hir_id: _, span, ref kind } = *hir_ty; + let hir::Ty { hir_id, span, ref kind } = *hir_ty; let hir::TyKind::Path(qpath) = kind else { unreachable!() }; match qpath { hir::QPath::Resolved(None, path) => { if let Res::Def(DefKind::TyParam, did) = path.res { - if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() { + if let Some(new_ty) = cx.args.get(&did).and_then(|p| p.as_ty()).cloned() { return new_ty; } if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) { @@ -1496,7 +1634,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type if let Some(expanded) = maybe_expand_private_type_alias(cx, path) { expanded } else { - let path = clean_path(path, cx); + // First we check if it's a private re-export. + let path = if let Some(path) = first_non_private(cx, hir_id, &path) { + path + } else { + clean_path(path, cx) + }; resolve_type(cx, path) } } @@ -1563,7 +1706,7 @@ fn maybe_expand_private_type_alias<'tcx>( cx: &mut DocContext<'tcx>, path: &hir::Path<'tcx>, ) -> Option { - let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None }; + 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()) @@ -1576,7 +1719,7 @@ fn maybe_expand_private_type_alias<'tcx>( let hir::ItemKind::TyAlias(ty, generics) = alias else { return None }; let provided_params = &path.segments.last().expect("segments were empty"); - let mut substs = DefIdMap::default(); + let mut args = DefIdMap::default(); let generic_args = provided_params.args(); let mut indices: hir::GenericParamCount = Default::default(); @@ -1600,7 +1743,7 @@ fn maybe_expand_private_type_alias<'tcx>( } else { Lifetime::elided() }; - substs.insert(param.def_id.to_def_id(), SubstParam::Lifetime(cleaned)); + args.insert(param.def_id.to_def_id(), SubstParam::Lifetime(cleaned)); } indices.lifetimes += 1; } @@ -1617,10 +1760,9 @@ fn maybe_expand_private_type_alias<'tcx>( _ => None, }); if let Some(ty) = type_ { - substs.insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(ty, cx))); + args.insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(ty, cx))); } else if let Some(default) = *default { - substs - .insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(default, cx))); + args.insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(default, cx))); } indices.types += 1; } @@ -1637,7 +1779,7 @@ fn maybe_expand_private_type_alias<'tcx>( _ => None, }); if let Some(ct) = const_ { - substs.insert( + args.insert( param.def_id.to_def_id(), SubstParam::Constant(clean_const(ct, cx)), ); @@ -1648,7 +1790,7 @@ fn maybe_expand_private_type_alias<'tcx>( } } - Some(cx.enter_alias(substs, def_id.to_def_id(), |cx| clean_ty(ty, cx))) + Some(cx.enter_alias(args, 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 { @@ -1725,11 +1867,11 @@ fn normalize<'tcx>( .map(|resolved| infcx.resolve_vars_if_possible(resolved.value)); match normalized { Ok(normalized_value) => { - debug!("normalized {:?} to {:?}", ty, normalized_value); + debug!("normalized {ty:?} to {normalized_value:?}"); Some(normalized_value) } Err(err) => { - debug!("failed to normalize {:?}: {:?}", ty, err); + debug!("failed to normalize {ty:?}: {err:?}"); None } } @@ -1922,7 +2064,7 @@ pub(crate) fn clean_middle_ty<'tcx>( abi: sig.abi(), })) } - ty::Adt(def, substs) => { + ty::Adt(def, args) => { let did = def.did(); let kind = match def.adt_kind() { AdtKind::Struct => ItemType::Struct, @@ -1930,7 +2072,7 @@ pub(crate) fn clean_middle_ty<'tcx>( AdtKind::Enum => ItemType::Enum, }; inline::record_extern_fqn(cx, did, kind); - let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs)); + let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(args)); Type::Path { path } } ty::Foreign(did) => { @@ -1940,7 +2082,7 @@ pub(crate) fn clean_middle_ty<'tcx>( did, false, ThinVec::new(), - ty::Binder::dummy(InternalSubsts::empty()), + ty::Binder::dummy(ty::GenericArgs::empty()), ); Type::Path { path } } @@ -1953,10 +2095,10 @@ pub(crate) fn clean_middle_ty<'tcx>( .principal_def_id() .or_else(|| dids.next()) .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?")); - let substs = match obj.principal() { - Some(principal) => principal.map_bound(|p| p.substs), - // marker traits have no substs. - _ => ty::Binder::dummy(InternalSubsts::empty()), + let args = match obj.principal() { + Some(principal) => principal.map_bound(|p| p.args), + // marker traits have no args. + _ => ty::Binder::dummy(ty::GenericArgs::empty()), }; inline::record_extern_fqn(cx, did, ItemType::Trait); @@ -1965,7 +2107,7 @@ pub(crate) fn clean_middle_ty<'tcx>( let mut bounds = dids .map(|did| { - let empty = ty::Binder::dummy(InternalSubsts::empty()); + let empty = ty::Binder::dummy(ty::GenericArgs::empty()); let path = external_path(cx, did, false, ThinVec::new(), empty); inline::record_extern_fqn(cx, did, ItemType::Trait); PolyTrait { trait_: path, generic_params: Vec::new() } @@ -1979,7 +2121,7 @@ pub(crate) fn clean_middle_ty<'tcx>( pb.map_bound(|pb| { pb // HACK(compiler-errors): Doesn't actually matter what self - // type we put here, because we're only using the GAT's substs. + // type we put here, because we're only using the GAT's args. .with_self_ty(cx.tcx, cx.tcx.types.self_param) .projection_ty }), @@ -2005,7 +2147,7 @@ pub(crate) fn clean_middle_ty<'tcx>( .collect(); let late_bound_regions = late_bound_regions.into_iter().collect(); - let path = external_path(cx, did, false, bindings, substs); + let path = external_path(cx, did, false, bindings, args); bounds.insert(0, PolyTrait { trait_: path, generic_params: late_bound_regions }); DynTrait(bounds, lifetime) @@ -2026,9 +2168,9 @@ pub(crate) fn clean_middle_ty<'tcx>( assoc: PathSegment { name: cx.tcx.associated_item(alias_ty.skip_binder().def_id).name, args: GenericArgs::AngleBracketed { - args: substs_to_args( + args: ty_args_to_args( cx, - alias_ty.map_bound(|ty| ty.substs.as_slice()), + alias_ty.map_bound(|ty| ty.args.as_slice()), true, None, ) @@ -2051,11 +2193,11 @@ pub(crate) fn clean_middle_ty<'tcx>( data.def_id, false, ThinVec::new(), - bound_ty.rebind(data.substs), + bound_ty.rebind(data.args), ); Type::Path { path } } else { - let ty = cx.tcx.type_of(data.def_id).subst(cx.tcx, data.substs); + let ty = cx.tcx.type_of(data.def_id).instantiate(cx.tcx, data.args); clean_middle_ty(bound_ty.rebind(ty), cx, None, None) } } @@ -2068,11 +2210,10 @@ pub(crate) fn clean_middle_ty<'tcx>( } } - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // 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)); + let path = external_path(cx, def_id, false, ThinVec::new(), bound_ty.rebind(args)); Type::Path { path } } else { *cx.current_type_aliases.entry(def_id).or_insert(0) += 1; @@ -2081,7 +2222,7 @@ pub(crate) fn clean_middle_ty<'tcx>( let bounds = cx .tcx .explicit_item_bounds(def_id) - .subst_iter_copied(cx.tcx, substs) + .iter_instantiated_copied(cx.tcx, args) .map(|(bound, _)| bound) .collect::>(); let ty = clean_middle_opaque_bounds(cx, bounds); @@ -2110,7 +2251,6 @@ fn clean_middle_opaque_bounds<'tcx>( cx: &mut DocContext<'tcx>, bounds: Vec>, ) -> Type { - let mut regions = vec![]; let mut has_sized = false; let mut bounds = bounds .iter() @@ -2119,10 +2259,7 @@ fn clean_middle_opaque_bounds<'tcx>( let trait_ref = match bound_predicate.skip_binder() { ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref), ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => { - if let Some(r) = clean_middle_region(reg) { - regions.push(GenericBound::Outlives(r)); - } - return None; + return clean_middle_region(reg).map(GenericBound::Outlives); } _ => return None, }; @@ -2158,10 +2295,20 @@ fn clean_middle_opaque_bounds<'tcx>( Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings)) }) .collect::>(); - bounds.extend(regions); - if !has_sized && !bounds.is_empty() { - bounds.insert(0, GenericBound::maybe_sized(cx)); + + if !has_sized { + bounds.push(GenericBound::maybe_sized(cx)); + } + + // Move trait bounds to the front. + bounds.sort_by_key(|b| !b.is_trait_bound()); + + // Add back a `Sized` bound if there are no *trait* bounds remaining (incl. `?Sized`). + // Since all potential trait bounds are at the front we can just check the first bound. + if bounds.first().map_or(true, |b| !b.is_trait_bound()) { + bounds.insert(0, GenericBound::sized(cx)); } + ImplTrait(bounds) } @@ -2174,7 +2321,7 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext field.did, field.name, clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(field.did).subst_identity()), + ty::Binder::dummy(cx.tcx.type_of(field.did).instantiate_identity()), cx, Some(field.did), None, @@ -2305,10 +2452,10 @@ fn clean_bare_fn_ty<'tcx>( pub(crate) fn reexport_chain<'tcx>( tcx: TyCtxt<'tcx>, import_def_id: LocalDefId, - target_def_id: LocalDefId, + target_def_id: DefId, ) -> &'tcx [Reexport] { 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()) + if child.res.opt_def_id() == Some(target_def_id) && child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id()) { return &child.reexport_chain; @@ -2321,7 +2468,7 @@ pub(crate) fn reexport_chain<'tcx>( fn get_all_import_attributes<'hir>( cx: &mut DocContext<'hir>, import_def_id: LocalDefId, - target_def_id: LocalDefId, + target_def_id: DefId, is_inline: bool, ) -> Vec<(Cow<'hir, ast::Attribute>, Option)> { let mut attrs = Vec::new(); @@ -2336,7 +2483,7 @@ fn get_all_import_attributes<'hir>( attrs = import_attrs.iter().map(|attr| (Cow::Borrowed(attr), Some(def_id))).collect(); first = false; // We don't add attributes of an intermediate re-export if it has `#[doc(hidden)]`. - } else if !cx.tcx.is_doc_hidden(def_id) { + } else if cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id) { add_without_unwanted_attributes(&mut attrs, import_attrs, is_inline, Some(def_id)); } } @@ -2344,19 +2491,19 @@ fn get_all_import_attributes<'hir>( } fn filter_tokens_from_list( - args_tokens: TokenStream, + args_tokens: &TokenStream, should_retain: impl Fn(&TokenTree) -> bool, ) -> Vec { let mut tokens = Vec::with_capacity(args_tokens.len()); let mut skip_next_comma = false; - for token in args_tokens.into_trees() { + for token in args_tokens.trees() { match token { TokenTree::Token(Token { kind: TokenKind::Comma, .. }, _) if skip_next_comma => { skip_next_comma = false; } - token if should_retain(&token) => { + token if should_retain(token) => { skip_next_comma = false; - tokens.push(token); + tokens.push(token.clone()); } _ => { skip_next_comma = true; @@ -2414,7 +2561,7 @@ fn add_without_unwanted_attributes<'hir>( match normal.item.args { ast::AttrArgs::Delimited(ref mut args) => { let tokens = - filter_tokens_from_list(args.tokens.clone(), |token| { + filter_tokens_from_list(&args.tokens, |token| { !matches!( token, TokenTree::Token( @@ -2458,8 +2605,9 @@ fn clean_maybe_renamed_item<'tcx>( ItemKind::Static(ty, mutability, body_id) => { StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) }) } - ItemKind::Const(ty, body_id) => ConstantItem(Constant { + ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant { type_: clean_ty(ty, cx), + generics: Box::new(clean_generics(generics, cx)), kind: ConstantKind::Local { body: body_id, def_id }, }), ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { @@ -2538,7 +2686,7 @@ fn clean_maybe_renamed_item<'tcx>( vec![generate_item_with_correct_attrs( cx, kind, - item.owner_id.def_id, + item.owner_id.def_id.to_def_id(), name, import_id, renamed, @@ -2574,8 +2722,8 @@ fn clean_impl<'tcx>( let for_ = clean_ty(impl_.self_ty, cx); 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()), + DefKind::TyAlias { .. } => Some(clean_middle_ty( + ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity()), cx, Some(def_id.to_def_id()), None, @@ -2640,15 +2788,12 @@ fn clean_extern_crate<'tcx>( } } - // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason - vec![Item { - name: Some(name), - attrs: Box::new(Attributes::from_ast(attrs)), - item_id: crate_def_id.into(), - kind: Box::new(ExternCrateItem { src: orig_name }), - cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), - inline_stmt_id: Some(krate_owner_def_id), - }] + vec![Item::from_def_id_and_parts( + krate_owner_def_id, + Some(name), + ExternCrateItem { src: orig_name }, + cx, + )] } fn clean_use_statement<'tcx>( @@ -2662,9 +2807,6 @@ fn clean_use_statement<'tcx>( let mut items = Vec::new(); let hir::UsePath { segments, ref res, span } = *path; for &res in res { - if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { - continue; - } let path = hir::Path { segments, res, span }; items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names)); } @@ -2679,6 +2821,9 @@ fn clean_use_statement_inner<'tcx>( cx: &mut DocContext<'tcx>, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, ) -> Vec { + if should_ignore_res(path.res) { + return Vec::new(); + } // We need this comparison because some imports (for std types for example) // are "inserted" as well but directly by the compiler and they should not be // taken into account. @@ -2691,11 +2836,12 @@ fn clean_use_statement_inner<'tcx>( let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline); let pub_underscore = visibility.is_public() && name == kw::Underscore; let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id); + let import_def_id = import.owner_id.def_id.to_def_id(); // The parent of the module in which this import resides. This // is the same as `current_mod` if that's already the top // level module. - let parent_mod = cx.tcx.parent_module_from_def_id(current_mod); + let parent_mod = cx.tcx.parent_module_from_def_id(current_mod.to_local_def_id()); // This checks if the import can be seen from a higher level module. // In other words, it checks if the visibility is the equivalent of @@ -2741,9 +2887,14 @@ fn clean_use_statement_inner<'tcx>( let inner = if kind == hir::UseKind::Glob { if !denied { let mut visited = DefIdSet::default(); - if let Some(items) = - inline::try_inline_glob(cx, path.res, current_mod, &mut visited, inlined_names) - { + if let Some(items) = inline::try_inline_glob( + cx, + path.res, + current_mod, + &mut visited, + inlined_names, + import, + ) { return items; } } @@ -2759,7 +2910,6 @@ fn clean_use_statement_inner<'tcx>( denied = true; } if !denied { - let import_def_id = import.owner_id.to_def_id(); if let Some(mut items) = inline::try_inline( cx, path.res, @@ -2779,7 +2929,7 @@ fn clean_use_statement_inner<'tcx>( Import::new_simple(name, resolve_use_source(cx, path), true) }; - vec![Item::from_def_id_and_parts(import.owner_id.to_def_id(), None, ImportItem(inner), cx)] + vec![Item::from_def_id_and_parts(import_def_id, None, ImportItem(inner), cx)] } fn clean_maybe_renamed_foreign_item<'tcx>( diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index ef38ca3c1..66d10f236 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -76,17 +76,13 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option reparsed_trees, - Err(diagnostic) => { - diagnostic.cancel(); - return None; - } - }; - if reparsed_trees.len() != 1 { + if parser.token == token::Eof { + return None; + } + let reparsed_tree = parser.parse_token_tree(); + if parser.token != token::Eof { return None; } - let reparsed_tree = reparsed_trees.pop().unwrap(); // Compare against the original tree. if reparsed_tree.eq_unspanned(matcher) { Some(snippet) } else { None } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 65b1b72ad..7b8f20326 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -47,7 +47,9 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> ThinVec, child: DefId, trait_: DefId) }) .any(|did| trait_is_same_or_supertrait(cx, did, trait_)) } + +/// Move bounds that are (likely) directly attached to generic parameters from the where-clause to +/// the respective parameter. +/// +/// There is no guarantee that this is what the user actually wrote but we have no way of knowing. +// FIXME(fmease): It'd make a lot of sense to just incorporate this logic into `clean_ty_generics` +// making every of its users benefit from it. +pub(crate) fn move_bounds_to_generic_parameters(generics: &mut clean::Generics) { + use clean::types::*; + + let mut where_predicates = ThinVec::new(); + for mut pred in generics.where_predicates.drain(..) { + if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.append(bounds); + } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.extend(bounds.drain(..).map(|bound| match bound { + GenericBound::Outlives(lifetime) => lifetime, + _ => unreachable!(), + })); + } else { + where_predicates.push(pred); + } + } + generics.where_predicates = where_predicates; +} diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 26139d527..49bde1d31 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -78,7 +78,7 @@ impl ItemId { #[track_caller] pub(crate) fn expect_def_id(self) -> DefId { self.as_def_id() - .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self)) + .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{self:?}` isn't a DefId")) } #[inline] @@ -352,7 +352,7 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool { match tcx.def_kind(parent) { DefKind::Struct | DefKind::Union => false, DefKind::Variant => true, - parent_kind => panic!("unexpected parent kind: {:?}", parent_kind), + parent_kind => panic!("unexpected parent kind: {parent_kind:?}"), } } @@ -436,7 +436,7 @@ impl Item { attrs: Box, cfg: Option>, ) -> Item { - trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg); + trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}"); Item { item_id: def_id.into(), @@ -451,11 +451,7 @@ impl Item { pub(crate) fn links(&self, cx: &Context<'_>) -> Vec { use crate::html::format::{href, link_tooltip}; - let Some(links) = cx.cache() - .intra_doc_links - .get(&self.item_id) else { - return vec![] - }; + let Some(links) = cx.cache().intra_doc_links.get(&self.item_id) else { return vec![] }; links .iter() .filter_map(|ItemLink { link: s, link_text, page_id: id, ref fragment }| { @@ -484,11 +480,9 @@ impl Item { /// the link text, but does need to know which `[]`-bracketed names /// are actually links. pub(crate) fn link_names(&self, cache: &Cache) -> Vec { - let Some(links) = cache - .intra_doc_links - .get(&self.item_id) else { - return vec![]; - }; + let Some(links) = cache.intra_doc_links.get(&self.item_id) else { + return vec![]; + }; links .iter() .map(|ItemLink { link: s, link_text, .. }| RenderedLink { @@ -830,9 +824,9 @@ pub(crate) enum ItemKind { ProcMacroItem(ProcMacro), PrimitiveItem(PrimitiveType), /// A required associated constant in a trait declaration. - TyAssocConstItem(Type), + TyAssocConstItem(Box, Type), /// An associated constant in a trait impl or a provided one in a trait declaration. - AssocConstItem(Type, ConstantKind), + AssocConstItem(Box, Type, ConstantKind), /// A required associated type in a trait declaration. /// /// The bounds may be non-empty if there is a `where` clause. @@ -877,8 +871,8 @@ impl ItemKind { | MacroItem(_) | ProcMacroItem(_) | PrimitiveItem(_) - | TyAssocConstItem(_) - | AssocConstItem(_, _) + | TyAssocConstItem(..) + | AssocConstItem(..) | TyAssocTypeItem(..) | AssocTypeItem(..) | StrippedItem(_) @@ -1225,15 +1219,24 @@ pub(crate) enum GenericBound { } impl GenericBound { + pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound { + Self::sized_with(cx, hir::TraitBoundModifier::None) + } + pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound { + Self::sized_with(cx, hir::TraitBoundModifier::Maybe) + } + + fn sized_with(cx: &mut DocContext<'_>, modifier: hir::TraitBoundModifier) -> GenericBound { let did = cx.tcx.require_lang_item(LangItem::Sized, None); - let empty = ty::Binder::dummy(ty::InternalSubsts::empty()); + let empty = ty::Binder::dummy(ty::GenericArgs::empty()); let path = external_path(cx, did, false, ThinVec::new(), empty); inline::record_extern_fqn(cx, did, ItemType::Trait); - GenericBound::TraitBound( - PolyTrait { trait_: path, generic_params: Vec::new() }, - hir::TraitBoundModifier::Maybe, - ) + GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifier) + } + + pub(crate) fn is_trait_bound(&self) -> bool { + matches!(self, Self::TraitBound(..)) } pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { @@ -1275,7 +1278,7 @@ impl Lifetime { } } -#[derive(Clone, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug)] pub(crate) enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec, bound_params: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, @@ -1345,7 +1348,7 @@ impl GenericParamDef { } // maybe use a Generic enum and use Vec? -#[derive(Clone, Debug, Default)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)] pub(crate) struct Generics { pub(crate) params: ThinVec, pub(crate) where_predicates: ThinVec, @@ -1782,7 +1785,6 @@ impl PrimitiveType { } pub(crate) fn simplified_types() -> &'static SimplifiedTypes { - use ty::fast_reject::SimplifiedType::*; use ty::{FloatTy, IntTy, UintTy}; use PrimitiveType::*; static CELL: OnceCell = OnceCell::new(); @@ -1790,38 +1792,38 @@ impl PrimitiveType { let single = |x| iter::once(x).collect(); CELL.get_or_init(move || { map! { - Isize => single(IntSimplifiedType(IntTy::Isize)), - I8 => single(IntSimplifiedType(IntTy::I8)), - I16 => single(IntSimplifiedType(IntTy::I16)), - I32 => single(IntSimplifiedType(IntTy::I32)), - I64 => single(IntSimplifiedType(IntTy::I64)), - I128 => single(IntSimplifiedType(IntTy::I128)), - Usize => single(UintSimplifiedType(UintTy::Usize)), - U8 => single(UintSimplifiedType(UintTy::U8)), - U16 => single(UintSimplifiedType(UintTy::U16)), - U32 => single(UintSimplifiedType(UintTy::U32)), - U64 => single(UintSimplifiedType(UintTy::U64)), - U128 => single(UintSimplifiedType(UintTy::U128)), - F32 => single(FloatSimplifiedType(FloatTy::F32)), - F64 => single(FloatSimplifiedType(FloatTy::F64)), - Str => single(StrSimplifiedType), - Bool => single(BoolSimplifiedType), - Char => single(CharSimplifiedType), - Array => single(ArraySimplifiedType), - Slice => single(SliceSimplifiedType), + Isize => single(SimplifiedType::Int(IntTy::Isize)), + I8 => single(SimplifiedType::Int(IntTy::I8)), + I16 => single(SimplifiedType::Int(IntTy::I16)), + I32 => single(SimplifiedType::Int(IntTy::I32)), + I64 => single(SimplifiedType::Int(IntTy::I64)), + I128 => single(SimplifiedType::Int(IntTy::I128)), + Usize => single(SimplifiedType::Uint(UintTy::Usize)), + U8 => single(SimplifiedType::Uint(UintTy::U8)), + U16 => single(SimplifiedType::Uint(UintTy::U16)), + U32 => single(SimplifiedType::Uint(UintTy::U32)), + U64 => single(SimplifiedType::Uint(UintTy::U64)), + U128 => single(SimplifiedType::Uint(UintTy::U128)), + F32 => single(SimplifiedType::Float(FloatTy::F32)), + F64 => single(SimplifiedType::Float(FloatTy::F64)), + Str => single(SimplifiedType::Str), + Bool => single(SimplifiedType::Bool), + Char => single(SimplifiedType::Char), + Array => single(SimplifiedType::Array), + Slice => single(SimplifiedType::Slice), // FIXME: If we ever add an inherent impl for tuples // with different lengths, they won't show in rustdoc. // // Either manually update this arrayvec at this point // or start with a more complex refactoring. - Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(), - Unit => single(TupleSimplifiedType(0)), - RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(), - Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(), + Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(), + Unit => single(SimplifiedType::Tuple(0)), + RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(), + Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(), // FIXME: This will be wrong if we ever add inherent impls // for function pointers. - Fn => single(FunctionSimplifiedType(1)), - Never => single(NeverSimplifiedType), + Fn => single(SimplifiedType::Function(1)), + Never => single(SimplifiedType::Never), } }) } @@ -2210,6 +2212,17 @@ pub(crate) enum GenericArgs { Parenthesized { inputs: Box<[Type]>, output: Option> }, } +impl GenericArgs { + pub(crate) fn is_empty(&self) -> bool { + match self { + GenericArgs::AngleBracketed { args, bindings } => { + args.is_empty() && bindings.is_empty() + } + GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(), + } + } +} + #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct PathSegment { pub(crate) name: Symbol, @@ -2253,6 +2266,7 @@ pub(crate) struct Static { #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub(crate) struct Constant { pub(crate) type_: Type, + pub(crate) generics: Box, pub(crate) kind: ConstantKind, } @@ -2502,7 +2516,8 @@ mod size_asserts { static_assert_size!(GenericParamDef, 56); static_assert_size!(Generics, 16); static_assert_size!(Item, 56); - static_assert_size!(ItemKind, 64); + // FIXME(generic_const_items): Further reduce the size. + static_assert_size!(ItemKind, 72); static_assert_size!(PathSegment, 40); static_assert_size!(Type, 32); // tidy-alphabetical-end diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs index 394954208..4907a5527 100644 --- a/src/librustdoc/clean/types/tests.rs +++ b/src/librustdoc/clean/types/tests.rs @@ -73,7 +73,7 @@ fn should_not_trim() { fn is_same_generic() { use crate::clean::types::{PrimitiveType, Type}; use crate::formats::cache::Cache; - let cache = Cache::new(false); + let cache = Cache::new(false, false); let generic = Type::Generic(rustc_span::symbol::sym::Any); let unit = Type::Primitive(PrimitiveType::Unit); assert!(!generic.is_doc_subtype_of(&unit, &cache)); diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index b786ecbe3..a86bbcc76 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -13,11 +13,10 @@ use rustc_ast as ast; use rustc_ast::tokenstream::TokenTree; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_middle::mir; use rustc_middle::mir::interpret::ConstValue; -use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; use std::fmt::Write as _; use std::mem; @@ -39,11 +38,15 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { for it in &module.items { // `compiler_builtins` should be masked too, but we can't apply // `#[doc(masked)]` to the injected `extern crate` because it's unstable. - if it.is_extern_crate() - && (it.attrs.has_doc_flag(sym::masked) - || cx.tcx.is_compiler_builtins(it.item_id.krate())) - { + if cx.tcx.is_compiler_builtins(it.item_id.krate()) { cx.cache.masked_crates.insert(it.item_id.krate()); + } else if it.is_extern_crate() + && it.attrs.has_doc_flag(sym::masked) + && let Some(def_id) = it.item_id.as_def_id() + && let Some(local_def_id) = def_id.as_local() + && let Some(cnum) = cx.tcx.extern_mod_stmt_cnum(local_def_id) + { + cx.cache.masked_crates.insert(cnum); } } } @@ -71,7 +74,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { Crate { module, external_traits: cx.external_traits.clone() } } -pub(crate) fn substs_to_args<'tcx>( +pub(crate) fn ty_args_to_args<'tcx>( cx: &mut DocContext<'tcx>, args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, has_self: bool, @@ -114,12 +117,12 @@ fn external_generic_args<'tcx>( did: DefId, has_self: bool, bindings: ThinVec, - substs: ty::Binder<'tcx, SubstsRef<'tcx>>, + ty_args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, ) -> GenericArgs { - let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self, Some(did)); + let args = ty_args_to_args(cx, ty_args.map_bound(|args| &args[..]), has_self, Some(did)); if cx.tcx.fn_trait_kind_from_def_id(did).is_some() { - let ty = substs + let ty = ty_args .iter() .nth(if has_self { 1 } else { 0 }) .unwrap() @@ -147,7 +150,7 @@ pub(super) fn external_path<'tcx>( did: DefId, has_self: bool, bindings: ThinVec, - substs: ty::Binder<'tcx, SubstsRef<'tcx>>, + args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, ) -> Path { let def_kind = cx.tcx.def_kind(did); let name = cx.tcx.item_name(did); @@ -155,7 +158,7 @@ pub(super) fn external_path<'tcx>( res: Res::Def(def_kind, did), segments: thin_vec![PathSegment { name, - args: external_generic_args(cx, did, has_self, bindings, substs), + args: external_generic_args(cx, did, has_self, bindings, args), }], } } @@ -217,7 +220,7 @@ pub(crate) fn build_deref_target_impls( pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { use rustc_hir::*; - debug!("trying to get a name from pattern: {:?}", p); + debug!("trying to get a name from pattern: {p:?}"); Symbol::intern(&match p.kind { PatKind::Wild | PatKind::Struct(..) => return kw::Underscore, @@ -250,7 +253,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { match n.kind() { - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs: _ }) => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => { let s = if let Some(def) = def.as_local() { print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def)) } else { @@ -275,7 +278,7 @@ pub(crate) fn print_evaluated_const( underscores_and_type: bool, ) -> Option { tcx.const_eval_poly(def_id).ok().and_then(|val| { - let ty = tcx.type_of(def_id).subst_identity(); + let ty = tcx.type_of(def_id).instantiate_identity(); match (val, ty.kind()) { (_, &ty::Ref(..)) => None, (ConstValue::Scalar(_), &ty::Adt(_, _)) => None, @@ -460,7 +463,7 @@ pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String { /// Given a type Path, resolve it to a Type using the TyCtxt pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type { - debug!("resolve_type({:?})", path); + debug!("resolve_type({path:?})"); match path.res { Res::PrimTy(p) => Primitive(PrimitiveType::from(p)), @@ -479,12 +482,6 @@ pub(crate) fn get_auto_trait_and_blanket_impls( cx: &mut DocContext<'_>, item_def_id: DefId, ) -> impl Iterator { - // FIXME: To be removed once `parallel_compiler` bugs are fixed! - // More information in . - if cfg!(parallel_compiler) { - return vec![].into_iter().chain(vec![].into_iter()); - } - let auto_impls = cx .sess() .prof @@ -505,16 +502,30 @@ pub(crate) fn get_auto_trait_and_blanket_impls( /// [`href()`]: crate::html::format::href pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { use DefKind::*; - debug!("register_res({:?})", res); + debug!("register_res({res:?})"); let (kind, did) = match res { Res::Def( - kind @ (AssocTy | AssocFn | AssocConst | Variant | Fn | TyAlias | Enum | Trait | Struct - | Union | Mod | ForeignTy | Const | Static(_) | Macro(..) | TraitAlias), + kind @ (AssocTy + | AssocFn + | AssocConst + | Variant + | Fn + | TyAlias { .. } + | Enum + | Trait + | Struct + | Union + | Mod + | ForeignTy + | Const + | Static(_) + | Macro(..) + | TraitAlias), did, ) => (kind.into(), did), - _ => panic!("register_res: unexpected {:?}", res), + _ => panic!("register_res: unexpected {res:?}"), }; if did.is_local() { return did; @@ -592,8 +603,12 @@ pub(super) fn render_macro_arms<'a>( ) -> String { let mut out = String::new(); for matcher in matchers { - writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(tcx, matcher), arm_delim) - .unwrap(); + writeln!( + out, + " {matcher} => {{ ... }}{arm_delim}", + matcher = render_macro_matcher(tcx, matcher), + ) + .unwrap(); } out } @@ -609,22 +624,54 @@ pub(super) fn display_macro_source( 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, ";")) + format!("macro_rules! {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ";")) } else { if matchers.len() <= 1 { format!( - "{}macro {}{} {{\n ...\n}}", - visibility_to_src_with_space(Some(vis), cx.tcx, def_id), - name, - matchers.map(|matcher| render_macro_matcher(cx.tcx, matcher)).collect::(), + "{vis}macro {name}{matchers} {{\n ...\n}}", + vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id), + matchers = matchers + .map(|matcher| render_macro_matcher(cx.tcx, matcher)) + .collect::(), ) } else { format!( - "{}macro {} {{\n{}}}", - visibility_to_src_with_space(Some(vis), cx.tcx, def_id), - name, - render_macro_arms(cx.tcx, matchers, ","), + "{vis}macro {name} {{\n{arms}}}", + vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id), + arms = render_macro_arms(cx.tcx, matchers, ","), ) } } } + +pub(crate) fn inherits_doc_hidden( + tcx: TyCtxt<'_>, + mut def_id: LocalDefId, + stop_at: Option, +) -> 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; + } else if let Some(node) = hir.find_by_def_id(def_id) && + matches!( + node, + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }), + ) + { + // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly + // on them, they don't inherit it from the parent context. + return false; + } + } + false +} + +#[inline] +pub(crate) fn should_ignore_res(res: Res) -> bool { + matches!(res, Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..)) +} diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 217f1a6ee..81fb13f41 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -50,7 +50,7 @@ impl TryFrom<&str> for OutputFormat { match value { "json" => Ok(OutputFormat::Json), "html" => Ok(OutputFormat::Html), - _ => Err(format!("unknown output format `{}`", value)), + _ => Err(format!("unknown output format `{value}`")), } } } @@ -383,7 +383,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); } } @@ -415,7 +415,7 @@ impl Options { println!("rustdoc: [check-theme] Starting tests! (Ignoring all other arguments)"); for theme_file in to_check.iter() { - print!(" - Checking \"{}\"...", theme_file); + print!(" - Checking \"{theme_file}\"..."); let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag); if !differences.is_empty() || !success { println!(" FAILED"); @@ -556,30 +556,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!( - "theme file \"{}\" is missing CSS rules from the default theme", - theme_s + "theme file \"{theme_s}\" is missing CSS rules from the default theme", )) .warn("the theme may appear incorrect when loaded") .help(format!( - "to see what rules are missing, call `rustdoc --check-theme \"{}\"`", - theme_s + "to see what rules are missing, call `rustdoc --check-theme \"{theme_s}\"`", )) .emit(); } @@ -608,7 +606,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); } } @@ -628,7 +626,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); } }; @@ -787,7 +785,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}` flag is deprecated")) .note( "see issue #44136 \ for more information", @@ -800,7 +798,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}` flag no longer functions")); err.note( "see issue #44136 \ for more information", diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9687b8b18..4c8dab61f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -10,6 +10,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{HirId, Path}; use rustc_interface::interface; +use rustc_lint::{late_lint_mod, MissingDoc}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks}; @@ -45,7 +46,7 @@ pub(crate) struct DocContext<'tcx> { // The current set of parameter substitutions, // 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, + pub(crate) args: DefIdMap, pub(crate) current_type_aliases: DefIdMap, /// Table synthetic type parameter for `impl Trait` in argument position -> bounds pub(crate) impl_trait_bounds: FxHashMap>, @@ -85,17 +86,17 @@ impl<'tcx> DocContext<'tcx> { /// the substitutions for a type alias' RHS. pub(crate) fn enter_alias( &mut self, - substs: DefIdMap, + args: DefIdMap, def_id: DefId, f: F, ) -> R where F: FnOnce(&mut Self) -> R, { - let old_substs = mem::replace(&mut self.substs, substs); + let old_args = mem::replace(&mut self.args, args); *self.current_type_aliases.entry(def_id).or_insert(0) += 1; let r = f(self); - self.substs = old_substs; + self.args = old_args; if let Some(count) = self.current_type_aliases.get_mut(&def_id) { *count -= 1; if *count == 0 { @@ -136,19 +137,13 @@ pub(crate) fn new_handler( ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); Box::new( - EmitterWriter::stderr( - color_config, - source_map.map(|sm| sm as _), - None, - fallback_bundle, - short, - unstable_opts.teach, - diagnostic_width, - false, - unstable_opts.track_diagnostics, - TerminalUrl::No, - ) - .ui_testing(unstable_opts.ui_testing), + EmitterWriter::stderr(color_config, fallback_bundle) + .sm(source_map.map(|sm| sm as _)) + .short_message(short) + .teach(unstable_opts.teach) + .diagnostic_width(diagnostic_width) + .track_diagnostics(unstable_opts.track_diagnostics) + .ui_testing(unstable_opts.ui_testing), ) } ErrorOutputType::Json { pretty, json_rendered } => { @@ -173,10 +168,8 @@ pub(crate) fn new_handler( } }; - rustc_errors::Handler::with_emitter_and_flags( - emitter, - unstable_opts.diagnostic_handler_flags(true), - ) + rustc_errors::Handler::with_emitter(emitter) + .with_flags(unstable_opts.diagnostic_handler_flags(true)) } /// Parse, resolve, and typecheck the given crate. @@ -270,8 +263,9 @@ pub(crate) fn create_config( parse_sess_created: None, register_lints: Some(Box::new(crate::lint::register_lints)), override_queries: Some(|_sess, providers, _external_providers| { + // We do not register late module lints, so this only runs `MissingDoc`. // Most lints will require typechecking, so just don't run them. - providers.lint_mod = |_, _| {}; + providers.lint_mod = |tcx, module_def_id| late_lint_mod(tcx, module_def_id, MissingDoc); // hack so that `used_trait_imports` won't try to call typeck providers.used_trait_imports = |_, _| { static EMPTY_SET: LazyLock> = LazyLock::new(UnordSet::default); @@ -289,13 +283,14 @@ pub(crate) fn create_config( let hir = tcx.hir(); let body = hir.body(hir.body_owned_by(def_id)); - debug!("visiting body for {:?}", def_id); + debug!("visiting body for {def_id:?}"); EmitIgnoredResolutionErrors::new(tcx).visit_body(body); (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; }), make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), + ice_file: None, } } @@ -324,9 +319,7 @@ pub(crate) fn run_global_ctxt( tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); tcx.sess.abort_if_errors(); - tcx.sess.time("missing_docs", || { - rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new); - }); + tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx)); tcx.sess.time("check_mod_attrs", || { tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module)) }); @@ -340,12 +333,12 @@ pub(crate) fn run_global_ctxt( param_env: ParamEnv::empty(), external_traits: Default::default(), active_extern_traits: Default::default(), - substs: Default::default(), + args: Default::default(), current_type_aliases: Default::default(), impl_trait_bounds: Default::default(), generated_synthetics: Default::default(), auto_traits, - cache: Cache::new(render_options.document_private), + cache: Cache::new(render_options.document_private, render_options.document_hidden), inlined: FxHashSet::default(), output_format, render_options, @@ -384,7 +377,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({name})]` attribute is deprecated")); msg.note( "see issue #44136 \ for more information", @@ -477,7 +470,7 @@ impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> { } fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) { - debug!("visiting path {:?}", path); + debug!("visiting path {path:?}"); if path.res == Res::Err { // We have less context here than in rustc_resolve, // so we can only emit the name and span. @@ -494,8 +487,7 @@ impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> { self.tcx.sess, path.span, E0433, - "failed to resolve: {}", - label + "failed to resolve: {label}", ); err.span_label(path.span, label); err.note("this error was originally ignored because you are running `rustdoc`"); diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs index d58b8dc6a..82c1a5039 100644 --- a/src/librustdoc/docfs.rs +++ b/src/librustdoc/docfs.rs @@ -72,9 +72,9 @@ impl DocFS { let sender = self.errors.clone().expect("can't write after closing"); self.pool.execute(move || { fs::write(&path, contents).unwrap_or_else(|e| { - sender.send(format!("\"{}\": {}", path.display(), e)).unwrap_or_else(|_| { - panic!("failed to send error on \"{}\"", path.display()) - }) + sender.send(format!("\"{path}\": {e}", path = path.display())).unwrap_or_else( + |_| panic!("failed to send error on \"{}\"", path.display()), + ) }); }); } else { diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 217257316..36d5adb63 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError, TerminalUrl}; +use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID}; use rustc_interface::interface; @@ -108,6 +108,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { override_queries: None, make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), + ice_file: None, }; let test_args = options.test_args.clone(); @@ -191,7 +192,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { // The allow lint level is not expected, // as if allow is specified, no message // is to be emitted. - v => unreachable!("Invalid lint level '{}'", v), + v => unreachable!("Invalid lint level '{v}'"), }) .unwrap_or("warn") .to_string(); @@ -403,7 +404,7 @@ fn run_test( compiler.stdin(Stdio::piped()); compiler.stderr(Stdio::piped()); - debug!("compiler invocation for doctest: {:?}", compiler); + debug!("compiler invocation for doctest: {compiler:?}"); let mut child = compiler.spawn().expect("Failed to spawn rustc process"); { @@ -468,7 +469,9 @@ fn run_test( // Run the code! let mut cmd; + let output_file = make_maybe_absolute_path(output_file); if let Some(tool) = runtool { + let tool = make_maybe_absolute_path(tool.into()); cmd = Command::new(tool); cmd.args(runtool_args); cmd.arg(output_file); @@ -502,6 +505,20 @@ fn run_test( Ok(()) } +/// Converts a path intended to use as a command to absolute if it is +/// relative, and not a single component. +/// +/// This is needed to deal with relative paths interacting with +/// `Command::current_dir` in a platform-specific way. +fn make_maybe_absolute_path(path: PathBuf) -> PathBuf { + if path.components().count() == 1 { + // Look up process via PATH. + path + } else { + std::env::current_dir().map(|c| c.join(&path)).unwrap_or_else(|_| path) + } +} + /// Transforms a test into code that can be compiled into a Rust binary, and returns the number of /// lines before the test code begins as well as if the output stream supports colors or not. pub(crate) fn make_test( @@ -557,36 +574,14 @@ pub(crate) fn make_test( rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false, ); - supports_color = EmitterWriter::stderr( - ColorConfig::Auto, - None, - None, - fallback_bundle.clone(), - false, - false, - Some(80), - false, - false, - TerminalUrl::No, - ) - .supports_color(); + supports_color = EmitterWriter::stderr(ColorConfig::Auto, fallback_bundle.clone()) + .diagnostic_width(Some(80)) + .supports_color(); - let emitter = EmitterWriter::new( - Box::new(io::sink()), - None, - None, - fallback_bundle, - false, - false, - false, - None, - false, - false, - TerminalUrl::No, - ); + let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser - let handler = Handler::with_emitter(false, None, Box::new(emitter)); + let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); let sess = ParseSess::with_span_handler(handler, sm); let mut found_main = false; @@ -653,8 +648,7 @@ pub(crate) fn make_test( (found_main, found_extern_crate, found_macro) }) }); - let Ok((already_has_main, already_has_extern_crate, found_macro)) = result - else { + let Ok((already_has_main, already_has_extern_crate, found_macro)) = result else { // If the parser panicked due to a fatal error, pass the test code through unchanged. // The error will be reported during compilation. return (s.to_owned(), 0, false); @@ -760,21 +754,9 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { false, ); - let emitter = EmitterWriter::new( - Box::new(io::sink()), - None, - None, - fallback_bundle, - false, - false, - false, - None, - false, - false, - TerminalUrl::No, - ); + let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); - let handler = Handler::with_emitter(false, None, Box::new(emitter)); + let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); let sess = ParseSess::with_span_handler(handler, sm); let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) { @@ -967,7 +949,7 @@ impl Collector { if !item_path.is_empty() { item_path.push(' '); } - format!("{} - {}(line {})", filename.prefer_local(), item_path, line) + format!("{} - {item_path}(line {line})", filename.prefer_local()) } pub(crate) fn set_position(&mut self, position: Span) { @@ -1044,7 +1026,7 @@ impl Tester for Collector { path.push(&test_id); if let Err(err) = std::fs::create_dir_all(&path) { - eprintln!("Couldn't create directory for doctest executables: {}", err); + eprintln!("Couldn't create directory for doctest executables: {err}"); panic::resume_unwind(Box::new(())); } @@ -1113,7 +1095,7 @@ impl Tester for Collector { eprint!("Test executable succeeded, but it's marked `should_panic`."); } TestFailure::MissingErrorCodes(codes) => { - eprint!("Some expected error codes were not found: {:?}", codes); + eprint!("Some expected error codes were not found: {codes:?}"); } TestFailure::ExecutionError(err) => { eprint!("Couldn't run the test: {err}"); diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 88049c4ca..f0ebb8e5a 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -37,8 +37,7 @@ impl ExternalHtml { let bc = load_external_files(before_content, diag)?; let m_bc = load_external_files(md_before_content, diag)?; let bc = format!( - "{}{}", - bc, + "{bc}{}", Markdown { content: &m_bc, links: &[], @@ -53,8 +52,7 @@ impl ExternalHtml { let ac = load_external_files(after_content, diag)?; let m_ac = load_external_files(md_after_content, diag)?; let ac = format!( - "{}{}", - ac, + "{ac}{}", Markdown { content: &m_ac, links: &[], @@ -83,7 +81,11 @@ pub(crate) fn load_string>( 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}`: {e}", + file_path = file_path.display() + )) + .emit(); return Err(LoadStringError::ReadFail); } }; diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index dac762e9f..d1deda0c7 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -86,6 +86,9 @@ pub(crate) struct Cache { /// Whether to document private items. /// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions. pub(crate) document_private: bool, + /// Whether to document hidden items. + /// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions. + pub(crate) document_hidden: bool, /// Crates marked with [`#[doc(masked)]`][doc_masked]. /// @@ -137,8 +140,8 @@ struct CacheBuilder<'a, 'tcx> { } impl Cache { - pub(crate) fn new(document_private: bool) -> Self { - Cache { document_private, ..Cache::default() } + pub(crate) fn new(document_private: bool, document_hidden: bool) -> Self { + Cache { document_private, document_hidden, ..Cache::default() } } /// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was @@ -473,7 +476,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => { dids.insert(path.def_id()); if let Some(generics) = path.generics() && - let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).subst_identity().kind() && + let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).instantiate_identity().kind() && adt.is_fundamental() { for ty in generics { if let Some(did) = ty.def_id(self.cache) { diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 452e14918..a78893558 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -115,7 +115,7 @@ impl From for ItemType { DefKind::Struct => Self::Struct, DefKind::Union => Self::Union, DefKind::Trait => Self::Trait, - DefKind::TyAlias => Self::Typedef, + DefKind::TyAlias { .. } => Self::Typedef, DefKind::TraitAlias => Self::TraitAlias, DefKind::Macro(kind) => match kind { MacroKind::Bang => ItemType::Macro, @@ -136,7 +136,6 @@ impl From for ItemType { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 6f9cc0266..c49f1a4d3 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -77,8 +77,11 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string()); cx.mod_item_in(&item)?; - let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = *item.kind - else { unreachable!() }; + let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = + *item.kind + else { + unreachable!() + }; for it in module.items { debug!("Adding {:?} to worklist", it.name); work.push((cx.make_child_renderer(), it)); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 54c0cd2ef..2f611c31a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -18,7 +18,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty; use rustc_middle::ty::TyCtxt; @@ -109,6 +109,10 @@ impl Buffer { self.buffer } + pub(crate) fn push(&mut self, c: char) { + self.buffer.push(c); + } + pub(crate) fn push_str(&mut self, s: &str) { self.buffer.push_str(s); } @@ -228,9 +232,9 @@ impl clean::GenericParamDef { if let Some(default) = default { if f.alternate() { - write!(f, " = {:#}", default)?; + write!(f, " = {default:#}")?; } else { - write!(f, " = {}", default)?; + write!(f, " = {default}")?; } } @@ -451,9 +455,9 @@ impl clean::GenericBound { hir::TraitBoundModifier::MaybeConst => "", }; if f.alternate() { - write!(f, "{}{:#}", modifier_str, ty.print(cx)) + write!(f, "{modifier_str}{ty:#}", ty = ty.print(cx)) } else { - write!(f, "{}{}", modifier_str, ty.print(cx)) + write!(f, "{modifier_str}{ty}", ty = ty.print(cx)) } } }) @@ -599,12 +603,12 @@ fn generate_macro_def_id_path( let cstore = CStore::from_tcx(tcx); // We need this to prevent a `panic` when this function is used from intra doc links... if !cstore.has_crate_data(def_id.krate) { - debug!("No data for crate {}", crate_name); + debug!("No data for crate {crate_name}"); return Err(HrefError::NotInExternalCache); } // Check to see if it is a macro 2.0 or built-in macro. // More information in . - let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx.sess) { + let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx) { LoadedMacro::MacroDef(def, _) => { // If `ast_def.macro_rules` is `true`, then it's not a macro 2.0. matches!(&def.kind, ast::ItemKind::MacroDef(ast_def) if !ast_def.macro_rules) @@ -631,19 +635,18 @@ fn generate_macro_def_id_path( let url = match cache.extern_locations[&def_id.krate] { ExternalLocation::Remote(ref s) => { // `ExternalLocation::Remote` always end with a `/`. - format!("{}{}", s, path.iter().map(|p| p.as_str()).join("/")) + format!("{s}{path}", path = path.iter().map(|p| p.as_str()).join("/")) } ExternalLocation::Local => { // `root_path` always end with a `/`. format!( - "{}{}/{}", - root_path.unwrap_or(""), - crate_name, - path.iter().map(|p| p.as_str()).join("/") + "{root_path}{crate_name}/{path}", + root_path = root_path.unwrap_or(""), + path = path.iter().map(|p| p.as_str()).join("/") ) } ExternalLocation::Unknown => { - debug!("crate {} not in cache when linkifying macros", crate_name); + debug!("crate {crate_name} not in cache when linkifying macros"); return Err(HrefError::NotInExternalCache); } }; @@ -662,6 +665,14 @@ pub(crate) fn href_with_root_path( // documented on their parent's page tcx.parent(did) } + DefKind::ExternCrate => { + // Link to the crate itself, not the `extern crate` item. + if let Some(local_did) = did.as_local() { + tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id() + } else { + did + } + } _ => did, }; let cache = cx.cache(); @@ -724,7 +735,7 @@ pub(crate) fn href_with_root_path( _ => { let prefix = shortty.as_str(); let last = fqp.last().unwrap(); - url_parts.push_fmt(format_args!("{}.{}.html", prefix, last)); + url_parts.push_fmt(format_args!("{prefix}.{last}.html")); } } Ok((url_parts.finish(), shortty, fqp.to_vec())) @@ -771,9 +782,10 @@ pub(crate) fn href_relative_parts<'fqp>( pub(crate) fn link_tooltip(did: DefId, fragment: &Option, cx: &Context<'_>) -> String { let cache = cx.cache(); - let Some((fqp, shortty)) = cache.paths.get(&did) - .or_else(|| cache.external_paths.get(&did)) - else { return String::new() }; + let Some((fqp, shortty)) = cache.paths.get(&did).or_else(|| cache.external_paths.get(&did)) + else { + return String::new(); + }; let mut buf = Buffer::new(); let fqp = if *shortty == ItemType::Primitive { // primitives are documented in a crate, but not actually part of it @@ -819,9 +831,9 @@ fn resolved_path<'cx>( let path = if use_absolute { if let Ok((_, _, fqp)) = href(did, cx) { format!( - "{}::{}", - join_with_double_colon(&fqp[..fqp.len() - 1]), - anchor(did, *fqp.last().unwrap(), cx) + "{path}::{anchor}", + path = join_with_double_colon(&fqp[..fqp.len() - 1]), + anchor = anchor(did, *fqp.last().unwrap(), cx) ) } else { last.name.to_string() @@ -829,7 +841,7 @@ fn resolved_path<'cx>( } else { anchor(did, last.name, cx).to_string() }; - write!(w, "{}{}", path, last.args.print(cx))?; + write!(w, "{path}{args}", args = last.args.print(cx))?; } Ok(()) } @@ -897,7 +909,7 @@ fn primitive_link_fragment( None => {} } } - write!(f, "{}", name)?; + f.write_str(name)?; if needs_termination { write!(f, "")?; } @@ -937,15 +949,11 @@ pub(crate) fn anchor<'a, 'cx: 'a>( if let Ok((url, short_ty, fqp)) = parts { write!( f, - r#"{}"#, - short_ty, - url, - short_ty, - join_with_double_colon(&fqp), - text.as_str() + r#"{text}"#, + path = join_with_double_colon(&fqp), ) } else { - write!(f, "{}", text) + f.write_str(text.as_str()) } }) } @@ -956,10 +964,10 @@ fn fmt_type<'cx>( use_absolute: bool, cx: &'cx Context<'_>, ) -> fmt::Result { - trace!("fmt_type(t = {:?})", t); + trace!("fmt_type(t = {t:?})"); match *t { - clean::Generic(name) => write!(f, "{}", name), + clean::Generic(name) => f.write_str(name.as_str()), clean::Type::Path { ref path } => { // Paths like `T::Output` and `Self::Output` should be rendered with all segments. let did = path.def_id(); @@ -1076,13 +1084,13 @@ fn fmt_type<'cx>( if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() { let text = if f.alternate() { - format!("*{} {:#}", m, t.print(cx)) + format!("*{m} {ty:#}", ty = t.print(cx)) } else { - format!("*{} {}", m, t.print(cx)) + format!("*{m} {ty}", ty = t.print(cx)) }; primitive_link(f, clean::PrimitiveType::RawPointer, &text, cx) } else { - primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m), cx)?; + primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{m} "), cx)?; fmt::Display::fmt(&t.print(cx), f) } } @@ -1093,22 +1101,35 @@ fn fmt_type<'cx>( }; let m = mutability.print_with_space(); let amp = if f.alternate() { "&" } else { "&" }; - match **ty { + + if let clean::Generic(name) = **ty { + return primitive_link( + f, + PrimitiveType::Reference, + &format!("{amp}{lt}{m}{name}"), + cx, + ); + } + + write!(f, "{amp}{lt}{m}")?; + + let needs_parens = match **ty { clean::DynTrait(ref bounds, ref trait_lt) if bounds.len() > 1 || trait_lt.is_some() => { - write!(f, "{}{}{}(", amp, lt, m)?; - fmt_type(ty, f, use_absolute, cx)?; - write!(f, ")") - } - clean::Generic(name) => { - primitive_link(f, PrimitiveType::Reference, &format!("{amp}{lt}{m}{name}"), cx) - } - _ => { - write!(f, "{}{}{}", amp, lt, m)?; - fmt_type(ty, f, use_absolute, cx) + true } + clean::ImplTrait(ref bounds) if bounds.len() > 1 => true, + _ => false, + }; + if needs_parens { + f.write_str("(")?; + } + fmt_type(ty, f, use_absolute, cx)?; + if needs_parens { + f.write_str(")")?; } + Ok(()) } clean::ImplTrait(ref bounds) => { if f.alternate() { @@ -1423,11 +1444,20 @@ impl clean::FnDecl { clean::SelfValue => { write!(f, "self")?; } - clean::SelfBorrowed(Some(ref lt), mtbl) => { - write!(f, "{}{} {}self", amp, lt.print(), mtbl.print_with_space())?; + clean::SelfBorrowed(Some(ref lt), mutability) => { + write!( + f, + "{amp}{lifetime} {mutability}self", + lifetime = lt.print(), + mutability = mutability.print_with_space(), + )?; } - clean::SelfBorrowed(None, mtbl) => { - write!(f, "{}{}self", amp, mtbl.print_with_space())?; + clean::SelfBorrowed(None, mutability) => { + write!( + f, + "{amp}{mutability}self", + mutability = mutability.print_with_space(), + )?; } clean::SelfExplicit(ref typ) => { write!(f, "self: ")?; @@ -1501,7 +1531,7 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>( "pub(super) ".into() } else { let path = cx.tcx().def_path(vis_did); - debug!("path={:?}", path); + debug!("path={path:?}"); // modified from `resolved_path()` to work with `DefPathData` let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); let anchor = anchor(vis_did, last_name, cx); @@ -1510,12 +1540,12 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>( for seg in &path.data[..path.data.len() - 1] { let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap()); } - let _ = write!(s, "{}) ", anchor); + let _ = write!(s, "{anchor}) "); s.into() } } }; - display_fn(move |f| write!(f, "{}", to_print)) + display_fn(move |f| f.write_str(&to_print)) } /// This function is the same as print_with_space, except that it renders no links. @@ -1610,7 +1640,7 @@ impl clean::Import { if name == self.source.path.last() { write!(f, "use {};", self.source.print(cx)) } else { - write!(f, "use {} as {};", self.source.print(cx), name) + write!(f, "use {source} as {name};", source = self.source.print(cx)) } } clean::ImportKind::Glob => { @@ -1639,7 +1669,7 @@ impl clean::ImportSource { if let hir::def::Res::PrimTy(p) = self.path.res { primitive_link(f, PrimitiveType::from(p), name.as_str(), cx)?; } else { - write!(f, "{}", name)?; + f.write_str(name.as_str())?; } Ok(()) } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index c94968b48..039e8cdb9 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -928,18 +928,16 @@ fn string_without_closing_tag( href_context: &Option>, open_tag: bool, ) -> Option<&'static str> { - let Some(klass) = klass - else { - write!(out, "{}", text).unwrap(); + let Some(klass) = klass else { + write!(out, "{text}").unwrap(); return None; }; - let Some(def_span) = klass.get_span() - else { + let Some(def_span) = klass.get_span() else { if !open_tag { - write!(out, "{}", text).unwrap(); + write!(out, "{text}").unwrap(); return None; } - write!(out, "{}", klass.as_html(), text).unwrap(); + write!(out, "{text}", klass = klass.as_html()).unwrap(); return Some(""); }; @@ -949,14 +947,17 @@ fn string_without_closing_tag( match t { "self" | "Self" => write!( &mut path, - "{}", - Class::Self_(DUMMY_SP).as_html(), - t + "{t}", + klass = Class::Self_(DUMMY_SP).as_html(), ), "crate" | "super" => { - write!(&mut path, "{}", Class::KeyWord.as_html(), t) + write!( + &mut path, + "{t}", + klass = Class::KeyWord.as_html(), + ) } - t => write!(&mut path, "{}", t), + t => write!(&mut path, "{t}"), } .expect("Failed to build source HTML path"); path @@ -988,19 +989,24 @@ fn string_without_closing_tag( ) .ok() .map(|(url, _, _)| url), + LinkFromSrc::Doc(def_id) => { + format::href_with_root_path(*def_id, context, Some(&href_context.root_path)) + .ok() + .map(|(doc_link, _, _)| doc_link) + } } }) { if !open_tag { // We're already inside an element which has the same klass, no need to give it // again. - write!(out, "{}", href, text_s).unwrap(); + write!(out, "{text_s}").unwrap(); } else { let klass_s = klass.as_html(); if klass_s.is_empty() { - write!(out, "{}", href, text_s).unwrap(); + write!(out, "{text_s}").unwrap(); } else { - write!(out, "{}", klass_s, href, text_s).unwrap(); + write!(out, "{text_s}").unwrap(); } } return Some(""); @@ -1015,7 +1021,7 @@ fn string_without_closing_tag( out.write_str(&text_s).unwrap(); Some("") } else { - write!(out, "{}", klass_s, text_s).unwrap(); + write!(out, "{text_s}").unwrap(); Some("") } } diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index 2c93b9a09..4c0874a68 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -23,7 +23,7 @@ fn test_html_highlighting() { let html = { let mut out = Buffer::new(); write_code(&mut out, src, None, None); - format!("{}
{}
\n", STYLE, out.into_inner()) + format!("{STYLE}
{}
\n", out.into_inner()) }; expect_file!["fixtures/sample.html"].assert_eq(&html); }); diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs index 4c8db2c67..8562e103d 100644 --- a/src/librustdoc/html/length_limit.rs +++ b/src/librustdoc/html/length_limit.rs @@ -78,8 +78,7 @@ impl HtmlWithLimit { pub(super) fn open_tag(&mut self, tag_name: &'static str) { assert!( tag_name.chars().all(|c| ('a'..='z').contains(&c)), - "tag_name contained non-alphabetic chars: {:?}", - tag_name + "tag_name contained non-alphabetic chars: {tag_name:?}", ); self.queued_tags.push(tag_name); } @@ -88,7 +87,7 @@ impl HtmlWithLimit { pub(super) fn close_tag(&mut self) { match self.unclosed_tags.pop() { // Close the most recently opened tag. - Some(tag_name) => write!(self.buf, "", tag_name).unwrap(), + Some(tag_name) => write!(self.buf, "").unwrap(), // There are valid cases where `close_tag()` is called without // there being any tags to close. For example, this occurs when // a tag is opened after the length limit is exceeded; @@ -101,7 +100,7 @@ impl HtmlWithLimit { /// Write all queued tags and add them to the `unclosed_tags` list. fn flush_queue(&mut self) { for tag_name in self.queued_tags.drain(..) { - write!(self.buf, "<{}>", tag_name).unwrap(); + write!(self.buf, "<{tag_name}>").unwrap(); self.unclosed_tags.push(tag_name); } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index fd00277e2..98cc38a10 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -50,7 +50,7 @@ use crate::html::render::small_url_encode; use crate::html::toc::TocBuilder; use pulldown_cmark::{ - html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, + html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag, }; #[cfg(test)] @@ -246,10 +246,9 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { return Some(Event::Html( format!( "
\ -
{}
\ +
{text}
\
", - lang, - Escape(&original_text), + text = Escape(&original_text), ) .into(), )); @@ -288,8 +287,9 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let test_escaped = small_url_encode(test); Some(format!( - r#"Run"#, - url, test_escaped, channel, edition, + "Run", )) }); @@ -308,7 +308,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { // insert newline to clearly separate it from the // previous block so we can shorten the html output let mut s = Buffer::new(); - s.push_str("\n"); + s.push('\n'); highlight::render_example_with_highlighting( &text, @@ -349,7 +349,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { dest, title, ))) => { - debug!("saw start of shortcut link to {} with title {}", dest, title); + debug!("saw start of shortcut link to {dest} with title {title}"); // If this is a shortcut link, it was resolved by the broken_link_callback. // So the URL will already be updated properly. let link = self.links.iter().find(|&link| *link.href == **dest); @@ -370,7 +370,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { dest, _, ))) => { - debug!("saw end of shortcut link to {}", dest); + debug!("saw end of shortcut link to {dest}"); if self.links.iter().any(|link| *link.href == **dest) { assert!(self.shortcut_link.is_some(), "saw closing link without opening tag"); self.shortcut_link = None; @@ -379,7 +379,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { // Handle backticks in inline code blocks, but only if we're in the middle of a shortcut link. // [`fn@f`] Some(Event::Code(text)) => { - trace!("saw code {}", text); + trace!("saw code {text}"); if let Some(link) = self.shortcut_link { // NOTE: this only replaces if the code block is the *entire* text. // If only part of the link has code highlighting, the disambiguator will not be removed. @@ -394,7 +394,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { l.href == link.href && Some(&**text) == l.original_text.get(1..l.original_text.len() - 1) }) { - debug!("replacing {} with {}", text, link.new_text); + debug!("replacing {text} with {new_text}", new_text = link.new_text); *text = CowStr::Borrowed(&link.new_text); } } @@ -402,7 +402,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { // Replace plain text in links, but only in the middle of a shortcut link. // [fn@f] Some(Event::Text(text)) => { - trace!("saw text {}", text); + trace!("saw text {text}"); if let Some(link) = self.shortcut_link { // NOTE: same limitations as `Event::Code` if let Some(link) = self @@ -410,7 +410,7 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { .iter() .find(|l| l.href == link.href && **text == *l.original_text) { - debug!("replacing {} with {}", text, link.new_text); + debug!("replacing {text} with {new_text}", new_text = link.new_text); *text = CowStr::Borrowed(&link.new_text); } } @@ -522,18 +522,16 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator let mut html_header = String::new(); html::push_html(&mut html_header, self.buf.iter().map(|(ev, _)| ev.clone())); let sec = builder.push(level as u32, html_header, id.clone()); - self.buf.push_front((Event::Html(format!("{} ", sec).into()), 0..0)); + self.buf.push_front((Event::Html(format!("{sec} ").into()), 0..0)); } let level = std::cmp::min(level as u32 + (self.heading_offset as u32), MAX_HEADER_LEVEL); - self.buf.push_back((Event::Html(format!("", level).into()), 0..0)); + self.buf.push_back((Event::Html(format!("").into()), 0..0)); let start_tags = format!( "\ ", - id = id, - level = level ); return Some((Event::Html(start_tags.into()), 0..0)); } @@ -683,14 +681,14 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { v.sort_by(|a, b| a.1.cmp(&b.1)); let mut ret = String::from("

    "); for (mut content, id) in v { - write!(ret, "
  1. ", id).unwrap(); + write!(ret, "
  2. ").unwrap(); let mut is_paragraph = false; if let Some(&Event::End(Tag::Paragraph)) = content.last() { content.pop(); is_paragraph = true; } html::push_html(&mut ret, content.into_iter()); - write!(ret, " ", id).unwrap(); + write!(ret, " ").unwrap(); if is_paragraph { ret.push_str("

    "); } @@ -961,7 +959,7 @@ impl LangString { } { if let Some(extra) = extra { extra.error_invalid_codeblock_attr( - format!("unknown attribute `{}`. Did you mean `{}`?", x, flag), + format!("unknown attribute `{x}`. Did you mean `{flag}`?"), help, ); } @@ -1040,7 +1038,7 @@ impl MarkdownWithToc<'_> { html::push_html(&mut s, p); } - format!("{}", toc.into_toc().print(), s) + format!("{s}", toc = toc.into_toc().print()) } } @@ -1242,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin pub(crate) struct MarkdownLink { pub kind: LinkType, pub link: String, + pub display_text: Option, pub range: MarkdownLinkRange, } @@ -1265,8 +1264,8 @@ impl MarkdownLinkRange { } } -pub(crate) fn markdown_links( - md: &str, +pub(crate) fn markdown_links<'md, R>( + md: &'md str, preprocess_link: impl Fn(MarkdownLink) -> Option, ) -> Vec { if md.is_empty() { @@ -1377,32 +1376,90 @@ pub(crate) fn markdown_links( MarkdownLinkRange::Destination(range.clone()) }; - Parser::new_with_broken_link_callback( + let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); + let mut event_iter = Parser::new_with_broken_link_callback( md, main_body_opts(), - Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))), + Some(&mut broken_link_callback), ) - .into_offset_iter() - .filter_map(|(event, span)| match event { - Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => { - 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) + .into_offset_iter(); + let mut links = Vec::new(); + + while let Some((event, span)) = event_iter.next() { + match event { + Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => { + 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!(), + }; + + let display_text = if matches!( + link_type, + LinkType::Inline + | LinkType::ReferenceUnknown + | LinkType::Reference + | LinkType::Shortcut + | LinkType::ShortcutUnknown + ) { + collect_link_data(&mut event_iter) + } else { + None + }; + + if let Some(link) = preprocess_link(MarkdownLink { + kind: link_type, + link: dest.into_string(), + display_text, + range, + }) { + links.push(link); } - LinkType::Autolink | LinkType::Email => unreachable!(), - }; - preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() }) + } + _ => {} } - _ => None, - }) - .collect() + } + + links +} + +/// Collects additional data of link. +fn collect_link_data<'input, 'callback>( + event_iter: &mut OffsetIter<'input, 'callback>, +) -> Option { + let mut display_text: Option = None; + let mut append_text = |text: CowStr<'_>| { + if let Some(display_text) = &mut display_text { + display_text.push_str(&text); + } else { + display_text = Some(text.to_string()); + } + }; + + while let Some((event, _span)) = event_iter.next() { + match event { + Event::Text(text) => { + append_text(text); + } + Event::Code(code) => { + append_text(code); + } + Event::End(_) => { + break; + } + _ => {} + } + } + + display_text } #[derive(Debug)] diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index e05635a02..db8504d15 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -38,7 +38,7 @@ fn test_unique_id() { ]; let mut map = IdMap::new(); - let actual: Vec = input.iter().map(|s| map.derive(s.to_string())).collect(); + let actual: Vec = input.iter().map(|s| map.derive(s)).collect(); assert_eq!(&actual[..], expected); } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 4c4762636..d7ff248a9 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -162,7 +162,7 @@ impl<'tcx> Context<'tcx> { self.shared.tcx.sess } - pub(super) fn derive_id(&mut self, id: String) -> String { + pub(super) fn derive_id + ToString>(&mut self, id: S) -> String { self.id_map.derive(id) } @@ -206,15 +206,14 @@ impl<'tcx> Context<'tcx> { format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate) } else { format!( - "API documentation for the Rust `{}` {} in crate `{}`.", - it.name.as_ref().unwrap(), - tyname, - self.shared.layout.krate + "API documentation for the Rust `{name}` {tyname} in crate `{krate}`.", + name = it.name.as_ref().unwrap(), + krate = self.shared.layout.krate, ) }; let name; let tyname_s = if it.is_crate() { - name = format!("{} crate", tyname); + name = format!("{tyname} crate"); name.as_str() } else { tyname.as_str() @@ -264,7 +263,12 @@ impl<'tcx> Context<'tcx> { current_path.push_str(&item_path(ty, names.last().unwrap().as_str())); redirections.borrow_mut().insert(current_path, path); } - None => return layout::redirect(&format!("{}{}", self.root_path(), path)), + None => { + return layout::redirect(&format!( + "{root}{path}", + root = self.root_path() + )); + } } } } @@ -382,11 +386,7 @@ impl<'tcx> Context<'tcx> { let hiline = span.hi(self.sess()).line; format!( "#{}", - if loline == hiline { - loline.to_string() - } else { - format!("{}-{}", loline, hiline) - } + if loline == hiline { loline.to_string() } else { format!("{loline}-{hiline}") } ) } else { "".to_string() @@ -798,15 +798,18 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { if let Some(def_id) = item.def_id() && self.cache().inlined_items.contains(&def_id) { self.is_inside_inlined_module = true; } - } else if item.is_doc_hidden() { + } else if !self.cache().document_hidden && item.is_doc_hidden() { // We're not inside an inlined module anymore since this one cannot be re-exported. self.is_inside_inlined_module = false; } // Render sidebar-items.js used throughout this module. if !self.render_redirect_pages { - let (clean::StrippedItem(box clean::ModuleItem(ref module)) | clean::ModuleItem(ref module)) = *item.kind - else { unreachable!() }; + let (clean::StrippedItem(box clean::ModuleItem(ref module)) + | clean::ModuleItem(ref module)) = *item.kind + else { + unreachable!() + }; let items = self.build_sidebar_items(module); let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix)); let v = format!("window.SIDEBAR_ITEMS = {};", serde_json::to_string(&items).unwrap()); @@ -852,12 +855,12 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // If the item is a macro, redirect from the old macro URL (with !) // to the new one (without). if item_type == ItemType::Macro { - let redir_name = format!("{}.{}!.html", item_type, name); + let redir_name = format!("{item_type}.{name}!.html"); if let Some(ref redirections) = self.shared.redirections { let crate_name = &self.shared.layout.krate; redirections.borrow_mut().insert( - format!("{}/{}", crate_name, redir_name), - format!("{}/{}", crate_name, file_name), + format!("{crate_name}/{redir_name}"), + format!("{crate_name}/{file_name}"), ); } else { let v = layout::redirect(file_name); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f923f9054..ac9c180a6 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -85,7 +85,7 @@ use crate::DOC_RUST_LANG_ORG_CHANNEL; pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ { crate::html::format::display_fn(move |f| { - if !v.ends_with('/') && !v.is_empty() { write!(f, "{}/", v) } else { f.write_str(v) } + if !v.ends_with('/') && !v.is_empty() { write!(f, "{v}/") } else { f.write_str(v) } }) } @@ -268,7 +268,7 @@ impl AllTypes { fn append(&mut self, item_name: String, item_type: &ItemType) { let mut url: Vec<_> = item_name.split("::").skip(1).collect(); if let Some(name) = url.pop() { - let new_url = format!("{}/{}.{}.html", url.join("/"), item_type, name); + let new_url = format!("{}/{item_type}.{name}.html", url.join("/")); url.push(name); let name = url.join("::"); match *item_type { @@ -385,16 +385,17 @@ impl AllTypes { fn scrape_examples_help(shared: &SharedContext<'_>) -> String { let mut content = SCRAPE_EXAMPLES_HELP_MD.to_owned(); content.push_str(&format!( - "## More information\n\n\ - If you want more information about this feature, please read the [corresponding chapter in the Rustdoc book]({}/rustdoc/scraped-examples.html).", - DOC_RUST_LANG_ORG_CHANNEL)); + "## More information\n\n\ + If you want more information about this feature, please read the [corresponding chapter in \ + the Rustdoc book]({DOC_RUST_LANG_ORG_CHANNEL}/rustdoc/scraped-examples.html)." + )); let mut ids = IdMap::default(); format!( "
    \ -

    About scraped examples

    \ -
    \ -
    {}
    ", +

    About scraped examples

    \ +
\ +
{}
", Markdown { content: &content, links: &[], @@ -415,7 +416,7 @@ fn document<'a, 'cx: 'a>( heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { if let Some(ref name) = item.name { - info!("Documenting {}", name); + info!("Documenting {name}"); } display_fn(move |f| { @@ -473,7 +474,7 @@ fn document_short<'a, 'cx: 'a>( MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content(); if has_more_content { - let link = format!(r#" Read more"#, assoc_href_attr(item, link, cx)); + let link = format!(" Read more", assoc_href_attr(item, link, cx)); if let Some(idx) = summary_html.rfind("

") { summary_html.insert_str(idx, &link); @@ -482,7 +483,7 @@ fn document_short<'a, 'cx: 'a>( } } - write!(f, "
{}
", summary_html)?; + write!(f, "
{summary_html}
")?; } Ok(()) }) @@ -512,14 +513,14 @@ fn document_full_inner<'a, 'cx: 'a>( ) -> impl fmt::Display + 'a + Captures<'cx> { display_fn(move |f| { if let Some(s) = item.opt_doc_value() { - debug!("Doc block: =====\n{}\n=====", s); + debug!("Doc block: =====\n{s}\n====="); if is_collapsible { write!( f, "
\ - \ + \ Expand description\ - {}
", + {}", render_markdown(cx, &s, item.links(cx), heading_offset) )?; } else { @@ -564,12 +565,10 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option, cx: &Context<'_>) let item_type = it.type_(); let href = match link { - AssocItemLink::Anchor(Some(ref id)) => Some(format!("#{}", id)), - AssocItemLink::Anchor(None) => Some(format!("#{}.{}", item_type, name)), + AssocItemLink::Anchor(Some(ref id)) => Some(format!("#{id}")), + AssocItemLink::Anchor(None) => Some(format!("#{item_type}.{name}")), AssocItemLink::GotoSource(did, provided_methods) => { // We're creating a link from the implementation of an associated item to its // declaration in the trait declaration. @@ -722,7 +721,7 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>) }; match href(did.expect_def_id(), cx) { - Ok((url, ..)) => Some(format!("{}#{}.{}", url, item_type, name)), + Ok((url, ..)) => Some(format!("{url}#{item_type}.{name}")), // The link is broken since it points to an external crate that wasn't documented. // Do not create any link in such case. This is better than falling back to a // dummy anchor like `#{item_type}.{name}` representing the `id` of *this* impl item @@ -735,37 +734,39 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>) // In this scenario, the actual `id` of this impl item would be // `#{item_type}.{name}-{n}` for some number `n` (a disambiguator). Err(HrefError::DocumentationNotBuilt) => None, - Err(_) => Some(format!("#{}.{}", item_type, name)), + Err(_) => Some(format!("#{item_type}.{name}")), } } }; // If there is no `href` for the reason explained above, simply do not render it which is valid: // https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements - href.map(|href| format!(" href=\"{}\"", href)).unwrap_or_default() + href.map(|href| format!(" href=\"{href}\"")).unwrap_or_default() } fn assoc_const( w: &mut Buffer, it: &clean::Item, + generics: &clean::Generics, ty: &clean::Type, default: Option<&clean::ConstantKind>, link: AssocItemLink<'_>, - extra: &str, + indent: usize, cx: &Context<'_>, ) { let tcx = cx.tcx(); write!( w, - "{extra}{vis}const {name}: {ty}", - extra = extra, + "{indent}{vis}const {name}{generics}: {ty}", + indent = " ".repeat(indent), vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), href = assoc_href_attr(it, link, cx), name = it.name.as_ref().unwrap(), + generics = generics.print(cx), ty = ty.print(cx), ); if let Some(default) = default { - write!(w, " = "); + w.write_str(" = "); // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the // hood which adds noisy underscores and a type suffix to number literals. @@ -774,6 +775,7 @@ fn assoc_const( // Find a way to print constants here without all that jazz. write!(w, "{}", Escape(&default.value(tcx).unwrap_or_else(|| default.expr(tcx)))); } + write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); } fn assoc_type( @@ -820,6 +822,7 @@ fn assoc_method( let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item"); let name = meth.name.as_ref().unwrap(); let vis = visibility_print_with_space(meth.visibility(tcx), meth.item_id, cx).to_string(); + let defaultness = print_default_space(meth.is_default()); // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove // this condition. let constness = match render_mode { @@ -830,7 +833,6 @@ fn assoc_method( }; let asyncness = header.asyncness.print_with_space(); let unsafety = header.unsafety.print_with_space(); - let defaultness = print_default_space(meth.is_default()); let abi = print_abi_with_space(header.abi).to_string(); let href = assoc_href_attr(meth, link, cx); @@ -838,10 +840,10 @@ fn assoc_method( let generics_len = format!("{:#}", g.print(cx)).len(); let mut header_len = "fn ".len() + vis.len() + + defaultness.len() + constness.len() + asyncness.len() + unsafety.len() - + defaultness.len() + abi.len() + name.as_str().len() + generics_len; @@ -860,14 +862,14 @@ fn assoc_method( w.reserve(header_len + "{".len() + "".len()); write!( w, - "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn \ + "{indent}{vis}{defaultness}{constness}{asyncness}{unsafety}{abi}fn \ {name}{generics}{decl}{notable_traits}{where_clause}", indent = indent_str, vis = vis, + defaultness = defaultness, constness = constness, asyncness = asyncness, unsafety = unsafety, - defaultness = defaultness, abi = abi, href = href, name = name, @@ -907,39 +909,41 @@ fn render_stability_since_raw_with_extra( if let Some(ver) = stable_version { stability.push_str(ver.as_str()); - title.push_str(&format!("Stable since Rust version {}", ver)); + title.push_str(&format!("Stable since Rust version {ver}")); } let const_title_and_stability = match const_stability { Some(ConstStability { level: StabilityLevel::Stable { since, .. }, .. }) if Some(since) != containing_const_ver => { - Some((format!("const since {}", since), format!("const: {}", since))) + Some((format!("const since {since}"), format!("const: {since}"))) } Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }) => { let unstable = if let Some(n) = issue { format!( - r#"unstable"#, - n, feature + "unstable" ) } else { String::from("unstable") }; - Some((String::from("const unstable"), format!("const: {}", unstable))) + Some((String::from("const unstable"), format!("const: {unstable}"))) } _ => None, }; if let Some((const_title, const_stability)) = const_title_and_stability { if !title.is_empty() { - title.push_str(&format!(", {}", const_title)); + title.push_str(&format!(", {const_title}")); } else { title.push_str(&const_title); } if !stability.is_empty() { - stability.push_str(&format!(" ({})", const_stability)); + stability.push_str(&format!(" ({const_stability})")); } else { stability.push_str(&const_stability); } @@ -986,19 +990,22 @@ fn render_assoc_item( clean::MethodItem(m, _) => { assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode) } - kind @ (clean::TyAssocConstItem(ty) | clean::AssocConstItem(ty, _)) => assoc_const( - w, - item, - ty, - match kind { - clean::TyAssocConstItem(_) => None, - clean::AssocConstItem(_, default) => Some(default), - _ => unreachable!(), - }, - link, - if parent == ItemType::Trait { " " } else { "" }, - cx, - ), + kind @ (clean::TyAssocConstItem(generics, ty) | clean::AssocConstItem(generics, ty, _)) => { + assoc_const( + w, + item, + generics, + ty, + match kind { + clean::TyAssocConstItem(..) => None, + clean::AssocConstItem(.., default) => Some(default), + _ => unreachable!(), + }, + link, + if parent == ItemType::Trait { 4 } else { 0 }, + cx, + ) + } clean::TyAssocTypeItem(ref generics, ref bounds) => assoc_type( w, item, @@ -1032,7 +1039,7 @@ fn render_attributes_in_pre<'a, 'b: 'a>( ) -> impl fmt::Display + Captures<'a> + Captures<'b> { crate::html::format::display_fn(move |f| { for a in it.attributes(tcx, false) { - writeln!(f, "{}{}", prefix, a)?; + writeln!(f, "{prefix}{a}")?; } Ok(()) }) @@ -1085,7 +1092,7 @@ pub(crate) fn render_all_impls( let impls = impls.into_inner(); if !impls.is_empty() { write_impl_section_heading(&mut w, "Trait Implementations", "trait-implementations"); - write!(w, "
{}
", impls).unwrap(); + write!(w, "
{impls}
").unwrap(); } if !synthetic.is_empty() { @@ -1144,9 +1151,7 @@ fn render_assoc_items_inner( AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { let id = cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx)))); - if let Some(def_id) = type_.def_id(cx.cache()) { - cx.deref_id_map.insert(def_id, id.clone()); - } + let derived_id = cx.derive_id(&id); write_impl_section_heading( &mut tmp_buf, &format!( @@ -1156,11 +1161,10 @@ fn render_assoc_items_inner( ), &id, ); - ( - RenderMode::ForDeref { mut_: deref_mut_ }, - cx.derive_id(id), - r#" class="impl-items""#, - ) + if let Some(def_id) = type_.def_id(cx.cache()) { + cx.deref_id_map.insert(def_id, id); + } + (RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#) } }; let mut impls_buf = Buffer::html(); @@ -1183,10 +1187,13 @@ fn render_assoc_items_inner( ); } if !impls_buf.is_empty() { - write!(w, "{}", tmp_buf.into_inner()).unwrap(); - write!(w, "
").unwrap(); - write!(w, "{}", impls_buf.into_inner()).unwrap(); - w.write_str("
").unwrap(); + write!( + w, + "{}
{}
", + tmp_buf.into_inner(), + impls_buf.into_inner() + ) + .unwrap(); } } @@ -1236,7 +1243,10 @@ fn render_deref_methods( _ => None, }) .expect("Expected associated type binding"); - debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target); + debug!( + "Render deref methods for {for_:#?}, target {target:#?}", + for_ = impl_.inner_impl().for_ + ); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut }; if let Some(did) = target.def_id(cache) { @@ -1386,7 +1396,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { } } if out.is_empty() { - write!(&mut out, "",); + out.write_str(""); } (format!("{:#}", ty.print(cx)), out.into_inner()) @@ -1532,25 +1542,25 @@ fn render_impl( let toggled = !doc_buffer.is_empty(); if toggled { let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; - write!(w, "
", method_toggle_class); + write!(w, "
"); } match &*item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => { // Only render when the method is not static or we allow static methods if render_method_item { - let id = cx.derive_id(format!("{}.{}", item_type, name)); + let id = cx.derive_id(format!("{item_type}.{name}")); let source_id = trait_ .and_then(|trait_| { trait_.items.iter().find(|item| { item.name.map(|n| n.as_str().eq(name.as_str())).unwrap_or(false) }) }) - .map(|item| format!("{}.{}", item.type_(), name)); - write!(w, "
", id, item_type, in_trait_class,); + .map(|item| format!("{}.{name}", item.type_())); + write!(w, "
"); render_rightside(w, cx, item, containing_item, render_mode); if trait_.is_some() { // Anchors are only used on trait impls. - write!(w, "§", id); + write!(w, "§"); } w.write_str("

"); render_assoc_item( @@ -1561,43 +1571,43 @@ fn render_impl( cx, render_mode, ); - w.write_str("

"); - w.write_str("
"); + w.write_str("
"); } } - kind @ (clean::TyAssocConstItem(ty) | clean::AssocConstItem(ty, _)) => { - let source_id = format!("{}.{}", item_type, name); - let id = cx.derive_id(source_id.clone()); - write!(w, "
", id, item_type, in_trait_class); + kind @ (clean::TyAssocConstItem(generics, ty) + | clean::AssocConstItem(generics, ty, _)) => { + let source_id = format!("{item_type}.{name}"); + let id = cx.derive_id(&source_id); + write!(w, "
"); render_rightside(w, cx, item, containing_item, render_mode); if trait_.is_some() { // Anchors are only used on trait impls. - write!(w, "§", id); + write!(w, "§"); } w.write_str("

"); assoc_const( w, item, + generics, ty, match kind { - clean::TyAssocConstItem(_) => None, - clean::AssocConstItem(_, default) => Some(default), + clean::TyAssocConstItem(..) => None, + clean::AssocConstItem(.., default) => Some(default), _ => unreachable!(), }, link.anchor(if trait_.is_some() { &source_id } else { &id }), - "", + 0, cx, ); - w.write_str("

"); - w.write_str("
"); + w.write_str("
"); } clean::TyAssocTypeItem(generics, bounds) => { - let source_id = format!("{}.{}", item_type, name); - let id = cx.derive_id(source_id.clone()); - write!(w, "
", id, item_type, in_trait_class); + let source_id = format!("{item_type}.{name}"); + let id = cx.derive_id(&source_id); + write!(w, "
"); if trait_.is_some() { // Anchors are only used on trait impls. - write!(w, "§", id); + write!(w, "§"); } w.write_str("

"); assoc_type( @@ -1610,16 +1620,15 @@ fn render_impl( 0, cx, ); - w.write_str("

"); - w.write_str("
"); + w.write_str("
"); } clean::AssocTypeItem(tydef, _bounds) => { - let source_id = format!("{}.{}", item_type, name); - let id = cx.derive_id(source_id.clone()); - write!(w, "
", id, item_type, in_trait_class); + let source_id = format!("{item_type}.{name}"); + let id = cx.derive_id(&source_id); + write!(w, "
"); if trait_.is_some() { // Anchors are only used on trait impls. - write!(w, "§", id); + write!(w, "§"); } w.write_str("

"); assoc_type( @@ -1632,8 +1641,7 @@ fn render_impl( 0, cx, ); - w.write_str("

"); - w.write_str("
"); + w.write_str("
"); } clean::StrippedItem(..) => return, _ => panic!("can't make docs for trait item with name {:?}", item.name), @@ -1678,11 +1686,11 @@ fn render_impl( rendering_params: ImplRenderingParameters, ) { for trait_item in &t.items { - // Skip over any default trait items that are impossible to call + // Skip over any default trait items that are impossible to reference // (e.g. if it has a `Self: Sized` bound on an unsized type). if let Some(impl_def_id) = parent.item_id.as_def_id() && let Some(trait_item_def_id) = trait_item.item_id.as_def_id() - && cx.tcx().is_impossible_method((impl_def_id, trait_item_def_id)) + && cx.tcx().is_impossible_associated_item((impl_def_id, trait_item_def_id)) { continue; } @@ -1736,10 +1744,10 @@ fn render_impl( close_tags.insert_str(0, "
"); write!( w, - "
", + "
\ + ", if rendering_params.toggle_open_by_default { " open" } else { "" } ); - write!(w, "") } render_impl_summary( w, @@ -1752,15 +1760,15 @@ fn render_impl( aliases, ); if toggled { - write!(w, "") + w.write_str(""); } if let Some(ref dox) = i.impl_item.opt_doc_value() { if trait_.is_none() && i.inner_impl().items.is_empty() { w.write_str( "
\ -
This impl block contains no items.
\ -
", +
This impl block contains no items.
\ + ", ); } write!( @@ -1819,11 +1827,11 @@ fn render_rightside( const_stable_since, if has_src_ref { "" } else { " rightside" }, ); - if let Some(l) = src_href { + if let Some(link) = src_href { if has_stability { - write!(rightside, " · source", l) + write!(rightside, " · source") } else { - write!(rightside, "source", l) + write!(rightside, "source") } } if has_stability && has_src_ref { @@ -1852,10 +1860,13 @@ pub(crate) fn render_impl_summary( } else { format!(" data-aliases=\"{}\"", aliases.join(",")) }; - write!(w, "
", id, aliases); + write!(w, "
"); render_rightside(w, cx, &i.impl_item, containing_item, RenderMode::Normal); - write!(w, "§", id); - write!(w, "

"); + write!( + w, + "§\ +

" + ); if let Some(use_absolute) = use_absolute { write!(w, "{}", inner_impl.print(use_absolute, cx)); @@ -1880,15 +1891,16 @@ pub(crate) fn render_impl_summary( } else { write!(w, "{}", inner_impl.print(false, cx)); } - write!(w, "

"); + w.write_str(""); let is_trait = inner_impl.trait_.is_some(); if is_trait { if let Some(portability) = portability(&i.impl_item, Some(parent)) { write!( w, - "
{}
", - portability + "\ +
{portability}
\ +
", ); } } @@ -1941,7 +1953,7 @@ pub(crate) fn small_url_encode(s: String) -> String { // consistent with itself when encoding them. st += "+"; } else { - write!(st, "%{:02X}", b).unwrap(); + write!(st, "%{b:02X}").unwrap(); } // Invariant: if the current byte is not at the start of a multi-byte character, // we need to get down here so that when the next turn of the loop comes around, @@ -1988,7 +2000,9 @@ pub(crate) fn get_filtered_impls_for_reference<'a>( ) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) { let def_id = it.item_id.expect_def_id(); // If the reference primitive is somehow not defined, exit early. - let Some(v) = shared.cache.impls.get(&def_id) else { return (Vec::new(), Vec::new(), Vec::new()) }; + let Some(v) = shared.cache.impls.get(&def_id) else { + return (Vec::new(), Vec::new(), Vec::new()); + }; // Since there is no "direct implementation" on the reference primitive type, we filter out // every implementation which isn't a trait implementation. let traits = v.iter().filter(|i| i.inner_impl().trait_.is_some()); @@ -2254,7 +2268,7 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c format!("lines {}-{}", line_lo + 1, line_hi + 1), ) }; - let url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor); + let url = format!("{}{}#{anchor}", cx.root_path(), call_data.url); (url, title) }; @@ -2264,7 +2278,7 @@ fn render_call_locations(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 {}: {err}", path.display())); return false; } }; @@ -2323,7 +2337,7 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c .unwrap(); if line_ranges.len() > 1 { - write!(w, r#" "#) + w.write_str(r#" "#) .unwrap(); } @@ -2359,7 +2373,7 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c highlight::DecorationInfo(decoration_info), sources::SourceContext::Embedded { offset: line_min, needs_expansion }, ); - write!(w, "").unwrap(); + w.write_str("").unwrap(); true }; @@ -2426,8 +2440,10 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c // For the remaining examples, generate a
    containing links to the source files. if it.peek().is_some() { - write!(w, r#"").unwrap(); } - write!(w, "
").unwrap(); + w.write_str("
").unwrap(); } - write!(w, "").unwrap(); + w.write_str("").unwrap(); } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 383e3c170..6cab34986 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -310,9 +310,8 @@ fn toggle_open(mut w: impl fmt::Write, text: impl fmt::Display) { w, "
\ \ - Show {}\ + Show {text}\ ", - text ) .unwrap(); } @@ -412,7 +411,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: ) }); - debug!("{:?}", indices); + debug!("{indices:?}"); let mut last_section = None; for &idx in &indices { @@ -431,9 +430,8 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: w, "

\ {name}\ -

{}", - ITEM_TABLE_OPEN, - id = cx.derive_id(my_section.id().to_owned()), + {ITEM_TABLE_OPEN}", + id = cx.derive_id(my_section.id()), name = my_section.name(), ); } @@ -485,7 +483,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: w.write_str(ITEM_TABLE_ROW_OPEN); let id = match import.kind { clean::ImportKind::Simple(s) => { - format!(" id=\"{}\"", cx.derive_id(format!("reexport.{}", s))) + format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}"))) } clean::ImportKind::Glob => String::new(), }; @@ -583,10 +581,8 @@ fn extra_info_tags<'a, 'tcx: 'a>( display_fn(move |f| { write!( f, - r#"{}"#, - class, - Escape(title), - contents + r#"{contents}"#, + title = Escape(title), ) }) } @@ -614,7 +610,12 @@ fn extra_info_tags<'a, 'tcx: 'a>( (cfg, _) => cfg.as_deref().cloned(), }; - debug!("Portability name={:?} {:?} - {:?} = {:?}", item.name, item.cfg, parent.cfg, cfg); + debug!( + "Portability name={name:?} {cfg:?} - {parent_cfg:?} = {cfg:?}", + name = item.name, + cfg = item.cfg, + parent_cfg = parent.cfg + ); if let Some(ref cfg) = cfg { write!( f, @@ -689,14 +690,13 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: wrap_item(w, |mut w| { write!( w, - "{attrs}{}{}{}trait {}{}{}", - visibility_print_with_space(it.visibility(tcx), it.item_id, cx), - t.unsafety(tcx).print_with_space(), - if t.is_auto(tcx) { "auto " } else { "" }, - it.name.unwrap(), - t.generics.print(cx), - bounds, + "{attrs}{vis}{unsafety}{is_auto}trait {name}{generics}{bounds}", attrs = render_attributes_in_pre(it, "", tcx), + vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + unsafety = t.unsafety(tcx).print_with_space(), + is_auto = if t.is_auto(tcx) { "auto " } else { "" }, + name = it.name.unwrap(), + generics = t.generics.print(cx), ); if !t.generics.where_predicates.is_empty() { @@ -742,11 +742,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: toggle_open( &mut w, format_args!( - "{} associated constant{} and {} method{}", - count_consts, - pluralize(count_consts), - count_methods, - pluralize(count_methods), + "{count_consts} associated constant{plural_const} and \ + {count_methods} method{plural_method}", + plural_const = pluralize(count_consts), + plural_method = pluralize(count_methods), ), ); } @@ -768,7 +767,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !toggle && should_hide_fields(count_methods) { toggle = true; - toggle_open(&mut w, format_args!("{} methods", count_methods)); + toggle_open(&mut w, format_args!("{count_methods} methods")); } if count_consts != 0 && count_methods != 0 { w.write_str("\n"); @@ -837,9 +836,9 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) { let name = m.name.unwrap(); - info!("Documenting {} on {:?}", name, t.name); + info!("Documenting {name} on {ty_name:?}", ty_name = t.name); let item_type = m.type_(); - let id = cx.derive_id(format!("{}.{}", item_type, name)); + let id = cx.derive_id(format!("{item_type}.{name}")); let mut content = Buffer::empty_from(w); write!(&mut content, "{}", document(cx, m, Some(t), HeadingOffset::H5)); let toggled = !content.is_empty(); @@ -847,7 +846,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; write!(w, "
"); } - write!(w, "
", id); + write!(w, "
"); render_rightside(w, cx, m, t, RenderMode::Normal); write!(w, "

"); render_assoc_item( @@ -1170,12 +1169,12 @@ fn item_trait_alias( wrap_item(w, |w| { write!( w, - "{attrs}trait {}{}{} = {};", - it.name.unwrap(), - t.generics.print(cx), - print_where_clause(&t.generics, cx, 0, Ending::Newline), - bounds(&t.bounds, true, cx), + "{attrs}trait {name}{generics}{where_b} = {bounds};", attrs = render_attributes_in_pre(it, "", cx.tcx()), + name = it.name.unwrap(), + generics = t.generics.print(cx), + where_b = print_where_clause(&t.generics, cx, 0, Ending::Newline), + bounds = bounds(&t.bounds, true, cx), ) .unwrap(); }); @@ -1198,12 +1197,12 @@ fn item_opaque_ty( wrap_item(w, |w| { write!( w, - "{attrs}type {}{}{where_clause} = impl {bounds};", - it.name.unwrap(), - t.generics.print(cx), + "{attrs}type {name}{generics}{where_clause} = impl {bounds};", + attrs = render_attributes_in_pre(it, "", cx.tcx()), + name = it.name.unwrap(), + generics = 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, "", cx.tcx()), ) .unwrap(); }); @@ -1223,13 +1222,13 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea wrap_item(w, |w| { write!( w, - "{attrs}{}type {}{}{where_clause} = {type_};", - visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), - it.name.unwrap(), - t.generics.print(cx), + "{attrs}{vis}type {name}{generics}{where_clause} = {type_};", + attrs = render_attributes_in_pre(it, "", cx.tcx()), + vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), + name = it.name.unwrap(), + generics = 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, "", cx.tcx()), ); }); } @@ -1354,7 +1353,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str("{\n"); let toggle = should_hide_fields(count_variants); if toggle { - toggle_open(&mut w, format_args!("{} variants", count_variants)); + toggle_open(&mut w, format_args!("{count_variants} variants")); } for v in e.variants() { w.write_str(" "); @@ -1362,7 +1361,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: match *v.kind { // FIXME(#101337): Show discriminant clean::VariantItem(ref var) => match var.kind { - clean::VariantKind::CLike => write!(w, "{}", name), + clean::VariantKind::CLike => w.write_str(name.as_str()), clean::VariantKind::Tuple(ref s) => { write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); } @@ -1418,7 +1417,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; if let clean::VariantKind::Tuple(ref s) = variant_data.kind { - write!(w, "({})", print_tuple_struct_fields(cx, s),); + write!(w, "({})", print_tuple_struct_fields(cx, s)); } w.write_str("

"); @@ -1543,10 +1542,12 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle write!( w, - "{vis}const {name}: {typ}", + "{vis}const {name}{generics}: {typ}{where_clause}", vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), name = it.name.unwrap(), + generics = c.generics.print(cx), typ = c.type_.print(cx), + where_clause = print_where_clause(&c.generics, cx, 0, Ending::NoNewline), ); // FIXME: The code below now prints @@ -1615,7 +1616,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean for (index, (field, ty)) in fields.enumerate() { let field_name = field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); - let id = cx.derive_id(format!("{}.{}", ItemType::StructField, field_name)); + let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField)); write!( w, "\ @@ -1720,7 +1721,7 @@ pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String { pub(super) fn item_path(ty: ItemType, name: &str) -> String { match ty { ItemType::Module => format!("{}index.html", ensure_trailing_slash(name)), - _ => format!("{}.{}.html", ty, name), + _ => format!("{ty}.{name}.html"), } } @@ -1843,7 +1844,7 @@ fn render_union<'a, 'cx: 'a>( fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); if toggle { - toggle_open(&mut f, format_args!("{} fields", count_fields)); + toggle_open(&mut f, format_args!("{count_fields} fields")); } for field in fields { @@ -1906,26 +1907,25 @@ fn render_struct( let has_visible_fields = count_fields > 0; let toggle = should_hide_fields(count_fields); if toggle { - toggle_open(&mut w, format_args!("{} fields", count_fields)); + toggle_open(&mut w, format_args!("{count_fields} fields")); } for field in fields { if let clean::StructFieldItem(ref ty) = *field.kind { write!( w, - "\n{} {}{}: {},", - tab, - visibility_print_with_space(field.visibility(tcx), field.item_id, cx), - field.name.unwrap(), - ty.print(cx), + "\n{tab} {vis}{name}: {ty},", + vis = visibility_print_with_space(field.visibility(tcx), field.item_id, cx), + name = field.name.unwrap(), + ty = ty.print(cx), ); } } if has_visible_fields { if it.has_stripped_entries().unwrap() { - write!(w, "\n{} /* private fields */", tab); + write!(w, "\n{tab} /* private fields */"); } - write!(w, "\n{}", tab); + write!(w, "\n{tab}"); } else if it.has_stripped_entries().unwrap() { write!(w, " /* private fields */ "); } diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 455b4e9ae..f3da61056 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -330,7 +330,7 @@ fn sidebar_deref_methods<'a>( ) { let c = cx.cache(); - debug!("found Deref: {:?}", impl_); + debug!("found Deref: {impl_:?}"); if let Some((target, real_target)) = impl_.inner_impl().items.iter().find_map(|item| match *item.kind { clean::AssocTypeItem(box ref t, _) => Some(match *t { @@ -340,7 +340,7 @@ fn sidebar_deref_methods<'a>( _ => None, }) { - debug!("found target, real_target: {:?} {:?}", target, real_target); + debug!("found target, real_target: {target:?} {real_target:?}"); if let Some(did) = target.def_id(c) && let Some(type_did) = impl_.inner_impl().for_.def_id(c) && // `impl Deref for S` @@ -357,7 +357,7 @@ fn sidebar_deref_methods<'a>( }) .and_then(|did| c.impls.get(&did)); if let Some(impls) = inner_impl { - debug!("found inner_impl: {:?}", impls); + debug!("found inner_impl: {impls:?}"); let mut ret = impls .iter() .filter(|i| i.inner_impl().trait_.is_none()) @@ -510,10 +510,10 @@ fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { return url; } let mut add = 1; - while !used_links.insert(format!("{}-{}", url, add)) { + while !used_links.insert(format!("{url}-{add}")) { add += 1; } - format!("{}-{}", url, add) + format!("{url}-{add}") } fn get_methods<'a>( @@ -529,7 +529,7 @@ fn get_methods<'a>( Some(ref name) if !name.is_empty() && item.is_method() => { if !for_deref || super::should_render_item(item, deref_mut, tcx) { Some(Link::new( - get_next_url(used_links, format!("{}.{}", ItemType::Method, name)), + get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::Method)), name.as_str(), )) } else { @@ -549,7 +549,7 @@ fn get_associated_constants<'a>( .iter() .filter_map(|item| match item.name { Some(ref name) if !name.is_empty() && item.is_associated_const() => Some(Link::new( - get_next_url(used_links, format!("{}.{}", ItemType::AssocConst, name)), + get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)), name.as_str(), )), _ => None, diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index eb9262f47..5f130f187 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -1,11 +1,11 @@ -use crate::clean::{self, PrimitiveType}; +use crate::clean::{self, rustc_span, PrimitiveType}; use crate::html::sources; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{ExprKind, HirId, Mod, Node}; +use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::hygiene::MacroKind; @@ -25,6 +25,7 @@ pub(crate) enum LinkFromSrc { Local(clean::Span), External(DefId), Primitive(PrimitiveType), + Doc(DefId), } /// This function will do at most two things: @@ -65,24 +66,43 @@ struct SpanMapVisitor<'tcx> { impl<'tcx> SpanMapVisitor<'tcx> { /// This function is where we handle `hir::Path` elements and add them into the "span map". fn handle_path(&mut self, path: &rustc_hir::Path<'_>) { - let info = match path.res { + match path.res { // FIXME: For now, we handle `DefKind` if it's not a `DefKind::TyParam`. // Would be nice to support them too alongside the other `DefKind` // (such as primitive types!). - Res::Def(kind, def_id) if kind != DefKind::TyParam => Some(def_id), - Res::Local(_) => None, + Res::Def(kind, def_id) if kind != DefKind::TyParam => { + let link = if def_id.as_local().is_some() { + LinkFromSrc::Local(rustc_span(def_id, self.tcx)) + } else { + LinkFromSrc::External(def_id) + }; + self.matches.insert(path.span, link); + } + Res::Local(_) => { + if let Some(span) = self.tcx.hir().res_span(path.res) { + self.matches.insert(path.span, LinkFromSrc::Local(clean::Span::new(span))); + } + } Res::PrimTy(p) => { // FIXME: Doesn't handle "path-like" primitives like arrays or tuples. self.matches.insert(path.span, LinkFromSrc::Primitive(PrimitiveType::from(p))); - return; } - Res::Err => return, - _ => return, - }; - if let Some(span) = self.tcx.hir().res_span(path.res) { - self.matches.insert(path.span, LinkFromSrc::Local(clean::Span::new(span))); - } else if let Some(def_id) = info { - self.matches.insert(path.span, LinkFromSrc::External(def_id)); + Res::Err => {} + _ => {} + } + } + + /// Used to generate links on items' definition to go to their documentation page. + pub(crate) fn extract_info_from_hir_id(&mut self, hir_id: HirId) { + if let Some(Node::Item(item)) = self.tcx.hir().find(hir_id) { + if let Some(span) = self.tcx.def_ident_span(item.owner_id) { + let cspan = clean::Span::new(span); + // If the span isn't from the current crate, we ignore it. + if cspan.inner().is_dummy() || cspan.cnum(self.tcx.sess) != LOCAL_CRATE { + return; + } + self.matches.insert(span, LinkFromSrc::Doc(item.owner_id.to_def_id())); + } } } @@ -117,10 +137,13 @@ impl<'tcx> SpanMapVisitor<'tcx> { _ => return true, }; let link_from_src = match data.macro_def_id { - Some(macro_def_id) if macro_def_id.is_local() => { - LinkFromSrc::Local(clean::Span::new(data.def_site)) + Some(macro_def_id) => { + if macro_def_id.is_local() { + LinkFromSrc::Local(clean::Span::new(data.def_site)) + } else { + LinkFromSrc::External(macro_def_id) + } } - Some(macro_def_id) => LinkFromSrc::External(macro_def_id), None => return true, }; let new_span = data.call_site; @@ -160,6 +183,9 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)), ); } + } else { + // If it's a "mod foo {}", we want to look to its documentation page. + self.extract_info_from_hir_id(id); } intravisit::walk_mod(self, m, id); } @@ -176,13 +202,12 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { .tcx .typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body")); if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) { - self.matches.insert( - segment.ident.span, - match hir.span_if_local(def_id) { - Some(span) => LinkFromSrc::Local(clean::Span::new(span)), - None => LinkFromSrc::External(def_id), - }, - ); + let link = if def_id.as_local().is_some() { + LinkFromSrc::Local(rustc_span(def_id, self.tcx)) + } else { + LinkFromSrc::External(def_id) + }; + self.matches.insert(segment.ident.span, link); } } else if self.handle_macro(expr.span) { // We don't want to go deeper into the macro. @@ -190,4 +215,28 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { } intravisit::walk_expr(self, expr); } + + fn visit_item(&mut self, item: &'tcx Item<'tcx>) { + match item.kind { + ItemKind::Static(_, _, _) + | ItemKind::Const(_, _, _) + | ItemKind::Fn(_, _, _) + | ItemKind::Macro(_, _) + | ItemKind::TyAlias(_, _) + | ItemKind::Enum(_, _) + | ItemKind::Struct(_, _) + | ItemKind::Union(_, _) + | ItemKind::Trait(_, _, _, _, _) + | ItemKind::TraitAlias(_, _) => self.extract_info_from_hir_id(item.hir_id()), + ItemKind::Impl(_) + | ItemKind::Use(_, _) + | ItemKind::ExternCrate(_) + | ItemKind::ForeignMod { .. } + | ItemKind::GlobalAsm(_) + | ItemKind::OpaqueTy(_) + // We already have "visit_mod" above so no need to check it here. + | ItemKind::Mod(_) => {} + } + intravisit::walk_item(self, item); + } } diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs index 0bc32ea5a..377daaeb9 100644 --- a/src/librustdoc/html/render/type_layout.rs +++ b/src/librustdoc/html/render/type_layout.rs @@ -39,7 +39,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( let tcx = cx.tcx(); let param_env = tcx.param_env(ty_def_id); - let ty = tcx.type_of(ty_def_id).subst_identity(); + let ty = tcx.type_of(ty_def_id).instantiate_identity(); let type_layout = tcx.layout_of(param_env.and(ty)); let variants = diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 54749e9a3..e824651e7 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -73,7 +73,7 @@ pub(super) fn write_shared( } let bytes = try_err!(fs::read(&entry.path), &entry.path); - let filename = format!("{}{}.{}", theme, cx.shared.resource_suffix, extension); + let filename = format!("{theme}{suffix}.{extension}", suffix = cx.shared.resource_suffix); cx.shared.fs.write(cx.dst.join(filename), bytes)?; } @@ -112,7 +112,7 @@ pub(super) fn write_shared( let mut krates = Vec::new(); if path.exists() { - let prefix = format!("\"{}\"", krate); + let prefix = format!("\"{krate}\""); for line in BufReader::new(File::open(path)?).lines() { let line = line?; if !line.starts_with('"') { @@ -157,7 +157,7 @@ pub(super) fn write_shared( let mut krates = Vec::new(); if path.exists() { - let prefix = format!("\"{}\"", krate); + let prefix = format!("\"{krate}\""); for line in BufReader::new(File::open(path)?).lines() { let line = line?; if !line.starts_with('"') { @@ -213,10 +213,10 @@ pub(super) fn write_shared( let dirs = if subs.is_empty() && files.is_empty() { String::new() } else { - format!(",[{}]", subs) + format!(",[{subs}]") }; let files = files.join(","); - let files = if files.is_empty() { String::new() } else { format!(",[{}]", files) }; + let files = if files.is_empty() { String::new() } else { format!(",[{files}]") }; format!( "[\"{name}\"{dirs}{files}]", name = self.elem.to_str().expect("invalid osstring conversion"), @@ -270,7 +270,7 @@ pub(super) fn write_shared( hierarchy.add_path(source); } let hierarchy = Rc::try_unwrap(hierarchy).unwrap(); - let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix)); + let dst = cx.dst.join(&format!("src-files{}.js", cx.shared.resource_suffix)); let make_sources = || { let (mut all_sources, _krates) = try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst); @@ -286,12 +286,12 @@ pub(super) fn write_shared( .replace("\\\"", "\\\\\"") )); all_sources.sort(); - let mut v = String::from("var sourcesIndex = JSON.parse('{\\\n"); + let mut v = String::from("var srcIndex = JSON.parse('{\\\n"); v.push_str(&all_sources.join(",\\\n")); - v.push_str("\\\n}');\ncreateSourceSidebar();\n"); + v.push_str("\\\n}');\ncreateSrcSidebar();\n"); Ok(v.into_bytes()) }; - write_invocation_specific("source-files.js", &make_sources)?; + write_invocation_specific("src-files.js", &make_sources)?; } // Update the search index and crate list. @@ -319,8 +319,8 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; })?; write_invocation_specific("crates.js", &|| { - let krates = krates.iter().map(|k| format!("\"{}\"", k)).join(","); - Ok(format!("window.ALL_CRATES = [{}];", krates).into_bytes()) + let krates = krates.iter().map(|k| format!("\"{k}\"")).join(","); + Ok(format!("window.ALL_CRATES = [{krates}];").into_bytes()) })?; if options.enable_index_page { @@ -349,9 +349,8 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; .iter() .map(|s| { format!( - "
  • {}
  • ", - ensure_trailing_slash(s), - s + "
  • {s}
  • ", + trailing_slash = ensure_trailing_slash(s), ) }) .collect::() @@ -444,7 +443,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; mydst.push(part.to_string()); } cx.shared.ensure_dir(&mydst)?; - mydst.push(&format!("{}.{}.js", remote_item_type, remote_path[remote_path.len() - 1])); + mydst.push(&format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); let (mut all_implementors, _) = try_err!(collect(&mydst, krate.name(cx.tcx()).as_str()), &mydst); diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index a26fa3749..c4a1ebbec 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -146,9 +146,8 @@ impl DocVisitor for SourceCollector<'_, '_> { self.cx.shared.tcx.sess.span_err( span, format!( - "failed to render source code for `{}`: {}", - filename.prefer_local(), - e, + "failed to render source code for `{filename}`: {e}", + filename = filename.prefer_local(), ), ); false @@ -227,7 +226,7 @@ impl SourceCollector<'_, '_> { let desc = format!("Source of the Rust file `{}`.", filename.prefer_remapped()); let page = layout::Page { title: &title, - css_class: "source", + css_class: "src", root_path: &root_path, static_root_path: shared.static_root_path.as_deref(), description: &desc, diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css index 54e8b6561..93aa11a58 100644 --- a/src/librustdoc/html/static/css/noscript.css +++ b/src/librustdoc/html/static/css/noscript.css @@ -19,7 +19,7 @@ nav.sub { display: none; } -.source .sidebar { +.src .sidebar { display: none; } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b7f455259..b1de8c152 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -194,7 +194,7 @@ h1, h2, h3, h4, h5, h6, .item-name > a, .out-of-band, span.since, -a.srclink, +a.src, #help-button > a, summary.hideme, .scraped-example-list, @@ -206,7 +206,7 @@ ul.all-items { #toggle-all-docs, a.anchor, .small-section-header a, -#source-sidebar a, +#src-sidebar a, .rust a, .sidebar h2 a, .sidebar h3 a, @@ -315,7 +315,7 @@ main { min-width: 0; /* avoid growing beyond the size limit */ } -.source main { +.src main { padding: 15px; } @@ -350,10 +350,10 @@ pre.item-decl { contain: initial; } -.source .content pre { +.src .content pre { padding: 20px; } -.rustdoc.source .example-wrap pre.src-line-numbers { +.rustdoc.src .example-wrap pre.src-line-numbers { padding: 20px 0 20px 4px; } @@ -392,7 +392,7 @@ img { left: 0; } -.rustdoc.source .sidebar { +.rustdoc.src .sidebar { flex-basis: 50px; border-right: 1px solid; overflow-x: hidden; @@ -402,7 +402,7 @@ img { } .sidebar, .mobile-topbar, .sidebar-menu-toggle, -#src-sidebar-toggle, #source-sidebar { +#src-sidebar-toggle, #src-sidebar { background-color: var(--sidebar-background-color); } @@ -410,16 +410,16 @@ img { background-color: var(--sidebar-background-color-hover); } -.source .sidebar > *:not(#src-sidebar-toggle) { +.src .sidebar > *:not(#src-sidebar-toggle) { visibility: hidden; } -.source-sidebar-expanded .source .sidebar { +.src-sidebar-expanded .src .sidebar { overflow-y: auto; flex-basis: 300px; } -.source-sidebar-expanded .source .sidebar > *:not(#src-sidebar-toggle) { +.src-sidebar-expanded .src .sidebar > *:not(#src-sidebar-toggle) { visibility: visible; } @@ -544,7 +544,7 @@ ul.block, .block li { flex-grow: 1; } -.rustdoc:not(.source) .example-wrap pre { +.rustdoc:not(.src) .example-wrap pre { overflow: auto hidden; } @@ -619,7 +619,7 @@ ul.block, .block li { } .docblock code, .docblock-short code, -pre, .rustdoc.source .example-wrap { +pre, .rustdoc.src .example-wrap { background-color: var(--code-block-background-color); } @@ -676,7 +676,7 @@ nav.sub { height: 34px; flex-grow: 1; } -.source nav.sub { +.src nav.sub { margin: 0 0 15px 0; } @@ -776,7 +776,6 @@ table, } #crate-search { min-width: 115px; - /* keep these two in sync with "@-moz-document url-prefix()" below */ padding: 0 23px 0 4px; /* prevents the s */ -@-moz-document url-prefix() { - #crate-search { - padding-left: 0px; /* == 4px - 4px */ - padding-right: 19px; /* == 23px - 4px */ - } -} /* pseudo-element for holding the dropdown-arrow image; needs to be a separate thing so that we can apply CSS-filters to change the arrow color in themes */ #crate-search-div::after { @@ -888,7 +879,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ justify-content: start; flex: 3; } -.search-results .result-name span.alias { +.search-results .result-name .alias { color: var(--search-results-alias-color); } .search-results .result-name .grey { @@ -904,6 +895,9 @@ so that we can apply CSS-filters to change the arrow color in themes */ max-width: calc(100% - var(--search-typename-width)); display: inline-block; } +.search-results .result-name .path > * { + display: inline; +} .popover { position: absolute; @@ -1074,7 +1068,7 @@ pre.rust .doccomment { color: var(--code-highlight-doc-comment-color); } -.rustdoc.source .example-wrap pre.rust a { +.rustdoc.src .example-wrap pre.rust a { background: var(--codeblock-link-background); } @@ -1301,22 +1295,22 @@ a.tooltip:hover::after { align-items: stretch; z-index: 10; } -#source-sidebar { +#src-sidebar { width: 100%; overflow: auto; } -#source-sidebar > .title { +#src-sidebar > .title { font-size: 1.5rem; text-align: center; border-bottom: 1px solid var(--border-color); margin-bottom: 6px; } -#source-sidebar div.files > a:hover, details.dir-entry summary:hover, -#source-sidebar div.files > a:focus, details.dir-entry summary:focus { - background-color: var(--source-sidebar-background-hover); +#src-sidebar div.files > a:hover, details.dir-entry summary:hover, +#src-sidebar div.files > a:focus, details.dir-entry summary:focus { + background-color: var(--src-sidebar-background-hover); } -#source-sidebar div.files > a.selected { - background-color: var(--source-sidebar-background-selected); +#src-sidebar div.files > a.selected { + background-color: var(--src-sidebar-background-selected); } #src-sidebar-toggle > button { font-size: inherit; @@ -1562,7 +1556,7 @@ However, it's not needed with smaller screen width because the doc/code block is /* WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY If you update this line, then you also need to update the line with the same warning -in source-script.js +in src-script.js */ @media (max-width: 700px) { /* When linking to an item with an `id` (for instance, by clicking a link in the sidebar, @@ -1619,8 +1613,8 @@ in source-script.js /* The source view uses a different design for the sidebar toggle, and doesn't have a topbar, so don't bump down the main content or the sidebar. */ - .source main, - .rustdoc.source .sidebar { + .src main, + .rustdoc.src .sidebar { top: 0; padding: 0; height: 100vh; @@ -1628,8 +1622,8 @@ in source-script.js } .sidebar.shown, - .source-sidebar-expanded .source .sidebar, - .rustdoc:not(.source) .sidebar:focus-within { + .src-sidebar-expanded .src .sidebar, + .rustdoc:not(.src) .sidebar:focus-within { left: 0; } @@ -1709,7 +1703,7 @@ in source-script.js border-left: 0; } - .source-sidebar-expanded #src-sidebar-toggle { + .src-sidebar-expanded #src-sidebar-toggle { left: unset; top: unset; width: unset; @@ -1749,7 +1743,7 @@ in source-script.js display: inline; } - .source-sidebar-expanded .source .sidebar { + .src-sidebar-expanded .src .sidebar { max-width: 100vw; width: 100vw; } @@ -1769,7 +1763,7 @@ in source-script.js margin-left: 34px; } - .source nav.sub { + .src nav.sub { margin: 0; padding: var(--nav-sub-mobile-padding); } @@ -1792,7 +1786,7 @@ in source-script.js } @media print { - nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path, + nav.sidebar, nav.sub, .out-of-band, a.src, #copy-path, details.toggle[open] > summary::before, details.toggle > summary::before, details.toggle.top-doc > summary { display: none; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 7145baad2..d8dae51eb 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -89,8 +89,8 @@ Original by Dempfi (https://github.com/dempfi/ayu) --crate-search-div-hover-filter: invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%); --crate-search-hover-border: #e0e0e0; - --source-sidebar-background-selected: #14191f; - --source-sidebar-background-hover: #14191f; + --src-sidebar-background-selected: #14191f; + --src-sidebar-background-hover: #14191f; --table-alt-row-background-color: #191f26; --codeblock-link-background: #333; --scrape-example-toggle-line-background: #999; @@ -107,7 +107,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) h1, h2, h3, h4, h1 a, .sidebar h2 a, .sidebar h3 a, -#source-sidebar > .title { +#src-sidebar > .title { color: #fff; } h4 { @@ -124,15 +124,15 @@ h4 { .docblock pre > code, pre, pre > code, .item-info code, -.rustdoc.source .example-wrap { +.rustdoc.src .example-wrap { color: #e6e1cf; } .sidebar .current, .sidebar a:hover, -#source-sidebar div.files > a:hover, details.dir-entry summary:hover, -#source-sidebar div.files > a:focus, details.dir-entry summary:focus, -#source-sidebar div.files > a.selected { +#src-sidebar div.files > a:hover, details.dir-entry summary:hover, +#src-sidebar div.files > a:focus, details.dir-entry summary:focus, +#src-sidebar div.files > a.selected { color: #ffb44c; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 3c1186a56..2b3029887 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -68,7 +68,7 @@ --test-arrow-color: #dedede; --test-arrow-background-color: rgba(78, 139, 202, 0.2); --test-arrow-hover-color: #dedede; - --test-arrow-hover-background-color: #4e8bca; + --test-arrow-hover-background-color: rgb(78, 139, 202); --target-background-color: #494a3d; --target-border-color: #bb7410; --kbd-color: #000; @@ -84,8 +84,8 @@ --crate-search-div-hover-filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%); --crate-search-hover-border: #2196f3; - --source-sidebar-background-selected: #333; - --source-sidebar-background-hover: #444; + --src-sidebar-background-selected: #333; + --src-sidebar-background-hover: #444; --table-alt-row-background-color: #2A2A2A; --codeblock-link-background: #333; --scrape-example-toggle-line-background: #999; diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index f8c287137..56fd8cbef 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -68,7 +68,7 @@ --test-arrow-color: #f5f5f5; --test-arrow-background-color: rgba(78, 139, 202, 0.2); --test-arrow-hover-color: #f5f5f5; - --test-arrow-hover-background-color: #4e8bca; + --test-arrow-hover-background-color: rgb(78, 139, 202); --target-background-color: #fdffd3; --target-border-color: #ad7c37; --kbd-color: #000; @@ -81,8 +81,8 @@ --crate-search-div-hover-filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%); --crate-search-hover-border: #717171; - --source-sidebar-background-selected: #fff; - --source-sidebar-background-hover: #e0e0e0; + --src-sidebar-background-selected: #fff; + --src-sidebar-background-hover: #e0e0e0; --table-alt-row-background-color: #F5F5F5; --codeblock-link-background: #eee; --scrape-example-toggle-line-background: #ccc; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 51d8e81ca..42088e735 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2108,29 +2108,22 @@ function initSearch(rawSearchIndex) { const resultName = document.createElement("div"); resultName.className = "result-name"; - if (item.is_alias) { - const alias = document.createElement("span"); - alias.className = "alias"; - - const bold = document.createElement("b"); - bold.innerText = item.alias; - alias.appendChild(bold); - - alias.insertAdjacentHTML( - "beforeend", - " - see "); + resultName.insertAdjacentHTML( + "beforeend", + `${typeName}`); + link.appendChild(resultName); - resultName.appendChild(alias); + let alias = " "; + if (item.is_alias) { + alias = `
    \ +${item.alias} - see \ +
    `; } - resultName.insertAdjacentHTML( "beforeend", - `\ -${typeName}\ -
    \ - ${item.displayPath}${name}\ + `
    ${alias}\ +${item.displayPath}${name}\
    `); - link.appendChild(resultName); const description = document.createElement("div"); description.className = "desc"; diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js deleted file mode 100644 index 6eb991360..000000000 --- a/src/librustdoc/html/static/js/source-script.js +++ /dev/null @@ -1,235 +0,0 @@ -// From rust: -/* global sourcesIndex */ - -// Local js definitions: -/* global addClass, getCurrentValue, onEachLazy, removeClass, browserSupportsHistoryApi */ -/* global updateLocalStorage, getVar */ - -"use strict"; - -(function() { - -const rootPath = getVar("root-path"); - -const NAME_OFFSET = 0; -const DIRS_OFFSET = 1; -const FILES_OFFSET = 2; - -// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY -// If you update this line, then you also need to update the media query with the same -// warning in rustdoc.css -const RUSTDOC_MOBILE_BREAKPOINT = 700; - -function closeSidebarIfMobile() { - if (window.innerWidth < RUSTDOC_MOBILE_BREAKPOINT) { - updateLocalStorage("source-sidebar-show", "false"); - } -} - -function createDirEntry(elem, parent, fullPath, hasFoundFile) { - const dirEntry = document.createElement("details"); - const summary = document.createElement("summary"); - - dirEntry.className = "dir-entry"; - - fullPath += elem[NAME_OFFSET] + "/"; - - summary.innerText = elem[NAME_OFFSET]; - dirEntry.appendChild(summary); - - const folders = document.createElement("div"); - folders.className = "folders"; - if (elem[DIRS_OFFSET]) { - for (const dir of elem[DIRS_OFFSET]) { - if (createDirEntry(dir, folders, fullPath, false)) { - dirEntry.open = true; - hasFoundFile = true; - } - } - } - dirEntry.appendChild(folders); - - 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); - if (!hasFoundFile && w === file.href) { - file.className = "selected"; - dirEntry.open = true; - hasFoundFile = true; - } - files.appendChild(file); - } - } - dirEntry.appendChild(files); - parent.appendChild(dirEntry); - return hasFoundFile; -} - -function toggleSidebar() { - const child = this.parentNode.children[0]; - if (child.innerText === ">") { - addClass(document.documentElement, "source-sidebar-expanded"); - child.innerText = "<"; - updateLocalStorage("source-sidebar-show", "true"); - } else { - removeClass(document.documentElement, "source-sidebar-expanded"); - child.innerText = ">"; - updateLocalStorage("source-sidebar-show", "false"); - } -} - -function createSidebarToggle() { - const sidebarToggle = document.createElement("div"); - sidebarToggle.id = "src-sidebar-toggle"; - - const inner = document.createElement("button"); - - if (getCurrentValue("source-sidebar-show") === "true") { - inner.innerText = "<"; - } else { - inner.innerText = ">"; - } - inner.onclick = toggleSidebar; - - sidebarToggle.appendChild(inner); - return sidebarToggle; -} - -// This function is called from "source-files.js", generated in `html/render/write_shared.rs`. -// eslint-disable-next-line no-unused-vars -function createSourceSidebar() { - const container = document.querySelector("nav.sidebar"); - - const sidebarToggle = createSidebarToggle(); - container.insertBefore(sidebarToggle, container.firstChild); - - const sidebar = document.createElement("div"); - sidebar.id = "source-sidebar"; - - let hasFoundFile = false; - - const title = document.createElement("div"); - title.className = "title"; - title.innerText = "Files"; - sidebar.appendChild(title); - Object.keys(sourcesIndex).forEach(key => { - sourcesIndex[key][NAME_OFFSET] = key; - hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", hasFoundFile); - }); - - container.appendChild(sidebar); - // Focus on the current file in the source files sidebar. - const selected_elem = sidebar.getElementsByClassName("selected")[0]; - if (typeof selected_elem !== "undefined") { - selected_elem.focus(); - } -} - -const lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/; - -function highlightSourceLines(match) { - if (typeof match === "undefined") { - match = window.location.hash.match(lineNumbersRegex); - } - if (!match) { - return; - } - let from = parseInt(match[1], 10); - let to = from; - if (typeof match[2] !== "undefined") { - to = parseInt(match[2], 10); - } - if (to < from) { - const tmp = to; - to = from; - from = tmp; - } - let elem = document.getElementById(from); - if (!elem) { - return; - } - const x = document.getElementById(from); - if (x) { - x.scrollIntoView(); - } - onEachLazy(document.getElementsByClassName("src-line-numbers"), e => { - onEachLazy(e.getElementsByTagName("a"), i_e => { - removeClass(i_e, "line-highlighted"); - }); - }); - for (let i = from; i <= to; ++i) { - elem = document.getElementById(i); - if (!elem) { - break; - } - addClass(elem, "line-highlighted"); - } -} - -const handleSourceHighlight = (function() { - let prev_line_id = 0; - - const set_fragment = name => { - const x = window.scrollX, - y = window.scrollY; - if (browserSupportsHistoryApi()) { - history.replaceState(null, null, "#" + name); - highlightSourceLines(); - } else { - location.replace("#" + name); - } - // Prevent jumps when selecting one or many lines - window.scrollTo(x, y); - }; - - return ev => { - let cur_line_id = parseInt(ev.target.id, 10); - // This event handler is attached to the entire line number column, but it should only - // be run if one of the anchors is clicked. It also shouldn't do anything if the anchor - // is clicked with a modifier key (to open a new browser tab). - if (isNaN(cur_line_id) || - ev.ctrlKey || - ev.altKey || - ev.metaKey) { - return; - } - ev.preventDefault(); - - if (ev.shiftKey && prev_line_id) { - // Swap selection if needed - if (prev_line_id > cur_line_id) { - const tmp = prev_line_id; - prev_line_id = cur_line_id; - cur_line_id = tmp; - } - - set_fragment(prev_line_id + "-" + cur_line_id); - } else { - prev_line_id = cur_line_id; - - set_fragment(cur_line_id); - } - }; -}()); - -window.addEventListener("hashchange", () => { - const match = window.location.hash.match(lineNumbersRegex); - if (match) { - return highlightSourceLines(match); - } -}); - -onEachLazy(document.getElementsByClassName("src-line-numbers"), el => { - el.addEventListener("click", handleSourceHighlight); -}); - -highlightSourceLines(); - -window.createSourceSidebar = createSourceSidebar; -})(); diff --git a/src/librustdoc/html/static/js/src-script.js b/src/librustdoc/html/static/js/src-script.js new file mode 100644 index 000000000..679c2341f --- /dev/null +++ b/src/librustdoc/html/static/js/src-script.js @@ -0,0 +1,235 @@ +// From rust: +/* global srcIndex */ + +// Local js definitions: +/* global addClass, getCurrentValue, onEachLazy, removeClass, browserSupportsHistoryApi */ +/* global updateLocalStorage, getVar */ + +"use strict"; + +(function() { + +const rootPath = getVar("root-path"); + +const NAME_OFFSET = 0; +const DIRS_OFFSET = 1; +const FILES_OFFSET = 2; + +// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY +// If you update this line, then you also need to update the media query with the same +// warning in rustdoc.css +const RUSTDOC_MOBILE_BREAKPOINT = 700; + +function closeSidebarIfMobile() { + if (window.innerWidth < RUSTDOC_MOBILE_BREAKPOINT) { + updateLocalStorage("source-sidebar-show", "false"); + } +} + +function createDirEntry(elem, parent, fullPath, hasFoundFile) { + const dirEntry = document.createElement("details"); + const summary = document.createElement("summary"); + + dirEntry.className = "dir-entry"; + + fullPath += elem[NAME_OFFSET] + "/"; + + summary.innerText = elem[NAME_OFFSET]; + dirEntry.appendChild(summary); + + const folders = document.createElement("div"); + folders.className = "folders"; + if (elem[DIRS_OFFSET]) { + for (const dir of elem[DIRS_OFFSET]) { + if (createDirEntry(dir, folders, fullPath, false)) { + dirEntry.open = true; + hasFoundFile = true; + } + } + } + dirEntry.appendChild(folders); + + 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); + if (!hasFoundFile && w === file.href) { + file.className = "selected"; + dirEntry.open = true; + hasFoundFile = true; + } + files.appendChild(file); + } + } + dirEntry.appendChild(files); + parent.appendChild(dirEntry); + return hasFoundFile; +} + +function toggleSidebar() { + const child = this.parentNode.children[0]; + if (child.innerText === ">") { + addClass(document.documentElement, "src-sidebar-expanded"); + child.innerText = "<"; + updateLocalStorage("source-sidebar-show", "true"); + } else { + removeClass(document.documentElement, "src-sidebar-expanded"); + child.innerText = ">"; + updateLocalStorage("source-sidebar-show", "false"); + } +} + +function createSidebarToggle() { + const sidebarToggle = document.createElement("div"); + sidebarToggle.id = "src-sidebar-toggle"; + + const inner = document.createElement("button"); + + if (getCurrentValue("source-sidebar-show") === "true") { + inner.innerText = "<"; + } else { + inner.innerText = ">"; + } + inner.onclick = toggleSidebar; + + sidebarToggle.appendChild(inner); + return sidebarToggle; +} + +// This function is called from "src-files.js", generated in `html/render/write_shared.rs`. +// eslint-disable-next-line no-unused-vars +function createSrcSidebar() { + const container = document.querySelector("nav.sidebar"); + + const sidebarToggle = createSidebarToggle(); + container.insertBefore(sidebarToggle, container.firstChild); + + const sidebar = document.createElement("div"); + sidebar.id = "src-sidebar"; + + let hasFoundFile = false; + + const title = document.createElement("div"); + title.className = "title"; + title.innerText = "Files"; + sidebar.appendChild(title); + Object.keys(srcIndex).forEach(key => { + srcIndex[key][NAME_OFFSET] = key; + hasFoundFile = createDirEntry(srcIndex[key], sidebar, "", hasFoundFile); + }); + + container.appendChild(sidebar); + // Focus on the current file in the source files sidebar. + const selected_elem = sidebar.getElementsByClassName("selected")[0]; + if (typeof selected_elem !== "undefined") { + selected_elem.focus(); + } +} + +const lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/; + +function highlightSrcLines(match) { + if (typeof match === "undefined") { + match = window.location.hash.match(lineNumbersRegex); + } + if (!match) { + return; + } + let from = parseInt(match[1], 10); + let to = from; + if (typeof match[2] !== "undefined") { + to = parseInt(match[2], 10); + } + if (to < from) { + const tmp = to; + to = from; + from = tmp; + } + let elem = document.getElementById(from); + if (!elem) { + return; + } + const x = document.getElementById(from); + if (x) { + x.scrollIntoView(); + } + onEachLazy(document.getElementsByClassName("src-line-numbers"), e => { + onEachLazy(e.getElementsByTagName("a"), i_e => { + removeClass(i_e, "line-highlighted"); + }); + }); + for (let i = from; i <= to; ++i) { + elem = document.getElementById(i); + if (!elem) { + break; + } + addClass(elem, "line-highlighted"); + } +} + +const handleSrcHighlight = (function() { + let prev_line_id = 0; + + const set_fragment = name => { + const x = window.scrollX, + y = window.scrollY; + if (browserSupportsHistoryApi()) { + history.replaceState(null, null, "#" + name); + highlightSrcLines(); + } else { + location.replace("#" + name); + } + // Prevent jumps when selecting one or many lines + window.scrollTo(x, y); + }; + + return ev => { + let cur_line_id = parseInt(ev.target.id, 10); + // This event handler is attached to the entire line number column, but it should only + // be run if one of the anchors is clicked. It also shouldn't do anything if the anchor + // is clicked with a modifier key (to open a new browser tab). + if (isNaN(cur_line_id) || + ev.ctrlKey || + ev.altKey || + ev.metaKey) { + return; + } + ev.preventDefault(); + + if (ev.shiftKey && prev_line_id) { + // Swap selection if needed + if (prev_line_id > cur_line_id) { + const tmp = prev_line_id; + prev_line_id = cur_line_id; + cur_line_id = tmp; + } + + set_fragment(prev_line_id + "-" + cur_line_id); + } else { + prev_line_id = cur_line_id; + + set_fragment(cur_line_id); + } + }; +}()); + +window.addEventListener("hashchange", () => { + const match = window.location.hash.match(lineNumbersRegex); + if (match) { + return highlightSrcLines(match); + } +}); + +onEachLazy(document.getElementsByClassName("src-line-numbers"), el => { + el.addEventListener("click", handleSrcHighlight); +}); + +highlightSrcLines(); + +window.createSrcSidebar = createSrcSidebar; +})(); diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 71961f6f2..af3ca42a6 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -185,7 +185,7 @@ updateTheme(); if (getSettingValue("source-sidebar-show") === "true") { // At this point in page load, `document.body` is not available yet. // Set a class on the `` element instead. - addClass(document.documentElement, "source-sidebar-expanded"); + addClass(document.documentElement, "src-sidebar-expanded"); } // If we navigate away (for example to a settings page), and then use the back or diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 767b974cc..a27aa2b58 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -53,7 +53,7 @@ pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf { // which would result in `style.min-suffix.css` which isn't what we // want. let (base, ext) = filename.split_once('.').unwrap(); - let filename = format!("{}{}.{}", base, suffix, ext); + let filename = format!("{base}{suffix}.{ext}"); filename.into() } @@ -97,7 +97,7 @@ static_files! { main_js => "static/js/main.js", search_js => "static/js/search.js", settings_js => "static/js/settings.js", - source_script_js => "static/js/source-script.js", + src_script_js => "static/js/src-script.js", storage_js => "static/js/storage.js", scrape_examples_js => "static/js/scrape-examples.js", wheel_svg => "static/images/wheel.svg", diff --git a/src/librustdoc/html/templates/STYLE.md b/src/librustdoc/html/templates/STYLE.md index 0281b1c47..38aac2a60 100644 --- a/src/librustdoc/html/templates/STYLE.md +++ b/src/librustdoc/html/templates/STYLE.md @@ -32,7 +32,7 @@ Askama templates support quite sophisticated control flow. To keep our templates simple and understandable, we use only a subset: `if` and `for`. In particular we avoid [assignments in the template logic][assignments] and [Askama macros][macros]. This also may make things easier if we switch to a different -Jinja-style template system, like Askama, in the future. +Jinja-style template system in the future. [assignments]: https://djc.github.io/askama/template_syntax.html#assignments [macros]: https://djc.github.io/askama/template_syntax.html#macros diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index d4ec9c34b..60ccfe4da 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -42,9 +42,9 @@ {# #} {% if page.css_class.contains("crate") %} {# #} - {% else if page.css_class == "source" %} - {# #} - {# #} + {% else if page.css_class == "src" %} + {# #} + {# #} {% else if !page.css_class.contains("mod") %} {# #} {% endif %} @@ -85,7 +85,7 @@
    {# #} {# #} {{ layout.external_html.before_content|safe }} - {% if page.css_class != "source" %} + {% if page.css_class != "src" %} {# #} {% endif %} {# #}
    {# #} - {% if page.css_class != "source" %}{% endif %}
    {# #} {{ layout.external_html.after_content|safe }} {# #} diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html index 68a295ae0..1d215c269 100644 --- a/src/librustdoc/html/templates/print_item.html +++ b/src/librustdoc/html/templates/print_item.html @@ -18,7 +18,7 @@ {% endif %} {% match src_href %} {% when Some with (href) %} - source · {#+ #} + source · {#+ #} {% else %} {% endmatch %}