diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86de37820003a..99140bec17029 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ name: CI - "**" defaults: run: - shell: bash + shell: "python src/ci/exec-with-shell.py {0}" jobs: pr: name: PR @@ -54,6 +54,7 @@ jobs: steps: - name: disable git crlf conversion run: git config --global core.autocrlf false + shell: bash - name: checkout the source code uses: actions/checkout@v1 with: @@ -65,59 +66,77 @@ jobs: if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" - name: add extra environment variables run: src/ci/scripts/setup-environment.sh + shell: bash env: EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" if: success() && !env.SKIP_JOB - name: decide whether to skip this job run: src/ci/scripts/should-skip-this.sh + shell: bash if: success() && !env.SKIP_JOB - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh + shell: bash if: success() && !env.SKIP_JOB - name: show the current environment run: src/ci/scripts/dump-environment.sh + shell: bash if: success() && !env.SKIP_JOB - name: install awscli run: src/ci/scripts/install-awscli.sh + shell: bash if: success() && !env.SKIP_JOB - name: install sccache run: src/ci/scripts/install-sccache.sh + shell: bash if: success() && !env.SKIP_JOB - name: install clang run: src/ci/scripts/install-clang.sh + shell: bash if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh + shell: bash if: success() && !env.SKIP_JOB - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh + shell: bash if: success() && !env.SKIP_JOB - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash if: success() && !env.SKIP_JOB - name: install MSYS2 run: src/ci/scripts/install-msys2.sh + shell: bash if: success() && !env.SKIP_JOB - name: install MinGW run: src/ci/scripts/install-mingw.sh + shell: bash if: success() && !env.SKIP_JOB - name: install ninja run: src/ci/scripts/install-ninja.sh + shell: bash if: success() && !env.SKIP_JOB - name: enable ipv6 on Docker run: src/ci/scripts/enable-docker-ipv6.sh + shell: bash if: success() && !env.SKIP_JOB - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash if: success() && !env.SKIP_JOB - name: checkout submodules run: src/ci/scripts/checkout-submodules.sh + shell: bash if: success() && !env.SKIP_JOB - name: ensure line endings are correct run: src/ci/scripts/verify-line-endings.sh + shell: bash if: success() && !env.SKIP_JOB - name: run the build run: src/ci/scripts/run-build-from-ci.sh + shell: bash env: AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" @@ -125,6 +144,7 @@ jobs: if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh + shell: bash env: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" @@ -153,6 +173,7 @@ jobs: steps: - name: disable git crlf conversion run: git config --global core.autocrlf false + shell: bash - name: checkout the source code uses: actions/checkout@v1 with: @@ -164,59 +185,77 @@ jobs: if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" - name: add extra environment variables run: src/ci/scripts/setup-environment.sh + shell: bash env: EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" if: success() && !env.SKIP_JOB - name: decide whether to skip this job run: src/ci/scripts/should-skip-this.sh + shell: bash if: success() && !env.SKIP_JOB - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh + shell: bash if: success() && !env.SKIP_JOB - name: show the current environment run: src/ci/scripts/dump-environment.sh + shell: bash if: success() && !env.SKIP_JOB - name: install awscli run: src/ci/scripts/install-awscli.sh + shell: bash if: success() && !env.SKIP_JOB - name: install sccache run: src/ci/scripts/install-sccache.sh + shell: bash if: success() && !env.SKIP_JOB - name: install clang run: src/ci/scripts/install-clang.sh + shell: bash if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh + shell: bash if: success() && !env.SKIP_JOB - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh + shell: bash if: success() && !env.SKIP_JOB - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash if: success() && !env.SKIP_JOB - name: install MSYS2 run: src/ci/scripts/install-msys2.sh + shell: bash if: success() && !env.SKIP_JOB - name: install MinGW run: src/ci/scripts/install-mingw.sh + shell: bash if: success() && !env.SKIP_JOB - name: install ninja run: src/ci/scripts/install-ninja.sh + shell: bash if: success() && !env.SKIP_JOB - name: enable ipv6 on Docker run: src/ci/scripts/enable-docker-ipv6.sh + shell: bash if: success() && !env.SKIP_JOB - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash if: success() && !env.SKIP_JOB - name: checkout submodules run: src/ci/scripts/checkout-submodules.sh + shell: bash if: success() && !env.SKIP_JOB - name: ensure line endings are correct run: src/ci/scripts/verify-line-endings.sh + shell: bash if: success() && !env.SKIP_JOB - name: run the build run: src/ci/scripts/run-build-from-ci.sh + shell: bash env: AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" @@ -224,6 +263,7 @@ jobs: if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh + shell: bash env: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" @@ -470,6 +510,7 @@ jobs: steps: - name: disable git crlf conversion run: git config --global core.autocrlf false + shell: bash - name: checkout the source code uses: actions/checkout@v1 with: @@ -481,59 +522,77 @@ jobs: if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" - name: add extra environment variables run: src/ci/scripts/setup-environment.sh + shell: bash env: EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" if: success() && !env.SKIP_JOB - name: decide whether to skip this job run: src/ci/scripts/should-skip-this.sh + shell: bash if: success() && !env.SKIP_JOB - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh + shell: bash if: success() && !env.SKIP_JOB - name: show the current environment run: src/ci/scripts/dump-environment.sh + shell: bash if: success() && !env.SKIP_JOB - name: install awscli run: src/ci/scripts/install-awscli.sh + shell: bash if: success() && !env.SKIP_JOB - name: install sccache run: src/ci/scripts/install-sccache.sh + shell: bash if: success() && !env.SKIP_JOB - name: install clang run: src/ci/scripts/install-clang.sh + shell: bash if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh + shell: bash if: success() && !env.SKIP_JOB - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh + shell: bash if: success() && !env.SKIP_JOB - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash if: success() && !env.SKIP_JOB - name: install MSYS2 run: src/ci/scripts/install-msys2.sh + shell: bash if: success() && !env.SKIP_JOB - name: install MinGW run: src/ci/scripts/install-mingw.sh + shell: bash if: success() && !env.SKIP_JOB - name: install ninja run: src/ci/scripts/install-ninja.sh + shell: bash if: success() && !env.SKIP_JOB - name: enable ipv6 on Docker run: src/ci/scripts/enable-docker-ipv6.sh + shell: bash if: success() && !env.SKIP_JOB - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash if: success() && !env.SKIP_JOB - name: checkout submodules run: src/ci/scripts/checkout-submodules.sh + shell: bash if: success() && !env.SKIP_JOB - name: ensure line endings are correct run: src/ci/scripts/verify-line-endings.sh + shell: bash if: success() && !env.SKIP_JOB - name: run the build run: src/ci/scripts/run-build-from-ci.sh + shell: bash env: AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" @@ -541,6 +600,7 @@ jobs: if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh + shell: bash env: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" @@ -595,6 +655,7 @@ jobs: steps: - name: disable git crlf conversion run: git config --global core.autocrlf false + shell: bash - name: checkout the source code uses: actions/checkout@v1 with: @@ -606,59 +667,77 @@ jobs: if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'" - name: add extra environment variables run: src/ci/scripts/setup-environment.sh + shell: bash env: EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" if: success() && !env.SKIP_JOB - name: decide whether to skip this job run: src/ci/scripts/should-skip-this.sh + shell: bash if: success() && !env.SKIP_JOB - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh + shell: bash if: success() && !env.SKIP_JOB - name: show the current environment run: src/ci/scripts/dump-environment.sh + shell: bash if: success() && !env.SKIP_JOB - name: install awscli run: src/ci/scripts/install-awscli.sh + shell: bash if: success() && !env.SKIP_JOB - name: install sccache run: src/ci/scripts/install-sccache.sh + shell: bash if: success() && !env.SKIP_JOB - name: install clang run: src/ci/scripts/install-clang.sh + shell: bash if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh + shell: bash if: success() && !env.SKIP_JOB - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh + shell: bash if: success() && !env.SKIP_JOB - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash if: success() && !env.SKIP_JOB - name: install MSYS2 run: src/ci/scripts/install-msys2.sh + shell: bash if: success() && !env.SKIP_JOB - name: install MinGW run: src/ci/scripts/install-mingw.sh + shell: bash if: success() && !env.SKIP_JOB - name: install ninja run: src/ci/scripts/install-ninja.sh + shell: bash if: success() && !env.SKIP_JOB - name: enable ipv6 on Docker run: src/ci/scripts/enable-docker-ipv6.sh + shell: bash if: success() && !env.SKIP_JOB - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash if: success() && !env.SKIP_JOB - name: checkout submodules run: src/ci/scripts/checkout-submodules.sh + shell: bash if: success() && !env.SKIP_JOB - name: ensure line endings are correct run: src/ci/scripts/verify-line-endings.sh + shell: bash if: success() && !env.SKIP_JOB - name: run the build run: src/ci/scripts/run-build-from-ci.sh + shell: bash env: AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" @@ -666,6 +745,7 @@ jobs: if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh + shell: bash env: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" diff --git a/.gitmodules b/.gitmodules index b914b7d6fa129..5c0ab737f63db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -44,6 +44,3 @@ [submodule "src/tools/rust-analyzer"] path = src/tools/rust-analyzer url = https://github.com/rust-analyzer/rust-analyzer.git -[submodule "src/backtrace"] - path = src/backtrace - url = https://github.com/rust-lang/backtrace-rs.git diff --git a/Cargo.lock b/Cargo.lock index 34a33eca3f40b..28ff6b3b1ebf2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,26 +1,10 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "addr2line" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" -dependencies = [ - "compiler_builtins", - "gimli", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "adler" -version = "0.2.2" +name = "adler32" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc9a9dd069569f212bc4330af9f17c4afb5e8ce185e83dbb14f1349dda18b10" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] +checksum = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" [[package]] name = "aho-corasick" @@ -141,14 +125,28 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.50" +version = "0.3.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" dependencies = [ - "addr2line", + "backtrace-sys", "cfg-if", + "compiler_builtins", "libc", - "miniz_oxide", - "object", "rustc-demangle", + "rustc-std-workspace-core", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fbebbe1c9d1f383a9cc7e8ccdb471b91c8d024ee9c2ca5b5346121fe8b4399" +dependencies = [ + "cc", + "compiler_builtins", + "libc", + "rustc-std-workspace-core", ] [[package]] @@ -690,9 +688,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.2.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +checksum = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" dependencies = [ "cfg-if", ] @@ -1025,9 +1023,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" -version = "1.0.16" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" +checksum = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" dependencies = [ "cfg-if", "crc32fast", @@ -1161,17 +1159,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "gimli" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "git2" version = "0.13.5" @@ -1832,14 +1819,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.0" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f" +checksum = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" dependencies = [ - "adler", - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", + "adler32", ] [[package]] @@ -1971,17 +1955,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "once_cell" version = "1.1.0" @@ -2169,12 +2142,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "pathdiff" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877630b3de15c0b64cc52f659345724fbf6bdad9bd9566699fc53688f3c34a34" - [[package]] name = "percent-encoding" version = "1.0.1" @@ -2821,13 +2788,6 @@ dependencies = [ "rls-span", ] -[[package]] -name = "rust-demangler" -version = "0.0.0" -dependencies = [ - "rustc-demangle", -] - [[package]] name = "rustbook" version = "0.1.0" @@ -3358,7 +3318,6 @@ dependencies = [ "log", "memmap", "num_cpus", - "pathdiff", "rustc_apfloat", "rustc_ast", "rustc_attr", @@ -4373,8 +4332,8 @@ dependencies = [ name = "std" version = "0.0.0" dependencies = [ - "addr2line", "alloc", + "backtrace", "cfg-if", "compiler_builtins", "core", @@ -4383,13 +4342,10 @@ dependencies = [ "hashbrown", "hermit-abi", "libc", - "miniz_oxide", - "object", "panic_abort", "panic_unwind", "profiler_builtins", "rand 0.7.3", - "rustc-demangle", "unwind", "wasi", ] diff --git a/Cargo.toml b/Cargo.toml index 9429e063b5110..be15e50e2bcca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ members = [ "src/tools/remote-test-client", "src/tools/remote-test-server", "src/tools/rust-installer", - "src/tools/rust-demangler", "src/tools/cargo", "src/tools/rustdoc", "src/tools/rls", @@ -80,11 +79,5 @@ rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' } rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' } rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' } -# This crate's integration with libstd is a bit wonky, so we use a submodule -# instead of a crates.io dependency. Make sure everything else in the repo is -# also using the submodule, however, so we can avoid duplicate copies of the -# source code for this crate. -backtrace = { path = "src/backtrace" } - [patch."https://github.com/rust-lang/rust-clippy"] clippy_lints = { path = "src/tools/clippy/clippy_lints" } diff --git a/rustfmt.toml b/rustfmt.toml index b16aecc463c91..c76a75fa07bb0 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -30,7 +30,6 @@ ignore = [ "src/tools/rust-analyzer", "src/tools/rust-installer", "src/tools/rustfmt", - "src/backtrace", # We do not format this file as it is externally sourced and auto-generated. "src/libstd/sys/cloudabi/abi/cloudabi.rs", diff --git a/src/backtrace b/src/backtrace deleted file mode 160000 index 5965cf5fc17af..0000000000000 --- a/src/backtrace +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5965cf5fc17affc84c11dc9972ae8f4dc2c32db1 diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c3f1bac177de7..1dfa635c694ac 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -349,7 +349,6 @@ def __init__(self): self.use_vendored_sources = '' self.verbose = False self.git_version = None - self.nix_deps_dir = None def download_stage0(self): """Fetch the build system for Rust, written in Rust @@ -389,12 +388,8 @@ def support_xz(): filename = "rustc-{}-{}{}".format(rustc_channel, self.build, tarball_suffix) self._download_stage0_helper(filename, "rustc", tarball_suffix) - self.fix_bin_or_dylib("{}/bin/rustc".format(self.bin_root())) - self.fix_bin_or_dylib("{}/bin/rustdoc".format(self.bin_root())) - lib_dir = "{}/lib".format(self.bin_root()) - for lib in os.listdir(lib_dir): - if lib.endswith(".so"): - self.fix_bin_or_dylib("{}/{}".format(lib_dir, lib)) + self.fix_executable("{}/bin/rustc".format(self.bin_root())) + self.fix_executable("{}/bin/rustdoc".format(self.bin_root())) with output(self.rustc_stamp()) as rust_stamp: rust_stamp.write(self.date) @@ -413,7 +408,7 @@ def support_xz(): filename = "cargo-{}-{}{}".format(cargo_channel, self.build, tarball_suffix) self._download_stage0_helper(filename, "cargo", tarball_suffix) - self.fix_bin_or_dylib("{}/bin/cargo".format(self.bin_root())) + self.fix_executable("{}/bin/cargo".format(self.bin_root())) with output(self.cargo_stamp()) as cargo_stamp: cargo_stamp.write(self.date) @@ -426,8 +421,8 @@ def support_xz(): [channel, date] = rustfmt_channel.split('-', 1) filename = "rustfmt-{}-{}{}".format(channel, self.build, tarball_suffix) self._download_stage0_helper(filename, "rustfmt-preview", tarball_suffix, date) - self.fix_bin_or_dylib("{}/bin/rustfmt".format(self.bin_root())) - self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(self.bin_root())) + self.fix_executable("{}/bin/rustfmt".format(self.bin_root())) + self.fix_executable("{}/bin/cargo-fmt".format(self.bin_root())) with output(self.rustfmt_stamp()) as rustfmt_stamp: rustfmt_stamp.write(self.date + self.rustfmt_channel) @@ -445,12 +440,12 @@ def _download_stage0_helper(self, filename, pattern, tarball_suffix, date=None): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose) - def fix_bin_or_dylib(self, fname): - """Modifies the interpreter section of 'fname' to fix the dynamic linker, - or the RPATH section, to fix the dynamic library search path + @staticmethod + def fix_executable(fname): + """Modifies the interpreter section of 'fname' to fix the dynamic linker This method is only required on NixOS and uses the PatchELF utility to - change the interpreter/RPATH of ELF executables. + change the dynamic linker of ELF executables. Please see https://nixos.org/patchelf.html for more information """ @@ -477,61 +472,38 @@ def fix_bin_or_dylib(self, fname): nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" print(nix_os_msg, fname) - # Only build `stage0/.nix-deps` once. - nix_deps_dir = self.nix_deps_dir - if not nix_deps_dir: - nix_deps_dir = "{}/.nix-deps".format(self.bin_root()) - if not os.path.exists(nix_deps_dir): - os.makedirs(nix_deps_dir) - - nix_deps = [ - # Needed for the path of `ld-linux.so` (via `nix-support/dynamic-linker`). - "stdenv.cc.bintools", - - # Needed as a system dependency of `libLLVM-*.so`. - "zlib", - - # Needed for patching ELF binaries (see doc comment above). - "patchelf", - ] - - # Run `nix-build` to "build" each dependency (which will likely reuse - # the existing `/nix/store` copy, or at most download a pre-built copy). - # Importantly, we don't rely on `nix-build` printing the `/nix/store` - # path on stdout, but use `-o` to symlink it into `stage0/.nix-deps/$dep`, - # ensuring garbage collection will never remove the `/nix/store` path - # (which would break our patched binaries that hardcode those paths). - for dep in nix_deps: - try: - subprocess.check_output([ - "nix-build", "", - "-A", dep, - "-o", "{}/{}".format(nix_deps_dir, dep), - ]) - except subprocess.CalledProcessError as reason: - print("warning: failed to call nix-build:", reason) - return - - self.nix_deps_dir = nix_deps_dir - - patchelf = "{}/patchelf/bin/patchelf".format(nix_deps_dir) - - if fname.endswith(".so"): - # Dynamic library, patch RPATH to point to system dependencies. - dylib_deps = ["zlib"] - rpath_entries = [ - # Relative default, all binary and dynamic libraries we ship - # appear to have this (even when `../lib` is redundant). - "$ORIGIN/../lib", - ] + ["{}/{}/lib".format(nix_deps_dir, dep) for dep in dylib_deps] - patchelf_args = ["--set-rpath", ":".join(rpath_entries)] + try: + interpreter = subprocess.check_output( + ["patchelf", "--print-interpreter", fname]) + interpreter = interpreter.strip().decode(default_encoding) + except subprocess.CalledProcessError as reason: + print("warning: failed to call patchelf:", reason) + return + + loader = interpreter.split("/")[-1] + + try: + ldd_output = subprocess.check_output( + ['ldd', '/run/current-system/sw/bin/sh']) + ldd_output = ldd_output.strip().decode(default_encoding) + except subprocess.CalledProcessError as reason: + print("warning: unable to call ldd:", reason) + return + + for line in ldd_output.splitlines(): + libname = line.split()[0] + if libname.endswith(loader): + loader_path = libname[:len(libname) - len(loader)] + break else: - bintools_dir = "{}/stdenv.cc.bintools".format(nix_deps_dir) - with open("{}/nix-support/dynamic-linker".format(bintools_dir)) as dynamic_linker: - patchelf_args = ["--set-interpreter", dynamic_linker.read().rstrip()] + print("warning: unable to find the path to the dynamic linker") + return + + correct_interpreter = loader_path + loader try: - subprocess.check_output([patchelf] + patchelf_args + [fname]) + subprocess.check_output( + ["patchelf", "--set-interpreter", correct_interpreter, fname]) except subprocess.CalledProcessError as reason: print("warning: failed to call patchelf:", reason) return diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 737176c48f878..a8161c9bfb859 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -370,7 +370,6 @@ impl<'a> Builder<'a> { tool::Cargo, tool::Rls, tool::RustAnalyzer, - tool::RustDemangler, tool::Rustdoc, tool::Clippy, tool::CargoClippy, @@ -1444,10 +1443,6 @@ pub struct Cargo { } impl Cargo { - pub fn rustdocflag(&mut self, arg: &str) -> &mut Cargo { - self.rustdocflags.arg(arg); - self - } pub fn rustflag(&mut self, arg: &str) -> &mut Cargo { self.rustflags.arg(arg); self @@ -1470,9 +1465,6 @@ impl Cargo { } pub fn env(&mut self, key: impl AsRef, value: impl AsRef) -> &mut Cargo { - // These are managed through rustflag/rustdocflag interfaces. - assert_ne!(key.as_ref(), "RUSTFLAGS"); - assert_ne!(key.as_ref(), "RUSTDOCFLAGS"); self.command.env(key.as_ref(), value.as_ref()); self } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 263c7b93fe55d..af30747a9592e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -91,7 +91,7 @@ impl Step for Docs { let name = pkgname(builder, "rust-docs"); if !builder.config.docs { - return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)); + return distdir(builder).join(format!("{}-{}.tar.gz", name, host)); } builder.default_doc(None); @@ -99,7 +99,7 @@ impl Step for Docs { builder.info(&format!("Dist docs ({})", host)); let _time = timeit(builder); - let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple)); + let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); let dst = image.join("share/doc/rust/html"); @@ -119,14 +119,14 @@ impl Step for Docs { .arg(&tmpdir(builder)) .arg("--output-dir") .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, host.triple)) + .arg(format!("--package-name={}-{}", name, host)) .arg("--component-name=rust-docs") .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--bulk-dirs=share/doc/rust/html"); builder.run(&mut cmd); builder.remove_dir(&image); - distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)) + distdir(builder).join(format!("{}-{}.tar.gz", name, host)) } } @@ -154,12 +154,12 @@ impl Step for RustcDocs { let name = pkgname(builder, "rustc-docs"); if !builder.config.compiler_docs { - return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)); + return distdir(builder).join(format!("{}-{}.tar.gz", name, host)); } builder.default_doc(None); - let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple)); + let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); let dst = image.join("share/doc/rust/html"); @@ -178,7 +178,7 @@ impl Step for RustcDocs { .arg(&tmpdir(builder)) .arg("--output-dir") .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, host.triple)) + .arg(format!("--package-name={}-{}", name, host)) .arg("--component-name=rustc-docs") .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--bulk-dirs=share/doc/rust/html"); @@ -188,7 +188,7 @@ impl Step for RustcDocs { builder.run(&mut cmd); builder.remove_dir(&image); - distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)) + distdir(builder).join(format!("{}-{}.tar.gz", name, host)) } } @@ -372,7 +372,7 @@ impl Step for Mingw { builder.info(&format!("Dist mingw ({})", host)); let _time = timeit(builder); let name = pkgname(builder, "rust-mingw"); - let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple)); + let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); t!(fs::create_dir_all(&image)); @@ -393,12 +393,12 @@ impl Step for Mingw { .arg(&tmpdir(builder)) .arg("--output-dir") .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, host.triple)) + .arg(format!("--package-name={}-{}", name, host)) .arg("--component-name=rust-mingw") .arg("--legacy-manifest-dirs=rustlib,cargo"); builder.run(&mut cmd); t!(fs::remove_dir_all(&image)); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple))) + Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host))) } } @@ -427,9 +427,9 @@ impl Step for Rustc { let host = self.compiler.host; let name = pkgname(builder, "rustc"); - let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple)); + let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); - let overlay = tmpdir(builder).join(format!("{}-{}-overlay", name, host.triple)); + let overlay = tmpdir(builder).join(format!("{}-{}-overlay", name, host)); let _ = fs::remove_dir_all(&overlay); // Prepare the rustc "image", what will actually end up getting installed @@ -483,17 +483,17 @@ impl Step for Rustc { .arg(&distdir(builder)) .arg("--non-installed-overlay") .arg(&overlay) - .arg(format!("--package-name={}-{}", name, host.triple)) + .arg(format!("--package-name={}-{}", name, host)) .arg("--component-name=rustc") .arg("--legacy-manifest-dirs=rustlib,cargo"); - builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host.triple)); + builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host)); let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); builder.remove_dir(&overlay); - return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)); + return distdir(builder).join(format!("{}-{}.tar.gz", name, host)); fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) { let host = compiler.host; @@ -707,14 +707,14 @@ impl Step for Std { let target = self.target; let name = pkgname(builder, "rust-std"); - let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)); + let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); if skip_host_target_lib(builder, compiler) { return archive; } builder.ensure(compile::Std { compiler, target }); - let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple)); + let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); @@ -732,8 +732,8 @@ impl Step for Std { .arg(&tmpdir(builder)) .arg("--output-dir") .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg(format!("--component-name=rust-std-{}", target.triple)) + .arg(format!("--package-name={}-{}", name, target)) + .arg(format!("--component-name=rust-std-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); builder @@ -776,14 +776,14 @@ impl Step for RustcDev { let target = self.target; let name = pkgname(builder, "rustc-dev"); - let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)); + let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); if skip_host_target_lib(builder, compiler) { return archive; } builder.ensure(compile::Rustc { compiler, target }); - let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple)); + let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); @@ -801,8 +801,8 @@ impl Step for RustcDev { .arg(&tmpdir(builder)) .arg("--output-dir") .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg(format!("--component-name=rustc-dev-{}", target.triple)) + .arg(format!("--package-name={}-{}", name, target)) + .arg(format!("--component-name=rustc-dev-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); builder.info(&format!( @@ -853,12 +853,12 @@ impl Step for Analysis { let name = pkgname(builder, "rust-analysis"); if compiler.host != builder.config.build { - return distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)); + return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); } builder.ensure(compile::Std { compiler, target }); - let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple)); + let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let src = builder .stage_out(compiler, Mode::Std) @@ -883,15 +883,15 @@ impl Step for Analysis { .arg(&tmpdir(builder)) .arg("--output-dir") .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, target.triple)) - .arg(format!("--component-name=rust-analysis-{}", target.triple)) + .arg(format!("--package-name={}-{}", name, target)) + .arg(format!("--component-name=rust-analysis-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); builder.info("Dist analysis"); let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); - distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)) + distdir(builder).join(format!("{}-{}.tar.gz", name, target)) } } @@ -1005,7 +1005,6 @@ impl Step for Src { // (essentially libstd and all of its path dependencies) let std_src_dirs = [ "src/build_helper", - "src/backtrace", "src/liballoc", "src/libcore", "src/libpanic_abort", @@ -1243,14 +1242,14 @@ impl Step for Cargo { .arg(&distdir(builder)) .arg("--non-installed-overlay") .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--component-name=cargo") .arg("--legacy-manifest-dirs=rustlib,cargo"); builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target)); let _time = timeit(builder); builder.run(&mut cmd); - distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)) + distdir(builder).join(format!("{}-{}.tar.gz", name, target)) } } @@ -1333,14 +1332,14 @@ impl Step for Rls { .arg(&distdir(builder)) .arg("--non-installed-overlay") .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=rls-preview"); - builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target.triple)); + builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target)); let _time = timeit(builder); builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } } @@ -1420,14 +1419,14 @@ impl Step for RustAnalyzer { .arg(&distdir(builder)) .arg("--non-installed-overlay") .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=rust-analyzer-preview"); builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target)); let _time = timeit(builder); builder.run(&mut cmd); - distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)) + distdir(builder).join(format!("{}-{}.tar.gz", name, target)) } } @@ -1511,14 +1510,14 @@ impl Step for Clippy { .arg(&distdir(builder)) .arg("--non-installed-overlay") .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=clippy-preview"); builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target)); let _time = timeit(builder); builder.run(&mut cmd); - distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)) + distdir(builder).join(format!("{}-{}.tar.gz", name, target)) } } @@ -1608,14 +1607,14 @@ impl Step for Miri { .arg(&distdir(builder)) .arg("--non-installed-overlay") .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=miri-preview"); builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target)); let _time = timeit(builder); builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } } @@ -1702,14 +1701,14 @@ impl Step for Rustfmt { .arg(&distdir(builder)) .arg("--non-installed-overlay") .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=rustfmt-preview"); builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target)); let _time = timeit(builder); builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } } @@ -1814,7 +1813,7 @@ impl Step for Extended { .arg(&work) .arg("--output-dir") .arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target.triple)) + .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target)) .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--input-tarballs") .arg(input_tarballs) @@ -1894,7 +1893,7 @@ impl Step for Extended { let prepare = |name: &str| { builder.create_dir(&pkg.join(name)); builder.cp_r( - &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)), + &work.join(&format!("{}-{}", pkgname(builder, name), target)), &pkg.join(name), ); builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755); @@ -1927,11 +1926,7 @@ impl Step for Extended { .arg(xform(&etc.join("pkg/Distribution.xml"))) .arg("--resources") .arg(pkg.join("res")) - .arg(distdir(builder).join(format!( - "{}-{}.pkg", - pkgname(builder, "rust"), - target.triple - ))) + .arg(distdir(builder).join(format!("{}-{}.pkg", pkgname(builder, "rust"), target))) .arg("--package-path") .arg(&pkg); let _time = timeit(builder); @@ -1945,7 +1940,7 @@ impl Step for Extended { let prepare = |name: &str| { builder.create_dir(&exe.join(name)); let dir = if name == "rust-std" || name == "rust-analysis" { - format!("{}-{}", name, target.triple) + format!("{}-{}", name, target) } else if name == "rls" { "rls-preview".to_string() } else if name == "rust-analyzer" { @@ -1958,7 +1953,7 @@ impl Step for Extended { name.to_string() }; builder.cp_r( - &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir), + &work.join(&format!("{}-{}", pkgname(builder, name), target)).join(dir), &exe.join(name), ); builder.remove(&exe.join(name).join("manifest.in")); @@ -2217,7 +2212,7 @@ impl Step for Extended { builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); builder.info(&format!("building `msi` installer with {:?}", light)); - let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple); + let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target); let mut cmd = Command::new(&light); cmd.arg("-nologo") .arg("-ext") @@ -2466,11 +2461,11 @@ impl Step for LlvmTools { .arg(&distdir(builder)) .arg("--non-installed-overlay") .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target.triple)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=llvm-tools-preview"); builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) + Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index f8a549afc88fb..b051390fc2671 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -527,9 +527,11 @@ impl Step for Rustc { // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc"); - cargo.rustdocflag("--document-private-items"); - cargo.rustdocflag("--enable-index-page"); - cargo.rustdocflag("-Zunstable-options"); + cargo.env( + "RUSTDOCFLAGS", + "--document-private-items \ + --enable-index-page -Zunstable-options", + ); compile::rustc_cargo(builder, &mut cargo, target); // Only include compiler crates, no dependencies of those, such as `libc`. @@ -622,7 +624,7 @@ impl Step for Rustdoc { cargo.arg("--no-deps"); cargo.arg("-p").arg("rustdoc"); - cargo.rustdocflag("--document-private-items"); + cargo.env("RUSTDOCFLAGS", "--document-private-items"); builder.run(&mut cargo.into()); } } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 1316f95dd4177..7266625ff39f8 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -107,7 +107,7 @@ fn install_sh( t!(fs::create_dir_all(&empty_dir)); let package_name = if let Some(host) = host { - format!("{}-{}", pkgname(builder, name), host.triple) + format!("{}-{}", pkgname(builder, name), host) } else { pkgname(builder, name) }; @@ -160,6 +160,11 @@ macro_rules! install { config.extended && config.tools.as_ref() .map_or(true, |t| t.contains($path)) } + + #[allow(dead_code)] + fn should_install(builder: &Builder<'_>) -> bool { + builder.config.tools.as_ref().map_or(false, |t| t.contains($path)) + } } impl Step for $name { @@ -206,7 +211,8 @@ install!((self, builder, _config), install_cargo(builder, self.compiler.stage, self.target); }; Rls, "rls", Self::should_build(_config), only_hosts: true, { - if builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }).is_some() { + if builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }).is_some() || + Self::should_install(builder) { install_rls(builder, self.compiler.stage, self.target); } else { builder.info( @@ -216,14 +222,27 @@ install!((self, builder, _config), }; RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, { builder.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target }); - install_rust_analyzer(builder, self.compiler.stage, self.target); + if Self::should_install(builder) { + install_rust_analyzer(builder, self.compiler.stage, self.target); + } else { + builder.info( + &format!("skipping Install rust-analyzer stage{} ({})", self.compiler.stage, self.target), + ); + } }; Clippy, "clippy", Self::should_build(_config), only_hosts: true, { builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target }); - install_clippy(builder, self.compiler.stage, self.target); + if Self::should_install(builder) { + install_clippy(builder, self.compiler.stage, self.target); + } else { + builder.info( + &format!("skipping Install clippy stage{} ({})", self.compiler.stage, self.target), + ); + } }; Miri, "miri", Self::should_build(_config), only_hosts: true, { - if builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }).is_some() { + if builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }).is_some() || + Self::should_install(builder) { install_miri(builder, self.compiler.stage, self.target); } else { builder.info( @@ -235,7 +254,7 @@ install!((self, builder, _config), if builder.ensure(dist::Rustfmt { compiler: self.compiler, target: self.target - }).is_some() { + }).is_some() || Self::should_install(builder) { install_rustfmt(builder, self.compiler.stage, self.target); } else { builder.info( diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index b76d80aa509a5..b6641180c92c0 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1022,10 +1022,6 @@ impl Step for Compiletest { cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler)); } - if mode == "run-make" && suite.ends_with("fulldeps") { - cmd.arg("--rust-demangler-path").arg(builder.tool_exe(Tool::RustDemangler)); - } - cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite)); cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite)); cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target)); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index fe3f1e78029d7..f66061975d64d 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -361,7 +361,6 @@ bootstrap_tool!( Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true; BuildManifest, "src/tools/build-manifest", "build-manifest"; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; - RustDemangler, "src/tools/rust-demangler", "rust-demangler"; RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes"; ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; 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 9a051caa06678..eac0ed24d509e 100644 --- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile @@ -1,44 +1,34 @@ -# We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other -# distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and -# SLES 11 SP4 (glibc 2.11, kernel 3.0). -FROM debian:6 +FROM centos:5 WORKDIR /build -# Debian 6 is EOL and no longer available from the usual mirrors, -# so we'll need to switch to http://archive.debian.org/ -RUN sed -i '/updates/d' /etc/apt/sources.list && \ - sed -i 's/httpredir/archive/' /etc/apt/sources.list +# Centos 5 is EOL and is no longer available from the usual mirrors, so switch +# to http://vault.centos.org/ +RUN sed -i 's/enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf +RUN sed -i 's/mirrorlist/#mirrorlist/' /etc/yum.repos.d/*.repo +RUN sed -i 's|#\(baseurl.*\)mirror.centos.org/centos/$releasever|\1vault.centos.org/5.11|' /etc/yum.repos.d/*.repo -RUN apt-get update && \ - apt-get install --allow-unauthenticated -y --no-install-recommends \ - automake \ - bzip2 \ - ca-certificates \ +RUN yum upgrade -y && yum install -y \ curl \ - file \ - g++ \ - g++-multilib \ + bzip2 \ gcc \ - gcc-multilib \ - git \ - lib32z1-dev \ - libedit-dev \ - libncurses-dev \ + gcc-c++ \ make \ - patch \ + glibc-devel \ perl \ - pkg-config \ - unzip \ + zlib-devel \ + file \ + xz \ + which \ + pkgconfig \ wget \ - xz-utils \ - zlib1g-dev + autoconf \ + gettext ENV PATH=/rustroot/bin:$PATH -ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib +ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig WORKDIR /tmp -RUN mkdir /home/user COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ # We need a build of openssl which supports SNI to download artifacts from @@ -48,14 +38,14 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/ RUN ./build-openssl.sh -# The `curl` binary on Debian 6 doesn't support SNI which is needed for fetching +# The `curl` binary on CentOS doesn't support SNI which is needed for fetching # some https urls we have, so install a new version of libcurl + curl which is # using the openssl we just built previously. # # Note that we also disable a bunch of optional features of curl that we don't # really need. COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/ -RUN ./build-curl.sh && apt-get remove -y curl +RUN ./build-curl.sh # binutils < 2.22 has a bug where the 32-bit executables it generates # immediately segfault in Rust, so we need to install our own binutils. @@ -64,24 +54,40 @@ RUN ./build-curl.sh && apt-get remove -y curl COPY host-x86_64/dist-x86_64-linux/build-binutils.sh /tmp/ RUN ./build-binutils.sh -# Need at least GCC 5.1 to compile LLVM nowadays +# libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS +# only has 2.6.4, so build our own +COPY host-x86_64/dist-x86_64-linux/build-cmake.sh /tmp/ +RUN ./build-cmake.sh + +# Need a newer version of gcc than centos has to compile LLVM nowadays COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/ -RUN ./build-gcc.sh && apt-get remove -y gcc g++ +RUN ./build-gcc.sh -# Debian 6 has Python 2.6 by default, but LLVM needs 2.7+ +# CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+ COPY host-x86_64/dist-x86_64-linux/build-python.sh /tmp/ RUN ./build-python.sh -# LLVM needs cmake 3.4.3 or higher, and is planning to raise to 3.13.4. -COPY host-x86_64/dist-x86_64-linux/build-cmake.sh /tmp/ -RUN ./build-cmake.sh - -# Now build LLVM+Clang, afterwards configuring further compilations to use the +# Now build LLVM+Clang 7, afterwards configuring further compilations to use the # clang/clang++ compilers. -COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ +COPY host-x86_64/dist-x86_64-linux/build-clang.sh host-x86_64/dist-x86_64-linux/llvm-project-centos.patch /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ +# Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for +# cloning, so download and build it here. +COPY host-x86_64/dist-x86_64-linux/build-git.sh /tmp/ +RUN ./build-git.sh + +# for sanitizers, we need kernel headers files newer than the ones CentOS ships +# with so we install newer ones here +COPY host-x86_64/dist-x86_64-linux/build-headers.sh /tmp/ +RUN ./build-headers.sh + +# OpenSSL requires a more recent version of perl +# with so we install newer ones here +COPY host-x86_64/dist-x86_64-linux/build-perl.sh /tmp/ +RUN ./build-perl.sh + COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh @@ -111,11 +117,4 @@ ENV CFLAGS -mstackrealign # libcurl, instead it should compile its own. ENV LIBCURL_NO_PKG_CONFIG 1 -# There was a bad interaction between "old" 32-bit binaries on current 64-bit -# kernels with selinux enabled, where ASLR mmap would sometimes choose a low -# address and then block it for being below `vm.mmap_min_addr` -> `EACCES`. -# This is probably a kernel bug, but setting `ulimit -Hs` works around it. -# See also `src/ci/run.sh` where this takes effect. -ENV SET_HARD_RLIMIT_STACK 1 - ENV DIST_REQUIRE_ALL_TOOLS 1 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 1f0978c0082c5..8b78214fbdd14 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 @@ -1,44 +1,34 @@ -# We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other -# distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and -# SLES 11 SP4 (glibc 2.11, kernel 3.0). -FROM debian:6 +FROM centos:5 WORKDIR /build -# Debian 6 is EOL and no longer available from the usual mirrors, -# so we'll need to switch to http://archive.debian.org/ -RUN sed -i '/updates/d' /etc/apt/sources.list && \ - sed -i 's/httpredir/archive/' /etc/apt/sources.list +# Centos 5 is EOL and is no longer available from the usual mirrors, so switch +# to http://vault.centos.org/ +RUN sed -i 's/enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf +RUN sed -i 's/mirrorlist/#mirrorlist/' /etc/yum.repos.d/*.repo +RUN sed -i 's|#\(baseurl.*\)mirror.centos.org/centos/$releasever|\1vault.centos.org/5.11|' /etc/yum.repos.d/*.repo -RUN apt-get update && \ - apt-get install --allow-unauthenticated -y --no-install-recommends \ - automake \ - bzip2 \ - ca-certificates \ +RUN yum upgrade -y && yum install -y \ curl \ - file \ - g++ \ - g++-multilib \ + bzip2 \ gcc \ - gcc-multilib \ - git \ - lib32z1-dev \ - libedit-dev \ - libncurses-dev \ + gcc-c++ \ make \ - patch \ + glibc-devel \ perl \ - pkg-config \ - unzip \ + zlib-devel \ + file \ + xz \ + which \ + pkgconfig \ wget \ - xz-utils \ - zlib1g-dev + autoconf \ + gettext ENV PATH=/rustroot/bin:$PATH -ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib +ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig WORKDIR /tmp -RUN mkdir /home/user COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ # We need a build of openssl which supports SNI to download artifacts from @@ -48,14 +38,14 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/ RUN ./build-openssl.sh -# The `curl` binary on Debian 6 doesn't support SNI which is needed for fetching +# The `curl` binary on CentOS doesn't support SNI which is needed for fetching # some https urls we have, so install a new version of libcurl + curl which is # using the openssl we just built previously. # # Note that we also disable a bunch of optional features of curl that we don't # really need. COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/ -RUN ./build-curl.sh && apt-get remove -y curl +RUN ./build-curl.sh # binutils < 2.22 has a bug where the 32-bit executables it generates # immediately segfault in Rust, so we need to install our own binutils. @@ -64,24 +54,40 @@ RUN ./build-curl.sh && apt-get remove -y curl COPY host-x86_64/dist-x86_64-linux/build-binutils.sh /tmp/ RUN ./build-binutils.sh -# Need at least GCC 5.1 to compile LLVM nowadays +# libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS +# only has 2.6.4, so build our own +COPY host-x86_64/dist-x86_64-linux/build-cmake.sh /tmp/ +RUN ./build-cmake.sh + +# Build a version of gcc capable of building LLVM 6 COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/ -RUN ./build-gcc.sh && apt-get remove -y gcc g++ +RUN ./build-gcc.sh -# Debian 6 has Python 2.6 by default, but LLVM needs 2.7+ +# CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+ COPY host-x86_64/dist-x86_64-linux/build-python.sh /tmp/ RUN ./build-python.sh -# LLVM needs cmake 3.4.3 or higher, and is planning to raise to 3.13.4. -COPY host-x86_64/dist-x86_64-linux/build-cmake.sh /tmp/ -RUN ./build-cmake.sh - -# Now build LLVM+Clang, afterwards configuring further compilations to use the +# Now build LLVM+Clang 7, afterwards configuring further compilations to use the # clang/clang++ compilers. -COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ +COPY host-x86_64/dist-x86_64-linux/build-clang.sh host-x86_64/dist-x86_64-linux/llvm-project-centos.patch /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ +# Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for +# cloning, so download and build it here. +COPY host-x86_64/dist-x86_64-linux/build-git.sh /tmp/ +RUN ./build-git.sh + +# for sanitizers, we need kernel headers files newer than the ones CentOS ships +# with so we install newer ones here +COPY host-x86_64/dist-x86_64-linux/build-headers.sh /tmp/ +RUN ./build-headers.sh + +# OpenSSL requires a more recent version of perl +# with so we install newer ones here +COPY host-x86_64/dist-x86_64-linux/build-perl.sh /tmp/ +RUN ./build-perl.sh + COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh index 2c00a628a1d35..518f6ef9b701d 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh @@ -12,6 +12,9 @@ cd llvm-project curl -L https://github.com/llvm/llvm-project/archive/$LLVM.tar.gz | \ tar xzf - --strip-components=1 +yum install -y patch +patch -Np1 < ../llvm-project-centos.patch + mkdir clang-build cd clang-build diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh index e17831a1afee5..84522a7b87a4b 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh @@ -3,15 +3,14 @@ set -ex source shared.sh -CMAKE=3.13.4 -curl -L https://github.com/Kitware/CMake/releases/download/v$CMAKE/cmake-$CMAKE.tar.gz | tar xzf - +curl https://cmake.org/files/v3.6/cmake-3.6.3.tar.gz | tar xzf - mkdir cmake-build cd cmake-build -hide_output ../cmake-$CMAKE/configure --prefix=/rustroot +hide_output ../cmake-3.6.3/configure --prefix=/rustroot hide_output make -j10 hide_output make install cd .. rm -rf cmake-build -rm -rf cmake-$CMAKE +rm -rf cmake-3.6.3 diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh index a60c6be9f3222..0c7eb5fdac9be 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh @@ -36,3 +36,4 @@ hide_output make install cd .. rm -rf curl-build rm -rf curl-$VERSION +yum erase -y curl diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh index 9d7461ebee32b..ddc2066537cef 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh @@ -37,3 +37,4 @@ ln -s gcc /rustroot/bin/cc cd .. rm -rf gcc-build rm -rf gcc-$GCC +yum erase -y gcc gcc-c++ binutils diff --git a/src/ci/exec-with-shell.py b/src/ci/exec-with-shell.py new file mode 100755 index 0000000000000..26ce69e33d9c3 --- /dev/null +++ b/src/ci/exec-with-shell.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# A simple wrapper that forwards the arguments to bash, unless the +# CI_OVERRIDE_SHELL environment variable is present: in that case the content +# of that environment variable is used as the shell path. + +import os +import sys +import subprocess + +try: + shell = os.environ["CI_OVERRIDE_SHELL"] +except KeyError: + shell = "bash" + +res = subprocess.call([shell] + sys.argv[1:]) +sys.exit(res) diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 5573d87aa2e55..0b3b77f217dbd 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -79,6 +79,7 @@ x--expand-yaml-anchors--remove: steps: - name: disable git crlf conversion run: git config --global core.autocrlf false + shell: bash - name: checkout the source code uses: actions/checkout@v1 @@ -94,6 +95,7 @@ x--expand-yaml-anchors--remove: - name: add extra environment variables run: src/ci/scripts/setup-environment.sh + shell: bash env: # Since it's not possible to merge `${{ matrix.env }}` with the other # variables in `job..env`, the variables defined in the matrix @@ -104,54 +106,67 @@ x--expand-yaml-anchors--remove: - name: decide whether to skip this job run: src/ci/scripts/should-skip-this.sh + shell: bash <<: *step - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh + shell: bash <<: *step - name: show the current environment run: src/ci/scripts/dump-environment.sh + shell: bash <<: *step - name: install awscli run: src/ci/scripts/install-awscli.sh + shell: bash <<: *step - name: install sccache run: src/ci/scripts/install-sccache.sh + shell: bash <<: *step - name: install clang run: src/ci/scripts/install-clang.sh + shell: bash <<: *step - name: install WIX run: src/ci/scripts/install-wix.sh + shell: bash <<: *step - name: ensure the build happens on a partition with enough space run: src/ci/scripts/symlink-build-dir.sh + shell: bash <<: *step - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash <<: *step - name: install MSYS2 run: src/ci/scripts/install-msys2.sh + shell: bash <<: *step - name: install MinGW run: src/ci/scripts/install-mingw.sh + shell: bash <<: *step - name: install ninja run: src/ci/scripts/install-ninja.sh + shell: bash <<: *step - name: enable ipv6 on Docker run: src/ci/scripts/enable-docker-ipv6.sh + shell: bash <<: *step # Disable automatic line ending conversion (again). On Windows, when we're @@ -161,18 +176,22 @@ x--expand-yaml-anchors--remove: # appropriate line endings. - name: disable git crlf conversion run: src/ci/scripts/disable-git-crlf-conversion.sh + shell: bash <<: *step - name: checkout submodules run: src/ci/scripts/checkout-submodules.sh + shell: bash <<: *step - name: ensure line endings are correct run: src/ci/scripts/verify-line-endings.sh + shell: bash <<: *step - name: run the build run: src/ci/scripts/run-build-from-ci.sh + shell: bash env: AWS_ACCESS_KEY_ID: ${{ env.CACHES_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }} @@ -181,6 +200,7 @@ x--expand-yaml-anchors--remove: - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh + shell: bash env: AWS_ACCESS_KEY_ID: ${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }} @@ -230,10 +250,18 @@ on: defaults: run: - # On Linux, macOS, and Windows, use the system-provided bash as the default - # shell. (This should only make a difference on Windows, where the default - # shell is PowerShell.) - shell: bash + # While on Linux and macOS builders it just forwards the arguments to the + # system bash, this wrapper allows switching from the host's bash.exe to + # the one we install along with MSYS2 mid-build on Windows. + # + # Once the step to install MSYS2 is executed, the CI_OVERRIDE_SHELL + # environment variable is set pointing to our MSYS2's bash.exe. From that + # moment the host's bash.exe will not be called anymore. + # + # This is needed because we can't launch our own bash.exe from the host + # bash.exe, as that would load two different cygwin1.dll in memory, causing + # "cygwin heap mismatch" errors. + shell: python src/ci/exec-with-shell.py {0} jobs: pr: diff --git a/src/ci/run.sh b/src/ci/run.sh index 5231aa2e76619..59f2736cbd406 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -20,18 +20,6 @@ if [ -f /proc/sys/kernel/core_pattern ]; then ulimit -c unlimited fi -# There was a bad interaction between "old" 32-bit binaries on current 64-bit -# kernels with selinux enabled, where ASLR mmap would sometimes choose a low -# address and then block it for being below `vm.mmap_min_addr` -> `EACCES`. -# This is probably a kernel bug, but setting `ulimit -Hs` works around it. -# See also `dist-i686-linux` where this setting is enabled. -if [ "$SET_HARD_RLIMIT_STACK" = "1" ]; then - rlimit_stack=$(ulimit -Ss) - if [ "$rlimit_stack" != "" ]; then - ulimit -Hs "$rlimit_stack" - fi -fi - ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh" diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh index 185d361582505..3a0c965a67710 100755 --- a/src/ci/scripts/install-msys2.sh +++ b/src/ci/scripts/install-msys2.sh @@ -12,6 +12,9 @@ if isWindows; then mkdir -p "${msys2Path}/home/${USERNAME}" ciCommandAddPath "${msys2Path}/usr/bin" + echo "switching shell to use our own bash" + ciCommandSetEnv CI_OVERRIDE_SHELL "${msys2Path}/usr/bin/bash.exe" + # Detect the native Python version installed on the agent. On GitHub # Actions, the C:\hostedtoolcache\windows\Python directory contains a # subdirectory for each installed Python version. diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 93908e9190e64..5e2e04c063bc4 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -26,9 +26,6 @@ of bugs: * Double-free, invalid free * Memory leaks -The memory leak detection is enabled by default on Linux, and can be enabled -with runtime flag `ASAN_OPTIONS=detect_leaks=1` on macOS. - AddressSanitizer is supported on the following targets: * `x86_64-apple-darwin` @@ -199,6 +196,10 @@ fn main() { ```shell $ export \ + CC=clang \ + CXX=clang++ \ + CFLAGS='-fsanitize=memory -fsanitize-memory-track-origins' \ + CXXFLAGS='-fsanitize=memory -fsanitize-memory-track-origins' \ RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' \ RUSTDOCFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' $ cargo clean diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 8398cfa3bd34e..15313e333ce73 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -1,9 +1,9 @@ //! A priority queue implemented with a binary heap. //! -//! Insertion and popping the largest element have *O*(log(*n*)) time complexity. -//! Checking the largest element is *O*(1). Converting a vector to a binary heap -//! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be -//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* \* log(*n*)) +//! Insertion and popping the largest element have `O(log(n))` time complexity. +//! Checking the largest element is `O(1)`. Converting a vector to a binary heap +//! can be done in-place, and has `O(n)` complexity. A binary heap can also be +//! converted to a sorted vector in-place, allowing it to be used for an `O(n * log(n))` //! in-place heapsort. //! //! # Examples @@ -235,7 +235,7 @@ use super::SpecExtend; /// /// | [push] | [pop] | [peek]/[peek\_mut] | /// |--------|-----------|--------------------| -/// | O(1)~ | *O*(log(*n*)) | *O*(1) | +/// | O(1)~ | O(log(n)) | O(1) | /// /// The value for `push` is an expected cost; the method documentation gives a /// more detailed analysis. @@ -398,7 +398,7 @@ impl BinaryHeap { /// /// # Time complexity /// - /// Cost is *O*(1) in the worst case. + /// Cost is `O(1)` in the worst case. #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub fn peek_mut(&mut self) -> Option> { if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: true }) } @@ -422,7 +422,7 @@ impl BinaryHeap { /// /// # Time complexity /// - /// The worst case cost of `pop` on a heap containing *n* elements is *O*(log(*n*)). + /// The worst case cost of `pop` on a heap containing *n* elements is `O(log(n))`. #[stable(feature = "rust1", since = "1.0.0")] pub fn pop(&mut self) -> Option { self.data.pop().map(|mut item| { @@ -455,15 +455,15 @@ impl BinaryHeap { /// /// The expected cost of `push`, averaged over every possible ordering of /// the elements being pushed, and over a sufficiently large number of - /// pushes, is *O*(1). This is the most meaningful cost metric when pushing + /// pushes, is `O(1)`. This is the most meaningful cost metric when pushing /// elements that are *not* already in any sorted pattern. /// /// The time complexity degrades if elements are pushed in predominantly /// ascending order. In the worst case, elements are pushed in ascending - /// sorted order and the amortized cost per push is *O*(log(*n*)) against a heap + /// sorted order and the amortized cost per push is `O(log(n))` against a heap /// containing *n* elements. /// - /// The worst case cost of a *single* call to `push` is *O*(*n*). The worst case + /// The worst case cost of a *single* call to `push` is `O(n)`. The worst case /// occurs when capacity is exhausted and needs a resize. The resize cost /// has been amortized in the previous figures. #[stable(feature = "rust1", since = "1.0.0")] @@ -643,7 +643,7 @@ impl BinaryHeap { /// The remaining elements will be removed on drop in heap order. /// /// Note: - /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`. + /// * `.drain_sorted()` is `O(n * log(n))`; much slower than `.drain()`. /// You should use the latter for most cases. /// /// # Examples @@ -756,7 +756,7 @@ impl BinaryHeap { /// /// # Time complexity /// - /// Cost is *O*(1) in the worst case. + /// Cost is `O(1)` in the worst case. #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&self) -> Option<&T> { self.data.get(0) @@ -1312,7 +1312,7 @@ unsafe impl TrustedLen for DrainSorted<'_, T> {} impl From> for BinaryHeap { /// Converts a `Vec` into a `BinaryHeap`. /// - /// This conversion happens in-place, and has *O*(*n*) time complexity. + /// This conversion happens in-place, and has `O(n)` time complexity. fn from(vec: Vec) -> BinaryHeap { let mut heap = BinaryHeap { data: vec }; heap.rebuild(); diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index d2f4278d0d0e0..bf5748739d470 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -47,9 +47,9 @@ use UnderflowResult::*; /// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. /// -/// [`Ord`]: core::cmp::Ord -/// [`Cell`]: core::cell::Cell -/// [`RefCell`]: core::cell::RefCell +/// [`Ord`]: ../../std/cmp/trait.Ord.html +/// [`Cell`]: ../../std/cell/struct.Cell.html +/// [`RefCell`]: ../../std/cell/struct.RefCell.html /// /// # Examples /// @@ -256,7 +256,8 @@ where /// This `struct` is created by the [`iter`] method on [`BTreeMap`]. See its /// documentation for more. /// -/// [`iter`]: BTreeMap::iter +/// [`iter`]: struct.BTreeMap.html#method.iter +/// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, K: 'a, V: 'a> { range: Range<'a, K, V>, @@ -275,7 +276,8 @@ impl fmt::Debug for Iter<'_, K, V> { /// This `struct` is created by the [`iter_mut`] method on [`BTreeMap`]. See its /// documentation for more. /// -/// [`iter_mut`]: BTreeMap::iter_mut +/// [`iter_mut`]: struct.BTreeMap.html#method.iter_mut +/// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct IterMut<'a, K: 'a, V: 'a> { @@ -288,7 +290,8 @@ pub struct IterMut<'a, K: 'a, V: 'a> { /// This `struct` is created by the [`into_iter`] method on [`BTreeMap`] /// (provided by the `IntoIterator` trait). See its documentation for more. /// -/// [`into_iter`]: IntoIterator::into_iter +/// [`into_iter`]: struct.BTreeMap.html#method.into_iter +/// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { front: Option, marker::Edge>>, @@ -312,7 +315,8 @@ impl fmt::Debug for IntoIter { /// This `struct` is created by the [`keys`] method on [`BTreeMap`]. See its /// documentation for more. /// -/// [`keys`]: BTreeMap::keys +/// [`keys`]: struct.BTreeMap.html#method.keys +/// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Keys<'a, K: 'a, V: 'a> { inner: Iter<'a, K, V>, @@ -330,7 +334,8 @@ impl fmt::Debug for Keys<'_, K, V> { /// This `struct` is created by the [`values`] method on [`BTreeMap`]. See its /// documentation for more. /// -/// [`values`]: BTreeMap::values +/// [`values`]: struct.BTreeMap.html#method.values +/// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K: 'a, V: 'a> { inner: Iter<'a, K, V>, @@ -348,7 +353,8 @@ impl fmt::Debug for Values<'_, K, V> { /// This `struct` is created by the [`values_mut`] method on [`BTreeMap`]. See its /// documentation for more. /// -/// [`values_mut`]: BTreeMap::values_mut +/// [`values_mut`]: struct.BTreeMap.html#method.values_mut +/// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "map_values_mut", since = "1.10.0")] #[derive(Debug)] pub struct ValuesMut<'a, K: 'a, V: 'a> { @@ -360,7 +366,8 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { /// This `struct` is created by the [`range`] method on [`BTreeMap`]. See its /// documentation for more. /// -/// [`range`]: BTreeMap::range +/// [`range`]: struct.BTreeMap.html#method.range +/// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, K: 'a, V: 'a> { front: Option, K, V, marker::Leaf>, marker::Edge>>, @@ -379,7 +386,8 @@ impl fmt::Debug for Range<'_, K, V> { /// This `struct` is created by the [`range_mut`] method on [`BTreeMap`]. See its /// documentation for more. /// -/// [`range_mut`]: BTreeMap::range_mut +/// [`range_mut`]: struct.BTreeMap.html#method.range_mut +/// [`BTreeMap`]: struct.BTreeMap.html #[stable(feature = "btree_range", since = "1.17.0")] pub struct RangeMut<'a, K: 'a, V: 'a> { front: Option, K, V, marker::Leaf>, marker::Edge>>, @@ -404,7 +412,8 @@ impl fmt::Debug for RangeMut<'_, K, V> { /// /// This `enum` is constructed from the [`entry`] method on [`BTreeMap`]. /// -/// [`entry`]: BTreeMap::entry +/// [`BTreeMap`]: struct.BTreeMap.html +/// [`entry`]: struct.BTreeMap.html#method.entry #[stable(feature = "rust1", since = "1.0.0")] pub enum Entry<'a, K: 'a, V: 'a> { /// A vacant entry. diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index 35f4ef1d9b4c7..d8959966fe5ad 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -22,9 +22,10 @@ use super::Recover; /// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. /// -/// [`Ord`]: core::cmp::Ord -/// [`Cell`]: core::cell::Cell -/// [`RefCell`]: core::cell::RefCell +/// [`BTreeMap`]: struct.BTreeMap.html +/// [`Ord`]: ../../std/cmp/trait.Ord.html +/// [`Cell`]: ../../std/cell/struct.Cell.html +/// [`RefCell`]: ../../std/cell/struct.RefCell.html /// /// # Examples /// @@ -77,7 +78,8 @@ impl Clone for BTreeSet { /// This `struct` is created by the [`iter`] method on [`BTreeSet`]. /// See its documentation for more. /// -/// [`iter`]: BTreeSet::iter +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`iter`]: struct.BTreeSet.html#method.iter #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { iter: Keys<'a, T, ()>, @@ -95,7 +97,8 @@ impl fmt::Debug for Iter<'_, T> { /// This `struct` is created by the [`into_iter`] method on [`BTreeSet`] /// (provided by the `IntoIterator` trait). See its documentation for more. /// -/// [`into_iter`]: BTreeSet#method.into_iter +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`into_iter`]: struct.BTreeSet.html#method.into_iter #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct IntoIter { @@ -107,7 +110,8 @@ pub struct IntoIter { /// This `struct` is created by the [`range`] method on [`BTreeSet`]. /// See its documentation for more. /// -/// [`range`]: BTreeSet::range +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`range`]: struct.BTreeSet.html#method.range #[derive(Debug)] #[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, T: 'a> { @@ -190,7 +194,8 @@ where /// This `struct` is created by the [`difference`] method on [`BTreeSet`]. /// See its documentation for more. /// -/// [`difference`]: BTreeSet::difference +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`difference`]: struct.BTreeSet.html#method.difference #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference<'a, T: 'a> { inner: DifferenceInner<'a, T>, @@ -222,7 +227,8 @@ impl fmt::Debug for Difference<'_, T> { /// This `struct` is created by the [`symmetric_difference`] method on /// [`BTreeSet`]. See its documentation for more. /// -/// [`symmetric_difference`]: BTreeSet::symmetric_difference +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference #[stable(feature = "rust1", since = "1.0.0")] pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner>); @@ -238,7 +244,8 @@ impl fmt::Debug for SymmetricDifference<'_, T> { /// This `struct` is created by the [`intersection`] method on [`BTreeSet`]. /// See its documentation for more. /// -/// [`intersection`]: BTreeSet::intersection +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`intersection`]: struct.BTreeSet.html#method.intersection #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection<'a, T: 'a> { inner: IntersectionInner<'a, T>, @@ -270,7 +277,8 @@ impl fmt::Debug for Intersection<'_, T> { /// This `struct` is created by the [`union`] method on [`BTreeSet`]. /// See its documentation for more. /// -/// [`union`]: BTreeSet::union +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`union`]: struct.BTreeSet.html#method.union #[stable(feature = "rust1", since = "1.0.0")] pub struct Union<'a, T: 'a>(MergeIterInner>); diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 1f875f6c5217f..36b5785fdf6c5 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -404,7 +404,7 @@ impl LinkedList { /// This reuses all the nodes from `other` and moves them into `self`. After /// this operation, `other` becomes empty. /// - /// This operation should compute in *O*(1) time and *O*(1) memory. + /// This operation should compute in `O(1)` time and `O(1)` memory. /// /// # Examples /// @@ -561,7 +561,7 @@ impl LinkedList { /// Returns `true` if the `LinkedList` is empty. /// - /// This operation should compute in *O*(1) time. + /// This operation should compute in `O(1)` time. /// /// # Examples /// @@ -582,7 +582,7 @@ impl LinkedList { /// Returns the length of the `LinkedList`. /// - /// This operation should compute in *O*(1) time. + /// This operation should compute in `O(1)` time. /// /// # Examples /// @@ -608,7 +608,7 @@ impl LinkedList { /// Removes all elements from the `LinkedList`. /// - /// This operation should compute in *O*(*n*) time. + /// This operation should compute in `O(n)` time. /// /// # Examples /// @@ -751,7 +751,7 @@ impl LinkedList { /// Adds an element first in the list. /// - /// This operation should compute in *O*(1) time. + /// This operation should compute in `O(1)` time. /// /// # Examples /// @@ -774,7 +774,7 @@ impl LinkedList { /// Removes the first element and returns it, or `None` if the list is /// empty. /// - /// This operation should compute in *O*(1) time. + /// This operation should compute in `O(1)` time. /// /// # Examples /// @@ -797,7 +797,7 @@ impl LinkedList { /// Appends an element to the back of a list. /// - /// This operation should compute in *O*(1) time. + /// This operation should compute in `O(1)` time. /// /// # Examples /// @@ -817,7 +817,7 @@ impl LinkedList { /// Removes the last element from a list and returns it, or `None` if /// it is empty. /// - /// This operation should compute in *O*(1) time. + /// This operation should compute in `O(1)` time. /// /// # Examples /// @@ -838,7 +838,7 @@ impl LinkedList { /// Splits the list into two at the given index. Returns everything after the given index, /// including the index. /// - /// This operation should compute in *O*(*n*) time. + /// This operation should compute in `O(n)` time. /// /// # Panics /// @@ -894,7 +894,7 @@ impl LinkedList { /// Removes the element at the given index and returns it. /// - /// This operation should compute in *O*(*n*) time. + /// This operation should compute in `O(n)` time. /// /// # Panics /// Panics if at >= len diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index fa65d6ce8d725..2efb94e8afe57 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1,7 +1,7 @@ //! A double-ended queue implemented with a growable ring buffer. //! -//! This queue has *O*(1) amortized inserts and removals from both ends of the -//! container. It also has *O*(1) indexing like a vector. The contained elements +//! This queue has `O(1)` amortized inserts and removals from both ends of the +//! container. It also has `O(1)` indexing like a vector. The contained elements //! are not required to be copyable, and the queue will be sendable if the //! contained type is sendable. @@ -1512,7 +1512,7 @@ impl VecDeque { /// Removes an element from anywhere in the `VecDeque` and returns it, /// replacing it with the first element. /// - /// This does not preserve ordering, but is *O*(1). + /// This does not preserve ordering, but is `O(1)`. /// /// Returns `None` if `index` is out of bounds. /// @@ -1547,7 +1547,7 @@ impl VecDeque { /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the /// last element. /// - /// This does not preserve ordering, but is *O*(1). + /// This does not preserve ordering, but is `O(1)`. /// /// Returns `None` if `index` is out of bounds. /// @@ -2331,7 +2331,7 @@ impl VecDeque { /// /// # Complexity /// - /// Takes `*O*(min(mid, len() - mid))` time and no extra space. + /// Takes `O(min(mid, len() - mid))` time and no extra space. /// /// # Examples /// @@ -2374,7 +2374,7 @@ impl VecDeque { /// /// # Complexity /// - /// Takes `*O*(min(k, len() - k))` time and no extra space. + /// Takes `O(min(k, len() - k))` time and no extra space. /// /// # Examples /// @@ -3076,7 +3076,7 @@ impl From> for Vec { /// [`Vec`]: crate::vec::Vec /// [`VecDeque`]: crate::collections::VecDeque /// - /// This never needs to re-allocate, but does need to do *O*(*n*) data movement if + /// This never needs to re-allocate, but does need to do `O(n)` data movement if /// the circular buffer doesn't happen to be at the beginning of the allocation. /// /// # Examples @@ -3084,7 +3084,7 @@ impl From> for Vec { /// ``` /// use std::collections::VecDeque; /// - /// // This one is *O*(1). + /// // This one is O(1). /// let deque: VecDeque<_> = (1..5).collect(); /// let ptr = deque.as_slices().0.as_ptr(); /// let vec = Vec::from(deque); diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 339592728ac24..57927c688479b 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -240,6 +240,8 @@ impl str { /// While doing so, it attempts to find matches of a pattern. If it finds any, it /// replaces them with the replacement string slice. /// + /// [`String`]: string/struct.String.html + /// /// # Examples /// /// Basic usage: @@ -278,6 +280,8 @@ impl str { /// While doing so, it attempts to find matches of a pattern. If it finds any, it /// replaces them with the replacement string slice at most `count` times. /// + /// [`String`]: string/struct.String.html + /// /// # Examples /// /// Basic usage: @@ -320,6 +324,8 @@ impl str { /// the case, this function returns a [`String`] instead of modifying the /// parameter in-place. /// + /// [`String`]: string/struct.String.html + /// /// # Examples /// /// Basic usage: @@ -405,6 +411,8 @@ impl str { /// the case, this function returns a [`String`] instead of modifying the /// parameter in-place. /// + /// [`String`]: string/struct.String.html + /// /// # Examples /// /// Basic usage: @@ -451,7 +459,8 @@ impl str { /// Converts a [`Box`] into a [`String`] without copying or allocating. /// - /// [`Box`]: Box + /// [`String`]: string/struct.String.html + /// [`Box`]: boxed/struct.Box.html /// /// # Examples /// @@ -476,6 +485,8 @@ impl str { /// /// This function will panic if the capacity would overflow. /// + /// [`String`]: string/struct.String.html + /// /// # Examples /// /// Basic usage: @@ -514,7 +525,7 @@ impl str { /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); /// ``` /// - /// [`make_ascii_uppercase`]: str::make_ascii_uppercase + /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase /// [`to_uppercase`]: #method.to_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] @@ -544,7 +555,7 @@ impl str { /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); /// ``` /// - /// [`make_ascii_lowercase`]: str::make_ascii_lowercase + /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase /// [`to_lowercase`]: #method.to_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 15f10df9a45cc..5b671b41b5bf6 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -4,6 +4,8 @@ //! [`ToString`]s, and several error types that may result from working with //! [`String`]s. //! +//! [`ToString`]: trait.ToString.html +//! //! # Examples //! //! There are multiple ways to create a new [`String`] from a string literal: @@ -18,6 +20,8 @@ //! You can create a new [`String`] from an existing one by concatenating with //! `+`: //! +//! [`String`]: struct.String.html +//! //! ``` //! let s = "Hello".to_string(); //! @@ -63,11 +67,11 @@ use crate::vec::Vec; /// contents of the string. It has a close relationship with its borrowed /// counterpart, the primitive [`str`]. /// -/// # Examples +/// [`str`]: ../../std/primitive.str.html /// -/// You can create a `String` from [a literal string][str] with [`String::from`]: +/// # Examples /// -/// [`String::from`]: From::from +/// You can create a `String` from a literal string with [`String::from`]: /// /// ``` /// let hello = String::from("Hello, world!"); @@ -83,8 +87,10 @@ use crate::vec::Vec; /// hello.push_str("orld!"); /// ``` /// -/// [`push`]: String::push -/// [`push_str`]: String::push_str +/// [`String::from`]: #method.from +/// [`char`]: ../../std/primitive.char.html +/// [`push`]: #method.push +/// [`push_str`]: #method.push_str /// /// If you have a vector of UTF-8 bytes, you can create a `String` from it with /// the [`from_utf8`] method: @@ -99,7 +105,7 @@ use crate::vec::Vec; /// assert_eq!("💖", sparkle_heart); /// ``` /// -/// [`from_utf8`]: String::from_utf8 +/// [`from_utf8`]: #method.from_utf8 /// /// # UTF-8 /// @@ -122,8 +128,8 @@ use crate::vec::Vec; /// The [`bytes`] and [`chars`] methods return iterators over the first /// two, respectively. /// -/// [`bytes`]: str::bytes -/// [`chars`]: str::chars +/// [`bytes`]: #method.bytes +/// [`chars`]: #method.chars /// /// # Deref /// @@ -209,9 +215,9 @@ use crate::vec::Vec; /// assert_eq!(String::from("Once upon a time..."), s); /// ``` /// -/// [`as_ptr`]: str::as_ptr -/// [`len`]: String::len -/// [`capacity`]: String::capacity +/// [`as_ptr`]: #method.as_ptr +/// [`len`]: #method.len +/// [`capacity`]: #method.capacity /// /// If a `String` has enough capacity, adding elements to it will not /// re-allocate. For example, consider this program: @@ -253,7 +259,7 @@ use crate::vec::Vec; /// } /// ``` /// -/// [`with_capacity`]: String::with_capacity +/// [`with_capacity`]: #method.with_capacity /// /// We end up with a different output: /// @@ -268,9 +274,9 @@ use crate::vec::Vec; /// /// Here, there's no need to allocate more memory inside the loop. /// -/// [`&str`]: str -/// [`Deref`]: core::ops::Deref -/// [`as_str()`]: String::as_str +/// [`&str`]: ../../std/primitive.str.html +/// [`Deref`]: ../../std/ops/trait.Deref.html +/// [`as_str()`]: struct.String.html#method.as_str #[derive(PartialOrd, Eq, Ord)] #[cfg_attr(not(test), rustc_diagnostic_item = "string_type")] #[stable(feature = "rust1", since = "1.0.0")] @@ -285,18 +291,20 @@ pub struct String { /// [`into_bytes`] method will give back the byte vector that was used in the /// conversion attempt. /// -/// [`from_utf8`]: String::from_utf8 -/// [`into_bytes`]: FromUtf8Error::into_bytes +/// [`from_utf8`]: struct.String.html#method.from_utf8 +/// [`String`]: struct.String.html +/// [`into_bytes`]: struct.FromUtf8Error.html#method.into_bytes /// /// The [`Utf8Error`] type provided by [`std::str`] represents an error that may /// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's /// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error` /// through the [`utf8_error`] method. /// -/// [`Utf8Error`]: core::str::Utf8Error -/// [`std::str`]: core::str -/// [`&str`]: str -/// [`utf8_error`]: Self::utf8_error +/// [`Utf8Error`]: ../../std/str/struct.Utf8Error.html +/// [`std::str`]: ../../std/str/index.html +/// [`u8`]: ../../std/primitive.u8.html +/// [`&str`]: ../../std/primitive.str.html +/// [`utf8_error`]: #method.utf8_error /// /// # Examples /// @@ -322,7 +330,9 @@ pub struct FromUtf8Error { /// /// This type is the error type for the [`from_utf16`] method on [`String`]. /// -/// [`from_utf16`]: String::from_utf16 +/// [`from_utf16`]: struct.String.html#method.from_utf16 +/// [`String`]: struct.String.html +/// /// # Examples /// /// Basic usage: @@ -348,7 +358,7 @@ impl String { /// consider the [`with_capacity`] method to prevent excessive /// re-allocation. /// - /// [`with_capacity`]: String::with_capacity + /// [`with_capacity`]: #method.with_capacity /// /// # Examples /// @@ -373,12 +383,12 @@ impl String { /// appending a bunch of data to the `String`, reducing the number of /// reallocations it needs to do. /// - /// [`capacity`]: String::capacity + /// [`capacity`]: #method.capacity /// /// If the given capacity is `0`, no allocation will occur, and this method /// is identical to the [`new`] method. /// - /// [`new`]: String::new + /// [`new`]: #method.new /// /// # Examples /// @@ -469,10 +479,15 @@ impl String { /// See the docs for [`FromUtf8Error`] for more details on what you can do /// with this error. /// - /// [`from_utf8_unchecked`]: String::from_utf8_unchecked - /// [`Vec`]: crate::vec::Vec - /// [`&str`]: str - /// [`into_bytes`]: String::into_bytes + /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked + /// [`String`]: struct.String.html + /// [`u8`]: ../../std/primitive.u8.html + /// [`Vec`]: ../../std/vec/struct.Vec.html + /// [`&str`]: ../../std/primitive.str.html + /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html + /// [`into_bytes`]: struct.String.html#method.into_bytes + /// [`FromUtf8Error`]: struct.FromUtf8Error.html + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8(vec: Vec) -> Result { @@ -491,15 +506,16 @@ impl String { /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: � /// + /// [`u8`]: ../../std/primitive.u8.html /// [byteslice]: ../../std/primitive.slice.html - /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html /// /// If you are sure that the byte slice is valid UTF-8, and you don't want /// to incur the overhead of the conversion, there is an unsafe version /// of this function, [`from_utf8_unchecked`], which has the same behavior /// but skips the checks. /// - /// [`from_utf8_unchecked`]: String::from_utf8_unchecked + /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked /// /// This function returns a [`Cow<'a, str>`]. If our byte slice is invalid /// UTF-8, then we need to insert the replacement characters, which will @@ -507,7 +523,7 @@ impl String { /// it's already valid UTF-8, we don't need a new allocation. This return /// type allows us to handle both cases. /// - /// [`Cow<'a, str>`]: crate::borrow::Cow + /// [`Cow<'a, str>`]: ../../std/borrow/enum.Cow.html /// /// # Examples /// @@ -567,6 +583,8 @@ impl String { /// Decode a UTF-16 encoded vector `v` into a `String`, returning [`Err`] /// if `v` contains any invalid data. /// + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// /// # Examples /// /// Basic usage: @@ -605,9 +623,9 @@ impl String { /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 /// conversion requires a memory allocation. /// - /// [`from_utf8_lossy`]: String::from_utf8_lossy - /// [`Cow<'a, str>`]: crate::borrow::Cow - /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// [`from_utf8_lossy`]: #method.from_utf8_lossy + /// [`Cow<'a, str>`]: ../borrow/enum.Cow.html + /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html /// /// # Examples /// @@ -641,7 +659,7 @@ impl String { /// into a `String` with the [`from_raw_parts`] function, allowing /// the destructor to perform the cleanup. /// - /// [`from_raw_parts`]: String::from_raw_parts + /// [`from_raw_parts`]: #method.from_raw_parts /// /// # Examples /// @@ -714,7 +732,7 @@ impl String { /// /// See the safe version, [`from_utf8`], for more details. /// - /// [`from_utf8`]: String::from_utf8 + /// [`from_utf8`]: struct.String.html#method.from_utf8 /// /// # Safety /// @@ -849,7 +867,8 @@ impl String { /// /// Panics if the new capacity overflows [`usize`]. /// - /// [`reserve_exact`]: String::reserve_exact + /// [`reserve_exact`]: struct.String.html#method.reserve_exact + /// [`usize`]: ../../std/primitive.usize.html /// /// # Examples /// @@ -892,7 +911,7 @@ impl String { /// Consider using the [`reserve`] method unless you absolutely know /// better than the allocator. /// - /// [`reserve`]: String::reserve + /// [`reserve`]: #method.reserve /// /// # Panics /// @@ -1057,6 +1076,8 @@ impl String { /// Appends the given [`char`] to the end of this `String`. /// + /// [`char`]: ../../std/primitive.char.html + /// /// # Examples /// /// Basic usage: @@ -1083,7 +1104,7 @@ impl String { /// /// The inverse of this method is [`from_utf8`]. /// - /// [`from_utf8`]: String::from_utf8 + /// [`from_utf8`]: #method.from_utf8 /// /// # Examples /// @@ -1112,6 +1133,8 @@ impl String { /// /// Panics if `new_len` does not lie on a [`char`] boundary. /// + /// [`char`]: ../../std/primitive.char.html + /// /// # Examples /// /// Basic usage: @@ -1136,6 +1159,8 @@ impl String { /// /// Returns [`None`] if this `String` is empty. /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// /// # Examples /// /// Basic usage: @@ -1162,7 +1187,7 @@ impl String { /// Removes a [`char`] from this `String` at a byte position and returns it. /// - /// This is an *O*(*n*) operation, as it requires copying every element in the + /// This is an `O(n)` operation, as it requires copying every element in the /// buffer. /// /// # Panics @@ -1170,6 +1195,8 @@ impl String { /// Panics if `idx` is larger than or equal to the `String`'s length, /// or if it does not lie on a [`char`] boundary. /// + /// [`char`]: ../../std/primitive.char.html + /// /// # Examples /// /// Basic usage: @@ -1262,7 +1289,7 @@ impl String { /// Inserts a character into this `String` at a byte position. /// - /// This is an *O*(*n*) operation as it requires copying every element in the + /// This is an `O(n)` operation as it requires copying every element in the /// buffer. /// /// # Panics @@ -1270,6 +1297,8 @@ impl String { /// Panics if `idx` is larger than the `String`'s length, or if it does not /// lie on a [`char`] boundary. /// + /// [`char`]: ../../std/primitive.char.html + /// /// # Examples /// /// Basic usage: @@ -1309,7 +1338,7 @@ impl String { /// Inserts a string slice into this `String` at a byte position. /// - /// This is an *O*(*n*) operation as it requires copying every element in the + /// This is an `O(n)` operation as it requires copying every element in the /// buffer. /// /// # Panics @@ -1317,6 +1346,8 @@ impl String { /// Panics if `idx` is larger than the `String`'s length, or if it does not /// lie on a [`char`] boundary. /// + /// [`char`]: ../../std/primitive.char.html + /// /// # Examples /// /// Basic usage: @@ -1476,6 +1507,8 @@ impl String { /// Panics if the starting point or end point do not lie on a [`char`] /// boundary, or if they're out of bounds. /// + /// [`char`]: ../../std/primitive.char.html + /// /// # Examples /// /// Basic usage: @@ -1534,6 +1567,9 @@ impl String { /// Panics if the starting point or end point do not lie on a [`char`] /// boundary, or if they're out of bounds. /// + /// [`char`]: ../../std/primitive.char.html + /// [`Vec::splice`]: ../../std/vec/struct.Vec.html#method.splice + /// /// # Examples /// /// Basic usage: @@ -1574,6 +1610,9 @@ impl String { /// /// This will drop any excess capacity. /// + /// [`Box`]: ../../std/boxed/struct.Box.html + /// [`str`]: ../../std/primitive.str.html + /// /// # Examples /// /// Basic usage: @@ -1641,8 +1680,10 @@ impl FromUtf8Error { /// an analogue to `FromUtf8Error`. See its documentation for more details /// on using it. /// - /// [`std::str`]: core::str - /// [`&str`]: str + /// [`Utf8Error`]: ../../std/str/struct.Utf8Error.html + /// [`std::str`]: ../../std/str/index.html + /// [`u8`]: ../../std/primitive.u8.html + /// [`&str`]: ../../std/primitive.str.html /// /// # Examples /// @@ -1971,7 +2012,7 @@ impl hash::Hash for String { /// /// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if /// necessary). This is done to avoid allocating a new `String` and copying the entire contents on -/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by +/// every operation, which would lead to `O(n^2)` running time when building an `n`-byte string by /// repeated concatenation. /// /// The string on the right-hand side is only borrowed; its contents are copied into the returned @@ -2146,7 +2187,7 @@ impl ops::DerefMut for String { /// /// This alias exists for backwards compatibility, and may be eventually deprecated. /// -/// [`Infallible`]: core::convert::Infallible +/// [`Infallible`]: ../../core/convert/enum.Infallible.html #[stable(feature = "str_parse_error", since = "1.5.0")] pub type ParseError = core::convert::Infallible; @@ -2166,7 +2207,7 @@ impl FromStr for String { /// [`Display`] should be implemented instead, and you get the `ToString` /// implementation for free. /// -/// [`Display`]: fmt::Display +/// [`Display`]: ../../std/fmt/trait.Display.html #[stable(feature = "rust1", since = "1.0.0")] pub trait ToString { /// Converts the given value to a `String`. @@ -2424,7 +2465,8 @@ impl fmt::Write for String { /// This struct is created by the [`drain`] method on [`String`]. See its /// documentation for more. /// -/// [`drain`]: String::drain +/// [`drain`]: struct.String.html#method.drain +/// [`String`]: struct.String.html #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a> { /// Will be used as &'a mut String in the destructor diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs index 37202b2774dc6..f6460470bfe18 100644 --- a/src/libcore/fmt/rt/v1.rs +++ b/src/libcore/fmt/rt/v1.rs @@ -33,13 +33,9 @@ pub enum Alignment { Unknown, } -/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers. #[derive(Copy, Clone)] pub enum Count { - /// Specified with a literal number, stores the value Is(usize), - /// Specified using `$` and `*` syntaxes, stores the index into `args` Param(usize), - /// Not specified Implied, } diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 3116815f5d655..9ebcde79b633d 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -45,8 +45,7 @@ use crate::intrinsics; /// ``` #[inline] #[stable(feature = "unreachable", since = "1.27.0")] -#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")] -pub const unsafe fn unreachable_unchecked() -> ! { +pub unsafe fn unreachable_unchecked() -> ! { // SAFETY: the safety contract for `intrinsics::unreachable` must // be upheld by the caller. unsafe { intrinsics::unreachable() } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 049f51fb1035a..080760aa81f30 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -932,7 +932,6 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::hint::unreachable_unchecked`](../../std/hint/fn.unreachable_unchecked.html). - #[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")] pub fn unreachable() -> !; /// Informs the optimizer that a condition is always true. @@ -1958,14 +1957,8 @@ extern "rust-intrinsic" { /// Internal placeholder for injecting code coverage counters when the "instrument-coverage" /// option is enabled. The placeholder is replaced with `llvm.instrprof.increment` during code /// generation. - #[cfg(not(bootstrap))] #[lang = "count_code_region"] - pub fn count_code_region( - function_source_hash: u64, - index: u32, - start_byte_pos: u32, - end_byte_pos: u32, - ); + pub fn count_code_region(index: u32, start_byte_pos: u32, end_byte_pos: u32); /// Internal marker for code coverage expressions, injected into the MIR when the /// "instrument-coverage" option is enabled. This intrinsic is not converted into a @@ -1973,8 +1966,6 @@ extern "rust-intrinsic" { /// "coverage map", which is injected into the generated code, as additional data. /// This marker identifies a code region and two other counters or counter expressions /// whose sum is the number of times the code region was executed. - #[cfg(not(bootstrap))] - #[lang = "coverage_counter_add"] pub fn coverage_counter_add( index: u32, left_index: u32, @@ -1986,8 +1977,6 @@ extern "rust-intrinsic" { /// This marker identifies a code region and two other counters or counter expressions /// whose difference is the number of times the code region was executed. /// (See `coverage_counter_add` for more information.) - #[cfg(not(bootstrap))] - #[lang = "coverage_counter_subtract"] pub fn coverage_counter_subtract( index: u32, left_index: u32, diff --git a/src/libcore/lazy.rs b/src/libcore/lazy.rs deleted file mode 100644 index 5cf7217ef11e8..0000000000000 --- a/src/libcore/lazy.rs +++ /dev/null @@ -1,379 +0,0 @@ -//! Lazy values and one-time initialization of static data. - -use crate::cell::{Cell, UnsafeCell}; -use crate::fmt; -use crate::mem; -use crate::ops::Deref; - -/// A cell which can be written to only once. -/// -/// Unlike `RefCell`, a `OnceCell` only provides shared `&T` references to its value. -/// Unlike `Cell`, a `OnceCell` doesn't require copying or replacing the value to access it. -/// -/// # Examples -/// -/// ``` -/// #![feature(once_cell)] -/// -/// use std::lazy::OnceCell; -/// -/// let cell = OnceCell::new(); -/// assert!(cell.get().is_none()); -/// -/// let value: &String = cell.get_or_init(|| { -/// "Hello, World!".to_string() -/// }); -/// assert_eq!(value, "Hello, World!"); -/// assert!(cell.get().is_some()); -/// ``` -#[unstable(feature = "once_cell", issue = "74465")] -pub struct OnceCell { - // Invariant: written to at most once. - inner: UnsafeCell>, -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl Default for OnceCell { - fn default() -> Self { - Self::new() - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl fmt::Debug for OnceCell { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.get() { - Some(v) => f.debug_tuple("OnceCell").field(v).finish(), - None => f.write_str("OnceCell(Uninit)"), - } - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl Clone for OnceCell { - fn clone(&self) -> OnceCell { - let res = OnceCell::new(); - if let Some(value) = self.get() { - match res.set(value.clone()) { - Ok(()) => (), - Err(_) => unreachable!(), - } - } - res - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl PartialEq for OnceCell { - fn eq(&self, other: &Self) -> bool { - self.get() == other.get() - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl Eq for OnceCell {} - -#[unstable(feature = "once_cell", issue = "74465")] -impl From for OnceCell { - fn from(value: T) -> Self { - OnceCell { inner: UnsafeCell::new(Some(value)) } - } -} - -impl OnceCell { - /// Creates a new empty cell. - #[unstable(feature = "once_cell", issue = "74465")] - pub const fn new() -> OnceCell { - OnceCell { inner: UnsafeCell::new(None) } - } - - /// Gets the reference to the underlying value. - /// - /// Returns `None` if the cell is empty. - #[unstable(feature = "once_cell", issue = "74465")] - pub fn get(&self) -> Option<&T> { - // Safety: Safe due to `inner`'s invariant - unsafe { &*self.inner.get() }.as_ref() - } - - /// Gets the mutable reference to the underlying value. - /// - /// Returns `None` if the cell is empty. - #[unstable(feature = "once_cell", issue = "74465")] - pub fn get_mut(&mut self) -> Option<&mut T> { - // Safety: Safe because we have unique access - unsafe { &mut *self.inner.get() }.as_mut() - } - - /// Sets the contents of the cell to `value`. - /// - /// # Errors - /// - /// This method returns `Ok(())` if the cell was empty and `Err(value)` if - /// it was full. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::OnceCell; - /// - /// let cell = OnceCell::new(); - /// assert!(cell.get().is_none()); - /// - /// assert_eq!(cell.set(92), Ok(())); - /// assert_eq!(cell.set(62), Err(62)); - /// - /// assert!(cell.get().is_some()); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn set(&self, value: T) -> Result<(), T> { - // Safety: Safe because we cannot have overlapping mutable borrows - let slot = unsafe { &*self.inner.get() }; - if slot.is_some() { - return Err(value); - } - - // Safety: This is the only place where we set the slot, no races - // due to reentrancy/concurrency are possible, and we've - // checked that slot is currently `None`, so this write - // maintains the `inner`'s invariant. - let slot = unsafe { &mut *self.inner.get() }; - *slot = Some(value); - Ok(()) - } - - /// Gets the contents of the cell, initializing it with `f` - /// if the cell was empty. - /// - /// # Panics - /// - /// If `f` panics, the panic is propagated to the caller, and the cell - /// remains uninitialized. - /// - /// It is an error to reentrantly initialize the cell from `f`. Doing - /// so results in a panic. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::OnceCell; - /// - /// let cell = OnceCell::new(); - /// let value = cell.get_or_init(|| 92); - /// assert_eq!(value, &92); - /// let value = cell.get_or_init(|| unreachable!()); - /// assert_eq!(value, &92); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn get_or_init(&self, f: F) -> &T - where - F: FnOnce() -> T, - { - match self.get_or_try_init(|| Ok::(f())) { - Ok(val) => val, - } - } - - /// Gets the contents of the cell, initializing it with `f` if - /// the cell was empty. If the cell was empty and `f` failed, an - /// error is returned. - /// - /// # Panics - /// - /// If `f` panics, the panic is propagated to the caller, and the cell - /// remains uninitialized. - /// - /// It is an error to reentrantly initialize the cell from `f`. Doing - /// so results in a panic. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::OnceCell; - /// - /// let cell = OnceCell::new(); - /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); - /// assert!(cell.get().is_none()); - /// let value = cell.get_or_try_init(|| -> Result { - /// Ok(92) - /// }); - /// assert_eq!(value, Ok(&92)); - /// assert_eq!(cell.get(), Some(&92)) - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn get_or_try_init(&self, f: F) -> Result<&T, E> - where - F: FnOnce() -> Result, - { - if let Some(val) = self.get() { - return Ok(val); - } - let val = f()?; - // Note that *some* forms of reentrant initialization might lead to - // UB (see `reentrant_init` test). I believe that just removing this - // `assert`, while keeping `set/get` would be sound, but it seems - // better to panic, rather than to silently use an old value. - assert!(self.set(val).is_ok(), "reentrant init"); - Ok(self.get().unwrap()) - } - - /// Consumes the cell, returning the wrapped value. - /// - /// Returns `None` if the cell was empty. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::OnceCell; - /// - /// let cell: OnceCell = OnceCell::new(); - /// assert_eq!(cell.into_inner(), None); - /// - /// let cell = OnceCell::new(); - /// cell.set("hello".to_string()).unwrap(); - /// assert_eq!(cell.into_inner(), Some("hello".to_string())); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn into_inner(self) -> Option { - // Because `into_inner` takes `self` by value, the compiler statically verifies - // that it is not currently borrowed. So it is safe to move out `Option`. - self.inner.into_inner() - } - - /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. - /// - /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. - /// - /// Safety is guaranteed by requiring a mutable reference. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::OnceCell; - /// - /// let mut cell: OnceCell = OnceCell::new(); - /// assert_eq!(cell.take(), None); - /// - /// let mut cell = OnceCell::new(); - /// cell.set("hello".to_string()).unwrap(); - /// assert_eq!(cell.take(), Some("hello".to_string())); - /// assert_eq!(cell.get(), None); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn take(&mut self) -> Option { - mem::take(self).into_inner() - } -} - -/// A value which is initialized on the first access. -/// -/// # Examples -/// -/// ``` -/// #![feature(once_cell)] -/// -/// use std::lazy::Lazy; -/// -/// let lazy: Lazy = Lazy::new(|| { -/// println!("initializing"); -/// 92 -/// }); -/// println!("ready"); -/// println!("{}", *lazy); -/// println!("{}", *lazy); -/// -/// // Prints: -/// // ready -/// // initializing -/// // 92 -/// // 92 -/// ``` -#[unstable(feature = "once_cell", issue = "74465")] -pub struct Lazy T> { - cell: OnceCell, - init: Cell>, -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl fmt::Debug for Lazy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() - } -} - -impl Lazy { - /// Creates a new lazy value with the given initializing function. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// # fn main() { - /// use std::lazy::Lazy; - /// - /// let hello = "Hello, World!".to_string(); - /// - /// let lazy = Lazy::new(|| hello.to_uppercase()); - /// - /// assert_eq!(&*lazy, "HELLO, WORLD!"); - /// # } - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub const fn new(init: F) -> Lazy { - Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) } - } -} - -impl T> Lazy { - /// Forces the evaluation of this lazy value and returns a reference to - /// the result. - /// - /// This is equivalent to the `Deref` impl, but is explicit. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::Lazy; - /// - /// let lazy = Lazy::new(|| 92); - /// - /// assert_eq!(Lazy::force(&lazy), &92); - /// assert_eq!(&*lazy, &92); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn force(this: &Lazy) -> &T { - this.cell.get_or_init(|| match this.init.take() { - Some(f) => f(), - None => panic!("`Lazy` instance has previously been poisoned"), - }) - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl T> Deref for Lazy { - type Target = T; - fn deref(&self) -> &T { - Lazy::force(self) - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl Default for Lazy { - /// Creates a new lazy value using `Default` as the initializing function. - fn default() -> Lazy { - Lazy::new(T::default) - } -} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 2e443064706d2..2f2206a117cf7 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -92,7 +92,6 @@ #![feature(const_slice_ptr_len)] #![feature(const_type_name)] #![feature(const_likely)] -#![feature(const_unreachable_unchecked)] #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] @@ -240,8 +239,6 @@ pub mod char; pub mod ffi; #[cfg(not(test))] // See #65860 pub mod iter; -#[unstable(feature = "once_cell", issue = "74465")] -pub mod lazy; pub mod option; pub mod panic; pub mod panicking; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 9fb7296ce31cc..061d1ea6b1c46 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -242,7 +242,7 @@ pub mod consts { /// The full circle constant (τ) /// /// Equal to 2π. - #[stable(feature = "tau_constant", since = "1.47.0")] + #[unstable(feature = "tau_constant", issue = "66770")] pub const TAU: f32 = 6.28318530717958647692528676655900577_f32; /// π/2 diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index bcb6cd4084691..b0df4d64f6ee1 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -242,7 +242,7 @@ pub mod consts { /// The full circle constant (τ) /// /// Equal to 2π. - #[stable(feature = "tau_constant", since = "1.47.0")] + #[unstable(feature = "tau_constant", issue = "66770")] pub const TAU: f64 = 6.28318530717958647692528676655900577_f64; /// π/2 diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 179038d1977c8..d86f39c4550c8 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -39,7 +39,7 @@ use crate::hash::Hash; /// [`Iterator`]: ../iter/trait.IntoIterator.html /// [slicing index]: ../slice/trait.SliceIndex.html #[doc(alias = "..")] -#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFull; @@ -71,7 +71,7 @@ impl fmt::Debug for RangeFull { /// assert_eq!(arr[1..=3], [ 1,2,3 ]); /// ``` #[doc(alias = "..")] -#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 210ac078b4fe7..309a4ddb00657 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1672,7 +1672,7 @@ impl [T] { /// Sorts the slice, but may not preserve the order of equal elements. /// /// This sort is unstable (i.e., may reorder equal elements), in-place - /// (i.e., does not allocate), and *O*(*n* \* log(*n*)) worst-case. + /// (i.e., does not allocate), and `O(n * log(n))` worst-case. /// /// # Current implementation /// @@ -1708,7 +1708,7 @@ impl [T] { /// elements. /// /// This sort is unstable (i.e., may reorder equal elements), in-place - /// (i.e., does not allocate), and *O*(*n* \* log(*n*)) worst-case. + /// (i.e., does not allocate), and `O(n * log(n))` worst-case. /// /// The comparator function must define a total ordering for the elements in the slice. If /// the ordering is not total, the order of the elements is unspecified. An order is a @@ -1763,8 +1763,8 @@ impl [T] { /// elements. /// /// This sort is unstable (i.e., may reorder equal elements), in-place - /// (i.e., does not allocate), and *O*(m \* *n* \* log(*n*)) worst-case, where the key function is - /// *O*(*m*). + /// (i.e., does not allocate), and `O(m * n * log(n))` worst-case, where the key function is + /// `O(m)`. /// /// # Current implementation /// @@ -1803,7 +1803,7 @@ impl [T] { /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index`. Additionally, this reordering is /// unstable (i.e. any number of equal elements may end up at position `index`), in-place - /// (i.e. does not allocate), and *O*(*n*) worst-case. This function is also/ known as "kth + /// (i.e. does not allocate), and `O(n)` worst-case. This function is also/ known as "kth /// element" in other libraries. It returns a triplet of the following values: all elements less /// than the one at the given index, the value at the given index, and all elements greater than /// the one at the given index. @@ -1852,7 +1852,7 @@ impl [T] { /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index` using the comparator function. /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at - /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function + /// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function /// is also known as "kth element" in other libraries. It returns a triplet of the following /// values: all elements less than the one at the given index, the value at the given index, /// and all elements greater than the one at the given index, using the provided comparator @@ -1906,7 +1906,7 @@ impl [T] { /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index` using the key extraction function. /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at - /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function + /// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function /// is also known as "kth element" in other libraries. It returns a triplet of the following /// values: all elements less than the one at the given index, the value at the given index, and /// all elements greater than the one at the given index, using the provided key extraction @@ -6095,7 +6095,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * `data` must be [valid] for boths reads and writes for `len * mem::size_of::()` many bytes, +/// * `data` must be [valid] for writes for `len * mem::size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// /// * The entire memory range of this slice must be contained within a single allocated object! diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 972a33d6489e9..8b2ac294764ff 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -121,7 +121,7 @@ where /// Partially sorts a slice by shifting several out-of-order elements around. /// -/// Returns `true` if the slice is sorted at the end. This function is *O*(*n*) worst-case. +/// Returns `true` if the slice is sorted at the end. This function is `O(n)` worst-case. #[cold] fn partial_insertion_sort(v: &mut [T], is_less: &mut F) -> bool where @@ -168,7 +168,7 @@ where false } -/// Sorts a slice using insertion sort, which is *O*(*n*^2) worst-case. +/// Sorts a slice using insertion sort, which is `O(n^2)` worst-case. fn insertion_sort(v: &mut [T], is_less: &mut F) where F: FnMut(&T, &T) -> bool, @@ -178,7 +178,7 @@ where } } -/// Sorts `v` using heapsort, which guarantees *O*(*n* \* log(*n*)) worst-case. +/// Sorts `v` using heapsort, which guarantees `O(n * log(n))` worst-case. #[cold] pub fn heapsort(v: &mut [T], is_less: &mut F) where @@ -751,7 +751,7 @@ where } } -/// Sorts `v` using pattern-defeating quicksort, which is *O*(*n* \* log(*n*)) worst-case. +/// Sorts `v` using pattern-defeating quicksort, which is `O(n * log(n))` worst-case. pub fn quicksort(v: &mut [T], mut is_less: F) where F: FnMut(&T, &T) -> bool, diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 790ec4bd24f8d..86e8d5c42b7ad 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -4,7 +4,7 @@ //! //! For more details, see the [`std::str`] module. //! -//! [`std::str`]: self +//! [`std::str`]: ../../std/str/index.html #![stable(feature = "rust1", since = "1.0.0")] @@ -31,8 +31,9 @@ pub mod lossy; /// `FromStr`'s [`from_str`] method is often used implicitly, through /// [`str`]'s [`parse`] method. See [`parse`]'s documentation for examples. /// -/// [`from_str`]: FromStr::from_str -/// [`parse`]: str::parse +/// [`from_str`]: #tymethod.from_str +/// [`str`]: ../../std/primitive.str.html +/// [`parse`]: ../../std/primitive.str.html#method.parse /// /// `FromStr` does not have a lifetime parameter, and so you can only parse types /// that do not contain a lifetime parameter themselves. In other words, you can @@ -142,7 +143,7 @@ impl FromStr for bool { /// An error returned when parsing a `bool` using [`from_str`] fails /// -/// [`from_str`]: FromStr::from_str +/// [`from_str`]: ../../std/primitive.bool.html#method.from_str #[derive(Debug, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct ParseBoolError { @@ -163,11 +164,13 @@ Section: Creating a string /// Errors which can occur when attempting to interpret a sequence of [`u8`] /// as a string. /// +/// [`u8`]: ../../std/primitive.u8.html +/// /// As such, the `from_utf8` family of functions and methods for both [`String`]s /// and [`&str`]s make use of this error, for example. /// /// [`String`]: ../../std/string/struct.String.html#method.from_utf8 -/// [`&str`]: from_utf8 +/// [`&str`]: ../../std/str/fn.from_utf8.html /// /// # Examples /// @@ -263,7 +266,8 @@ impl Utf8Error { /// that it is valid UTF-8. `from_utf8()` checks to ensure that the bytes are valid /// UTF-8, and then does the conversion. /// -/// [`&str`]: str +/// [`&str`]: ../../std/primitive.str.html +/// [`u8`]: ../../std/primitive.u8.html /// [byteslice]: ../../std/primitive.slice.html /// /// If you are sure that the byte slice is valid UTF-8, and you don't want to @@ -394,7 +398,7 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { /// it are valid UTF-8. If this constraint is violated, undefined behavior /// results, as the rest of Rust assumes that [`&str`]s are valid UTF-8. /// -/// [`&str`]: str +/// [`&str`]: ../../std/primitive.str.html /// /// # Examples /// @@ -425,7 +429,9 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { /// Converts a slice of bytes to a string slice without checking /// that the string contains valid UTF-8; mutable version. /// -/// See the immutable version, [`from_utf8_unchecked()`] for more information. +/// See the immutable version, [`from_utf8_unchecked()`][fromutf8], for more information. +/// +/// [fromutf8]: fn.from_utf8_unchecked.html /// /// # Examples /// @@ -470,11 +476,13 @@ Section: Iterators /// An iterator over the [`char`]s of a string slice. /// +/// [`char`]: ../../std/primitive.char.html /// /// This struct is created by the [`chars`] method on [`str`]. /// See its documentation for more. /// -/// [`chars`]: str::chars +/// [`chars`]: ../../std/primitive.str.html#method.chars +/// [`str`]: ../../std/primitive.str.html #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Chars<'a> { @@ -668,10 +676,13 @@ impl<'a> Chars<'a> { /// An iterator over the [`char`]s of a string slice, and their positions. /// +/// [`char`]: ../../std/primitive.char.html +/// /// This struct is created by the [`char_indices`] method on [`str`]. /// See its documentation for more. /// -/// [`char_indices`]: str::char_indices +/// [`char_indices`]: ../../std/primitive.str.html#method.char_indices +/// [`str`]: ../../std/primitive.str.html #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct CharIndices<'a> { @@ -745,7 +756,8 @@ impl<'a> CharIndices<'a> { /// This struct is created by the [`bytes`] method on [`str`]. /// See its documentation for more. /// -/// [`bytes`]: str::bytes +/// [`bytes`]: ../../std/primitive.str.html#method.bytes +/// [`str`]: ../../std/primitive.str.html #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone, Debug)] pub struct Bytes<'a>(Copied>); @@ -1237,12 +1249,12 @@ generate_pattern_iterators! { forward: /// Created with the method [`split`]. /// - /// [`split`]: str::split + /// [`split`]: ../../std/primitive.str.html#method.split struct Split; reverse: /// Created with the method [`rsplit`]. /// - /// [`rsplit`]: str::rsplit + /// [`rsplit`]: ../../std/primitive.str.html#method.rsplit struct RSplit; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -1255,12 +1267,12 @@ generate_pattern_iterators! { forward: /// Created with the method [`split_terminator`]. /// - /// [`split_terminator`]: str::split_terminator + /// [`split_terminator`]: ../../std/primitive.str.html#method.split_terminator struct SplitTerminator; reverse: /// Created with the method [`rsplit_terminator`]. /// - /// [`rsplit_terminator`]: str::rsplit_terminator + /// [`rsplit_terminator`]: ../../std/primitive.str.html#method.rsplit_terminator struct RSplitTerminator; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -1331,12 +1343,12 @@ generate_pattern_iterators! { forward: /// Created with the method [`splitn`]. /// - /// [`splitn`]: str::splitn + /// [`splitn`]: ../../std/primitive.str.html#method.splitn struct SplitN; reverse: /// Created with the method [`rsplitn`]. /// - /// [`rsplitn`]: str::rsplitn + /// [`rsplitn`]: ../../std/primitive.str.html#method.rsplitn struct RSplitN; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -1386,12 +1398,12 @@ generate_pattern_iterators! { forward: /// Created with the method [`match_indices`]. /// - /// [`match_indices`]: str::match_indices + /// [`match_indices`]: ../../std/primitive.str.html#method.match_indices struct MatchIndices; reverse: /// Created with the method [`rmatch_indices`]. /// - /// [`rmatch_indices`]: str::rmatch_indices + /// [`rmatch_indices`]: ../../std/primitive.str.html#method.rmatch_indices struct RMatchIndices; stability: #[stable(feature = "str_match_indices", since = "1.5.0")] @@ -1443,12 +1455,12 @@ generate_pattern_iterators! { forward: /// Created with the method [`matches`]. /// - /// [`matches`]: str::matches + /// [`matches`]: ../../std/primitive.str.html#method.matches struct Matches; reverse: /// Created with the method [`rmatches`]. /// - /// [`rmatches`]: str::rmatches + /// [`rmatches`]: ../../std/primitive.str.html#method.rmatches struct RMatches; stability: #[stable(feature = "str_matches", since = "1.2.0")] @@ -1462,7 +1474,8 @@ generate_pattern_iterators! { /// This struct is created with the [`lines`] method on [`str`]. /// See its documentation for more. /// -/// [`lines`]: str::lines +/// [`lines`]: ../../std/primitive.str.html#method.lines +/// [`str`]: ../../std/primitive.str.html #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone, Debug)] pub struct Lines<'a>(Map, LinesAnyMap>); @@ -1500,7 +1513,7 @@ impl FusedIterator for Lines<'_> {} /// Created with the method [`lines_any`]. /// -/// [`lines_any`]: str::lines_any +/// [`lines_any`]: ../../std/primitive.str.html#method.lines_any #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")] #[derive(Clone, Debug)] @@ -2334,7 +2347,9 @@ impl str { } /// Converts a string slice to a byte slice. To convert the byte slice back - /// into a string slice, use the [`from_utf8`] function. + /// into a string slice, use the [`str::from_utf8`] function. + /// + /// [`str::from_utf8`]: ./str/fn.from_utf8.html /// /// # Examples /// @@ -2414,7 +2429,8 @@ impl str { /// The caller must ensure that the returned pointer is never written to. /// If you need to mutate the contents of the string slice, use [`as_mut_ptr`]. /// - /// [`as_mut_ptr`]: str::as_mut_ptr + /// [`u8`]: primitive.u8.html + /// [`as_mut_ptr`]: #method.as_mut_ptr /// /// # Examples /// @@ -2439,6 +2455,8 @@ impl str { /// /// It is your responsibility to make sure that the string slice only gets /// modified in a way that it remains valid UTF-8. + /// + /// [`u8`]: primitive.u8.html #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] #[inline] pub fn as_mut_ptr(&mut self) -> *mut u8 { @@ -2450,6 +2468,8 @@ impl str { /// This is the non-panicking alternative to indexing the `str`. Returns /// [`None`] whenever equivalent indexing operation would panic. /// + /// [`None`]: option/enum.Option.html#variant.None + /// /// # Examples /// /// ``` @@ -2475,6 +2495,8 @@ impl str { /// This is the non-panicking alternative to indexing the `str`. Returns /// [`None`] whenever equivalent indexing operation would panic. /// + /// [`None`]: option/enum.Option.html#variant.None + /// /// # Examples /// /// ``` @@ -2578,7 +2600,8 @@ impl str { /// This is generally not recommended, use with caution! For a safe /// alternative see [`str`] and [`Index`]. /// - /// [`Index`]: crate::ops::Index + /// [`str`]: primitive.str.html + /// [`Index`]: ops/trait.Index.html /// /// This new slice goes from `begin` to `end`, including `begin` but /// excluding `end`. @@ -2586,7 +2609,7 @@ impl str { /// To get a mutable string slice instead, see the /// [`slice_mut_unchecked`] method. /// - /// [`slice_mut_unchecked`]: str::slice_mut_unchecked + /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked /// /// # Safety /// @@ -2629,7 +2652,8 @@ impl str { /// This is generally not recommended, use with caution! For a safe /// alternative see [`str`] and [`IndexMut`]. /// - /// [`IndexMut`]: crate::ops::IndexMut + /// [`str`]: primitive.str.html + /// [`IndexMut`]: ops/trait.IndexMut.html /// /// This new slice goes from `begin` to `end`, including `begin` but /// excluding `end`. @@ -2637,7 +2661,7 @@ impl str { /// To get an immutable string slice instead, see the /// [`slice_unchecked`] method. /// - /// [`slice_unchecked`]: str::slice_unchecked + /// [`slice_unchecked`]: #method.slice_unchecked /// /// # Safety /// @@ -2668,7 +2692,7 @@ impl str { /// To get mutable string slices instead, see the [`split_at_mut`] /// method. /// - /// [`split_at_mut`]: str::split_at_mut + /// [`split_at_mut`]: #method.split_at_mut /// /// # Panics /// @@ -2709,7 +2733,7 @@ impl str { /// /// To get immutable string slices instead, see the [`split_at`] method. /// - /// [`split_at`]: str::split_at + /// [`split_at`]: #method.split_at /// /// # Panics /// @@ -2889,7 +2913,7 @@ impl str { /// Core Property `White_Space`. If you only want to split on ASCII whitespace /// instead, use [`split_ascii_whitespace`]. /// - /// [`split_ascii_whitespace`]: str::split_ascii_whitespace + /// [`split_ascii_whitespace`]: #method.split_ascii_whitespace /// /// # Examples /// @@ -2930,7 +2954,7 @@ impl str { /// /// To split by Unicode `Whitespace` instead, use [`split_whitespace`]. /// - /// [`split_whitespace`]: str::split_whitespace + /// [`split_whitespace`]: #method.split_whitespace /// /// # Examples /// @@ -3044,7 +3068,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -3070,7 +3095,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -3095,7 +3121,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -3123,7 +3150,9 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`None`]: option/enum.Option.html#variant.None + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -3170,7 +3199,9 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`None`]: option/enum.Option.html#variant.None + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -3216,7 +3247,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Iterator behavior /// @@ -3224,10 +3256,12 @@ impl str { /// allows a reverse search and forward/reverse search yields the same /// elements. This is true for, e.g., [`char`], but not for `&str`. /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// /// If the pattern allows a reverse search but its results might differ /// from a forward search, the [`rsplit`] method can be used. /// - /// [`rsplit`]: str::rsplit + /// [`rsplit`]: #method.rsplit /// /// # Examples /// @@ -3314,7 +3348,7 @@ impl str { /// /// Use [`split_whitespace`] for this behavior. /// - /// [`split_whitespace`]: str::split_whitespace + /// [`split_whitespace`]: #method.split_whitespace #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { @@ -3335,7 +3369,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -3374,7 +3409,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Iterator behavior /// @@ -3382,9 +3418,11 @@ impl str { /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse /// search yields the same elements. /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// /// For iterating from the front, the [`split`] method can be used. /// - /// [`split`]: str::split + /// [`split`]: #method.split /// /// # Examples /// @@ -3425,12 +3463,13 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// Equivalent to [`split`], except that the trailing substring /// is skipped if empty. /// - /// [`split`]: str::split + /// [`split`]: #method.split /// /// This method can be used for string data that is _terminated_, /// rather than _separated_ by a pattern. @@ -3441,10 +3480,12 @@ impl str { /// allows a reverse search and forward/reverse search yields the same /// elements. This is true for, e.g., [`char`], but not for `&str`. /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// /// If the pattern allows a reverse search but its results might differ /// from a forward search, the [`rsplit_terminator`] method can be used. /// - /// [`rsplit_terminator`]: str::rsplit_terminator + /// [`rsplit_terminator`]: #method.rsplit_terminator /// /// # Examples /// @@ -3469,12 +3510,13 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// Equivalent to [`split`], except that the trailing substring is /// skipped if empty. /// - /// [`split`]: str::split + /// [`split`]: #method.split /// /// This method can be used for string data that is _terminated_, /// rather than _separated_ by a pattern. @@ -3488,7 +3530,7 @@ impl str { /// For iterating from the front, the [`split_terminator`] method can be /// used. /// - /// [`split_terminator`]: str::split_terminator + /// [`split_terminator`]: #method.split_terminator /// /// # Examples /// @@ -3517,7 +3559,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Iterator behavior /// @@ -3527,7 +3570,7 @@ impl str { /// If the pattern allows a reverse search, the [`rsplitn`] method can be /// used. /// - /// [`rsplitn`]: str::rsplitn + /// [`rsplitn`]: #method.rsplitn /// /// # Examples /// @@ -3569,7 +3612,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Iterator behavior /// @@ -3578,7 +3622,7 @@ impl str { /// /// For splitting from the front, the [`splitn`] method can be used. /// - /// [`splitn`]: str::splitn + /// [`splitn`]: #method.splitn /// /// # Examples /// @@ -3616,7 +3660,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Iterator behavior /// @@ -3624,10 +3669,12 @@ impl str { /// allows a reverse search and forward/reverse search yields the same /// elements. This is true for, e.g., [`char`], but not for `&str`. /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// /// If the pattern allows a reverse search but its results might differ /// from a forward search, the [`rmatches`] method can be used. /// - /// [`rmatches`]: str::matches + /// [`rmatches`]: #method.rmatches /// /// # Examples /// @@ -3652,7 +3699,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Iterator behavior /// @@ -3660,9 +3708,11 @@ impl str { /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse /// search yields the same elements. /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// /// For iterating from the front, the [`matches`] method can be used. /// - /// [`matches`]: str::matches + /// [`matches`]: #method.matches /// /// # Examples /// @@ -3693,7 +3743,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Iterator behavior /// @@ -3701,10 +3752,12 @@ impl str { /// allows a reverse search and forward/reverse search yields the same /// elements. This is true for, e.g., [`char`], but not for `&str`. /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// /// If the pattern allows a reverse search but its results might differ /// from a forward search, the [`rmatch_indices`] method can be used. /// - /// [`rmatch_indices`]: str::match_indices + /// [`rmatch_indices`]: #method.rmatch_indices /// /// # Examples /// @@ -3735,7 +3788,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Iterator behavior /// @@ -3743,9 +3797,11 @@ impl str { /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse /// search yields the same elements. /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// /// For iterating from the front, the [`match_indices`] method can be used. /// - /// [`match_indices`]: str::match_indices + /// [`match_indices`]: #method.match_indices /// /// # Examples /// @@ -3953,7 +4009,8 @@ impl str { /// The [pattern] can be a [`char`], a slice of [`char`]s, or a function /// or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -4000,7 +4057,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Text directionality /// @@ -4044,7 +4102,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -4071,7 +4130,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Examples /// @@ -4097,7 +4157,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Text directionality /// @@ -4145,7 +4206,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Text directionality /// @@ -4181,7 +4243,8 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// - /// [pattern]: self::pattern + /// [`char`]: primitive.char.html + /// [pattern]: str/pattern/index.html /// /// # Text directionality /// @@ -4229,14 +4292,15 @@ impl str { /// you're trying to parse into. /// /// `parse` can parse any type that implements the [`FromStr`] trait. - + /// + /// [`FromStr`]: str/trait.FromStr.html /// /// # Errors /// /// Will return [`Err`] if it's not possible to parse this string slice into /// the desired type. /// - /// [`Err`]: FromStr::Err + /// [`Err`]: str/trait.FromStr.html#associatedtype.Err /// /// # Examples /// @@ -4364,6 +4428,8 @@ impl str { /// Note: only extended grapheme codepoints that begin the string will be /// escaped. /// + /// [`char::escape_debug`]: ../std/primitive.char.html#method.escape_debug + /// /// # Examples /// /// As an iterator: @@ -4408,6 +4474,8 @@ impl str { /// Return an iterator that escapes each char in `self` with [`char::escape_default`]. /// + /// [`char::escape_default`]: ../std/primitive.char.html#method.escape_default + /// /// # Examples /// /// As an iterator: @@ -4444,6 +4512,8 @@ impl str { /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`]. /// + /// [`char::escape_unicode`]: ../std/primitive.char.html#method.escape_unicode + /// /// # Examples /// /// As an iterator: @@ -4526,7 +4596,8 @@ impl Default for &mut str { /// This struct is created by the [`split_whitespace`] method on [`str`]. /// See its documentation for more. /// -/// [`split_whitespace`]: str::split_whitespace +/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace +/// [`str`]: ../../std/primitive.str.html #[stable(feature = "split_whitespace", since = "1.1.0")] #[derive(Clone, Debug)] pub struct SplitWhitespace<'a> { @@ -4539,7 +4610,8 @@ pub struct SplitWhitespace<'a> { /// This struct is created by the [`split_ascii_whitespace`] method on [`str`]. /// See its documentation for more. /// -/// [`split_ascii_whitespace`]: str::split_ascii_whitespace +/// [`split_ascii_whitespace`]: ../../std/primitive.str.html#method.split_ascii_whitespace +/// [`str`]: ../../std/primitive.str.html #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[derive(Clone, Debug)] pub struct SplitAsciiWhitespace<'a> { @@ -4554,7 +4626,8 @@ pub struct SplitAsciiWhitespace<'a> { /// This struct is created by the [`split_inclusive`] method on [`str`]. /// See its documentation for more. /// -/// [`split_inclusive`]: str::split_inclusive +/// [`split_inclusive`]: ../../std/primitive.str.html#method.split_inclusive +/// [`str`]: ../../std/primitive.str.html #[unstable(feature = "split_inclusive", issue = "72360")] pub struct SplitInclusive<'a, P: Pattern<'a>>(SplitInternal<'a, P>); @@ -4688,10 +4761,13 @@ impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {} /// An iterator of [`u16`] over the string encoded as UTF-16. /// +/// [`u16`]: ../../std/primitive.u16.html +/// /// This struct is created by the [`encode_utf16`] method on [`str`]. /// See its documentation for more. /// -/// [`encode_utf16`]: str::encode_utf16 +/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16 +/// [`str`]: ../../std/primitive.str.html #[derive(Clone)] #[stable(feature = "encode_utf16", since = "1.8.0")] pub struct EncodeUtf16<'a> { @@ -4742,6 +4818,8 @@ impl<'a> Iterator for EncodeUtf16<'a> { impl FusedIterator for EncodeUtf16<'_> {} /// The return type of [`str::escape_debug`]. +/// +/// [`str::escape_debug`]: ../../std/primitive.str.html#method.escape_debug #[stable(feature = "str_escape", since = "1.34.0")] #[derive(Clone, Debug)] pub struct EscapeDebug<'a> { @@ -4752,6 +4830,8 @@ pub struct EscapeDebug<'a> { } /// The return type of [`str::escape_default`]. +/// +/// [`str::escape_default`]: ../../std/primitive.str.html#method.escape_default #[stable(feature = "str_escape", since = "1.34.0")] #[derive(Clone, Debug)] pub struct EscapeDefault<'a> { @@ -4759,6 +4839,8 @@ pub struct EscapeDefault<'a> { } /// The return type of [`str::escape_unicode`]. +/// +/// [`str::escape_unicode`]: ../../std/primitive.str.html#method.escape_unicode #[stable(feature = "str_escape", since = "1.34.0")] #[derive(Clone, Debug)] pub struct EscapeUnicode<'a> { diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 3d6f4f5971a62..27760749c1d4b 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -9,7 +9,3 @@ pub use self::poll::Poll; mod wake; #[stable(feature = "futures_api", since = "1.36.0")] pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; - -mod ready; -#[unstable(feature = "ready_macro", issue = "70922")] -pub use ready::ready; diff --git a/src/libcore/task/ready.rs b/src/libcore/task/ready.rs deleted file mode 100644 index d4e733eb2bcf5..0000000000000 --- a/src/libcore/task/ready.rs +++ /dev/null @@ -1,60 +0,0 @@ -/// Extracts the successful type of a `Poll`. -/// -/// This macro bakes in propagation of `Pending` signals by returning early. -/// -/// # Examples -/// -/// ``` -/// #![feature(future_readiness_fns)] -/// #![feature(ready_macro)] -/// -/// use core::task::{ready, Context, Poll}; -/// use core::future::{self, Future}; -/// use core::pin::Pin; -/// -/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { -/// let mut fut = future::ready(42); -/// let fut = Pin::new(&mut fut); -/// -/// let num = ready!(fut.poll(cx)); -/// # drop(num); -/// // ... use num -/// -/// Poll::Ready(()) -/// } -/// ``` -/// -/// The `ready!` call expands to: -/// -/// ``` -/// # #![feature(future_readiness_fns)] -/// # #![feature(ready_macro)] -/// # -/// # use core::task::{Context, Poll}; -/// # use core::future::{self, Future}; -/// # use core::pin::Pin; -/// # -/// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { -/// # let mut fut = future::ready(42); -/// # let fut = Pin::new(&mut fut); -/// # -/// let num = match fut.poll(cx) { -/// Poll::Ready(t) => t, -/// Poll::Pending => return Poll::Pending, -/// }; -/// # drop(num); -/// # // ... use num -/// # -/// # Poll::Ready(()) -/// # } -/// ``` -#[unstable(feature = "ready_macro", issue = "70922")] -#[rustc_macro_transparency = "semitransparent"] -pub macro ready($e:expr) { - match $e { - $crate::task::Poll::Ready(t) => t, - $crate::task::Poll::Pending => { - return $crate::task::Poll::Pending; - } - } -} diff --git a/src/libcore/tests/lazy.rs b/src/libcore/tests/lazy.rs deleted file mode 100644 index 1c0bddb9aef62..0000000000000 --- a/src/libcore/tests/lazy.rs +++ /dev/null @@ -1,124 +0,0 @@ -use core::{ - cell::Cell, - lazy::{Lazy, OnceCell}, - sync::atomic::{AtomicUsize, Ordering::SeqCst}, -}; - -#[test] -fn once_cell() { - let c = OnceCell::new(); - assert!(c.get().is_none()); - c.get_or_init(|| 92); - assert_eq!(c.get(), Some(&92)); - - c.get_or_init(|| panic!("Kabom!")); - assert_eq!(c.get(), Some(&92)); -} - -#[test] -fn once_cell_get_mut() { - let mut c = OnceCell::new(); - assert!(c.get_mut().is_none()); - c.set(90).unwrap(); - *c.get_mut().unwrap() += 2; - assert_eq!(c.get_mut(), Some(&mut 92)); -} - -#[test] -fn once_cell_drop() { - static DROP_CNT: AtomicUsize = AtomicUsize::new(0); - struct Dropper; - impl Drop for Dropper { - fn drop(&mut self) { - DROP_CNT.fetch_add(1, SeqCst); - } - } - - let x = OnceCell::new(); - x.get_or_init(|| Dropper); - assert_eq!(DROP_CNT.load(SeqCst), 0); - drop(x); - assert_eq!(DROP_CNT.load(SeqCst), 1); -} - -#[test] -fn unsync_once_cell_drop_empty() { - let x = OnceCell::<&'static str>::new(); - drop(x); -} - -#[test] -fn clone() { - let s = OnceCell::new(); - let c = s.clone(); - assert!(c.get().is_none()); - - s.set("hello").unwrap(); - let c = s.clone(); - assert_eq!(c.get().map(|c| *c), Some("hello")); -} - -#[test] -fn from_impl() { - assert_eq!(OnceCell::from("value").get(), Some(&"value")); - assert_ne!(OnceCell::from("foo").get(), Some(&"bar")); -} - -#[test] -fn partialeq_impl() { - assert!(OnceCell::from("value") == OnceCell::from("value")); - assert!(OnceCell::from("foo") != OnceCell::from("bar")); - - assert!(OnceCell::<&'static str>::new() == OnceCell::new()); - assert!(OnceCell::<&'static str>::new() != OnceCell::from("value")); -} - -#[test] -fn into_inner() { - let cell: OnceCell<&'static str> = OnceCell::new(); - assert_eq!(cell.into_inner(), None); - let cell = OnceCell::new(); - cell.set("hello").unwrap(); - assert_eq!(cell.into_inner(), Some("hello")); -} - -#[test] -fn lazy_new() { - let called = Cell::new(0); - let x = Lazy::new(|| { - called.set(called.get() + 1); - 92 - }); - - assert_eq!(called.get(), 0); - - let y = *x - 30; - assert_eq!(y, 62); - assert_eq!(called.get(), 1); - - let y = *x - 30; - assert_eq!(y, 62); - assert_eq!(called.get(), 1); -} - -#[test] -fn aliasing_in_get() { - let x = OnceCell::new(); - x.set(42).unwrap(); - let at_x = x.get().unwrap(); // --- (shared) borrow of inner `Option` --+ - let _ = x.set(27); // <-- temporary (unique) borrow of inner `Option` | - println!("{}", at_x); // <------- up until here ---------------------------+ -} - -#[test] -#[should_panic(expected = "reentrant init")] -fn reentrant_init() { - let x: OnceCell> = OnceCell::new(); - let dangling_ref: Cell> = Cell::new(None); - x.get_or_init(|| { - let r = x.get_or_init(|| Box::new(92)); - dangling_ref.set(Some(r)); - Box::new(62) - }); - eprintln!("use after free: {:?}", dangling_ref.get().unwrap()); -} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 47ed6db6c677b..090ce47174566 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -43,7 +43,6 @@ #![feature(option_unwrap_none)] #![feature(peekable_next_if)] #![feature(partition_point)] -#![feature(once_cell)] #![feature(unsafe_block_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)] @@ -63,7 +62,6 @@ mod fmt; mod hash; mod intrinsics; mod iter; -mod lazy; mod manually_drop; mod mem; mod nonzero; diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 227a87ff81994..89b548a9c5ab2 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -133,9 +133,6 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { return; } - // FIXME(richkadel): Make sure probestack plays nice with `-Z instrument-coverage` - // or disable it if not, similar to above early exits. - // Flag our internal `__rust_probestack` function as the stack probe symbol. // This is defined in the `compiler-builtins` crate for each architecture. llvm::AddFunctionAttrStringValue( diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index b19199b9cfabd..d5e0d7d36ee7a 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -144,18 +144,17 @@ pub fn compile_codegen_unit( } } - // Finalize code coverage by injecting the coverage map. Note, the coverage map will - // also be added to the `llvm.used` variable, created next. - if cx.sess().opts.debugging_opts.instrument_coverage { - cx.coverageinfo_finalize(); - } - // Create the llvm.used variable // This variable has type [N x i8*] and is stored in the llvm.metadata section if !cx.used_statics().borrow().is_empty() { cx.create_used_variable() } + // Finalize code coverage by injecting the coverage map + if cx.sess().opts.debugging_opts.instrument_coverage { + cx.coverageinfo_finalize(); + } + // Finalize debuginfo if cx.sess().opts.debuginfo != DebugInfo::None { cx.debuginfo_finalize(); diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index d58aad340a1dc..6a38323f7ca9e 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -1060,7 +1060,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn_name, hash, num_counters, index ); - let llfn = unsafe { llvm::LLVMRustGetInstrProfIncrementIntrinsic(self.cx().llmod) }; + let llfn = unsafe { llvm::LLVMRustGetInstrprofIncrementIntrinsic(self.cx().llmod) }; let args = &[fn_name, hash, num_counters, index]; let args = self.check_call("call", llfn, args); diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 75b4f2e3ca5a5..7b341651adf3d 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -13,7 +13,7 @@ use log::debug; use rustc_codegen_ssa::traits::*; use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; -use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::{Instance, TypeFoldable}; /// Codegens a reference to a fn/method item, monomorphizing and /// inlining as it goes. @@ -29,18 +29,14 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value assert!(!instance.substs.needs_infer()); assert!(!instance.substs.has_escaping_bound_vars()); + assert!(!instance.substs.has_param_types_or_consts()); if let Some(&llfn) = cx.instances.borrow().get(&instance) { return llfn; } let sym = tcx.symbol_name(instance).name; - debug!( - "get_fn({:?}: {:?}) => {}", - instance, - instance.ty(cx.tcx(), ty::ParamEnv::reveal_all()), - sym - ); + debug!("get_fn({:?}: {:?}) => {}", instance, instance.monomorphic_ty(cx.tcx()), sym); let fn_abi = FnAbi::of_instance(cx, instance, &[]); diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index e8d475405096a..90887b760fb7d 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -203,7 +203,7 @@ impl CodegenCx<'ll, 'tcx> { def_id ); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = instance.monomorphic_ty(self.tcx); let sym = self.tcx.symbol_name(instance).name; debug!("get_static: sym={} instance={:?}", sym, instance); @@ -361,7 +361,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { }; let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = instance.monomorphic_ty(self.tcx); let llty = self.layout_of(ty).llvm_type(self); let g = if val_llty == llty { g @@ -493,14 +493,10 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { } if attrs.flags.contains(CodegenFnAttrFlags::USED) { - self.add_used_global(g); + // This static will be stored in the llvm.used variable which is an array of i8* + let cast = llvm::LLVMConstPointerCast(g, self.type_i8p()); + self.used_statics.borrow_mut().push(cast); } } } - - /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. - fn add_used_global(&self, global: &'ll Value) { - let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) }; - self.used_statics.borrow_mut().push(cast); - } } diff --git a/src/librustc_codegen_llvm/coverageinfo/mapgen.rs b/src/librustc_codegen_llvm/coverageinfo/mapgen.rs deleted file mode 100644 index 7f48b1d864c7c..0000000000000 --- a/src/librustc_codegen_llvm/coverageinfo/mapgen.rs +++ /dev/null @@ -1,274 +0,0 @@ -use crate::llvm; - -use crate::common::CodegenCx; -use crate::coverageinfo; - -use log::debug; -use rustc_codegen_ssa::coverageinfo::map::*; -use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, MiscMethods}; -use rustc_data_structures::fx::FxHashMap; -use rustc_llvm::RustString; -use rustc_middle::ty::Instance; -use rustc_middle::{bug, mir}; - -use std::collections::BTreeMap; -use std::ffi::CString; -use std::path::PathBuf; - -// FIXME(richkadel): Complete all variations of generating and exporting the coverage map to LLVM. -// The current implementation is an initial foundation with basic capabilities (Counters, but not -// CounterExpressions, etc.). - -/// Generates and exports the Coverage Map. -/// -/// This Coverage Map complies with Coverage Mapping Format version 3 (zero-based encoded as 2), -/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format) -/// and published in Rust's current (July 2020) fork of LLVM. This version is supported by the -/// LLVM coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM. -/// -/// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with -/// version 3. Clang's implementation of Coverage Map generation was referenced when implementing -/// this Rust version, and though the format documentation is very explicit and detailed, some -/// undocumented details in Clang's implementation (that may or may not be important) were also -/// replicated for Rust's Coverage Map. -pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { - let mut coverage_writer = CoverageMappingWriter::new(cx); - - let function_coverage_map = cx.coverage_context().take_function_coverage_map(); - - // Encode coverage mappings and generate function records - let mut function_records = Vec::<&'ll llvm::Value>::new(); - let coverage_mappings_buffer = llvm::build_byte_buffer(|coverage_mappings_buffer| { - for (instance, function_coverage) in function_coverage_map.into_iter() { - if let Some(function_record) = coverage_writer.write_function_mappings_and_record( - instance, - function_coverage, - coverage_mappings_buffer, - ) { - function_records.push(function_record); - } - } - }); - - // Encode all filenames covered in this module, ordered by `file_id` - let filenames_buffer = llvm::build_byte_buffer(|filenames_buffer| { - coverageinfo::write_filenames_section_to_buffer( - &coverage_writer.filenames, - filenames_buffer, - ); - }); - - if coverage_mappings_buffer.len() > 0 { - // Generate the LLVM IR representation of the coverage map and store it in a well-known - // global constant. - coverage_writer.write_coverage_map( - function_records, - filenames_buffer, - coverage_mappings_buffer, - ); - } -} - -struct CoverageMappingWriter<'a, 'll, 'tcx> { - cx: &'a CodegenCx<'ll, 'tcx>, - filenames: Vec, - filename_to_index: FxHashMap, -} - -impl<'a, 'll, 'tcx> CoverageMappingWriter<'a, 'll, 'tcx> { - fn new(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { - Self { cx, filenames: Vec::new(), filename_to_index: FxHashMap::::default() } - } - - /// For the given function, get the coverage region data, stream it to the given buffer, and - /// then generate and return a new function record. - fn write_function_mappings_and_record( - &mut self, - instance: Instance<'tcx>, - mut function_coverage: FunctionCoverage, - coverage_mappings_buffer: &RustString, - ) -> Option<&'ll llvm::Value> { - let cx = self.cx; - let coverageinfo: &mir::CoverageInfo = cx.tcx.coverageinfo(instance.def_id()); - debug!( - "Generate coverage map for: {:?}, num_counters: {}, num_expressions: {}", - instance, coverageinfo.num_counters, coverageinfo.num_expressions - ); - debug_assert!(coverageinfo.num_counters > 0); - - let regions_in_file_order = function_coverage.regions_in_file_order(cx.sess().source_map()); - if regions_in_file_order.len() == 0 { - return None; - } - - // Stream the coverage mapping regions for the function (`instance`) to the buffer, and - // compute the data byte size used. - let old_len = coverage_mappings_buffer.len(); - self.regions_to_mappings(regions_in_file_order, coverage_mappings_buffer); - let mapping_data_size = coverage_mappings_buffer.len() - old_len; - debug_assert!(mapping_data_size > 0); - - let mangled_function_name = cx.tcx.symbol_name(instance).to_string(); - let name_ref = coverageinfo::compute_hash(&mangled_function_name); - let function_source_hash = function_coverage.source_hash(); - - // Generate and return the function record - let name_ref_val = cx.const_u64(name_ref); - let mapping_data_size_val = cx.const_u32(mapping_data_size as u32); - let func_hash_val = cx.const_u64(function_source_hash); - Some(cx.const_struct( - &[name_ref_val, mapping_data_size_val, func_hash_val], - /*packed=*/ true, - )) - } - - /// For each coverage region, extract its coverage data from the earlier coverage analysis. - /// Use LLVM APIs to convert the data into buffered bytes compliant with the LLVM Coverage - /// Mapping format. - fn regions_to_mappings( - &mut self, - regions_in_file_order: BTreeMap>, - coverage_mappings_buffer: &RustString, - ) { - let mut virtual_file_mapping = Vec::new(); - let mut mapping_regions = coverageinfo::SmallVectorCounterMappingRegion::new(); - let mut expressions = coverageinfo::SmallVectorCounterExpression::new(); - - for (file_id, (file_path, file_coverage_regions)) in - regions_in_file_order.into_iter().enumerate() - { - let file_id = file_id as u32; - let filename = CString::new(file_path.to_string_lossy().to_string()) - .expect("null error converting filename to C string"); - debug!(" file_id: {} = '{:?}'", file_id, filename); - let filenames_index = match self.filename_to_index.get(&filename) { - Some(index) => *index, - None => { - let index = self.filenames.len() as u32; - self.filenames.push(filename.clone()); - self.filename_to_index.insert(filename, index); - index - } - }; - virtual_file_mapping.push(filenames_index); - - let mut mapping_indexes = vec![0 as u32; file_coverage_regions.len()]; - for (mapping_index, (region_id, _)) in file_coverage_regions.values().enumerate() { - mapping_indexes[*region_id] = mapping_index as u32; - } - - for (region_loc, (region_id, region_kind)) in file_coverage_regions.into_iter() { - let mapping_index = mapping_indexes[region_id]; - match region_kind { - CoverageKind::Counter => { - debug!( - " Counter {}, file_id: {}, region_loc: {}", - mapping_index, file_id, region_loc - ); - mapping_regions.push_from( - mapping_index, - file_id, - region_loc.start_line, - region_loc.start_col, - region_loc.end_line, - region_loc.end_col, - ); - } - CoverageKind::CounterExpression(lhs, op, rhs) => { - debug!( - " CounterExpression {} = {} {:?} {}, file_id: {}, region_loc: {:?}", - mapping_index, lhs, op, rhs, file_id, region_loc, - ); - mapping_regions.push_from( - mapping_index, - file_id, - region_loc.start_line, - region_loc.start_col, - region_loc.end_line, - region_loc.end_col, - ); - expressions.push_from(op, lhs, rhs); - } - CoverageKind::Unreachable => { - debug!( - " Unreachable region, file_id: {}, region_loc: {:?}", - file_id, region_loc, - ); - bug!("Unreachable region not expected and not yet handled!") - // FIXME(richkadel): implement and call - // mapping_regions.push_from(...) for unreachable regions - } - } - } - } - - // Encode and append the current function's coverage mapping data - coverageinfo::write_mapping_to_buffer( - virtual_file_mapping, - expressions, - mapping_regions, - coverage_mappings_buffer, - ); - } - - fn write_coverage_map( - self, - function_records: Vec<&'ll llvm::Value>, - filenames_buffer: Vec, - mut coverage_mappings_buffer: Vec, - ) { - let cx = self.cx; - - // Concatenate the encoded filenames and encoded coverage mappings, and add additional zero - // bytes as-needed to ensure 8-byte alignment. - let mut coverage_size = coverage_mappings_buffer.len(); - let filenames_size = filenames_buffer.len(); - let remaining_bytes = - (filenames_size + coverage_size) % coverageinfo::COVMAP_VAR_ALIGN_BYTES; - if remaining_bytes > 0 { - let pad = coverageinfo::COVMAP_VAR_ALIGN_BYTES - remaining_bytes; - coverage_mappings_buffer.append(&mut [0].repeat(pad)); - coverage_size += pad; - } - let filenames_and_coverage_mappings = [filenames_buffer, coverage_mappings_buffer].concat(); - let filenames_and_coverage_mappings_val = - cx.const_bytes(&filenames_and_coverage_mappings[..]); - - debug!( - "cov map: n_records = {}, filenames_size = {}, coverage_size = {}, 0-based version = {}", - function_records.len(), - filenames_size, - coverage_size, - coverageinfo::mapping_version() - ); - - // Create the coverage data header - let n_records_val = cx.const_u32(function_records.len() as u32); - let filenames_size_val = cx.const_u32(filenames_size as u32); - let coverage_size_val = cx.const_u32(coverage_size as u32); - let version_val = cx.const_u32(coverageinfo::mapping_version()); - let cov_data_header_val = cx.const_struct( - &[n_records_val, filenames_size_val, coverage_size_val, version_val], - /*packed=*/ false, - ); - - // Create the function records array - let name_ref_from_u64 = cx.type_i64(); - let mapping_data_size_from_u32 = cx.type_i32(); - let func_hash_from_u64 = cx.type_i64(); - let function_record_ty = cx.type_struct( - &[name_ref_from_u64, mapping_data_size_from_u32, func_hash_from_u64], - /*packed=*/ true, - ); - let function_records_val = cx.const_array(function_record_ty, &function_records[..]); - - // Create the complete LLVM coverage data value to add to the LLVM IR - let cov_data_val = cx.const_struct( - &[cov_data_header_val, function_records_val, filenames_and_coverage_mappings_val], - /*packed=*/ false, - ); - - // Save the coverage data value to LLVM IR - coverageinfo::save_map_to_mod(cx, cov_data_val); - } -} diff --git a/src/librustc_codegen_llvm/coverageinfo/mod.rs b/src/librustc_codegen_llvm/coverageinfo/mod.rs index 76894bcd6c1b1..ff9f8f7aeaa54 100644 --- a/src/librustc_codegen_llvm/coverageinfo/mod.rs +++ b/src/librustc_codegen_llvm/coverageinfo/mod.rs @@ -1,44 +1,67 @@ -use crate::llvm; - use crate::builder::Builder; use crate::common::CodegenCx; - -use libc::c_uint; use log::debug; use rustc_codegen_ssa::coverageinfo::map::*; -use rustc_codegen_ssa::traits::{ - BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, StaticMethods, -}; +use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; use rustc_data_structures::fx::FxHashMap; -use rustc_llvm::RustString; use rustc_middle::ty::Instance; use std::cell::RefCell; -use std::ffi::CString; - -pub mod mapgen; - -const COVMAP_VAR_ALIGN_BYTES: usize = 8; /// A context object for maintaining all state needed by the coverageinfo module. pub struct CrateCoverageContext<'tcx> { // Coverage region data for each instrumented function identified by DefId. - pub(crate) function_coverage_map: RefCell, FunctionCoverage>>, + pub(crate) coverage_regions: RefCell, FunctionCoverageRegions>>, } impl<'tcx> CrateCoverageContext<'tcx> { pub fn new() -> Self { - Self { function_coverage_map: Default::default() } + Self { coverage_regions: Default::default() } } +} - pub fn take_function_coverage_map(&self) -> FxHashMap, FunctionCoverage> { - self.function_coverage_map.replace(FxHashMap::default()) +/// Generates and exports the Coverage Map. +// FIXME(richkadel): Actually generate and export the coverage map to LLVM. +// The current implementation is actually just debug messages to show the data is available. +pub fn finalize(cx: &CodegenCx<'_, '_>) { + let coverage_regions = &*cx.coverage_context().coverage_regions.borrow(); + for instance in coverage_regions.keys() { + let coverageinfo = cx.tcx.coverageinfo(instance.def_id()); + debug_assert!(coverageinfo.num_counters > 0); + debug!( + "Generate coverage map for: {:?}, hash: {}, num_counters: {}", + instance, coverageinfo.hash, coverageinfo.num_counters + ); + let function_coverage_regions = &coverage_regions[instance]; + for (index, region) in function_coverage_regions.indexed_regions() { + match region.kind { + CoverageKind::Counter => debug!( + " Counter {}, for {}..{}", + index, region.coverage_span.start_byte_pos, region.coverage_span.end_byte_pos + ), + CoverageKind::CounterExpression(lhs, op, rhs) => debug!( + " CounterExpression {} = {} {:?} {}, for {}..{}", + index, + lhs, + op, + rhs, + region.coverage_span.start_byte_pos, + region.coverage_span.end_byte_pos + ), + } + } + for unreachable in function_coverage_regions.unreachable_regions() { + debug!( + " Unreachable code region: {}..{}", + unreachable.start_byte_pos, unreachable.end_byte_pos + ); + } } } impl CoverageInfoMethods for CodegenCx<'ll, 'tcx> { fn coverageinfo_finalize(&self) { - mapgen::finalize(self) + finalize(self) } } @@ -46,22 +69,20 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn add_counter_region( &mut self, instance: Instance<'tcx>, - function_source_hash: u64, index: u32, start_byte_pos: u32, end_byte_pos: u32, ) { debug!( - "adding counter to coverage_regions: instance={:?}, function_source_hash={}, index={}, byte range {}..{}", - instance, function_source_hash, index, start_byte_pos, end_byte_pos, + "adding counter to coverage map: instance={:?}, index={}, byte range {}..{}", + instance, index, start_byte_pos, end_byte_pos, + ); + let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); + coverage_regions.entry(instance).or_default().add_counter( + index, + start_byte_pos, + end_byte_pos, ); - let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut(); - coverage_regions - .entry(instance) - .or_insert_with(|| { - FunctionCoverage::with_coverageinfo(self.tcx.coverageinfo(instance.def_id())) - }) - .add_counter(function_source_hash, index, start_byte_pos, end_byte_pos); } fn add_counter_expression_region( @@ -75,16 +96,18 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { end_byte_pos: u32, ) { debug!( - "adding counter expression to coverage_regions: instance={:?}, index={}, {} {:?} {}, byte range {}..{}", + "adding counter expression to coverage map: instance={:?}, index={}, {} {:?} {}, byte range {}..{}", instance, index, lhs, op, rhs, start_byte_pos, end_byte_pos, ); - let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut(); - coverage_regions - .entry(instance) - .or_insert_with(|| { - FunctionCoverage::with_coverageinfo(self.tcx.coverageinfo(instance.def_id())) - }) - .add_counter_expression(index, lhs, op, rhs, start_byte_pos, end_byte_pos); + let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); + coverage_regions.entry(instance).or_default().add_counter_expression( + index, + lhs, + op, + rhs, + start_byte_pos, + end_byte_pos, + ); } fn add_unreachable_region( @@ -94,175 +117,10 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { end_byte_pos: u32, ) { debug!( - "adding unreachable code to coverage_regions: instance={:?}, byte range {}..{}", + "adding unreachable code to coverage map: instance={:?}, byte range {}..{}", instance, start_byte_pos, end_byte_pos, ); - let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut(); - coverage_regions - .entry(instance) - .or_insert_with(|| { - FunctionCoverage::with_coverageinfo(self.tcx.coverageinfo(instance.def_id())) - }) - .add_unreachable(start_byte_pos, end_byte_pos); - } -} - -/// This struct wraps an opaque reference to the C++ template instantiation of -/// `llvm::SmallVector`. Each `coverage::CounterExpression` object is -/// constructed from primative-typed arguments, and pushed to the `SmallVector`, in the C++ -/// implementation of `LLVMRustCoverageSmallVectorCounterExpressionAdd()` (see -/// `src/rustllvm/CoverageMappingWrapper.cpp`). -pub struct SmallVectorCounterExpression<'a> { - pub raw: &'a mut llvm::coverageinfo::SmallVectorCounterExpression<'a>, -} - -impl SmallVectorCounterExpression<'a> { - pub fn new() -> Self { - SmallVectorCounterExpression { - raw: unsafe { llvm::LLVMRustCoverageSmallVectorCounterExpressionCreate() }, - } - } - - pub fn as_ptr(&self) -> *const llvm::coverageinfo::SmallVectorCounterExpression<'a> { - self.raw - } - - pub fn push_from( - &mut self, - kind: rustc_codegen_ssa::coverageinfo::CounterOp, - left_index: u32, - right_index: u32, - ) { - unsafe { - llvm::LLVMRustCoverageSmallVectorCounterExpressionAdd( - &mut *(self.raw as *mut _), - kind, - left_index, - right_index, - ) - } - } -} - -impl Drop for SmallVectorCounterExpression<'a> { - fn drop(&mut self) { - unsafe { - llvm::LLVMRustCoverageSmallVectorCounterExpressionDispose(&mut *(self.raw as *mut _)); - } - } -} - -/// This struct wraps an opaque reference to the C++ template instantiation of -/// `llvm::SmallVector`. Each `coverage::CounterMappingRegion` -/// object is constructed from primative-typed arguments, and pushed to the `SmallVector`, in the -/// C++ implementation of `LLVMRustCoverageSmallVectorCounterMappingRegionAdd()` (see -/// `src/rustllvm/CoverageMappingWrapper.cpp`). -pub struct SmallVectorCounterMappingRegion<'a> { - pub raw: &'a mut llvm::coverageinfo::SmallVectorCounterMappingRegion<'a>, -} - -impl SmallVectorCounterMappingRegion<'a> { - pub fn new() -> Self { - SmallVectorCounterMappingRegion { - raw: unsafe { llvm::LLVMRustCoverageSmallVectorCounterMappingRegionCreate() }, - } - } - - pub fn as_ptr(&self) -> *const llvm::coverageinfo::SmallVectorCounterMappingRegion<'a> { - self.raw - } - - pub fn push_from( - &mut self, - index: u32, - file_id: u32, - line_start: u32, - column_start: u32, - line_end: u32, - column_end: u32, - ) { - unsafe { - llvm::LLVMRustCoverageSmallVectorCounterMappingRegionAdd( - &mut *(self.raw as *mut _), - index, - file_id, - line_start, - column_start, - line_end, - column_end, - ) - } - } -} - -impl Drop for SmallVectorCounterMappingRegion<'a> { - fn drop(&mut self) { - unsafe { - llvm::LLVMRustCoverageSmallVectorCounterMappingRegionDispose( - &mut *(self.raw as *mut _), - ); - } - } -} - -pub(crate) fn write_filenames_section_to_buffer(filenames: &Vec, buffer: &RustString) { - let c_str_vec = filenames.iter().map(|cstring| cstring.as_ptr()).collect::>(); - unsafe { - llvm::LLVMRustCoverageWriteFilenamesSectionToBuffer( - c_str_vec.as_ptr(), - c_str_vec.len(), - buffer, - ); - } -} - -pub(crate) fn write_mapping_to_buffer( - virtual_file_mapping: Vec, - expressions: SmallVectorCounterExpression<'_>, - mapping_regions: SmallVectorCounterMappingRegion<'_>, - buffer: &RustString, -) { - unsafe { - llvm::LLVMRustCoverageWriteMappingToBuffer( - virtual_file_mapping.as_ptr(), - virtual_file_mapping.len() as c_uint, - expressions.as_ptr(), - mapping_regions.as_ptr(), - buffer, - ); + let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); + coverage_regions.entry(instance).or_default().add_unreachable(start_byte_pos, end_byte_pos); } } - -pub(crate) fn compute_hash(name: &str) -> u64 { - let name = CString::new(name).expect("null error converting hashable name to C string"); - unsafe { llvm::LLVMRustCoverageComputeHash(name.as_ptr()) } -} - -pub(crate) fn mapping_version() -> u32 { - unsafe { llvm::LLVMRustCoverageMappingVersion() } -} - -pub(crate) fn save_map_to_mod<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - cov_data_val: &'ll llvm::Value, -) { - let covmap_var_name = llvm::build_string(|s| unsafe { - llvm::LLVMRustCoverageWriteMappingVarNameToString(s); - }) - .expect("Rust Coverage Mapping var name failed UTF-8 conversion"); - debug!("covmap var name: {:?}", covmap_var_name); - - let covmap_section_name = llvm::build_string(|s| unsafe { - llvm::LLVMRustCoverageWriteSectionNameToString(cx.llmod, s); - }) - .expect("Rust Coverage section name failed UTF-8 conversion"); - debug!("covmap section name: {:?}", covmap_section_name); - - let llglobal = llvm::add_global(cx.llmod, cx.val_ty(cov_data_val), &covmap_var_name); - llvm::set_initializer(llglobal, cov_data_val); - llvm::set_global_constant(llglobal, true); - llvm::set_linkage(llglobal, llvm::Linkage::InternalLinkage); - llvm::set_section(llglobal, &covmap_section_name); - llvm::set_alignment(llglobal, COVMAP_VAR_ALIGN_BYTES); - cx.add_used_global(llglobal); -} diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 6ae7c7efaee62..ef9d42968ae2e 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -700,8 +700,6 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp prepare_tuple_metadata(cx, t, &tys, unique_type_id, usage_site_span, NO_SCOPE_METADATA) .finalize(cx) } - // Type parameters from polymorphized functions. - ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false), _ => bug!("debuginfo: unexpected type in type_metadata: {:?}", t), }; @@ -957,20 +955,6 @@ fn pointer_type_metadata( } } -fn param_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { - debug!("param_type_metadata: {:?}", t); - let name = format!("{:?}", t); - return unsafe { - llvm::LLVMRustDIBuilderCreateBasicType( - DIB(cx), - name.as_ptr().cast(), - name.len(), - Size::ZERO.bits(), - DW_ATE_unsigned, - ) - }; -} - pub fn compile_unit_metadata( tcx: TyCtxt<'_>, codegen_unit_name: &str, @@ -2481,7 +2465,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global }; let is_local_to_unit = is_node_local_to_unit(cx, def_id); - let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); + let variable_type = Instance::mono(cx.tcx, def_id).monomorphic_ty(cx.tcx); let type_metadata = type_metadata(cx, variable_type, span); let var_name = tcx.item_name(def_id).as_str(); let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name; diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index a01b855372129..44993d7602fe6 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -26,7 +26,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable}; +use rustc_middle::ty::{self, Instance, ParamEnv, Ty}; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::Symbol; use rustc_span::{self, BytePos, Span}; @@ -470,9 +470,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { match impl_self_ty.kind { ty::Adt(def, ..) if !def.is_box() => { // Again, only create type information if full debuginfo is enabled - if cx.sess().opts.debuginfo == DebugInfo::Full - && !impl_self_ty.needs_subst() - { + if cx.sess().opts.debuginfo == DebugInfo::Full { Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP)) } else { Some(namespace::item_namespace(cx, def.did)) diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 2e5929a433de0..d095587a1e8cb 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -90,64 +90,45 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { args: &Vec>, caller_instance: ty::Instance<'tcx>, ) -> bool { - if self.tcx.sess.opts.debugging_opts.instrument_coverage { - // Add the coverage information from the MIR to the Codegen context. Some coverage - // intrinsics are used only to pass along the coverage information (returns `false` - // for `is_codegen_intrinsic()`), but `count_code_region` is also converted into an - // LLVM intrinsic to increment a coverage counter. - match intrinsic { - sym::count_code_region => { - use coverage::count_code_region_args::*; - self.add_counter_region( - caller_instance, - op_to_u64(&args[FUNCTION_SOURCE_HASH]), - op_to_u32(&args[COUNTER_INDEX]), - op_to_u32(&args[START_BYTE_POS]), - op_to_u32(&args[END_BYTE_POS]), - ); - return true; // Also inject the counter increment in the backend - } - sym::coverage_counter_add | sym::coverage_counter_subtract => { - use coverage::coverage_counter_expression_args::*; - self.add_counter_expression_region( - caller_instance, - op_to_u32(&args[COUNTER_EXPRESSION_INDEX]), - op_to_u32(&args[LEFT_INDEX]), - if intrinsic == sym::coverage_counter_add { - CounterOp::Add - } else { - CounterOp::Subtract - }, - op_to_u32(&args[RIGHT_INDEX]), - op_to_u32(&args[START_BYTE_POS]), - op_to_u32(&args[END_BYTE_POS]), - ); - return false; // Does not inject backend code - } - sym::coverage_unreachable => { - use coverage::coverage_unreachable_args::*; - self.add_unreachable_region( - caller_instance, - op_to_u32(&args[START_BYTE_POS]), - op_to_u32(&args[END_BYTE_POS]), - ); - return false; // Does not inject backend code - } - _ => {} - } - } else { - // NOT self.tcx.sess.opts.debugging_opts.instrument_coverage - if intrinsic == sym::count_code_region { - // An external crate may have been pre-compiled with coverage instrumentation, and - // some references from the current crate to the external crate might carry along - // the call terminators to coverage intrinsics, like `count_code_region` (for - // example, when instantiating a generic function). If the current crate has - // `instrument_coverage` disabled, the `count_code_region` call terminators should - // be ignored. - return false; // Do not inject coverage counters inlined from external crates + match intrinsic { + sym::count_code_region => { + use coverage::count_code_region_args::*; + self.add_counter_region( + caller_instance, + op_to_u32(&args[COUNTER_INDEX]), + op_to_u32(&args[START_BYTE_POS]), + op_to_u32(&args[END_BYTE_POS]), + ); + true // Also inject the counter increment in the backend + } + sym::coverage_counter_add | sym::coverage_counter_subtract => { + use coverage::coverage_counter_expression_args::*; + self.add_counter_expression_region( + caller_instance, + op_to_u32(&args[COUNTER_EXPRESSION_INDEX]), + op_to_u32(&args[LEFT_INDEX]), + if intrinsic == sym::coverage_counter_add { + CounterOp::Add + } else { + CounterOp::Subtract + }, + op_to_u32(&args[RIGHT_INDEX]), + op_to_u32(&args[START_BYTE_POS]), + op_to_u32(&args[END_BYTE_POS]), + ); + false // Does not inject backend code + } + sym::coverage_unreachable => { + use coverage::coverage_unreachable_args::*; + self.add_unreachable_region( + caller_instance, + op_to_u32(&args[START_BYTE_POS]), + op_to_u32(&args[END_BYTE_POS]), + ); + false // Does not inject backend code } + _ => true, // Unhandled intrinsics should be passed to `codegen_intrinsic_call()` } - true // Unhandled intrinsics should be passed to `codegen_intrinsic_call()` } fn codegen_intrinsic_call( @@ -160,7 +141,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { caller_instance: ty::Instance<'tcx>, ) { let tcx = self.tcx; - let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let callee_ty = instance.monomorphic_ty(tcx); let (def_id, substs) = match callee_ty.kind { ty::FnDef(def_id, substs) => (def_id, substs), @@ -216,13 +197,12 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let coverageinfo = tcx.coverageinfo(caller_instance.def_id()); let mangled_fn = tcx.symbol_name(caller_instance); let (mangled_fn_name, _len_val) = self.const_str(Symbol::intern(mangled_fn.name)); + let hash = self.const_u64(coverageinfo.hash); let num_counters = self.const_u32(coverageinfo.num_counters); use coverage::count_code_region_args::*; - let hash = args[FUNCTION_SOURCE_HASH].immediate(); let index = args[COUNTER_INDEX].immediate(); debug!( - "translating Rust intrinsic `count_code_region()` to LLVM intrinsic: \ - instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})", + "count_code_region to LLVM intrinsic instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})", mangled_fn.name, hash, num_counters, index, ); self.instrprof_increment(mangled_fn_name, hash, num_counters, index) @@ -2242,7 +2222,3 @@ fn float_type_width(ty: Ty<'_>) -> Option { fn op_to_u32<'tcx>(op: &Operand<'tcx>) -> u32 { Operand::scalar_from_const(op).to_u32().expect("Scalar is u32") } - -fn op_to_u64<'tcx>(op: &Operand<'tcx>) -> u64 { - Operand::scalar_from_const(op).to_u64().expect("Scalar is u64") -} diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 9784beaa079de..64f5e103f0b0d 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1,8 +1,6 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -use super::coverageinfo::{SmallVectorCounterExpression, SmallVectorCounterMappingRegion}; - use super::debuginfo::{ DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator, DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DINameSpace, DISPFlags, DIScope, @@ -652,16 +650,6 @@ pub struct Linker<'a>(InvariantOpaque<'a>); pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); -pub mod coverageinfo { - use super::InvariantOpaque; - - #[repr(C)] - pub struct SmallVectorCounterExpression<'a>(InvariantOpaque<'a>); - - #[repr(C)] - pub struct SmallVectorCounterMappingRegion<'a>(InvariantOpaque<'a>); -} - pub mod debuginfo { use super::{InvariantOpaque, Metadata}; use bitflags::bitflags; @@ -1377,7 +1365,7 @@ extern "C" { // Miscellaneous instructions pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; - pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &'a Value; + pub fn LLVMRustGetInstrprofIncrementIntrinsic(M: &Module) -> &'a Value; pub fn LLVMRustBuildCall( B: &Builder<'a>, Fn: &'a Value, @@ -1645,58 +1633,6 @@ extern "C" { ConstraintsLen: size_t, ) -> bool; - pub fn LLVMRustCoverageSmallVectorCounterExpressionCreate() - -> &'a mut SmallVectorCounterExpression<'a>; - pub fn LLVMRustCoverageSmallVectorCounterExpressionDispose( - Container: &'a mut SmallVectorCounterExpression<'a>, - ); - pub fn LLVMRustCoverageSmallVectorCounterExpressionAdd( - Container: &mut SmallVectorCounterExpression<'a>, - Kind: rustc_codegen_ssa::coverageinfo::CounterOp, - LeftIndex: c_uint, - RightIndex: c_uint, - ); - - pub fn LLVMRustCoverageSmallVectorCounterMappingRegionCreate() - -> &'a mut SmallVectorCounterMappingRegion<'a>; - pub fn LLVMRustCoverageSmallVectorCounterMappingRegionDispose( - Container: &'a mut SmallVectorCounterMappingRegion<'a>, - ); - pub fn LLVMRustCoverageSmallVectorCounterMappingRegionAdd( - Container: &mut SmallVectorCounterMappingRegion<'a>, - Index: c_uint, - FileID: c_uint, - LineStart: c_uint, - ColumnStart: c_uint, - LineEnd: c_uint, - ColumnEnd: c_uint, - ); - - #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteFilenamesSectionToBuffer( - Filenames: *const *const c_char, - FilenamesLen: size_t, - BufferOut: &RustString, - ); - - #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteMappingToBuffer( - VirtualFileMappingIDs: *const c_uint, - NumVirtualFileMappingIDs: c_uint, - Expressions: *const SmallVectorCounterExpression<'_>, - MappingRegions: *const SmallVectorCounterMappingRegion<'_>, - BufferOut: &RustString, - ); - - pub fn LLVMRustCoverageComputeHash(Name: *const c_char) -> u64; - - #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteSectionNameToString(M: &Module, Str: &RustString); - - #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString); - - pub fn LLVMRustCoverageMappingVersion() -> u32; pub fn LLVMRustDebugMetadataVersion() -> u32; pub fn LLVMRustVersionMajor() -> u32; pub fn LLVMRustVersionMinor() -> u32; diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index c09e3659f80a2..b7f1e1789c9e2 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -12,7 +12,7 @@ use libc::c_uint; use rustc_data_structures::small_c_str::SmallCStr; use rustc_llvm::RustString; use std::cell::RefCell; -use std::ffi::{CStr, CString}; +use std::ffi::CStr; use std::str::FromStr; use std::string::FromUtf8Error; @@ -189,42 +189,6 @@ pub fn mk_section_iter(llof: &ffi::ObjectFile) -> SectionIter<'_> { unsafe { SectionIter { llsi: LLVMGetSections(llof) } } } -pub fn set_section(llglobal: &Value, section_name: &str) { - let section_name_cstr = CString::new(section_name).expect("unexpected CString error"); - unsafe { - LLVMSetSection(llglobal, section_name_cstr.as_ptr()); - } -} - -pub fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name: &str) -> &'a Value { - let name_cstr = CString::new(name).expect("unexpected CString error"); - unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) } -} - -pub fn set_initializer(llglobal: &Value, constant_val: &Value) { - unsafe { - LLVMSetInitializer(llglobal, constant_val); - } -} - -pub fn set_global_constant(llglobal: &Value, is_constant: bool) { - unsafe { - LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False }); - } -} - -pub fn set_linkage(llglobal: &Value, linkage: Linkage) { - unsafe { - LLVMRustSetLinkage(llglobal, linkage); - } -} - -pub fn set_alignment(llglobal: &Value, bytes: usize) { - unsafe { - ffi::LLVMSetAlignment(llglobal, bytes as c_uint); - } -} - /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun. pub fn get_param(llfn: &Value, index: c_uint) -> &Value { unsafe { @@ -261,12 +225,6 @@ pub fn build_string(f: impl FnOnce(&RustString)) -> Result Vec { - let sr = RustString { bytes: RefCell::new(Vec::new()) }; - f(&sr); - sr.bytes.into_inner() -} - pub fn twine_to_string(tr: &Twine) -> String { unsafe { build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM") diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index 0936deb7bb5a9..486ea7f22dfff 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::FnAbiExt; -use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::{Instance, TypeFoldable}; use rustc_target::abi::LayoutOf; impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -22,7 +22,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { symbol_name: &str, ) { let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = instance.monomorphic_ty(self.tcx); let llty = self.layout_of(ty).llvm_type(self); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { @@ -47,7 +47,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { visibility: Visibility, symbol_name: &str, ) { - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.needs_infer() && !instance.substs.has_param_types_or_consts()); let fn_abi = FnAbi::of_instance(self, instance, &[]); let lldecl = self.declare_fn(symbol_name, &fn_abi); diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index e100e0095c92a..eeb6b4aabcf29 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -18,7 +18,6 @@ log = "0.4.5" libc = "0.2.50" jobserver = "0.1.11" tempfile = "3.1" -pathdiff = "0.2.0" rustc_serialize = { path = "../librustc_serialize" } rustc_ast = { path = "../librustc_ast" } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 2d65282ce7798..3adaa07db91b0 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1659,7 +1659,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( // FIXME: Order dependent, applies to the following objects. Where should it be placed? // Try to strip as much out of the generated object by removing unused // sections if possible. See more comments in linker.rs - if sess.opts.cg.link_dead_code != Some(true) { + if !sess.opts.cg.link_dead_code { let keep_metadata = crate_type == CrateType::Dylib; cmd.gc_sections(keep_metadata); } @@ -1695,7 +1695,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( ); // OBJECT-FILES-NO, AUDIT-ORDER - if sess.opts.cg.profile_generate.enabled() || sess.opts.debugging_opts.instrument_coverage { + if sess.opts.cg.profile_generate.enabled() { cmd.pgo_gen(); } diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index e64aafa599fd8..6f40aac83eb9c 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -28,7 +28,9 @@ use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor}; pub fn disable_localization(linker: &mut Command) { // No harm in setting both env vars simultaneously. // Unix-style linkers. - linker.env("LC_ALL", "C"); + // We use an UTF-8 locale, as the generic C locale disables support for non-ASCII + // bytes in filenames on some platforms. + linker.env("LC_ALL", "en_US.UTF-8"); // MSVC's `link.exe`. linker.env("VSLANG", "1033"); } diff --git a/src/librustc_codegen_ssa/back/rpath.rs b/src/librustc_codegen_ssa/back/rpath.rs index 005d2efdd3b26..c02e4f279b1fb 100644 --- a/src/librustc_codegen_ssa/back/rpath.rs +++ b/src/librustc_codegen_ssa/back/rpath.rs @@ -1,4 +1,3 @@ -use pathdiff::diff_paths; use rustc_data_structures::fx::FxHashSet; use std::env; use std::fs; @@ -110,7 +109,37 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> Str // In particular, this handles the case on unix where both paths are // absolute but with only the root as the common directory. fn path_relative_from(path: &Path, base: &Path) -> Option { - diff_paths(path, base) + use std::path::Component; + + if path.is_absolute() != base.is_absolute() { + path.is_absolute().then(|| PathBuf::from(path)) + } else { + let mut ita = path.components(); + let mut itb = base.components(); + let mut comps: Vec> = vec![]; + loop { + match (ita.next(), itb.next()) { + (None, None) => break, + (Some(a), None) => { + comps.push(a); + comps.extend(ita.by_ref()); + break; + } + (None, _) => comps.push(Component::ParentDir), + (Some(a), Some(b)) if comps.is_empty() && a == b => (), + (Some(a), Some(b)) if b == Component::CurDir => comps.push(a), + (Some(_), Some(b)) if b == Component::ParentDir => return None, + (Some(a), Some(_)) => { + comps.push(Component::ParentDir); + comps.extend(itb.map(|_| Component::ParentDir)); + comps.push(a); + comps.extend(ita.by_ref()); + break; + } + } + } + Some(comps.iter().map(|c| c.as_os_str()).collect()) + } } fn get_install_prefix_rpath(config: &mut RPathConfig<'_>) -> String { diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 7d742e7a7afd2..3287e7b856a37 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -203,17 +203,6 @@ fn exported_symbols_provider_local( })); } - if tcx.sess.opts.debugging_opts.instrument_coverage { - // Similar to PGO profiling, preserve symbols used by LLVM InstrProf coverage profiling. - const COVERAGE_WEAK_SYMBOLS: [&str; 3] = - ["__llvm_profile_filename", "__llvm_coverage_mapping", "__llvm_covmap"]; - - symbols.extend(COVERAGE_WEAK_SYMBOLS.iter().map(|sym| { - let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym)); - (exported_symbol, SymbolExportLevel::C) - })); - } - if tcx.sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::MEMORY) { // Similar to profiling, preserve weak msan symbol during LTO. const MSAN_WEAK_SYMBOLS: [&str; 2] = ["__msan_track_origins", "__msan_keep_going"]; diff --git a/src/librustc_codegen_ssa/coverageinfo/map.rs b/src/librustc_codegen_ssa/coverageinfo/map.rs index a8ffef8bc5b6b..3bd262cf2b213 100644 --- a/src/librustc_codegen_ssa/coverageinfo/map.rs +++ b/src/librustc_codegen_ssa/coverageinfo/map.rs @@ -1,154 +1,32 @@ -use rustc_data_structures::sync::Lrc; -use rustc_middle::mir; -use rustc_span::source_map::{Pos, SourceFile, SourceMap}; -use rustc_span::{BytePos, FileName, RealFileName}; - -use std::cmp::{Ord, Ordering}; -use std::collections::BTreeMap; -use std::fmt; -use std::path::PathBuf; +use rustc_data_structures::fx::FxHashMap; +use std::collections::hash_map; +use std::slice; #[derive(Copy, Clone, Debug)] -#[repr(C)] pub enum CounterOp { - // Note the order (and therefore the default values) is important. With the attribute - // `#[repr(C)]`, this enum matches the layout of the LLVM enum defined for the nested enum, - // `llvm::coverage::CounterExpression::ExprKind`, as shown in the following source snippet: - // https://github.com/rust-lang/llvm-project/blob/f208b70fbc4dee78067b3c5bd6cb92aa3ba58a1e/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L146 - Subtract, Add, + Subtract, } -#[derive(Copy, Clone, Debug)] pub enum CoverageKind { Counter, CounterExpression(u32, CounterOp, u32), - Unreachable, } -#[derive(Clone, Debug)] -pub struct CoverageRegion { - pub kind: CoverageKind, +pub struct CoverageSpan { pub start_byte_pos: u32, pub end_byte_pos: u32, } -impl CoverageRegion { - pub fn source_loc(&self, source_map: &SourceMap) -> Option<(Lrc, CoverageLoc)> { - let (start_file, start_line, start_col) = - lookup_file_line_col(source_map, BytePos::from_u32(self.start_byte_pos)); - let (end_file, end_line, end_col) = - lookup_file_line_col(source_map, BytePos::from_u32(self.end_byte_pos)); - let start_file_path = match &start_file.name { - FileName::Real(RealFileName::Named(path)) => path, - _ => { - bug!("start_file_path should be a RealFileName, but it was: {:?}", start_file.name) - } - }; - let end_file_path = match &end_file.name { - FileName::Real(RealFileName::Named(path)) => path, - _ => bug!("end_file_path should be a RealFileName, but it was: {:?}", end_file.name), - }; - if start_file_path == end_file_path { - Some((start_file, CoverageLoc { start_line, start_col, end_line, end_col })) - } else { - None - // FIXME(richkadel): There seems to be a problem computing the file location in - // some cases. I need to investigate this more. When I generate and show coverage - // for the example binary in the crates.io crate `json5format`, I had a couple of - // notable problems: - // - // 1. I saw a lot of coverage spans in `llvm-cov show` highlighting regions in - // various comments (not corresponding to rustdoc code), indicating a possible - // problem with the byte_pos-to-source-map implementation. - // - // 2. And (perhaps not related) when I build the aforementioned example binary with: - // `RUST_FLAGS="-Zinstrument-coverage" cargo build --example formatjson5` - // and then run that binary with - // `LLVM_PROFILE_FILE="formatjson5.profraw" ./target/debug/examples/formatjson5 \ - // some.json5` for some reason the binary generates *TWO* `.profraw` files. One - // named `default.profraw` and the other named `formatjson5.profraw` (the expected - // name, in this case). - // - // If the byte range conversion is wrong, fix it. But if it - // is right, then it is possible for the start and end to be in different files. - // Can I do something other than ignore coverages that span multiple files? - // - // If I can resolve this, remove the "Option<>" result type wrapper - // `regions_in_file_order()` accordingly. - } - } -} - -impl Default for CoverageRegion { - fn default() -> Self { - Self { - // The default kind (Unreachable) is a placeholder that will be overwritten before - // backend codegen. - kind: CoverageKind::Unreachable, - start_byte_pos: 0, - end_byte_pos: 0, - } - } -} - -/// A source code region used with coverage information. -#[derive(Debug, Eq, PartialEq)] -pub struct CoverageLoc { - /// The (1-based) line number of the region start. - pub start_line: u32, - /// The (1-based) column number of the region start. - pub start_col: u32, - /// The (1-based) line number of the region end. - pub end_line: u32, - /// The (1-based) column number of the region end. - pub end_col: u32, -} - -impl Ord for CoverageLoc { - fn cmp(&self, other: &Self) -> Ordering { - (self.start_line, &self.start_col, &self.end_line, &self.end_col).cmp(&( - other.start_line, - &other.start_col, - &other.end_line, - &other.end_col, - )) - } -} - -impl PartialOrd for CoverageLoc { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl fmt::Display for CoverageLoc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Customize debug format, and repeat the file name, so generated location strings are - // "clickable" in many IDEs. - write!(f, "{}:{} - {}:{}", self.start_line, self.start_col, self.end_line, self.end_col) - } -} - -fn lookup_file_line_col(source_map: &SourceMap, byte_pos: BytePos) -> (Lrc, u32, u32) { - let found = source_map - .lookup_line(byte_pos) - .expect("should find coverage region byte position in source"); - let file = found.sf; - let line_pos = file.line_begin_pos(byte_pos); - - // Use 1-based indexing. - let line = (found.line + 1) as u32; - let col = (byte_pos - line_pos).to_u32() + 1; - - (file, line, col) +pub struct CoverageRegion { + pub kind: CoverageKind, + pub coverage_span: CoverageSpan, } /// Collects all of the coverage regions associated with (a) injected counters, (b) counter /// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero), /// for a given Function. Counters and counter expressions are indexed because they can be operands -/// in an expression. This struct also stores the `function_source_hash`, computed during -/// instrumentation and forwarded with counters. +/// in an expression. /// /// Note, it's important to distinguish the `unreachable` region type from what LLVM's refers to as /// a "gap region" (or "gap area"). A gap region is a code region within a counted region (either @@ -156,134 +34,50 @@ fn lookup_file_line_col(source_map: &SourceMap, byte_pos: BytePos) -> (Lrc, - expressions: Vec, - unreachable: Vec, - translated: bool, +#[derive(Default)] +pub struct FunctionCoverageRegions { + indexed: FxHashMap, + unreachable: Vec, } -impl FunctionCoverage { - pub fn with_coverageinfo<'tcx>(coverageinfo: &'tcx mir::CoverageInfo) -> Self { - Self { - source_hash: 0, // will be set with the first `add_counter()` - counters: vec![CoverageRegion::default(); coverageinfo.num_counters as usize], - expressions: vec![CoverageRegion::default(); coverageinfo.num_expressions as usize], - unreachable: Vec::new(), - translated: false, - } - } - - /// Adds a code region to be counted by an injected counter intrinsic. Return a counter ID - /// for the call. - pub fn add_counter( - &mut self, - source_hash: u64, - index: u32, - start_byte_pos: u32, - end_byte_pos: u32, - ) { - self.source_hash = source_hash; - self.counters[index as usize] = - CoverageRegion { kind: CoverageKind::Counter, start_byte_pos, end_byte_pos }; +impl FunctionCoverageRegions { + pub fn add_counter(&mut self, index: u32, start_byte_pos: u32, end_byte_pos: u32) { + self.indexed.insert( + index, + CoverageRegion { + kind: CoverageKind::Counter, + coverage_span: CoverageSpan { start_byte_pos, end_byte_pos }, + }, + ); } pub fn add_counter_expression( &mut self, - translated_index: u32, + index: u32, lhs: u32, op: CounterOp, rhs: u32, start_byte_pos: u32, end_byte_pos: u32, ) { - let index = u32::MAX - translated_index; - // Counter expressions start with "translated indexes", descending from `u32::MAX`, so - // the range of expression indexes is disjoint from the range of counter indexes. This way, - // both counters and expressions can be operands in other expressions. - // - // Once all counters have been added, the final "region index" for an expression is - // `counters.len() + expression_index` (where `expression_index` is its index in - // `self.expressions`), and the expression operands (`lhs` and `rhs`) can be converted to - // final "region index" references by the same conversion, after subtracting from - // `u32::MAX`. - self.expressions[index as usize] = CoverageRegion { - kind: CoverageKind::CounterExpression(lhs, op, rhs), - start_byte_pos, - end_byte_pos, - }; + self.indexed.insert( + index, + CoverageRegion { + kind: CoverageKind::CounterExpression(lhs, op, rhs), + coverage_span: CoverageSpan { start_byte_pos, end_byte_pos }, + }, + ); } pub fn add_unreachable(&mut self, start_byte_pos: u32, end_byte_pos: u32) { - self.unreachable.push(CoverageRegion { - kind: CoverageKind::Unreachable, - start_byte_pos, - end_byte_pos, - }); - } - - pub fn source_hash(&self) -> u64 { - self.source_hash - } - - fn regions(&'a mut self) -> impl Iterator { - assert!(self.source_hash != 0); - self.ensure_expressions_translated(); - self.counters.iter().chain(self.expressions.iter().chain(self.unreachable.iter())) + self.unreachable.push(CoverageSpan { start_byte_pos, end_byte_pos }); } - pub fn regions_in_file_order( - &'a mut self, - source_map: &SourceMap, - ) -> BTreeMap> { - let mut regions_in_file_order = BTreeMap::new(); - for (region_id, region) in self.regions().enumerate() { - if let Some((source_file, region_loc)) = region.source_loc(source_map) { - // FIXME(richkadel): `region.source_loc()` sometimes fails with two different - // filenames for the start and end byte position. This seems wrong, but for - // now, if encountered, the region is skipped. If resolved, convert the result - // to a non-option value so regions are never skipped. - let real_file_path = match &(*source_file).name { - FileName::Real(RealFileName::Named(path)) => path.clone(), - _ => bug!("coverage mapping expected only real, named files"), - }; - let file_coverage_regions = - regions_in_file_order.entry(real_file_path).or_insert_with(|| BTreeMap::new()); - file_coverage_regions.insert(region_loc, (region_id, region.kind)); - } - } - regions_in_file_order + pub fn indexed_regions(&self) -> hash_map::Iter<'_, u32, CoverageRegion> { + self.indexed.iter() } - /// A one-time translation of expression operands is needed, for any operands referencing - /// other CounterExpressions. CounterExpression operands get an initial operand ID that is - /// computed by the simple translation: `u32::max - expression_index` because, when created, - /// the total number of Counters is not yet known. This function recomputes region indexes - /// for expressions so they start with the next region index after the last counter index. - fn ensure_expressions_translated(&mut self) { - if !self.translated { - self.translated = true; - let start = self.counters.len() as u32; - assert!( - (start as u64 + self.expressions.len() as u64) < u32::MAX as u64, - "the number of counters and counter expressions in a single function exceeds {}", - u32::MAX - ); - for region in self.expressions.iter_mut() { - match region.kind { - CoverageKind::CounterExpression(lhs, op, rhs) => { - let lhs = to_region_index(start, lhs); - let rhs = to_region_index(start, rhs); - region.kind = CoverageKind::CounterExpression(lhs, op, rhs); - } - _ => bug!("expressions must only contain CounterExpression kinds"), - } - } - } + pub fn unreachable_regions(&self) -> slice::Iter<'_, CoverageSpan> { + self.unreachable.iter() } } - -fn to_region_index(start: u32, index: u32) -> u32 { - if index < start { index } else { start + (u32::MAX - index) } -} diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index fb8f5a6298911..20d440433cbb0 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -205,17 +205,14 @@ pub fn push_debuginfo_type_name<'tcx>( tcx.def_key(def_id).disambiguated_data.disambiguator )); } - // Type parameters from polymorphized functions. - ty::Param(_) => { - output.push_str(&format!("{:?}", t)); - } ty::Error(_) | ty::Infer(_) | ty::Placeholder(..) | ty::Projection(..) | ty::Bound(..) | ty::Opaque(..) - | ty::GeneratorWitness(..) => { + | ty::GeneratorWitness(..) + | ty::Param(_) => { bug!( "debuginfo: Trying to create type name for \ unexpected type: {:?}", diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index cfa01280e5a97..199dd8c7df42f 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -94,8 +94,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( def_id, substs, ) - .unwrap() - .polymorphize(cx.tcx()), + .unwrap(), ) }) }); diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 2e386c1e5946b..db935c2b3e265 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -124,7 +124,8 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. - let elem_ty = base_ty.projection_ty(cx.tcx(), self.fx.monomorphize(&elem)).ty; + let elem_ty = base_ty.projection_ty(cx.tcx(), elem).ty; + let elem_ty = self.fx.monomorphize(&elem_ty); let span = self.fx.mir.local_decls[place_ref.local].source_info.span; if cx.spanned_layout_of(elem_ty, span).is_zst() { return; diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index e1de9677f807a..7116bb8c92517 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -543,8 +543,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Some( ty::Instance::resolve(bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs) .unwrap() - .unwrap() - .polymorphize(bx.tcx()), + .unwrap(), ), None, ), diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 9c108998bc907..4b2be7b5321ff 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -190,15 +190,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if bx.cx().tcx().has_attr(def_id, sym::rustc_args_required_const) { bug!("reifying a fn ptr that requires const arguments"); } - let instance = ty::Instance::resolve_for_fn_ptr( - bx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - substs, + OperandValue::Immediate( + bx.get_fn_addr( + ty::Instance::resolve_for_fn_ptr( + bx.tcx(), + ty::ParamEnv::reveal_all(), + def_id, + substs, + ) + .unwrap(), + ), ) - .unwrap() - .polymorphize(bx.cx().tcx()); - OperandValue::Immediate(bx.get_fn_addr(instance)) } _ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty), } @@ -211,8 +213,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def_id, substs, ty::ClosureKind::FnOnce, - ) - .polymorphize(bx.cx().tcx()); + ); OperandValue::Immediate(bx.cx().get_fn_addr(instance)) } _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty), diff --git a/src/librustc_codegen_ssa/traits/coverageinfo.rs b/src/librustc_codegen_ssa/traits/coverageinfo.rs index 1b9faa42484f1..d80f90fa4fa0d 100644 --- a/src/librustc_codegen_ssa/traits/coverageinfo.rs +++ b/src/librustc_codegen_ssa/traits/coverageinfo.rs @@ -10,7 +10,6 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { fn add_counter_region( &mut self, instance: Instance<'tcx>, - function_source_hash: u64, index: u32, start_byte_pos: u32, end_byte_pos: u32, diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index 817fc02d166a3..a6462b358347b 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -5,18 +5,6 @@ use rustc_target::abi::Align; pub trait StaticMethods: BackendTypes { fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; fn codegen_static(&self, def_id: DefId, is_mutable: bool); - - /// Mark the given global value as "used", to prevent a backend from potentially removing a - /// static variable that may otherwise appear unused. - /// - /// Static variables in Rust can be annotated with the `#[used]` attribute to direct the `rustc` - /// compiler to mark the variable as a "used global". - /// - /// ```no_run - /// #[used] - /// static FOO: u32 = 0; - /// ``` - fn add_used_global(&self, global: Self::Value); } pub trait StaticBuilderMethods: BackendTypes { diff --git a/src/librustc_data_structures/sorted_map/index_map.rs b/src/librustc_data_structures/sorted_map/index_map.rs index 2bb421a47efa6..b7005ccdc998b 100644 --- a/src/librustc_data_structures/sorted_map/index_map.rs +++ b/src/librustc_data_structures/sorted_map/index_map.rs @@ -7,8 +7,8 @@ use std::iter::FromIterator; use crate::stable_hasher::{HashStable, StableHasher}; use rustc_index::vec::{Idx, IndexVec}; -/// An indexed multi-map that preserves insertion order while permitting both *O*(log *n*) lookup of -/// an item by key and *O*(1) lookup by index. +/// An indexed multi-map that preserves insertion order while permitting both `O(log n)` lookup of +/// an item by key and `O(1)` lookup by index. /// /// This data structure is a hybrid of an [`IndexVec`] and a [`SortedMap`]. Like `IndexVec`, /// `SortedIndexMultiMap` assigns a typed index to each item while preserving insertion order. @@ -20,7 +20,7 @@ use rustc_index::vec::{Idx, IndexVec}; /// items will be yielded in insertion order. /// /// Unlike a general-purpose map like `BTreeSet` or `HashSet`, `SortedMap` and -/// `SortedIndexMultiMap` require *O*(*n*) time to insert a single item. This is because we may need +/// `SortedIndexMultiMap` require `O(n)` time to insert a single item. This is because we may need /// to insert into the middle of the sorted array. Users should avoid mutating this data structure /// in-place. /// diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index c1c79b174f415..97b02eaef35d0 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -469,15 +469,6 @@ impl HashStable for bit_set::BitMatrix } } -impl HashStable for bit_set::FiniteBitSet -where - T: HashStable + bit_set::FiniteBitSetTy, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - self.0.hash_stable(hcx, hasher); - } -} - impl_stable_hash_via_hash!(::std::path::Path); impl_stable_hash_via_hash!(::std::path::PathBuf); diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 279c65ce03d2d..6160450d76676 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -453,7 +453,6 @@ E0767: include_str!("./error_codes/E0767.md"), E0768: include_str!("./error_codes/E0768.md"), E0769: include_str!("./error_codes/E0769.md"), E0770: include_str!("./error_codes/E0770.md"), -E0771: include_str!("./error_codes/E0771.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard @@ -555,7 +554,7 @@ E0771: include_str!("./error_codes/E0771.md"), // E0420, merged into 532 // E0421, merged into 531 // E0427, merged into 530 -// E0456, // plugin `..` is not available for triple `..` + E0456, // plugin `..` is not available for triple `..` E0457, // plugin `..` only found in rlib format, but must be available... E0460, // found possibly newer version of crate `..` E0461, // couldn't find crate `..` with expected target triple .. diff --git a/src/librustc_error_codes/error_codes/E0771.md b/src/librustc_error_codes/error_codes/E0771.md deleted file mode 100644 index 824a955f6b3f4..0000000000000 --- a/src/librustc_error_codes/error_codes/E0771.md +++ /dev/null @@ -1,23 +0,0 @@ -A non-`'static` lifetime was used in a const generic. This is currently not -allowed. - -Erroneous code example: - -```compile_fail,E0771 -#![feature(const_generics)] - -fn function_with_str<'a, const STRING: &'a str>() {} // error! -``` - -To fix this issue, the lifetime in the const generic need to be changed to -`'static`: - -``` -#![feature(const_generics)] - -fn function_with_str() {} // ok! -``` - -For more information, see [GitHub issue #74052]. - -[GitHub issue #74052]: https://github.com/rust-lang/rust/issues/74052 diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index 879f06f89a70a..4e2aea34fe7fb 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -568,7 +568,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!(TEST, rustc_synthetic, AssumedUsed, template!(Word)), rustc_attr!(TEST, rustc_symbol_name, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_polymorphize_error, AssumedUsed, template!(Word)), rustc_attr!(TEST, rustc_def_path, AssumedUsed, template!(Word)), rustc_attr!(TEST, rustc_mir, AssumedUsed, template!(List: "arg1, arg2, ...")), rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)), diff --git a/src/librustc_hir/fake_lang_items.rs b/src/librustc_hir/fake_lang_items.rs deleted file mode 100644 index 91db58054b61f..0000000000000 --- a/src/librustc_hir/fake_lang_items.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! Validity checking for fake lang items - -use crate::def_id::DefId; -use crate::{lang_items, LangItem, LanguageItems}; - -use rustc_data_structures::fx::FxHashMap; -use rustc_span::symbol::{sym, Symbol}; - -use lazy_static::lazy_static; - -macro_rules! fake_lang_items { - ($($item:ident, $name:ident, $method:ident;)*) => ( - -lazy_static! { - pub static ref FAKE_ITEMS_REFS: FxHashMap = { - let mut map = FxHashMap::default(); - $(map.insert(sym::$name, lang_items::$item);)* - map - }; -} - -impl LanguageItems { - pub fn is_fake_lang_item(&self, item_def_id: DefId) -> bool { - let did = Some(item_def_id); - - $(self.$method() == did)||* - } -} - -) } - -fake_lang_items! { -// Variant name, Symbol, Method name, - CountCodeRegionFnLangItem, count_code_region, count_code_region_fn; - CoverageCounterAddFnLangItem, coverage_counter_add, coverage_counter_add_fn; - CoverageCounterSubtractFnLangItem, coverage_counter_subtract, coverage_counter_subtract_fn; -} diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index 4b71407acfb8c..88c97d874bed6 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -276,6 +276,8 @@ language_item_table! { StartFnLangItem, sym::start, start_fn, Target::Fn; + CountCodeRegionFnLangItem, sym::count_code_region, count_code_region_fn, Target::Fn; + EhPersonalityLangItem, sym::eh_personality, eh_personality, Target::Fn; EhCatchTypeinfoLangItem, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static; @@ -293,9 +295,4 @@ language_item_table! { TerminationTraitLangItem, sym::termination, termination, Target::Trait; TryTraitLangItem, kw::Try, try_trait, Target::Trait; - - // language items related to source code coverage instrumentation (-Zinstrument-coverage) - CountCodeRegionFnLangItem, sym::count_code_region, count_code_region_fn, Target::Fn; - CoverageCounterAddFnLangItem, sym::coverage_counter_add, coverage_counter_add_fn, Target::Fn; - CoverageCounterSubtractFnLangItem, sym::coverage_counter_subtract, coverage_counter_subtract_fn, Target::Fn; } diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs index 52131cb3d3d4c..37041923890cd 100644 --- a/src/librustc_hir/lib.rs +++ b/src/librustc_hir/lib.rs @@ -17,7 +17,6 @@ mod arena; pub mod def; pub mod definitions; pub use rustc_span::def_id; -pub mod fake_lang_items; mod hir; pub mod hir_id; pub mod intravisit; diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs index b369be252185b..3e1d4b68c6fa1 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_index/bit_set.rs @@ -4,7 +4,6 @@ use std::fmt; use std::iter; use std::marker::PhantomData; use std::mem; -use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Not, Range, Shl}; use std::slice; #[cfg(test)] @@ -773,7 +772,7 @@ impl BitMatrix { } /// Returns those indices that are true in rows `a` and `b`. This - /// is an *O*(*n*) operation where *n* is the number of elements + /// is an O(n) operation where `n` is the number of elements /// (somewhat independent from the actual size of the /// intersection, in particular). pub fn intersect_rows(&self, row1: R, row2: R) -> Vec { @@ -1002,137 +1001,3 @@ fn word_index_and_mask(elem: T) -> (usize, Word) { let mask = 1 << (elem % WORD_BITS); (word_index, mask) } - -/// Integral type used to represent the bit set. -pub trait FiniteBitSetTy: - BitAnd - + BitAndAssign - + BitOrAssign - + Clone - + Copy - + Shl - + Not - + PartialEq - + Sized -{ - /// Size of the domain representable by this type, e.g. 64 for `u64`. - const DOMAIN_SIZE: u32; - - /// Value which represents the `FiniteBitSet` having every bit set. - const FILLED: Self; - /// Value which represents the `FiniteBitSet` having no bits set. - const EMPTY: Self; - - /// Value for one as the integral type. - const ONE: Self; - /// Value for zero as the integral type. - const ZERO: Self; - - /// Perform a checked left shift on the integral type. - fn checked_shl(self, rhs: u32) -> Option; - /// Perform a checked right shift on the integral type. - fn checked_shr(self, rhs: u32) -> Option; -} - -impl FiniteBitSetTy for u64 { - const DOMAIN_SIZE: u32 = 64; - - const FILLED: Self = Self::MAX; - const EMPTY: Self = Self::MIN; - - const ONE: Self = 1u64; - const ZERO: Self = 0u64; - - fn checked_shl(self, rhs: u32) -> Option { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:064b}", self.0) - } -} - -impl FiniteBitSetTy for u128 { - const DOMAIN_SIZE: u32 = 128; - - const FILLED: Self = Self::MAX; - const EMPTY: Self = Self::MIN; - - const ONE: Self = 1u128; - const ZERO: Self = 0u128; - - fn checked_shl(self, rhs: u32) -> Option { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:0128b}", self.0) - } -} - -/// A fixed-sized bitset type represented by an integer type. Indices outwith than the range -/// representable by `T` are considered set. -#[derive(Copy, Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)] -pub struct FiniteBitSet(pub T); - -impl FiniteBitSet { - /// Creates a new, empty bitset. - pub fn new_empty() -> Self { - Self(T::EMPTY) - } - - /// Sets the `index`th bit. - pub fn set(&mut self, index: u32) { - self.0 |= T::ONE.checked_shl(index).unwrap_or(T::ZERO); - } - - /// Unsets the `index`th bit. - pub fn clear(&mut self, index: u32) { - self.0 &= !T::ONE.checked_shl(index).unwrap_or(T::ZERO); - } - - /// Sets the `i`th to `j`th bits. - pub fn set_range(&mut self, range: Range) { - let bits = T::FILLED - .checked_shl(range.end - range.start) - .unwrap_or(T::ZERO) - .not() - .checked_shl(range.start) - .unwrap_or(T::ZERO); - self.0 |= bits; - } - - /// Is the set empty? - pub fn is_empty(&self) -> bool { - self.0 == T::EMPTY - } - - /// Returns the domain size of the bitset. - pub fn within_domain(&self, index: u32) -> bool { - index < T::DOMAIN_SIZE - } - - /// Returns if the `index`th bit is set. - pub fn contains(&self, index: u32) -> Option { - self.within_domain(index) - .then(|| ((self.0.checked_shr(index).unwrap_or(T::ONE)) & T::ONE) == T::ONE) - } -} - -impl Default for FiniteBitSet { - fn default() -> Self { - Self::new_empty() - } -} diff --git a/src/librustc_index/lib.rs b/src/librustc_index/lib.rs index 7ee881b0639da..eaef4c7b54a62 100644 --- a/src/librustc_index/lib.rs +++ b/src/librustc_index/lib.rs @@ -1,5 +1,4 @@ #![feature(allow_internal_unstable)] -#![feature(bool_to_option)] #![feature(const_fn)] #![feature(const_panic)] #![feature(extend_one)] diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 3c549b8852368..651a77912c6d0 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -401,7 +401,7 @@ fn test_codegen_options_tracking_hash() { untracked!(incremental, Some(String::from("abc"))); // `link_arg` is omitted because it just forwards to `link_args`. untracked!(link_args, vec![String::from("abc"), String::from("def")]); - untracked!(link_dead_code, Some(true)); + untracked!(link_dead_code, true); untracked!(linker, Some(PathBuf::from("linker"))); untracked!(linker_flavor, Some(LinkerFlavor::Gcc)); untracked!(no_stack_check, true); diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 1affc9457b89e..8c82765c45d43 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -531,11 +531,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match ty.kind { ty::FnPtr(_) => true, ty::Ref(..) => true, - ty::Adt(def, _) - if def.is_box() && matches!(self.mode, ImproperCTypesMode::Definitions) => - { - true - } ty::Adt(def, substs) if def.repr.transparent() && !def.is_union() => { let guaranteed_nonnull_optimization = self .cx @@ -563,7 +558,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } /// Check if this enum can be safely exported based on the "nullable pointer optimization". - /// Currently restricted to function pointers, boxes, references, `core::num::NonZero*`, + /// Currently restricted to function pointers, references, `core::num::NonZero*`, /// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes. fn is_repr_nullable_ptr( &self, @@ -697,12 +692,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match ty.kind { - ty::Adt(def, _) - if def.is_box() && matches!(self.mode, ImproperCTypesMode::Definitions) => - { - FfiSafe - } - ty::Adt(def, substs) => { if def.is_phantom_data() { return FfiPhantom(ty); diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 78e27b10ec657..5145b3b5e6fcc 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -104,16 +104,8 @@ fn main() { optional_components.push("riscv"); } - let required_components = &[ - "ipo", - "bitreader", - "bitwriter", - "linker", - "asmparser", - "lto", - "coverage", - "instrumentation", - ]; + let required_components = + &["ipo", "bitreader", "bitwriter", "linker", "asmparser", "lto", "instrumentation"]; let components = output(Command::new(&llvm_config).arg("--components")); let mut components = components.split_whitespace().collect::>(); @@ -177,7 +169,6 @@ fn main() { cfg.file("../rustllvm/PassWrapper.cpp") .file("../rustllvm/RustWrapper.cpp") .file("../rustllvm/ArchiveWrapper.cpp") - .file("../rustllvm/CoverageMappingWrapper.cpp") .file("../rustllvm/Linker.cpp") .cpp(true) .cpp_link_stdlib(None) // we handle this below diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 9d23397ade08e..36300d9efee7f 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -13,12 +13,6 @@ pub struct RustString { pub bytes: RefCell>, } -impl RustString { - pub fn len(&self) -> usize { - self.bytes.borrow().len() - } -} - /// Appending to a Rust string -- used by RawRustStringOstream. #[no_mangle] #[allow(improper_ctypes_definitions)] diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 0d2101cb2cb08..0563894e6348d 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -1,7 +1,6 @@ //! Validates all used crates and extern libraries and loads their metadata -use crate::dynamic_lib::DynamicLibrary; -use crate::locator::{CrateError, CrateLocator, CratePaths}; +use crate::locator::{CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind}; @@ -9,12 +8,15 @@ use rustc_ast::{ast, attr}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; +use rustc_errors::struct_span_err; use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_index::vec::IndexVec; -use rustc_middle::middle::cstore::{CrateSource, DepKind, ExternCrate}; -use rustc_middle::middle::cstore::{ExternCrateSource, MetadataLoaderDyn}; +use rustc_middle::middle::cstore::DepKind; +use rustc_middle::middle::cstore::{ + CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn, +}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, CrateType, ExternLocation}; use rustc_session::lint; @@ -29,7 +31,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use log::{debug, info, log_enabled}; use proc_macro::bridge::client::ProcMacro; use std::path::Path; -use std::{cmp, env, fs}; +use std::{cmp, fs}; #[derive(Clone)] pub struct CStore { @@ -67,6 +69,18 @@ enum LoadResult { Loaded(Library), } +enum LoadError<'a> { + LocatorError(CrateLocator<'a>), +} + +impl<'a> LoadError<'a> { + fn report(self) -> ! { + match self { + LoadError::LocatorError(locator) => locator.report_errs(), + } + } +} + /// A reference to `CrateMetadata` that can also give access to whole crate store when necessary. #[derive(Clone, Copy)] crate struct CrateMetadataRef<'a> { @@ -266,43 +280,60 @@ impl<'a> CrateLoader<'a> { ret } - fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { + fn verify_no_symbol_conflicts(&self, span: Span, root: &CrateRoot<'_>) { // Check for (potential) conflicts with the local crate if self.local_crate_name == root.name() && self.sess.local_crate_disambiguator() == root.disambiguator() { - return Err(CrateError::SymbolConflictsCurrent(root.name())); + struct_span_err!( + self.sess, + span, + E0519, + "the current crate is indistinguishable from one of its \ + dependencies: it has the same crate-name `{}` and was \ + compiled with the same `-C metadata` arguments. This \ + will result in symbol conflicts between the two.", + root.name() + ) + .emit() } // Check for conflicts with any crate loaded so far - let mut res = Ok(()); self.cstore.iter_crate_data(|_, other| { if other.name() == root.name() && // same crate-name - other.disambiguator() == root.disambiguator() && // same crate-disambiguator + other.disambiguator() == root.disambiguator() && // same crate-disambiguator other.hash() != root.hash() { // but different SVH - res = Err(CrateError::SymbolConflictsOthers(root.name())); + struct_span_err!( + self.sess, + span, + E0523, + "found two different crates with name `{}` that are \ + not distinguished by differing `-C metadata`. This \ + will result in symbol conflicts between the two.", + root.name() + ) + .emit(); } }); - - res } fn register_crate( &mut self, host_lib: Option, root: Option<&CratePaths>, + span: Span, lib: Library, dep_kind: DepKind, name: Symbol, - ) -> Result { + ) -> CrateNum { let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - self.verify_no_symbol_conflicts(&crate_root)?; + self.verify_no_symbol_conflicts(span, &crate_root); let private_dep = self.sess.opts.externs.get(&name.as_str()).map(|e| e.is_private_dep).unwrap_or(false); @@ -322,7 +353,7 @@ impl<'a> CrateLoader<'a> { &crate_paths }; - let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?; + let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind); let raw_proc_macros = if crate_root.is_proc_macro_crate() { let temp_root; @@ -334,7 +365,7 @@ impl<'a> CrateLoader<'a> { None => (&source, &crate_root), }; let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); - Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?) + Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator(), span)) } else { None }; @@ -355,14 +386,14 @@ impl<'a> CrateLoader<'a> { ), ); - Ok(cnum) + cnum } fn load_proc_macro<'b>( &self, locator: &mut CrateLocator<'b>, path_kind: PathKind, - ) -> Result)>, CrateError> + ) -> Option<(LoadResult, Option)> where 'a: 'b, { @@ -377,11 +408,8 @@ impl<'a> CrateLoader<'a> { let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros { proc_macro_locator.reset(); let result = match self.load(&mut proc_macro_locator)? { - Some(LoadResult::Previous(cnum)) => { - return Ok(Some((LoadResult::Previous(cnum), None))); - } - Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)), - None => return Ok(None), + LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)), + LoadResult::Loaded(library) => Some(LoadResult::Loaded(library)), }; locator.hash = locator.host_hash; // Use the locator when looking for the host proc macro crate, as that is required @@ -399,12 +427,9 @@ impl<'a> CrateLoader<'a> { locator.triple = TargetTriple::from_triple(config::host_triple()); locator.filesearch = self.sess.host_filesearch(path_kind); - let host_result = match self.load(locator)? { - Some(host_result) => host_result, - None => return Ok(None), - }; + let host_result = self.load(locator)?; - Ok(Some(if self.sess.opts.debugging_opts.dual_proc_macros { + Some(if self.sess.opts.debugging_opts.dual_proc_macros { let host_result = match host_result { LoadResult::Previous(..) => { panic!("host and target proc macros must be loaded in lock-step") @@ -414,7 +439,7 @@ impl<'a> CrateLoader<'a> { (target_result.unwrap(), Some(host_result)) } else { (host_result, None) - })) + }) } fn resolve_crate<'b>( @@ -427,20 +452,25 @@ impl<'a> CrateLoader<'a> { if dep.is_none() { self.used_extern_options.insert(name); } - self.maybe_resolve_crate(name, dep_kind, dep) - .unwrap_or_else(|err| err.report(self.sess, span)) + if !name.as_str().is_ascii() { + self.sess + .struct_span_err( + span, + &format!("cannot load a crate with a non-ascii name `{}`", name,), + ) + .emit(); + } + self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report()) } fn maybe_resolve_crate<'b>( &'b mut self, name: Symbol, + span: Span, mut dep_kind: DepKind, dep: Option<(&'b CratePaths, &'b CrateDep)>, - ) -> Result { + ) -> Result> { info!("resolving crate `{}`", name); - if !name.as_str().is_ascii() { - return Err(CrateError::NonAsciiName(name)); - } let (root, hash, host_hash, extra_filename, path_kind) = match dep { Some((root, dep)) => ( Some(root), @@ -464,20 +494,18 @@ impl<'a> CrateLoader<'a> { extra_filename, false, // is_host path_kind, + span, root, Some(false), // is_proc_macro ); - match self.load(&mut locator)? { - Some(res) => (res, None), - None => { + self.load(&mut locator) + .map(|r| (r, None)) + .or_else(|| { dep_kind = DepKind::MacrosOnly; - match self.load_proc_macro(&mut locator, path_kind)? { - Some(res) => res, - None => return Err(locator.into_error()), - } - } - } + self.load_proc_macro(&mut locator, path_kind) + }) + .ok_or_else(move || LoadError::LocatorError(locator))? }; match result { @@ -490,17 +518,14 @@ impl<'a> CrateLoader<'a> { Ok(cnum) } (LoadResult::Loaded(library), host_library) => { - self.register_crate(host_library, root, library, dep_kind, name) + Ok(self.register_crate(host_library, root, span, library, dep_kind, name)) } _ => panic!(), } } - fn load(&self, locator: &mut CrateLocator<'_>) -> Result, CrateError> { - let library = match locator.maybe_load_library_crate()? { - Some(library) => library, - None => return Ok(None), - }; + fn load(&self, locator: &mut CrateLocator<'_>) -> Option { + let library = locator.maybe_load_library_crate()?; // In the case that we're loading a crate, but not matching // against a hash, we could load a crate which has the same hash @@ -511,7 +536,7 @@ impl<'a> CrateLoader<'a> { // don't want to match a host crate against an equivalent target one // already loaded. let root = library.metadata.get_root(); - Ok(Some(if locator.triple == self.sess.opts.target_triple { + if locator.triple == self.sess.opts.target_triple { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { if data.name() == root.name() && root.hash() == data.hash() { @@ -520,10 +545,10 @@ impl<'a> CrateLoader<'a> { result = LoadResult::Previous(cnum); } }); - result + Some(result) } else { - LoadResult::Loaded(library) - })) + Some(LoadResult::Loaded(library)) + } } fn update_extern_crate(&self, cnum: CrateNum, extern_crate: ExternCrate) { @@ -544,51 +569,53 @@ impl<'a> CrateLoader<'a> { crate_root: &CrateRoot<'_>, metadata: &MetadataBlob, krate: CrateNum, + span: Span, dep_kind: DepKind, - ) -> Result { + ) -> CrateNumMap { debug!("resolving deps of external crate"); if crate_root.is_proc_macro_crate() { - return Ok(CrateNumMap::new()); + return CrateNumMap::new(); } // The map from crate numbers in the crate we're resolving to local crate numbers. // We map 0 and all other holes in the map to our parent crate. The "additional" // self-dependencies should be harmless. - let deps = crate_root.decode_crate_deps(metadata); - let mut crate_num_map = CrateNumMap::with_capacity(1 + deps.len()); - crate_num_map.push(krate); - for dep in deps { - info!( - "resolving dep crate {} hash: `{}` extra filename: `{}`", - dep.name, dep.hash, dep.extra_filename - ); - let dep_kind = match dep_kind { - DepKind::MacrosOnly => DepKind::MacrosOnly, - _ => dep.kind, - }; - let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?; - crate_num_map.push(cnum); - } - Ok(crate_num_map) + std::iter::once(krate) + .chain(crate_root.decode_crate_deps(metadata).map(|dep| { + info!( + "resolving dep crate {} hash: `{}` extra filename: `{}`", + dep.name, dep.hash, dep.extra_filename + ); + let dep_kind = match dep_kind { + DepKind::MacrosOnly => DepKind::MacrosOnly, + _ => dep.kind, + }; + self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))) + })) + .collect() } fn dlsym_proc_macros( &self, path: &Path, disambiguator: CrateDisambiguator, - ) -> Result<&'static [ProcMacro], CrateError> { + span: Span, + ) -> &'static [ProcMacro] { + use crate::dynamic_lib::DynamicLibrary; + use std::env; + // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); let lib = match DynamicLibrary::open(&path) { Ok(lib) => lib, - Err(s) => return Err(CrateError::DlOpen(s)), + Err(err) => self.sess.span_fatal(span, &err), }; let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator); let decls = unsafe { let sym = match lib.symbol(&sym) { Ok(f) => f, - Err(s) => return Err(CrateError::DlSym(s)), + Err(err) => self.sess.span_fatal(span, &err), }; *(sym as *const &[ProcMacro]) }; @@ -597,7 +624,7 @@ impl<'a> CrateLoader<'a> { // since the library can make things that will live arbitrarily long. std::mem::forget(lib); - Ok(decls) + decls } fn inject_panic_runtime(&mut self, krate: &ast::Crate) { @@ -925,7 +952,7 @@ impl<'a> CrateLoader<'a> { cnum } - pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { - self.maybe_resolve_crate(name, DepKind::Explicit, None).ok() + pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option { + self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok() } } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 371ec4cd91148..1bdac1039b55a 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -216,10 +216,9 @@ use crate::creader::Library; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_middle::middle::cstore::{CrateSource, MetadataLoader}; use rustc_session::config::{self, CrateType}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; @@ -229,12 +228,25 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; -use flate2::read::DeflateDecoder; -use log::{debug, info, warn}; -use std::io::{Read, Result as IoResult, Write}; +use std::cmp; +use std::fmt; +use std::fs; +use std::io::{self, Read}; use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::{cmp, fmt, fs}; +use std::time::Instant; + +use flate2::read::DeflateDecoder; + +use rustc_data_structures::owning_ref::OwningRef; + +use log::{debug, info, warn}; + +#[derive(Clone)] +struct CrateMismatch { + path: PathBuf, + got: String, +} #[derive(Clone)] crate struct CrateLocator<'a> { @@ -251,6 +263,7 @@ crate struct CrateLocator<'a> { pub target: &'a Target, pub triple: TargetTriple, pub filesearch: FileSearch<'a>, + span: Span, root: Option<&'a CratePaths>, pub is_proc_macro: Option, @@ -262,7 +275,6 @@ crate struct CrateLocator<'a> { rejected_via_filename: Vec, } -#[derive(Clone)] crate struct CratePaths { name: Symbol, source: CrateSource, @@ -275,7 +287,7 @@ impl CratePaths { } #[derive(Copy, Clone, PartialEq)] -crate enum CrateFlavor { +enum CrateFlavor { Rlib, Rmeta, Dylib, @@ -301,6 +313,7 @@ impl<'a> CrateLocator<'a> { extra_filename: Option<&'a str>, is_host: bool, path_kind: PathKind, + span: Span, root: Option<&'a CratePaths>, is_proc_macro: Option, ) -> CrateLocator<'a> { @@ -336,6 +349,7 @@ impl<'a> CrateLocator<'a> { } else { sess.target_filesearch(path_kind) }, + span, root, is_proc_macro, rejected_via_hash: Vec::new(), @@ -354,30 +368,166 @@ impl<'a> CrateLocator<'a> { self.rejected_via_filename.clear(); } - crate fn maybe_load_library_crate(&mut self) -> Result, CrateError> { + crate fn maybe_load_library_crate(&mut self) -> Option { if !self.exact_paths.is_empty() { return self.find_commandline_library(); } let mut seen_paths = FxHashSet::default(); - if let Some(extra_filename) = self.extra_filename { - if let library @ Some(_) = self.find_library_crate(extra_filename, &mut seen_paths)? { - return Ok(library); + match self.extra_filename { + Some(s) => self + .find_library_crate(s, &mut seen_paths) + .or_else(|| self.find_library_crate("", &mut seen_paths)), + None => self.find_library_crate("", &mut seen_paths), + } + } + + crate fn report_errs(self) -> ! { + let add = match self.root { + None => String::new(), + Some(r) => format!(" which `{}` depends on", r.name), + }; + let mut msg = "the following crate versions were found:".to_string(); + let mut err = if !self.rejected_via_hash.is_empty() { + let mut err = struct_span_err!( + self.sess, + self.span, + E0460, + "found possibly newer version of crate `{}`{}", + self.crate_name, + add + ); + err.note("perhaps that crate needs to be recompiled?"); + let mismatches = self.rejected_via_hash.iter(); + for &CrateMismatch { ref path, .. } in mismatches { + msg.push_str(&format!("\ncrate `{}`: {}", self.crate_name, path.display())); + } + match self.root { + None => {} + Some(r) => { + for path in r.source.paths() { + msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); + } + } + } + err.note(&msg); + err + } else if !self.rejected_via_triple.is_empty() { + let mut err = struct_span_err!( + self.sess, + self.span, + E0461, + "couldn't find crate `{}` \ + with expected target triple {}{}", + self.crate_name, + self.triple, + add + ); + let mismatches = self.rejected_via_triple.iter(); + for &CrateMismatch { ref path, ref got } in mismatches { + msg.push_str(&format!( + "\ncrate `{}`, target triple {}: {}", + self.crate_name, + got, + path.display() + )); + } + err.note(&msg); + err + } else if !self.rejected_via_kind.is_empty() { + let mut err = struct_span_err!( + self.sess, + self.span, + E0462, + "found staticlib `{}` instead of rlib or dylib{}", + self.crate_name, + add + ); + err.help("please recompile that crate using --crate-type lib"); + let mismatches = self.rejected_via_kind.iter(); + for &CrateMismatch { ref path, .. } in mismatches { + msg.push_str(&format!("\ncrate `{}`: {}", self.crate_name, path.display())); + } + err.note(&msg); + err + } else if !self.rejected_via_version.is_empty() { + let mut err = struct_span_err!( + self.sess, + self.span, + E0514, + "found crate `{}` compiled by an incompatible version \ + of rustc{}", + self.crate_name, + add + ); + err.help(&format!( + "please recompile that crate using this compiler ({})", + rustc_version() + )); + let mismatches = self.rejected_via_version.iter(); + for &CrateMismatch { ref path, ref got } in mismatches { + msg.push_str(&format!( + "\ncrate `{}` compiled by {}: {}", + self.crate_name, + got, + path.display() + )); + } + err.note(&msg); + err + } else { + let mut err = struct_span_err!( + self.sess, + self.span, + E0463, + "can't find crate for `{}`{}", + self.crate_name, + add + ); + + if (self.crate_name == sym::std || self.crate_name == sym::core) + && self.triple != TargetTriple::from_triple(config::host_triple()) + { + err.note(&format!("the `{}` target may not be installed", self.triple)); + } else if self.crate_name == sym::profiler_builtins { + err.note(&"the compiler may have been built without the profiler runtime"); + } + err.span_label(self.span, "can't find crate"); + err + }; + + if !self.rejected_via_filename.is_empty() { + let dylibname = self.dylibname(); + let mismatches = self.rejected_via_filename.iter(); + for &CrateMismatch { ref path, .. } in mismatches { + err.note(&format!( + "extern location for {} is of an unknown type: {}", + self.crate_name, + path.display() + )) + .help(&format!( + "file name should be lib*.rlib or {}*.{}", + dylibname.0, dylibname.1 + )); } } - self.find_library_crate("", &mut seen_paths) + + err.emit(); + self.sess.abort_if_errors(); + unreachable!(); } fn find_library_crate( &mut self, extra_prefix: &str, seen_paths: &mut FxHashSet, - ) -> Result, CrateError> { + ) -> Option { + let dypair = self.dylibname(); + let staticpair = self.staticlibname(); + // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" - let dylib_prefix = - format!("{}{}{}", self.target.options.dll_prefix, self.crate_name, extra_prefix); + let dylib_prefix = format!("{}{}{}", dypair.0, self.crate_name, extra_prefix); let rlib_prefix = format!("lib{}{}", self.crate_name, extra_prefix); - let staticlib_prefix = - format!("{}{}{}", self.target.options.staticlib_prefix, self.crate_name, extra_prefix); + let staticlib_prefix = format!("{}{}{}", staticpair.0, self.crate_name, extra_prefix); let mut candidates: FxHashMap<_, (FxHashMap<_, _>, FxHashMap<_, _>, FxHashMap<_, _>)> = Default::default(); @@ -405,18 +555,10 @@ impl<'a> CrateLocator<'a> { (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib) } else if file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") { (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta) - } else if file.starts_with(&dylib_prefix) - && file.ends_with(&self.target.options.dll_suffix) - { - ( - &file - [(dylib_prefix.len())..(file.len() - self.target.options.dll_suffix.len())], - CrateFlavor::Dylib, - ) + } else if file.starts_with(&dylib_prefix) && file.ends_with(&dypair.1) { + (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib) } else { - if file.starts_with(&staticlib_prefix) - && file.ends_with(&self.target.options.staticlib_suffix) - { + if file.starts_with(&staticlib_prefix) && file.ends_with(&staticpair.1) { staticlibs .push(CrateMismatch { path: spf.path.clone(), got: "static".to_string() }); } @@ -425,7 +567,9 @@ impl<'a> CrateLocator<'a> { info!("lib candidate: {}", spf.path.display()); - let (rlibs, rmetas, dylibs) = candidates.entry(hash.to_string()).or_default(); + let hash_str = hash.to_string(); + let slot = candidates.entry(hash_str).or_default(); + let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot; fs::canonicalize(&spf.path) .map(|p| { if seen_paths.contains(&p) { @@ -433,10 +577,16 @@ impl<'a> CrateLocator<'a> { }; seen_paths.insert(p.clone()); match found_kind { - CrateFlavor::Rlib => rlibs.insert(p, kind), - CrateFlavor::Rmeta => rmetas.insert(p, kind), - CrateFlavor::Dylib => dylibs.insert(p, kind), - }; + CrateFlavor::Rlib => { + rlibs.insert(p, kind); + } + CrateFlavor::Rmeta => { + rmetas.insert(p, kind); + } + CrateFlavor::Dylib => { + dylibs.insert(p, kind); + } + } FileMatches }) .unwrap_or(FileDoesntMatch) @@ -453,7 +603,7 @@ impl<'a> CrateLocator<'a> { // search is being performed for. let mut libraries = FxHashMap::default(); for (_hash, (rlibs, rmetas, dylibs)) in candidates { - if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs)? { + if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs) { libraries.insert(svh, lib); } } @@ -462,9 +612,39 @@ impl<'a> CrateLocator<'a> { // what we've got and figure out if we found multiple candidates for // libraries or not. match libraries.len() { - 0 => Ok(None), - 1 => Ok(Some(libraries.into_iter().next().unwrap().1)), - _ => Err(CrateError::MultipleMatchingCrates(self.crate_name, libraries)), + 0 => None, + 1 => Some(libraries.into_iter().next().unwrap().1), + _ => { + let mut err = struct_span_err!( + self.sess, + self.span, + E0464, + "multiple matching crates for `{}`", + self.crate_name + ); + let candidates = libraries + .iter() + .filter_map(|(_, lib)| { + let crate_name = &lib.metadata.get_root().name().as_str(); + match &(&lib.source.dylib, &lib.source.rlib) { + &(&Some((ref pd, _)), &Some((ref pr, _))) => Some(format!( + "\ncrate `{}`: {}\n{:>padding$}", + crate_name, + pd.display(), + pr.display(), + padding = 8 + crate_name.len() + )), + &(&Some((ref p, _)), &None) | &(&None, &Some((ref p, _))) => { + Some(format!("\ncrate `{}`: {}", crate_name, p.display())) + } + &(&None, &None) => None, + } + }) + .collect::(); + err.note(&format!("candidates:{}", candidates)); + err.emit(); + None + } } } @@ -473,16 +653,16 @@ impl<'a> CrateLocator<'a> { rlibs: FxHashMap, rmetas: FxHashMap, dylibs: FxHashMap, - ) -> Result, CrateError> { + ) -> Option<(Svh, Library)> { let mut slot = None; // Order here matters, rmeta should come first. See comment in // `extract_one` below. let source = CrateSource { - rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot)?, - rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot)?, - dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot)?, + rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot), + rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot), + dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot), }; - Ok(slot.map(|(svh, metadata)| (svh, Library { source, metadata }))) + slot.map(|(svh, metadata)| (svh, Library { source, metadata })) } fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool { @@ -518,7 +698,10 @@ impl<'a> CrateLocator<'a> { m: FxHashMap, flavor: CrateFlavor, slot: &mut Option<(Svh, MetadataBlob)>, - ) -> Result, CrateError> { + ) -> Option<(PathBuf, PathKind)> { + let mut ret: Option<(PathBuf, PathKind)> = None; + let mut error = 0; + // If we are producing an rlib, and we've already loaded metadata, then // we should not attempt to discover further crate sources (unless we're // locating a proc macro; exact logic is in needs_crate_flavor). This means @@ -535,14 +718,13 @@ impl<'a> CrateLocator<'a> { // from the other crate sources. if slot.is_some() { if m.is_empty() || !self.needs_crate_flavor(flavor) { - return Ok(None); + return None; } else if m.len() == 1 { - return Ok(Some(m.into_iter().next().unwrap())); + return Some(m.into_iter().next().unwrap()); } } - let mut ret: Option<(PathBuf, PathKind)> = None; - let mut err_data: Option> = None; + let mut err: Option> = None; for (lib, kind) in m { info!("{} reading metadata from: {}", flavor, lib.display()); let (hash, metadata) = @@ -562,18 +744,30 @@ impl<'a> CrateLocator<'a> { }; // If we see multiple hashes, emit an error about duplicate candidates. if slot.as_ref().map_or(false, |s| s.0 != hash) { - if let Some(candidates) = err_data { - return Err(CrateError::MultipleCandidates( - self.crate_name, - flavor, - candidates, - )); + let mut e = struct_span_err!( + self.sess, + self.span, + E0465, + "multiple {} candidates for `{}` found", + flavor, + self.crate_name + ); + e.span_note( + self.span, + &format!(r"candidate #1: {}", ret.as_ref().unwrap().0.display()), + ); + if let Some(ref mut e) = err { + e.emit(); } - err_data = Some(vec![ret.as_ref().unwrap().0.clone()]); + err = Some(e); + error = 1; *slot = None; } - if let Some(candidates) = &mut err_data { - candidates.push(lib); + if error > 0 { + error += 1; + err.as_mut() + .unwrap() + .span_note(self.span, &format!(r"candidate #{}: {}", error, lib.display())); continue; } @@ -596,7 +790,7 @@ impl<'a> CrateLocator<'a> { // As a result, we favor the sysroot crate here. Note that the // candidates are all canonicalized, so we canonicalize the sysroot // as well. - if let Some((prev, _)) = &ret { + if let Some((ref prev, _)) = ret { let sysroot = &self.sess.sysroot; let sysroot = sysroot.canonicalize().unwrap_or_else(|_| sysroot.to_path_buf()); if prev.starts_with(&sysroot) { @@ -607,10 +801,11 @@ impl<'a> CrateLocator<'a> { ret = Some((lib, kind)); } - if let Some(candidates) = err_data { - Err(CrateError::MultipleCandidates(self.crate_name, flavor, candidates)) + if error > 0 { + err.unwrap().emit(); + None } else { - Ok(ret) + ret } } @@ -665,29 +860,71 @@ impl<'a> CrateLocator<'a> { Some(hash) } - fn find_commandline_library(&mut self) -> Result, CrateError> { + // Returns the corresponding (prefix, suffix) that files need to have for + // dynamic libraries + fn dylibname(&self) -> (String, String) { + let t = &self.target; + (t.options.dll_prefix.clone(), t.options.dll_suffix.clone()) + } + + // Returns the corresponding (prefix, suffix) that files need to have for + // static libraries + fn staticlibname(&self) -> (String, String) { + let t = &self.target; + (t.options.staticlib_prefix.clone(), t.options.staticlib_suffix.clone()) + } + + fn find_commandline_library(&mut self) -> Option { // First, filter out all libraries that look suspicious. We only accept // files which actually exist that have the correct naming scheme for // rlibs/dylibs. + let sess = self.sess; + let dylibname = self.dylibname(); let mut rlibs = FxHashMap::default(); let mut rmetas = FxHashMap::default(); let mut dylibs = FxHashMap::default(); - for loc in &self.exact_paths { - if !loc.exists() { - return Err(CrateError::ExternLocationNotExist(self.crate_name, loc.clone())); - } - let file = match loc.file_name().and_then(|s| s.to_str()) { - Some(file) => file, - None => { - return Err(CrateError::ExternLocationNotFile(self.crate_name, loc.clone())); + { + let crate_name = self.crate_name; + let rejected_via_filename = &mut self.rejected_via_filename; + let locs = self.exact_paths.iter().filter(|loc| { + if !loc.exists() { + sess.err(&format!( + "extern location for {} does not exist: {}", + crate_name, + loc.display() + )); + return false; + } + let file = match loc.file_name().and_then(|s| s.to_str()) { + Some(file) => file, + None => { + sess.err(&format!( + "extern location for {} is not a file: {}", + crate_name, + loc.display() + )); + return false; + } + }; + if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta")) + { + return true; + } else { + let (ref prefix, ref suffix) = dylibname; + if file.starts_with(&prefix[..]) && file.ends_with(&suffix[..]) { + return true; + } } - }; - if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta")) - || file.starts_with(&self.target.options.dll_prefix) - && file.ends_with(&self.target.options.dll_suffix) - { - // Make sure there's at most one rlib and at most one dylib. + rejected_via_filename + .push(CrateMismatch { path: (*loc).clone(), got: String::new() }); + + false + }); + + // Now that we have an iterator of good candidates, make sure + // there's at most one rlib and at most one dylib. + for loc in locs { if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") { rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") { @@ -695,30 +932,25 @@ impl<'a> CrateLocator<'a> { } else { dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); } - } else { - self.rejected_via_filename - .push(CrateMismatch { path: loc.clone(), got: String::new() }); } - } + }; // Extract the dylib/rlib/rmeta triple. - Ok(self.extract_lib(rlibs, rmetas, dylibs)?.map(|(_, lib)| lib)) + self.extract_lib(rlibs, rmetas, dylibs).map(|(_, lib)| lib) } +} - crate fn into_error(self) -> CrateError { - CrateError::LocatorCombined(CombinedLocatorError { - crate_name: self.crate_name, - root: self.root.cloned(), - triple: self.triple, - dll_prefix: self.target.options.dll_prefix.clone(), - dll_suffix: self.target.options.dll_suffix.clone(), - rejected_via_hash: self.rejected_via_hash, - rejected_via_triple: self.rejected_via_triple, - rejected_via_kind: self.rejected_via_kind, - rejected_via_version: self.rejected_via_version, - rejected_via_filename: self.rejected_via_filename, - }) - } +// Just a small wrapper to time how long reading metadata takes. +fn get_metadata_section( + target: &Target, + flavor: CrateFlavor, + filename: &Path, + loader: &dyn MetadataLoader, +) -> Result { + let start = Instant::now(); + let ret = get_metadata_section_imp(target, flavor, filename, loader); + info!("reading {:?} => {:?}", filename.file_name().unwrap(), start.elapsed()); + ret } /// A trivial wrapper for `Mmap` that implements `StableDeref`. @@ -734,7 +966,7 @@ impl Deref for StableDerefMmap { unsafe impl stable_deref_trait::StableDeref for StableDerefMmap {} -fn get_metadata_section( +fn get_metadata_section_imp( target: &Target, flavor: CrateFlavor, filename: &Path, @@ -794,19 +1026,12 @@ pub fn find_plugin_registrar( metadata_loader: &dyn MetadataLoader, span: Span, name: Symbol, -) -> (PathBuf, CrateDisambiguator) { - match find_plugin_registrar_impl(sess, metadata_loader, name) { - Ok(res) => res, - Err(err) => err.report(sess, span), - } -} - -fn find_plugin_registrar_impl<'a>( - sess: &'a Session, - metadata_loader: &dyn MetadataLoader, - name: Symbol, -) -> Result<(PathBuf, CrateDisambiguator), CrateError> { +) -> Option<(PathBuf, CrateDisambiguator)> { info!("find plugin registrar `{}`", name); + let target_triple = sess.opts.target_triple.clone(); + let host_triple = TargetTriple::from_triple(config::host_triple()); + let is_cross = target_triple != host_triple; + let mut target_only = false; let mut locator = CrateLocator::new( sess, metadata_loader, @@ -816,16 +1041,57 @@ fn find_plugin_registrar_impl<'a>( None, // extra_filename true, // is_host PathKind::Crate, + span, None, // root None, // is_proc_macro ); - match locator.maybe_load_library_crate()? { - Some(library) => match library.source.dylib { - Some(dylib) => Ok((dylib.0, library.metadata.get_root().disambiguator())), - None => Err(CrateError::NonDylibPlugin(name)), - }, - None => Err(locator.into_error()), + let library = locator.maybe_load_library_crate().or_else(|| { + if !is_cross { + return None; + } + // Try loading from target crates. This will abort later if we + // try to load a plugin registrar function, + target_only = true; + + locator.target = &sess.target.target; + locator.triple = target_triple; + locator.filesearch = sess.target_filesearch(PathKind::Crate); + + locator.maybe_load_library_crate() + }); + let library = match library { + Some(l) => l, + None => locator.report_errs(), + }; + + if target_only { + let message = format!( + "plugin `{}` is not available for triple `{}` (only found {})", + name, + config::host_triple(), + sess.opts.target_triple + ); + struct_span_err!(sess, span, E0456, "{}", &message).emit(); + return None; + } + + match library.source.dylib { + Some(dylib) => Some((dylib.0, library.metadata.get_root().disambiguator())), + None => { + struct_span_err!( + sess, + span, + E0457, + "plugin `{}` only found in rlib format, but must be available \ + in dylib format", + name + ) + .emit(); + // No need to abort because the loading code will just ignore this + // empty dylib. + None + } } } @@ -834,8 +1100,8 @@ pub fn list_file_metadata( target: &Target, path: &Path, metadata_loader: &dyn MetadataLoader, - out: &mut dyn Write, -) -> IoResult<()> { + out: &mut dyn io::Write, +) -> io::Result<()> { let filename = path.file_name().unwrap().to_str().unwrap(); let flavor = if filename.ends_with(".rlib") { CrateFlavor::Rlib @@ -849,259 +1115,3 @@ pub fn list_file_metadata( Err(msg) => write!(out, "{}\n", msg), } } - -// ------------------------------------------ Error reporting ------------------------------------- - -#[derive(Clone)] -struct CrateMismatch { - path: PathBuf, - got: String, -} - -/// Candidate rejection reasons collected during crate search. -/// If no candidate is accepted, then these reasons are presented to the user, -/// otherwise they are ignored. -crate struct CombinedLocatorError { - crate_name: Symbol, - root: Option, - triple: TargetTriple, - dll_prefix: String, - dll_suffix: String, - rejected_via_hash: Vec, - rejected_via_triple: Vec, - rejected_via_kind: Vec, - rejected_via_version: Vec, - rejected_via_filename: Vec, -} - -crate enum CrateError { - NonAsciiName(Symbol), - ExternLocationNotExist(Symbol, PathBuf), - ExternLocationNotFile(Symbol, PathBuf), - MultipleCandidates(Symbol, CrateFlavor, Vec), - MultipleMatchingCrates(Symbol, FxHashMap), - SymbolConflictsCurrent(Symbol), - SymbolConflictsOthers(Symbol), - DlOpen(String), - DlSym(String), - LocatorCombined(CombinedLocatorError), - NonDylibPlugin(Symbol), -} - -impl CrateError { - crate fn report(self, sess: &Session, span: Span) -> ! { - let mut err = match self { - CrateError::NonAsciiName(crate_name) => sess.struct_span_err( - span, - &format!("cannot load a crate with a non-ascii name `{}`", crate_name), - ), - CrateError::ExternLocationNotExist(crate_name, loc) => sess.struct_span_err( - span, - &format!("extern location for {} does not exist: {}", crate_name, loc.display()), - ), - CrateError::ExternLocationNotFile(crate_name, loc) => sess.struct_span_err( - span, - &format!("extern location for {} is not a file: {}", crate_name, loc.display()), - ), - CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - let mut err = struct_span_err!( - sess, - span, - E0465, - "multiple {} candidates for `{}` found", - flavor, - crate_name, - ); - for (i, candidate) in candidates.iter().enumerate() { - err.span_note(span, &format!("candidate #{}: {}", i + 1, candidate.display())); - } - err - } - CrateError::MultipleMatchingCrates(crate_name, libraries) => { - let mut err = struct_span_err!( - sess, - span, - E0464, - "multiple matching crates for `{}`", - crate_name - ); - let candidates = libraries - .iter() - .filter_map(|(_, lib)| { - let crate_name = &lib.metadata.get_root().name().as_str(); - match (&lib.source.dylib, &lib.source.rlib) { - (Some((pd, _)), Some((pr, _))) => Some(format!( - "\ncrate `{}`: {}\n{:>padding$}", - crate_name, - pd.display(), - pr.display(), - padding = 8 + crate_name.len() - )), - (Some((p, _)), None) | (None, Some((p, _))) => { - Some(format!("\ncrate `{}`: {}", crate_name, p.display())) - } - (None, None) => None, - } - }) - .collect::(); - err.note(&format!("candidates:{}", candidates)); - err - } - CrateError::SymbolConflictsCurrent(root_name) => struct_span_err!( - sess, - span, - E0519, - "the current crate is indistinguishable from one of its dependencies: it has the \ - same crate-name `{}` and was compiled with the same `-C metadata` arguments. \ - This will result in symbol conflicts between the two.", - root_name, - ), - CrateError::SymbolConflictsOthers(root_name) => struct_span_err!( - sess, - span, - E0523, - "found two different crates with name `{}` that are not distinguished by differing \ - `-C metadata`. This will result in symbol conflicts between the two.", - root_name, - ), - CrateError::DlOpen(s) | CrateError::DlSym(s) => sess.struct_span_err(span, &s), - CrateError::LocatorCombined(locator) => { - let crate_name = locator.crate_name; - let add = match &locator.root { - None => String::new(), - Some(r) => format!(" which `{}` depends on", r.name), - }; - let mut msg = "the following crate versions were found:".to_string(); - let mut err = if !locator.rejected_via_hash.is_empty() { - let mut err = struct_span_err!( - sess, - span, - E0460, - "found possibly newer version of crate `{}`{}", - crate_name, - add, - ); - err.note("perhaps that crate needs to be recompiled?"); - let mismatches = locator.rejected_via_hash.iter(); - for CrateMismatch { path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); - } - if let Some(r) = locator.root { - for path in r.source.paths() { - msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); - } - } - err.note(&msg); - err - } else if !locator.rejected_via_triple.is_empty() { - let mut err = struct_span_err!( - sess, - span, - E0461, - "couldn't find crate `{}` with expected target triple {}{}", - crate_name, - locator.triple, - add, - ); - let mismatches = locator.rejected_via_triple.iter(); - for CrateMismatch { path, got } in mismatches { - msg.push_str(&format!( - "\ncrate `{}`, target triple {}: {}", - crate_name, - got, - path.display(), - )); - } - err.note(&msg); - err - } else if !locator.rejected_via_kind.is_empty() { - let mut err = struct_span_err!( - sess, - span, - E0462, - "found staticlib `{}` instead of rlib or dylib{}", - crate_name, - add, - ); - err.help("please recompile that crate using --crate-type lib"); - let mismatches = locator.rejected_via_kind.iter(); - for CrateMismatch { path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); - } - err.note(&msg); - err - } else if !locator.rejected_via_version.is_empty() { - let mut err = struct_span_err!( - sess, - span, - E0514, - "found crate `{}` compiled by an incompatible version of rustc{}", - crate_name, - add, - ); - err.help(&format!( - "please recompile that crate using this compiler ({})", - rustc_version(), - )); - let mismatches = locator.rejected_via_version.iter(); - for CrateMismatch { path, got } in mismatches { - msg.push_str(&format!( - "\ncrate `{}` compiled by {}: {}", - crate_name, - got, - path.display(), - )); - } - err.note(&msg); - err - } else { - let mut err = struct_span_err!( - sess, - span, - E0463, - "can't find crate for `{}`{}", - crate_name, - add, - ); - - if (crate_name == sym::std || crate_name == sym::core) - && locator.triple != TargetTriple::from_triple(config::host_triple()) - { - err.note(&format!("the `{}` target may not be installed", locator.triple)); - } else if crate_name == sym::profiler_builtins { - err.note(&"the compiler may have been built without the profiler runtime"); - } - err.span_label(span, "can't find crate"); - err - }; - - if !locator.rejected_via_filename.is_empty() { - let mismatches = locator.rejected_via_filename.iter(); - for CrateMismatch { path, .. } in mismatches { - err.note(&format!( - "extern location for {} is of an unknown type: {}", - crate_name, - path.display(), - )) - .help(&format!( - "file name should be lib*.rlib or {}*.{}", - locator.dll_prefix, locator.dll_suffix - )); - } - } - err - } - CrateError::NonDylibPlugin(crate_name) => struct_span_err!( - sess, - span, - E0457, - "plugin `{}` only found in rlib format, but must be available in dylib format", - crate_name, - ), - }; - - err.emit(); - sess.abort_if_errors(); - unreachable!(); - } -} diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index a6d708ebe9048..4746e53ce59a9 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1132,16 +1132,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, tcx)) } - fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet { - self.root - .tables - .unused_generic_params - .get(self, id) - .filter(|_| !self.is_proc_macro(id)) - .map(|params| params.decode(self)) - .unwrap_or_default() - } - fn get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> IndexVec> { self.root .tables diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index 9160327c1d1b5..be153758a2a0c 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -113,7 +113,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, } optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) } promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } - unused_generic_params => { cdata.get_unused_generic_params(def_id.index) } mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 186828b6a19f6..a8c46d3e32e6a 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1065,8 +1065,6 @@ impl EncodeContext<'tcx> { debug!("EntryBuilder::encode_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id)); - record!(self.tables.unused_generic_params[def_id.to_def_id()] <- - self.tcx.unused_generic_params(def_id)); } } diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index e616e8cf00a2f..8abc3784d6d2f 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, DefIndex}; use rustc_hir::lang_items; -use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; +use rustc_index::vec::IndexVec; use rustc_middle::hir::exports::Export; use rustc_middle::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; @@ -277,7 +277,6 @@ define_tables! { super_predicates: Table)>, mir: Table)>, promoted_mir: Table>)>, - unused_generic_params: Table>>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs index a68301385b7a5..b7dccb8d8ce6d 100644 --- a/src/librustc_middle/lib.rs +++ b/src/librustc_middle/lib.rs @@ -27,7 +27,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(cmp_min_max_by)] #![feature(const_fn)] #![feature(const_panic)] #![feature(const_fn_transmute)] diff --git a/src/librustc_middle/mir/coverage/mod.rs b/src/librustc_middle/mir/coverage/mod.rs index 1e06dadfa2453..327f321bd7534 100644 --- a/src/librustc_middle/mir/coverage/mod.rs +++ b/src/librustc_middle/mir/coverage/mod.rs @@ -2,10 +2,9 @@ /// Positional arguments to `libcore::count_code_region()` pub mod count_code_region_args { - pub const FUNCTION_SOURCE_HASH: usize = 0; - pub const COUNTER_INDEX: usize = 1; - pub const START_BYTE_POS: usize = 2; - pub const END_BYTE_POS: usize = 3; + pub const COUNTER_INDEX: usize = 0; + pub const START_BYTE_POS: usize = 1; + pub const END_BYTE_POS: usize = 2; } /// Positional arguments to `libcore::coverage_counter_add()` and diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs index bb204223b6060..d22bde2ff8b1e 100644 --- a/src/librustc_middle/mir/mono.rs +++ b/src/librustc_middle/mir/mono.rs @@ -86,7 +86,7 @@ impl<'tcx> MonoItem<'tcx> { .debugging_opts .inline_in_all_cgus .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No) - && tcx.sess.opts.cg.link_dead_code != Some(true); + && !tcx.sess.opts.cg.link_dead_code; match *self { MonoItem::Fn(ref instance) => { @@ -168,7 +168,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::GlobalAsm(..) => return true, }; - !tcx.subst_and_check_impossible_predicates((def_id, &substs)) + tcx.substitute_normalize_and_test_predicates((def_id, &substs)) } pub fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String { diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs index 6ce5d61fbed1b..402a5c421a7b5 100644 --- a/src/librustc_middle/mir/query.rs +++ b/src/librustc_middle/mir/query.rs @@ -400,11 +400,13 @@ pub struct DestructuredConst<'tcx> { /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct CoverageInfo { + /// A hash value that can be used by the consumer of the coverage profile data to detect + /// changes to the instrumented source of the associated MIR body (typically, for an + /// individual function). + pub hash: u64, + /// The total number of coverage region counters added to the MIR `Body`. pub num_counters: u32, - - /// The total number of coverage region counter expressions added to the MIR `Body`. - pub num_expressions: u32, } impl<'tcx> TyCtxt<'tcx> { diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index f857af28622d1..4dd8723bd72a1 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -103,13 +103,9 @@ rustc_queries! { /// // ^ While calling `opt_const_param_of` for other bodies returns `None`. /// } /// ``` - // It looks like caching this query on disk actually slightly - // worsened performance in #74376. - // - // Once const generics are more prevalently used, we might want to - // consider only caching calls returning `Some`. query opt_const_param_of(key: LocalDefId) -> Option { desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) } + // FIXME(#74113): consider storing this query on disk. } /// Records the type of every item. @@ -1313,13 +1309,6 @@ rustc_queries! { query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> { desc { "codegen_unit" } } - query unused_generic_params(key: DefId) -> FiniteBitSet { - cache_on_disk_if { key.is_local() } - desc { - |tcx| "determining which generic parameters are unused by `{}`", - tcx.def_path_str(key) - } - } query backend_optimization_level(_: CrateNum) -> OptLevel { desc { "optimization level used by backend" } } @@ -1472,9 +1461,9 @@ rustc_queries! { desc { "normalizing `{:?}`", goal } } - query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { + query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { desc { |tcx| - "impossible substituted predicates:`{}`", + "testing substituted normalized predicates:`{}`", tcx.def_path_str(key.0) } } diff --git a/src/librustc_middle/traits/specialization_graph.rs b/src/librustc_middle/traits/specialization_graph.rs index c9aae8980076f..f4961617b81c6 100644 --- a/src/librustc_middle/traits/specialization_graph.rs +++ b/src/librustc_middle/traits/specialization_graph.rs @@ -1,6 +1,5 @@ use crate::ich::{self, StableHashingContext}; use crate::ty::fast_reject::SimplifiedType; -use crate::ty::fold::TypeFoldable; use crate::ty::{self, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -227,8 +226,7 @@ pub fn ancestors( start_from_impl: DefId, ) -> Result, ErrorReported> { let specialization_graph = tcx.specialization_graph_of(trait_def_id); - - if specialization_graph.has_errored || tcx.type_of(start_from_impl).references_error() { + if specialization_graph.has_errored { Err(ErrorReported) } else { Ok(Ancestors { diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index 11a8bedb6605b..0e86fcf53b247 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -85,19 +85,7 @@ impl FlagComputation { } &ty::Generator(_, ref substs, _) => { - let substs = substs.as_generator(); - let should_remove_further_specializable = - !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_substs(substs.parent_substs()); - if should_remove_further_specializable { - self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; - } - - self.add_ty(substs.resume_ty()); - self.add_ty(substs.return_ty()); - self.add_ty(substs.witness()); - self.add_ty(substs.yield_ty()); - self.add_ty(substs.tupled_upvars_ty()); + self.add_substs(substs); } &ty::GeneratorWitness(ts) => { @@ -107,17 +95,7 @@ impl FlagComputation { } &ty::Closure(_, substs) => { - let substs = substs.as_closure(); - let should_remove_further_specializable = - !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_substs(substs.parent_substs()); - if should_remove_further_specializable { - self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; - } - - self.add_ty(substs.sig_as_fn_ptr_ty()); - self.add_ty(substs.kind_ty()); - self.add_ty(substs.tupled_upvars_ty()); + self.add_substs(substs); } &ty::Bound(debruijn, _) => { diff --git a/src/librustc_middle/ty/instance.rs b/src/librustc_middle/ty/instance.rs index cdb883da32bb0..f627d05d3e9d2 100644 --- a/src/librustc_middle/ty/instance.rs +++ b/src/librustc_middle/ty/instance.rs @@ -1,6 +1,5 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::print::{FmtPrinter, Printer}; -use crate::ty::subst::InternalSubsts; use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable}; use rustc_errors::ErrorReported; use rustc_hir::def::Namespace; @@ -107,9 +106,32 @@ pub enum InstanceDef<'tcx> { } impl<'tcx> Instance<'tcx> { - /// Returns the `Ty` corresponding to this `Instance`, with generic substitutions applied and - /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. - pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { + /// Returns the `Ty` corresponding to this `Instance`, + /// with generic substitutions applied and lifetimes erased. + /// + /// This method can only be called when the 'substs' for this Instance + /// are fully monomorphic (no `ty::Param`'s are present). + /// This is usually the case (e.g. during codegen). + /// However, during constant evaluation, we may want + /// to try to resolve a `Instance` using generic parameters + /// (e.g. when we are attempting to to do const-propagation). + /// In this case, `Instance.ty_env` should be used to provide + /// the `ParamEnv` for our generic context. + pub fn monomorphic_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + let ty = tcx.type_of(self.def.def_id()); + // There shouldn't be any params - if there are, then + // Instance.ty_env should have been used to provide the proper + // ParamEnv + if self.substs.has_param_types_or_consts() { + bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs); + } + tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty) + } + + /// Like `Instance.ty`, but allows a `ParamEnv` to be specified for use during + /// normalization. This method is only really useful during constant evaluation, + /// where we are dealing with potentially generic types. + pub fn ty_env(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty) } @@ -464,42 +486,6 @@ impl<'tcx> Instance<'tcx> { | InstanceDef::VtableShim(..) => Some(self.substs), } } - - /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by - /// identify parameters if they are determined to be unused in `instance.def`. - pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self { - debug!("polymorphize: running polymorphization analysis"); - if !tcx.sess.opts.debugging_opts.polymorphize { - return self; - } - - if let InstanceDef::Item(def) = self.def { - let unused = tcx.unused_generic_params(def.did); - - if unused.is_empty() { - // Exit early if every parameter was used. - return self; - } - - debug!("polymorphize: unused={:?}", unused); - let polymorphized_substs = - InternalSubsts::for_item(tcx, def.did, |param, _| match param.kind { - // If parameter is a const or type parameter.. - ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if - // ..and is within range and unused.. - unused.contains(param.index).unwrap_or(false) => - // ..then use the identity for this parameter. - tcx.mk_param_from_def(param), - // Otherwise, use the parameter as before. - _ => self.substs[param.index as usize], - }); - - debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs); - Self { def: self.def, substs: polymorphized_substs } - } else { - self - } - } } fn needs_fn_once_adapter_shim( diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index cb937bf0112ae..82daae7d921b2 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -876,8 +876,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .iter_enumerated() .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32())); - let mut niche_filling_layout = None; - // Niche-filling enum optimization. if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants { let mut dataful_variant = None; @@ -974,7 +972,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let largest_niche = Niche::from_scalar(dl, offset, niche_scalar.clone()); - niche_filling_layout = Some(Layout { + return Ok(tcx.intern_layout(Layout { variants: Variants::Multiple { tag: niche_scalar, tag_encoding: TagEncoding::Niche { @@ -993,7 +991,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { largest_niche, size, align, - }); + })); } } } @@ -1216,7 +1214,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone()); - let tagged_layout = Layout { + tcx.intern_layout(Layout { variants: Variants::Multiple { tag, tag_encoding: TagEncoding::Direct, @@ -1231,23 +1229,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { abi, align, size, - }; - - let best_layout = match (tagged_layout, niche_filling_layout) { - (tagged_layout, Some(niche_filling_layout)) => { - // Pick the smaller layout; otherwise, - // pick the layout with the larger niche; otherwise, - // pick tagged as it has simpler codegen. - cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| { - let niche_size = - layout.largest_niche.as_ref().map_or(0, |n| n.available(dl)); - (layout.size, cmp::Reverse(niche_size)) - }) - } - (tagged_layout, None) => tagged_layout, - }; - - tcx.intern_layout(best_layout) + }) } // Types with no meaningful known layout. @@ -2299,22 +2281,12 @@ impl<'tcx> ty::Instance<'tcx> { // or should go through `FnAbi` instead, to avoid losing any // adjustments `FnAbi::of_instance` might be performing. fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function. - let ty = self.ty(tcx, ty::ParamEnv::reveal_all()); + let ty = self.monomorphic_ty(tcx); match ty.kind { - ty::FnDef(..) => { - // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering - // parameters unused if they show up in the signature, but not in the `mir::Body` - // (i.e. due to being inside a projection that got normalized, see - // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping - // track of a polymorphization `ParamEnv` to allow normalizing later. - let mut sig = match ty.kind { - ty::FnDef(def_id, substs) => tcx - .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id)) - .subst(tcx, substs), - _ => unreachable!(), - }; - + ty::FnDef(..) | + // Shims currently have type FnPtr. Not sure this should remain. + ty::FnPtr(_) => { + let mut sig = ty.fn_sig(tcx); if let ty::InstanceDef::VtableShim(..) = self.def { // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. sig = sig.map_bound(|mut sig| { @@ -2330,15 +2302,13 @@ impl<'tcx> ty::Instance<'tcx> { let sig = substs.as_closure().sig(); let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| { - tcx.mk_fn_sig( - iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), - sig.output(), - sig.c_variadic, - sig.unsafety, - sig.abi, - ) - }) + sig.map_bound(|sig| tcx.mk_fn_sig( + iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.c_variadic, + sig.unsafety, + sig.abi + )) } ty::Generator(_, substs, _) => { let sig = substs.as_generator().poly_sig(); @@ -2354,8 +2324,10 @@ impl<'tcx> ty::Instance<'tcx> { sig.map_bound(|sig| { let state_did = tcx.require_lang_item(GeneratorStateLangItem, None); let state_adt_ref = tcx.adt_def(state_did); - let state_substs = - tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); + let state_substs = tcx.intern_substs(&[ + sig.yield_ty.into(), + sig.return_ty.into(), + ]); let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); tcx.mk_fn_sig( @@ -2363,11 +2335,11 @@ impl<'tcx> ty::Instance<'tcx> { &ret_ty, false, hir::Unsafety::Normal, - rustc_target::spec::abi::Abi::Rust, + rustc_target::spec::abi::Abi::Rust ) }) } - _ => bug!("unexpected type {:?} in Instance::fn_sig", ty), + _ => bug!("unexpected type {:?} in Instance::fn_sig", ty) } } } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 51a353c013241..21745977b04b1 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -890,7 +890,6 @@ impl<'tcx> Generics { false } - /// Returns the `GenericParamDef` with the given index. pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { if let Some(index) = param_index.checked_sub(self.parent_count) { &self.params[index] @@ -900,7 +899,6 @@ impl<'tcx> Generics { } } - /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`. pub fn region_param( &'tcx self, param: &EarlyBoundRegion, @@ -922,7 +920,7 @@ impl<'tcx> Generics { } } - /// Returns the `GenericParamDef` associated with this `ParamConst`. + /// Returns the `ConstParameterDef` associated with this `ParamConst`. pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { let param = self.param_at(param.index as usize, tcx); match param.kind { diff --git a/src/librustc_middle/ty/normalize_erasing_regions.rs b/src/librustc_middle/ty/normalize_erasing_regions.rs index 48a62b6460467..2f0a57c59eb14 100644 --- a/src/librustc_middle/ty/normalize_erasing_regions.rs +++ b/src/librustc_middle/ty/normalize_erasing_regions.rs @@ -54,6 +54,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable<'tcx>, { + assert!(!value.needs_subst()); let value = self.erase_late_bound_regions(value); self.normalize_erasing_regions(param_env, value) } diff --git a/src/librustc_middle/ty/print/obsolete.rs b/src/librustc_middle/ty/print/obsolete.rs index 2ea7cd2a6dc7a..67b6433b61143 100644 --- a/src/librustc_middle/ty/print/obsolete.rs +++ b/src/librustc_middle/ty/print/obsolete.rs @@ -144,14 +144,12 @@ impl DefPathBasedNames<'tcx> { let substs = substs.truncate_to(self.tcx, generics); self.push_generic_params(substs, iter::empty(), output, debug); } - ty::Param(_) => { - output.push_str(&t.to_string()); - } ty::Error(_) | ty::Bound(..) | ty::Infer(_) | ty::Placeholder(..) | ty::Projection(..) + | ty::Param(_) | ty::GeneratorWitness(_) | ty::Opaque(..) => { if debug { diff --git a/src/librustc_middle/ty/query/mod.rs b/src/librustc_middle/ty/query/mod.rs index 2f7a9aee536d8..2ad49b1acce43 100644 --- a/src/librustc_middle/ty/query/mod.rs +++ b/src/librustc_middle/ty/query/mod.rs @@ -44,7 +44,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate}; -use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; +use rustc_index::vec::IndexVec; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::utils::NativeLibKind; use rustc_session::CrateDisambiguator; diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 03bf51c95c5a3..2f17db6223362 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -318,7 +318,6 @@ pub struct ClosureSubsts<'tcx> { /// Struct returned by `split()`. Note that these are subslices of the /// parent slice and not canonical substs themselves. struct SplitClosureSubsts<'tcx> { - parent: &'tcx [GenericArg<'tcx>], closure_kind_ty: GenericArg<'tcx>, closure_sig_as_fn_ptr_ty: GenericArg<'tcx>, tupled_upvars_ty: GenericArg<'tcx>, @@ -330,13 +329,8 @@ impl<'tcx> ClosureSubsts<'tcx> { /// ordering. fn split(self) -> SplitClosureSubsts<'tcx> { match self.substs[..] { - [ref parent @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { - SplitClosureSubsts { - parent, - closure_kind_ty, - closure_sig_as_fn_ptr_ty, - tupled_upvars_ty, - } + [.., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { + SplitClosureSubsts { closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty } } _ => bug!("closure substs missing synthetics"), } @@ -351,20 +345,9 @@ impl<'tcx> ClosureSubsts<'tcx> { self.substs.len() >= 3 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_)) } - /// Returns the substitutions of the closure's parent. - pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { - self.split().parent - } - #[inline] pub fn upvar_tys(self) -> impl Iterator> + 'tcx { - self.tupled_upvars_ty().tuple_fields() - } - - /// Returns the tuple type representing the upvars for this closure. - #[inline] - pub fn tupled_upvars_ty(self) -> Ty<'tcx> { - self.split().tupled_upvars_ty.expect_ty() + self.split().tupled_upvars_ty.expect_ty().tuple_fields() } /// Returns the closure kind for this closure; may return a type @@ -409,7 +392,6 @@ pub struct GeneratorSubsts<'tcx> { } struct SplitGeneratorSubsts<'tcx> { - parent: &'tcx [GenericArg<'tcx>], resume_ty: GenericArg<'tcx>, yield_ty: GenericArg<'tcx>, return_ty: GenericArg<'tcx>, @@ -420,15 +402,8 @@ struct SplitGeneratorSubsts<'tcx> { impl<'tcx> GeneratorSubsts<'tcx> { fn split(self) -> SplitGeneratorSubsts<'tcx> { match self.substs[..] { - [ref parent @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { - SplitGeneratorSubsts { - parent, - resume_ty, - yield_ty, - return_ty, - witness, - tupled_upvars_ty, - } + [.., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { + SplitGeneratorSubsts { resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty } } _ => bug!("generator substs missing synthetics"), } @@ -443,11 +418,6 @@ impl<'tcx> GeneratorSubsts<'tcx> { self.substs.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_)) } - /// Returns the substitutions of the generator's parent. - pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { - self.split().parent - } - /// This describes the types that can be contained in a generator. /// It will be a type variable initially and unified in the last stages of typeck of a body. /// It contains a tuple of all the types that could end up on a generator frame. @@ -459,13 +429,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { #[inline] pub fn upvar_tys(self) -> impl Iterator> + 'tcx { - self.tupled_upvars_ty().tuple_fields() - } - - /// Returns the tuple type representing the upvars for this generator. - #[inline] - pub fn tupled_upvars_ty(self) -> Ty<'tcx> { - self.split().tupled_upvars_ty.expect_ty() + self.split().tupled_upvars_ty.expect_ty().tuple_fields() } /// Returns the type representing the resume type of the generator. diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 705a1b2ae79e5..dc3e01f3d1561 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -240,7 +240,7 @@ pub fn const_eval_validated_provider<'tcx>( // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def { - let ty = key.value.instance.ty(tcx, key.param_env); + let ty = key.value.instance.ty_env(tcx, key.param_env); let substs = match ty.kind { ty::FnDef(_, substs) => substs, _ => bug!("intrinsic with type {:?}", ty), diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 5836fc9c95a80..851862640226f 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -95,7 +95,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (dest, ret) = match ret { None => match intrinsic_name { sym::transmute => throw_ub_format!("transmuting to uninhabited type"), - sym::unreachable => throw_ub!(Unreachable), sym::abort => M::abort(self)?, // Unsupported diverging intrinsic. _ => return Ok(false), diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 663f61b11554c..4681079a22ddf 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -221,7 +221,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // ABI check { let callee_abi = { - let instance_ty = instance.ty(*self.tcx, self.param_env); + let instance_ty = instance.ty_env(*self.tcx, self.param_env); match instance_ty.kind { ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(), ty::Closure(..) => Abi::RustCall, diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 49a80ca13457d..a1d124bb7602e 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -142,7 +142,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // to determine the type. let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?; trace!("Found drop fn: {:?}", drop_instance); - let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx); + let fn_sig = drop_instance.ty_env(*self.tcx, self.param_env).fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig); // The drop function takes `*mut T` where `T` is the type being dropped, so get that. let args = fn_sig.inputs(); diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 4e7142a93aedc..cd6c38997f18f 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -51,7 +51,6 @@ pub fn provide(providers: &mut Providers) { shim::provide(providers); transform::provide(providers); monomorphize::partitioning::provide(providers); - monomorphize::polymorphize::provide(providers); providers.const_eval_validated = const_eval::const_eval_validated_provider; providers.const_eval_raw = const_eval::const_eval_raw_provider; providers.const_caller_location = const_eval::const_caller_location; diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 0b5f27fc17a72..35fb950ce66b9 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -358,9 +358,9 @@ fn collect_items_rec<'tcx>( let instance = Instance::mono(tcx, def_id); // Sanity check whether this ended up being collected accidentally - debug_assert!(should_codegen_locally(tcx, &instance)); + debug_assert!(should_monomorphize_locally(tcx, &instance)); - let ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let ty = instance.monomorphic_ty(tcx); visit_drop_use(tcx, ty, true, starting_point.span, &mut neighbors); recursion_depth_reset = None; @@ -371,7 +371,7 @@ fn collect_items_rec<'tcx>( } MonoItem::Fn(instance) => { // Sanity check whether this ended up being collected accidentally - debug_assert!(should_codegen_locally(tcx, &instance)); + debug_assert!(should_monomorphize_locally(tcx, &instance)); // Keep track of the monomorphization recursion depth recursion_depth_reset = @@ -584,8 +584,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { substs, ty::ClosureKind::FnOnce, ); - if should_codegen_locally(self.tcx, &instance) { - self.output.push(create_fn_mono_item(self.tcx, instance, span)); + if should_monomorphize_locally(self.tcx, &instance) { + self.output.push(create_fn_mono_item(instance, span)); } } _ => bug!(), @@ -596,14 +596,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { let exchange_malloc_fn_def_id = tcx.require_lang_item(ExchangeMallocFnLangItem, None); let instance = Instance::mono(tcx, exchange_malloc_fn_def_id); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(self.tcx, instance, span)); + if should_monomorphize_locally(tcx, &instance) { + self.output.push(create_fn_mono_item(instance, span)); } } mir::Rvalue::ThreadLocalRef(def_id) => { assert!(self.tcx.is_thread_local_static(def_id)); let instance = Instance::mono(self.tcx, def_id); - if should_codegen_locally(self.tcx, &instance) { + if should_monomorphize_locally(self.tcx, &instance) { trace!("collecting thread-local static {:?}", def_id); self.output.push(respan(span, MonoItem::Static(def_id))); } @@ -664,7 +664,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { } mir::InlineAsmOperand::SymStatic { def_id } => { let instance = Instance::mono(self.tcx, def_id); - if should_codegen_locally(self.tcx, &instance) { + if should_monomorphize_locally(self.tcx, &instance) { trace!("collecting asm sym static {:?}", def_id); self.output.push(respan(source, MonoItem::Static(def_id))); } @@ -735,7 +735,7 @@ fn visit_instance_use<'tcx>( output: &mut Vec>>, ) { debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call); - if !should_codegen_locally(tcx, &instance) { + if !should_monomorphize_locally(tcx, &instance) { return; } @@ -748,7 +748,7 @@ fn visit_instance_use<'tcx>( ty::InstanceDef::DropGlue(_, None) => { // Don't need to emit noop drop glue if we are calling directly. if !is_direct_call { - output.push(create_fn_mono_item(tcx, instance, source)); + output.push(create_fn_mono_item(instance, source)); } } ty::InstanceDef::DropGlue(_, Some(_)) @@ -758,7 +758,7 @@ fn visit_instance_use<'tcx>( | ty::InstanceDef::Item(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::CloneShim(..) => { - output.push(create_fn_mono_item(tcx, instance, source)); + output.push(create_fn_mono_item(instance, source)); } } } @@ -766,7 +766,7 @@ fn visit_instance_use<'tcx>( // Returns `true` if we should codegen an instance in the local crate. // Returns `false` if we can just link to the upstream crate and therefore don't // need a mono item. -fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool { +fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool { let def_id = match instance.def { ty::InstanceDef::Item(def) => def.did, ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id, @@ -781,19 +781,20 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> }; if tcx.is_foreign_item(def_id) { - // Foreign items are always linked against, there's no way of instantiating them. + // Foreign items are always linked against, there's no way of + // instantiating them. return false; } if def_id.is_local() { - // Local items cannot be referred to locally without monomorphizing them locally. + // Local items cannot be referred to locally without + // monomorphizing them locally. return true; } - if tcx.is_reachable_non_generic(def_id) - || instance.polymorphize(tcx).upstream_monomorphization(tcx).is_some() - { - // We can link to the item in question, no instance needed in this crate. + if tcx.is_reachable_non_generic(def_id) || instance.upstream_monomorphization(tcx).is_some() { + // We can link to the item in question, no instance needed + // in this crate. return false; } @@ -902,13 +903,9 @@ fn find_vtable_types_for_unsizing<'tcx>( } } -fn create_fn_mono_item<'tcx>( - tcx: TyCtxt<'tcx>, - instance: Instance<'tcx>, - source: Span, -) -> Spanned> { +fn create_fn_mono_item(instance: Instance<'_>, source: Span) -> Spanned> { debug!("create_fn_mono_item(instance={})", instance); - respan(source, MonoItem::Fn(instance.polymorphize(tcx))) + respan(source, MonoItem::Fn(instance)) } /// Creates a `MonoItem` for each method that is referenced by the vtable for @@ -920,7 +917,12 @@ fn create_mono_items_for_vtable_methods<'tcx>( source: Span, output: &mut Vec>>, ) { - assert!(!trait_ty.has_escaping_bound_vars() && !impl_ty.has_escaping_bound_vars()); + assert!( + !trait_ty.needs_subst() + && !trait_ty.has_escaping_bound_vars() + && !impl_ty.needs_subst() + && !impl_ty.has_escaping_bound_vars() + ); if let ty::Dynamic(ref trait_ty, ..) = trait_ty.kind { if let Some(principal) = trait_ty.principal() { @@ -942,8 +944,8 @@ fn create_mono_items_for_vtable_methods<'tcx>( ) .unwrap() }) - .filter(|&instance| should_codegen_locally(tcx, &instance)) - .map(|item| create_fn_mono_item(tcx, item, source)); + .filter(|&instance| should_monomorphize_locally(tcx, &instance)) + .map(|item| create_fn_mono_item(item, source)); output.extend(methods); } @@ -995,7 +997,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { ); let ty = Instance::new(def_id.to_def_id(), InternalSubsts::empty()) - .ty(self.tcx, ty::ParamEnv::reveal_all()); + .monomorphic_ty(self.tcx); visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output); } } @@ -1067,7 +1069,7 @@ impl RootCollector<'_, 'v> { debug!("RootCollector::push_if_root: found root def_id={:?}", def_id); let instance = Instance::mono(self.tcx, def_id.to_def_id()); - self.output.push(create_fn_mono_item(self.tcx, instance, DUMMY_SP)); + self.output.push(create_fn_mono_item(instance, DUMMY_SP)); } } @@ -1104,7 +1106,7 @@ impl RootCollector<'_, 'v> { .unwrap() .unwrap(); - self.output.push(create_fn_mono_item(self.tcx, start_instance, DUMMY_SP)); + self.output.push(create_fn_mono_item(start_instance, DUMMY_SP)); } } @@ -1161,8 +1163,9 @@ fn create_mono_items_for_default_impls<'tcx>( .unwrap() .unwrap(); - let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP); - if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) + let mono_item = create_fn_mono_item(instance, DUMMY_SP); + if mono_item.node.is_instantiable(tcx) + && should_monomorphize_locally(tcx, &instance) { output.push(mono_item); } @@ -1183,7 +1186,7 @@ fn collect_miri<'tcx>( GlobalAlloc::Static(def_id) => { assert!(!tcx.is_thread_local_static(def_id)); let instance = Instance::mono(tcx, def_id); - if should_codegen_locally(tcx, &instance) { + if should_monomorphize_locally(tcx, &instance) { trace!("collecting static {:?}", def_id); output.push(dummy_spanned(MonoItem::Static(def_id))); } @@ -1197,9 +1200,9 @@ fn collect_miri<'tcx>( } } GlobalAlloc::Function(fn_instance) => { - if should_codegen_locally(tcx, &fn_instance) { + if should_monomorphize_locally(tcx, &fn_instance) { trace!("collecting {:?} with {:#?}", alloc_id, fn_instance); - output.push(create_fn_mono_item(tcx, fn_instance, DUMMY_SP)); + output.push(create_fn_mono_item(fn_instance, DUMMY_SP)); } } } diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 15d7b11124071..76c1c465a8be0 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -6,7 +6,6 @@ use rustc_hir::lang_items::CoerceUnsizedTraitLangItem; pub mod collector; pub mod partitioning; -pub mod polymorphize; pub fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 6162651db14a0..410ed66e008dc 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -161,7 +161,7 @@ where // Next we try to make as many symbols "internal" as possible, so LLVM has // more freedom to optimize. - if tcx.sess.opts.cg.link_dead_code != Some(true) { + if !tcx.sess.opts.cg.link_dead_code { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols"); internalize_symbols(tcx, &mut post_inlining, inlining_map); } @@ -906,7 +906,7 @@ fn collect_and_partition_mono_items( } } None => { - if tcx.sess.opts.cg.link_dead_code == Some(true) { + if tcx.sess.opts.cg.link_dead_code { MonoItemCollectionMode::Eager } else { MonoItemCollectionMode::Lazy diff --git a/src/librustc_mir/monomorphize/polymorphize.rs b/src/librustc_mir/monomorphize/polymorphize.rs deleted file mode 100644 index 071b9bb971139..0000000000000 --- a/src/librustc_mir/monomorphize/polymorphize.rs +++ /dev/null @@ -1,285 +0,0 @@ -//! Polymorphization Analysis -//! ========================= -//! -//! This module implements an analysis of functions, methods and closures to determine which -//! generic parameters are unused (and eventually, in what ways generic parameters are used - only -//! for their size, offset of a field, etc.). - -use rustc_hir::{def::DefKind, def_id::DefId}; -use rustc_index::bit_set::FiniteBitSet; -use rustc_middle::mir::{ - visit::{TyContext, Visitor}, - Local, LocalDecl, Location, -}; -use rustc_middle::ty::{ - self, - fold::{TypeFoldable, TypeVisitor}, - query::Providers, - Const, Ty, TyCtxt, -}; -use rustc_span::symbol::sym; -use std::convert::TryInto; - -/// Provide implementations of queries relating to polymorphization analysis. -pub fn provide(providers: &mut Providers) { - providers.unused_generic_params = unused_generic_params; -} - -/// Determine which generic parameters are used by the function/method/closure represented by -/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty` -/// indicates all parameters are used). -fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet { - debug!("unused_generic_params({:?})", def_id); - - if !tcx.sess.opts.debugging_opts.polymorphize { - // If polymorphization disabled, then all parameters are used. - return FiniteBitSet::new_empty(); - } - - let generics = tcx.generics_of(def_id); - debug!("unused_generic_params: generics={:?}", generics); - - // Exit early when there are no parameters to be unused. - if generics.count() == 0 { - return FiniteBitSet::new_empty(); - } - - // Exit early when there is no MIR available. - if !tcx.is_mir_available(def_id) { - debug!("unused_generic_params: (no mir available) def_id={:?}", def_id); - return FiniteBitSet::new_empty(); - } - - // Create a bitset with N rightmost ones for each parameter. - let generics_count: u32 = - generics.count().try_into().expect("more generic parameters than can fit into a `u32`"); - let mut unused_parameters = FiniteBitSet::::new_empty(); - unused_parameters.set_range(0..generics_count); - debug!("unused_generic_params: (start) unused_parameters={:?}", unused_parameters); - mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters); - debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters); - - // Visit MIR and accumululate used generic parameters. - let body = tcx.optimized_mir(def_id); - let mut vis = - UsedGenericParametersVisitor { tcx, def_id, unused_parameters: &mut unused_parameters }; - vis.visit_body(body); - debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters); - - mark_used_by_predicates(tcx, def_id, &mut unused_parameters); - debug!("unused_generic_params: (end) unused_parameters={:?}", unused_parameters); - - // Emit errors for debugging and testing if enabled. - if !unused_parameters.is_empty() { - emit_unused_generic_params_error(tcx, def_id, generics, &unused_parameters); - } - - unused_parameters -} - -/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy -/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should -/// be `true` if the item that `unused_generic_params` was invoked on is a closure. -fn mark_used_by_default_parameters<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - generics: &'tcx ty::Generics, - unused_parameters: &mut FiniteBitSet, -) { - if !tcx.is_trait(def_id) && (tcx.is_closure(def_id) || tcx.type_of(def_id).is_generator()) { - for param in &generics.params { - debug!("mark_used_by_default_parameters: (closure/gen) param={:?}", param); - unused_parameters.clear(param.index); - } - } else { - for param in &generics.params { - debug!("mark_used_by_default_parameters: (other) param={:?}", param); - if let ty::GenericParamDefKind::Lifetime = param.kind { - unused_parameters.clear(param.index); - } - } - } - - if let Some(parent) = generics.parent { - mark_used_by_default_parameters(tcx, parent, tcx.generics_of(parent), unused_parameters); - } -} - -/// Search the predicates on used generic parameters for any unused generic parameters, and mark -/// those as used. -fn mark_used_by_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - unused_parameters: &mut FiniteBitSet, -) { - let def_id = tcx.closure_base_def_id(def_id); - - let is_self_ty_used = |unused_parameters: &mut FiniteBitSet, self_ty: Ty<'tcx>| { - debug!("unused_generic_params: self_ty={:?}", self_ty); - if let ty::Param(param) = self_ty.kind { - !unused_parameters.contains(param.index).unwrap_or(false) - } else { - false - } - }; - - let mark_ty = |unused_parameters: &mut FiniteBitSet, ty: Ty<'tcx>| { - let mut vis = UsedGenericParametersVisitor { tcx, def_id, unused_parameters }; - ty.visit_with(&mut vis); - }; - - let predicates = tcx.explicit_predicates_of(def_id); - debug!("mark_parameters_used_in_predicates: predicates_of={:?}", predicates); - for (predicate, _) in predicates.predicates { - match predicate.kind() { - ty::PredicateKind::Trait(predicate, ..) => { - let trait_ref = predicate.skip_binder().trait_ref; - if is_self_ty_used(unused_parameters, trait_ref.self_ty()) { - for ty in trait_ref.substs.types() { - debug!("unused_generic_params: (trait) ty={:?}", ty); - mark_ty(unused_parameters, ty); - } - } - } - ty::PredicateKind::Projection(predicate, ..) => { - let self_ty = predicate.skip_binder().projection_ty.self_ty(); - if is_self_ty_used(unused_parameters, self_ty) { - let ty = predicate.ty(); - debug!("unused_generic_params: (projection) ty={:?}", ty); - mark_ty(unused_parameters, ty.skip_binder()); - } - } - _ => (), - } - } -} - -/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic -/// parameter which was unused. -fn emit_unused_generic_params_error<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - generics: &'tcx ty::Generics, - unused_parameters: &FiniteBitSet, -) { - debug!("emit_unused_generic_params_error: def_id={:?}", def_id); - let base_def_id = tcx.closure_base_def_id(def_id); - if !tcx.get_attrs(base_def_id).iter().any(|a| a.check_name(sym::rustc_polymorphize_error)) { - return; - } - - debug!("emit_unused_generic_params_error: unused_parameters={:?}", unused_parameters); - let fn_span = match tcx.opt_item_name(def_id) { - Some(ident) => ident.span, - _ => tcx.def_span(def_id), - }; - - let mut err = tcx.sess.struct_span_err(fn_span, "item has unused generic parameters"); - - let mut next_generics = Some(generics); - while let Some(generics) = next_generics { - for param in &generics.params { - if unused_parameters.contains(param.index).unwrap_or(false) { - debug!("emit_unused_generic_params_error: param={:?}", param); - let def_span = tcx.def_span(param.def_id); - err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name)); - } - } - - next_generics = generics.parent.map(|did| tcx.generics_of(did)); - } - - err.emit(); -} - -/// Visitor used to aggregate generic parameter uses. -struct UsedGenericParametersVisitor<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - def_id: DefId, - unused_parameters: &'a mut FiniteBitSet, -} - -impl<'a, 'tcx> Visitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> { - fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { - debug!("visit_local_decl: local_decl={:?}", local_decl); - if local == Local::from_usize(1) { - let def_kind = self.tcx.def_kind(self.def_id); - if matches!(def_kind, DefKind::Closure | DefKind::Generator) { - // Skip visiting the closure/generator that is currently being processed. This only - // happens because the first argument to the closure is a reference to itself and - // that will call `visit_substs`, resulting in each generic parameter captured being - // considered used by default. - debug!("visit_local_decl: skipping closure substs"); - return; - } - } - - self.super_local_decl(local, local_decl); - } - - fn visit_const(&mut self, c: &&'tcx Const<'tcx>, _: Location) { - c.visit_with(self); - } - - fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) { - ty.visit_with(self); - } -} - -impl<'a, 'tcx> TypeVisitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> { - fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> bool { - debug!("visit_const: c={:?}", c); - if !c.has_param_types_or_consts() { - return false; - } - - match c.val { - ty::ConstKind::Param(param) => { - debug!("visit_const: param={:?}", param); - self.unused_parameters.clear(param.index); - false - } - _ => c.super_visit_with(self), - } - } - - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - debug!("visit_ty: ty={:?}", ty); - if !ty.has_param_types_or_consts() { - return false; - } - - match ty.kind { - ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => { - debug!("visit_ty: def_id={:?}", def_id); - // Avoid cycle errors with generators. - if def_id == self.def_id { - return false; - } - - // Consider any generic parameters used by any closures/generators as used in the - // parent. - let unused = self.tcx.unused_generic_params(def_id); - debug!( - "visit_ty: unused_parameters={:?} unused={:?}", - self.unused_parameters, unused - ); - for (i, arg) in substs.iter().enumerate() { - let i = i.try_into().unwrap(); - if !unused.contains(i).unwrap_or(false) { - arg.visit_with(self); - } - } - debug!("visit_ty: unused_parameters={:?}", self.unused_parameters); - - false - } - ty::Param(param) => { - debug!("visit_ty: param={:?}", param); - self.unused_parameters.clear(param.index); - false - } - _ => ty.super_visit_with(self), - } - } -} diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index bfa9bb9e0f0e1..98286cddea68b 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -4,7 +4,7 @@ use rustc_hir::lang_items::FnMutTraitLangItem; use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{InternalSubsts, Subst}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_target::abi::VariantIdx; use rustc_index::vec::{Idx, IndexVec}; @@ -36,6 +36,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' build_call_shim(tcx, instance, Some(Adjustment::Deref), CallKind::Direct(def_id), None) } ty::InstanceDef::FnPtrShim(def_id, ty) => { + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + let trait_ = tcx.trait_of_item(def_id).unwrap(); let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) { Some(ty::ClosureKind::FnOnce) => Adjustment::Identity, @@ -78,8 +83,22 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' None, ) } - ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty), - ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty), + ty::InstanceDef::DropGlue(def_id, ty) => { + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + + build_drop_shim(tcx, def_id, ty) + } + ty::InstanceDef::CloneShim(def_id, ty) => { + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + + build_clone_shim(tcx, def_id, ty) + } ty::InstanceDef::Virtual(..) => { bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance) } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 3073bf53afd78..237a5a64f8bf8 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -116,7 +116,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { .predicates .iter() .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); - if traits::impossible_predicates( + if !traits::normalize_and_test_predicates( tcx, traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(), ) { diff --git a/src/librustc_mir/transform/instrument_coverage.rs b/src/librustc_mir/transform/instrument_coverage.rs index 9933a975e4dac..76904b7edd533 100644 --- a/src/librustc_mir/transform/instrument_coverage.rs +++ b/src/librustc_mir/transform/instrument_coverage.rs @@ -35,64 +35,46 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, mir_def_id: DefId) -> Coverage // represents a single function. Validate and/or correct if inlining (which should be disabled // if -Zinstrument-coverage is enabled) and/or monomorphization invalidates these assumptions. let count_code_region_fn = tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None); - let coverage_counter_add_fn = - tcx.require_lang_item(lang_items::CoverageCounterAddFnLangItem, None); - let coverage_counter_subtract_fn = - tcx.require_lang_item(lang_items::CoverageCounterSubtractFnLangItem, None); // The `num_counters` argument to `llvm.instrprof.increment` is the number of injected // counters, with each counter having an index from `0..num_counters-1`. MIR optimization // may split and duplicate some BasicBlock sequences. Simply counting the calls may not // not work; but computing the num_counters by adding `1` to the highest index (for a given // instrumented function) is valid. - // - // `num_expressions` is the number of counter expressions added to the MIR body. Both - // `num_counters` and `num_expressions` are used to initialize new vectors, during backend - // code generate, to lookup counters and expressions by their simple u32 indexes. let mut num_counters: u32 = 0; - let mut num_expressions: u32 = 0; - for terminator in - traversal::preorder(mir_body).map(|(_, data)| data).filter_map(call_terminators) + for terminator in traversal::preorder(mir_body) + .map(|(_, data)| (data, count_code_region_fn)) + .filter_map(terminators_that_call_given_fn) { - if let TerminatorKind::Call { func: Operand::Constant(func), args, .. } = &terminator.kind { - match func.literal.ty.kind { - FnDef(id, _) if id == count_code_region_fn => { - let index_arg = - args.get(count_code_region_args::COUNTER_INDEX).expect("arg found"); - let counter_index = mir::Operand::scalar_from_const(index_arg) - .to_u32() - .expect("index arg is u32"); - num_counters = std::cmp::max(num_counters, counter_index + 1); - } - FnDef(id, _) - if id == coverage_counter_add_fn || id == coverage_counter_subtract_fn => - { - let index_arg = args - .get(coverage_counter_expression_args::COUNTER_EXPRESSION_INDEX) - .expect("arg found"); - let translated_index = mir::Operand::scalar_from_const(index_arg) - .to_u32() - .expect("index arg is u32"); - // Counter expressions start with "translated indexes", descending from - // `u32::MAX`, so the range of expression indexes is disjoint from the range of - // counter indexes. This way, both counters and expressions can be operands in - // other expressions. - let expression_index = u32::MAX - translated_index; - num_expressions = std::cmp::max(num_expressions, expression_index + 1); + if let TerminatorKind::Call { args, .. } = &terminator.kind { + let index_arg = args.get(count_code_region_args::COUNTER_INDEX).expect("arg found"); + let index = + mir::Operand::scalar_from_const(index_arg).to_u32().expect("index arg is u32"); + num_counters = std::cmp::max(num_counters, index + 1); + } + } + let hash = if num_counters > 0 { hash_mir_source(tcx, mir_def_id) } else { 0 }; + CoverageInfo { num_counters, hash } +} + +fn terminators_that_call_given_fn( + (data, fn_def_id): (&'tcx BasicBlockData<'tcx>, DefId), +) -> Option<&'tcx Terminator<'tcx>> { + if let Some(terminator) = &data.terminator { + if let TerminatorKind::Call { func: Operand::Constant(func), .. } = &terminator.kind { + if let FnDef(called_fn_def_id, _) = func.literal.ty.kind { + if called_fn_def_id == fn_def_id { + return Some(&terminator); } - _ => {} } } } - CoverageInfo { num_counters, num_expressions } + None } -fn call_terminators(data: &'tcx BasicBlockData<'tcx>) -> Option<&'tcx Terminator<'tcx>> { - let terminator = data.terminator(); - match terminator.kind { - TerminatorKind::Call { .. } => Some(terminator), - _ => None, - } +struct Instrumentor<'tcx> { + tcx: TyCtxt<'tcx>, + num_counters: u32, } impl<'tcx> MirPass<'tcx> for InstrumentCoverage { @@ -101,168 +83,57 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { // If the InstrumentCoverage pass is called on promoted MIRs, skip them. // See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601 if src.promoted.is_none() { - Instrumentor::new(tcx, src, mir_body).inject_counters(); + debug!( + "instrumenting {:?}, span: {}", + src.def_id(), + tcx.sess.source_map().span_to_string(mir_body.span) + ); + Instrumentor::new(tcx).inject_counters(mir_body); } } } } -/// Distinguishes the expression operators. -enum Op { - Add, - Subtract, -} - -struct Instrumentor<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - mir_def_id: DefId, - mir_body: &'a mut mir::Body<'tcx>, - hir_body: &'tcx rustc_hir::Body<'tcx>, - function_source_hash: Option, - num_counters: u32, - num_expressions: u32, -} - -impl<'a, 'tcx> Instrumentor<'a, 'tcx> { - fn new(tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, mir_body: &'a mut mir::Body<'tcx>) -> Self { - let mir_def_id = src.def_id(); - let hir_body = hir_body(tcx, mir_def_id); - Self { - tcx, - mir_def_id, - mir_body, - hir_body, - function_source_hash: None, - num_counters: 0, - num_expressions: 0, - } +impl<'tcx> Instrumentor<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + Self { tcx, num_counters: 0 } } - /// Counter IDs start from zero and go up. fn next_counter(&mut self) -> u32 { - assert!(self.num_counters < u32::MAX - self.num_expressions); let next = self.num_counters; self.num_counters += 1; next } - /// Expression IDs start from u32::MAX and go down because a CounterExpression can reference - /// (add or subtract counts) of both Counter regions and CounterExpression regions. The indexes - /// of each type of region must be contiguous, but also must be unique across both sets. - /// The expression IDs are eventually translated into region indexes (starting after the last - /// counter index, for the given function), during backend code generation, by the helper method - /// `rustc_codegen_ssa::coverageinfo::map::FunctionCoverage::translate_expressions()`. - fn next_expression(&mut self) -> u32 { - assert!(self.num_counters < u32::MAX - self.num_expressions); - let next = u32::MAX - self.num_expressions; - self.num_expressions += 1; - next - } - - fn function_source_hash(&mut self) -> u64 { - match self.function_source_hash { - Some(hash) => hash, - None => { - let hash = hash_mir_source(self.tcx, self.hir_body); - self.function_source_hash.replace(hash); - hash - } - } - } - - fn inject_counters(&mut self) { - let body_span = self.hir_body.value.span; - debug!( - "instrumenting {:?}, span: {}", - self.mir_def_id, - self.tcx.sess.source_map().span_to_string(body_span) - ); - + fn inject_counters(&mut self, mir_body: &mut mir::Body<'tcx>) { // FIXME(richkadel): As a first step, counters are only injected at the top of each // function. The complete solution will inject counters at each conditional code branch. + let code_region = mir_body.span; let next_block = START_BLOCK; - self.inject_counter(body_span, next_block); - - // FIXME(richkadel): The next step to implement source based coverage analysis will be - // instrumenting branches within functions, and some regions will be counted by "counter - // expression". The function to inject counter expression is implemented. Replace this - // "fake use" with real use. - let fake_use = false; - if fake_use { - let add = false; - if add { - self.inject_counter_expression(body_span, next_block, 1, Op::Add, 2); - } else { - self.inject_counter_expression(body_span, next_block, 1, Op::Subtract, 2); - } - } + self.inject_counter(mir_body, code_region, next_block); } - fn inject_counter(&mut self, code_region: Span, next_block: BasicBlock) -> u32 { - let counter_id = self.next_counter(); - let function_source_hash = self.function_source_hash(); - let injection_point = code_region.shrink_to_lo(); - - let count_code_region_fn = function_handle( - self.tcx, - self.tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None), - injection_point, - ); - - let mut args = Vec::new(); - - use count_code_region_args::*; - debug_assert_eq!(FUNCTION_SOURCE_HASH, args.len()); - args.push(self.const_u64(function_source_hash, injection_point)); - - debug_assert_eq!(COUNTER_INDEX, args.len()); - args.push(self.const_u32(counter_id, injection_point)); - - debug_assert_eq!(START_BYTE_POS, args.len()); - args.push(self.const_u32(code_region.lo().to_u32(), injection_point)); - - debug_assert_eq!(END_BYTE_POS, args.len()); - args.push(self.const_u32(code_region.hi().to_u32(), injection_point)); - - self.inject_call(count_code_region_fn, args, injection_point, next_block); - - counter_id - } - - fn inject_counter_expression( + fn inject_counter( &mut self, + mir_body: &mut mir::Body<'tcx>, code_region: Span, next_block: BasicBlock, - lhs: u32, - op: Op, - rhs: u32, - ) -> u32 { - let expression_id = self.next_expression(); + ) { let injection_point = code_region.shrink_to_lo(); let count_code_region_fn = function_handle( self.tcx, - self.tcx.require_lang_item( - match op { - Op::Add => lang_items::CoverageCounterAddFnLangItem, - Op::Subtract => lang_items::CoverageCounterSubtractFnLangItem, - }, - None, - ), + self.tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None), injection_point, ); - let mut args = Vec::new(); - - use coverage_counter_expression_args::*; - debug_assert_eq!(COUNTER_EXPRESSION_INDEX, args.len()); - args.push(self.const_u32(expression_id, injection_point)); + let index = self.next_counter(); - debug_assert_eq!(LEFT_INDEX, args.len()); - args.push(self.const_u32(lhs, injection_point)); + let mut args = Vec::new(); - debug_assert_eq!(RIGHT_INDEX, args.len()); - args.push(self.const_u32(rhs, injection_point)); + use count_code_region_args::*; + debug_assert_eq!(COUNTER_INDEX, args.len()); + args.push(self.const_u32(index, injection_point)); debug_assert_eq!(START_BYTE_POS, args.len()); args.push(self.const_u32(code_region.lo().to_u32(), injection_point)); @@ -270,52 +141,36 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { debug_assert_eq!(END_BYTE_POS, args.len()); args.push(self.const_u32(code_region.hi().to_u32(), injection_point)); - self.inject_call(count_code_region_fn, args, injection_point, next_block); - - expression_id - } - - fn inject_call( - &mut self, - func: Operand<'tcx>, - args: Vec>, - fn_span: Span, - next_block: BasicBlock, - ) { - let mut patch = MirPatch::new(self.mir_body); + let mut patch = MirPatch::new(mir_body); - let temp = patch.new_temp(self.tcx.mk_unit(), fn_span); - let new_block = patch.new_block(placeholder_block(fn_span)); + let temp = patch.new_temp(self.tcx.mk_unit(), code_region); + let new_block = patch.new_block(placeholder_block(code_region)); patch.patch_terminator( new_block, TerminatorKind::Call { - func, + func: count_code_region_fn, args, // new_block will swapped with the next_block, after applying patch destination: Some((Place::from(temp), new_block)), cleanup: None, from_hir_call: false, - fn_span, + fn_span: injection_point, }, ); patch.add_statement(new_block.start_location(), StatementKind::StorageLive(temp)); patch.add_statement(next_block.start_location(), StatementKind::StorageDead(temp)); - patch.apply(self.mir_body); + patch.apply(mir_body); // To insert the `new_block` in front of the first block in the counted branch (the // `next_block`), just swap the indexes, leaving the rest of the graph unchanged. - self.mir_body.basic_blocks_mut().swap(next_block, new_block); + mir_body.basic_blocks_mut().swap(next_block, new_block); } fn const_u32(&self, value: u32, span: Span) -> Operand<'tcx> { Operand::const_from_scalar(self.tcx, self.tcx.types.u32, Scalar::from_u32(value), span) } - - fn const_u64(&self, value: u64, span: Span) -> Operand<'tcx> { - Operand::const_from_scalar(self.tcx, self.tcx.types.u64, Scalar::from_u64(value), span) - } } fn function_handle<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, span: Span) -> Operand<'tcx> { @@ -337,13 +192,10 @@ fn placeholder_block(span: Span) -> BasicBlockData<'tcx> { } } -fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx rustc_hir::Body<'tcx> { +fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> u64 { let hir_node = tcx.hir().get_if_local(def_id).expect("DefId is local"); let fn_body_id = hir::map::associated_body(hir_node).expect("HIR node is a function with body"); - tcx.hir().body(fn_body_id) -} - -fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { + let hir_body = tcx.hir().body(fn_body_id); let mut hcx = tcx.create_no_span_stable_hashing_context(); hash(&mut hcx, &hir_body.value).to_smaller_hash() } diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs index 3b11fb379625f..d85d8401db676 100644 --- a/src/librustc_passes/weak_lang_items.rs +++ b/src/librustc_passes/weak_lang_items.rs @@ -3,13 +3,14 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::fake_lang_items::FAKE_ITEMS_REFS; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::lang_items; +use rustc_hir::lang_items::ITEM_REFS; use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS; use rustc_middle::middle::lang_items::required; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; +use rustc_span::symbol::sym; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -76,14 +77,15 @@ impl<'a, 'tcx> Context<'a, 'tcx> { if self.items.require(item).is_err() { self.items.missing.push(item); } - } else if let Some(&item) = FAKE_ITEMS_REFS.get(&name) { - // Ensure "fake lang items" are registered. These are `extern` lang items that are - // injected into the MIR automatically (such as source code coverage counters), but are - // never actually linked; therefore, unlike "weak lang items", they cannot by registered - // when used, because they never appear to be used. - if self.items.items[item as usize].is_none() { - let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id(); - self.items.items[item as usize] = Some(item_def_id); + } else if name == sym::count_code_region { + // `core::intrinsics::code_count_region()` is (currently) the only `extern` lang item + // that is never actually linked. It is not a `weak_lang_item` that can be registered + // when used, and should be registered here instead. + if let Some((item_index, _)) = ITEM_REFS.get(&name).cloned() { + if self.items.items[item_index].is_none() { + let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id(); + self.items.items[item_index] = Some(item_def_id); + } } } else { struct_span_err!(self.tcx.sess, span, E0264, "unknown external lang item: `{}`", name) diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs index 62a87b47a2f74..c3a6016696888 100644 --- a/src/librustc_plugin_impl/load.rs +++ b/src/librustc_plugin_impl/load.rs @@ -55,11 +55,13 @@ fn load_plugin( metadata_loader: &dyn MetadataLoader, ident: Ident, ) { - let (lib, disambiguator) = - locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name); - let symbol = sess.generate_plugin_registrar_symbol(disambiguator); - let fun = dylink_registrar(sess, ident.span, lib, symbol); - plugins.push(fun); + let registrar = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name); + + if let Some((lib, disambiguator)) = registrar { + let symbol = sess.generate_plugin_registrar_symbol(disambiguator); + let fun = dylink_registrar(sess, ident.span, lib, symbol); + plugins.push(fun); + } } // Dynamically link a registrar function into the compiler process. diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index a7a005bdeb9f2..575049c6bac2f 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -859,7 +859,9 @@ impl<'a> Resolver<'a> { // otherwise cause duplicate suggestions. continue; } - if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name) { + if let Some(crate_id) = + self.crate_loader.maybe_process_path_extern(ident.name, ident.span) + { let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); suggestions.extend(self.lookup_import_candidates_from_module( diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 261c2031364f6..ed88e54969215 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1500,17 +1500,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { pat_src: PatternSource, bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, ) { - let is_tuple_struct_pat = matches!(pat.kind, PatKind::TupleStruct(_, _)); - // Visit all direct subpatterns of this pattern. pat.walk(&mut |pat| { debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind); match pat.kind { - // In tuple struct patterns ignore the invalid `ident @ ...`. - // It will be handled as an error by the AST lowering. - PatKind::Ident(bmode, ident, ref sub) - if !(is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some()) => - { + PatKind::Ident(bmode, ident, ref sub) => { // First try to resolve the identifier as some existing entity, // then fall back to a fresh binding. let has_sub = sub.is_some(); diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index c86b414184759..95888c38ba5e1 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -760,8 +760,10 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { if !module.no_implicit_prelude { let extern_prelude = self.r.extern_prelude.clone(); names.extend(extern_prelude.iter().flat_map(|(ident, _)| { - self.r.crate_loader.maybe_process_path_extern(ident.name).and_then( - |crate_id| { + self.r + .crate_loader + .maybe_process_path_extern(ident.name, ident.span) + .and_then(|crate_id| { let crate_mod = Res::Def( DefKind::Mod, DefId { krate: crate_id, index: CRATE_DEF_INDEX }, @@ -772,8 +774,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { } else { None } - }, - ) + }) })); if let Some(prelude) = self.r.prelude { @@ -1141,24 +1142,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { err.emit(); } - // FIXME(const_generics): This patches over a ICE caused by non-'static lifetimes in const - // generics. We are disallowing this until we can decide on how we want to handle non-'static - // lifetimes in const generics. See issue #74052 for discussion. - crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &hir::Lifetime) { - let mut err = struct_span_err!( - self.tcx.sess, - lifetime_ref.span, - E0771, - "use of non-static lifetime `{}` in const generic", - lifetime_ref - ); - err.note( - "for more information, see issue #74052 \ - ", - ); - err.emit(); - } - crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool { if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res { if [ diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 6009e48a54f5e..567db8edec9af 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -173,8 +173,6 @@ crate struct LifetimeContext<'a, 'tcx> { /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax. is_in_fn_syntax: bool, - is_in_const_generic: bool, - /// List of labels in the function/method currently under analysis. labels_in_fn: Vec, @@ -335,7 +333,6 @@ fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { scope: ROOT_SCOPE, trait_ref_hack: false, is_in_fn_syntax: false, - is_in_const_generic: false, labels_in_fn: vec![], xcrate_object_lifetime_defaults: Default::default(), lifetime_uses: &mut Default::default(), @@ -831,10 +828,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.insert_lifetime(lifetime_ref, Region::Static); return; } - if self.is_in_const_generic && lifetime_ref.name != LifetimeName::Error { - self.emit_non_static_lt_in_const_generic_error(lifetime_ref); - return; - } self.resolve_lifetime_ref(lifetime_ref); } @@ -867,11 +860,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } GenericParamKind::Const { ref ty, .. } => { - let was_in_const_generic = self.is_in_const_generic; - self.is_in_const_generic = true; walk_list!(self, visit_param_bound, param.bounds); self.visit_ty(&ty); - self.is_in_const_generic = was_in_const_generic; } } } @@ -1327,7 +1317,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { scope: &wrap_scope, trait_ref_hack: self.trait_ref_hack, is_in_fn_syntax: self.is_in_fn_syntax, - is_in_const_generic: self.is_in_const_generic, labels_in_fn, xcrate_object_lifetime_defaults, lifetime_uses, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index da39f79efcd3b..686385e24ece8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2957,7 +2957,7 @@ impl<'a> Resolver<'a> { let crate_id = if !speculative { self.crate_loader.process_path_extern(ident.name, ident.span) } else { - self.crate_loader.maybe_process_path_extern(ident.name)? + self.crate_loader.maybe_process_path_extern(ident.name, ident.span)? }; let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); Some( diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 839ffa5785ada..348fe105a4315 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1707,31 +1707,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } - if debugging_opts.instrument_coverage { - if cg.profile_generate.enabled() || cg.profile_use.is_some() { - early_error( - error_format, - "option `-Z instrument-coverage` is not compatible with either `-C profile-use` \ - or `-C profile-generate`", - ); - } - - // `-Z instrument-coverage` implies: - // * `-Z symbol-mangling-version=v0` - to ensure consistent and reversable name mangling. - // Note, LLVM coverage tools can analyze coverage over multiple runs, including some - // changes to source code; so mangled names must be consistent across compilations. - // * `-C link-dead-code` - so unexecuted code is still counted as zero, rather than be - // optimized out. Note that instrumenting dead code can be explicitly disabled with: - // `-Z instrument-coverage -C link-dead-code=no`. - debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0; - if cg.link_dead_code == None { - // FIXME(richkadel): Investigate if the `instrument-coverage` implementation can - // inject ["zero counters"](https://llvm.org/docs/CoverageMappingFormat.html#counter) - // in the coverage map when "dead code" is removed, rather than forcing `link-dead-code`. - cg.link_dead_code = Some(true); - } - } - if !cg.embed_bitcode { match cg.lto { LtoCli::No | LtoCli::Unspecified => {} diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 6b2097240e215..2ad7d09cbf415 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -715,7 +715,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "a single extra argument to append to the linker invocation (can be used several times)"), link_args: Vec = (Vec::new(), parse_list, [UNTRACKED], "extra arguments to append to the linker invocation (space separated)"), - link_dead_code: Option = (None, parse_opt_bool, [UNTRACKED], + link_dead_code: bool = (false, parse_bool, [UNTRACKED], "keep dead code at link time (useful for code coverage) (default: no)"), linker: Option = (None, parse_opt_pathbuf, [UNTRACKED], "system linker to link outputs with"), @@ -880,12 +880,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (such as entering an empty infinite loop) by inserting llvm.sideeffect \ (default: no)"), instrument_coverage: bool = (false, parse_bool, [TRACKED], - "instrument the generated code to support LLVM source-based code coverage \ - reports (note, the compiler build config must include `profiler = true`, \ - and is mutually exclusive with `-C profile-generate`/`-C profile-use`); \ - implies `-C link-dead-code` (unless explicitly disabled)` and - `-Z symbol-mangling-version=v0`; and disables/overrides some optimization \ - options (default: no)"), + "instrument the generated code with LLVM code region counters to (in the \ + future) generate coverage reports; disables/overrides some optimization \ + options (note, the compiler build config must include `profiler = true`) \ + (default: no)"), instrument_mcount: bool = (false, parse_bool, [TRACKED], "insert function instrument code for mcount-based tracing (default: no)"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], @@ -949,8 +947,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (default: PLT is disabled if full relro is enabled)"), polonius: bool = (false, parse_bool, [UNTRACKED], "enable polonius-based borrow-checker (default: no)"), - polymorphize: bool = (true, parse_bool, [TRACKED], - "perform polymorphization analysis"), pre_link_arg: (/* redirected to pre_link_args */) = ((), parse_string_push, [UNTRACKED], "a single extra argument to prepend the linker invocation (can be used several times)"), pre_link_args: Vec = (Vec::new(), parse_list, [UNTRACKED], diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 4ad95e95e9a86..fcd5dab94a6c2 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -1357,20 +1357,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { ); } - // FIXME(richkadel): See `src/test/run-make-fulldeps/instrument-coverage/Makefile`. After - // compiling with `-Zinstrument-coverage`, the resulting binary generates a segfault during - // the program's exit process (likely while attempting to generate the coverage stats in - // the "*.profraw" file). An investigation to resolve the problem on Windows is ongoing, - // but until this is resolved, the option is disabled on Windows, and the test is skipped - // when targeting `MSVC`. - if sess.opts.debugging_opts.instrument_coverage && sess.target.target.options.is_like_msvc { - sess.warn( - "Rust source-based code coverage instrumentation (with `-Z instrument-coverage`) \ - is not yet supported on Windows when targeting MSVC. The resulting binaries will \ - still be instrumented for experimentation purposes, but may not execute correctly.", - ); - } - const ASAN_SUPPORTED_TARGETS: &[&str] = &[ "aarch64-fuchsia", "aarch64-unknown-linux-gnu", diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 22a5115c7f556..5d332ddf5f3df 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -921,7 +921,6 @@ symbols! { rustc_peek_liveness, rustc_peek_maybe_init, rustc_peek_maybe_uninit, - rustc_polymorphize_error, rustc_private, rustc_proc_macro_decls, rustc_promotable, diff --git a/src/librustc_symbol_mangling/legacy.rs b/src/librustc_symbol_mangling/legacy.rs index 90c89ea6b0a86..3038b0c6bd7eb 100644 --- a/src/librustc_symbol_mangling/legacy.rs +++ b/src/librustc_symbol_mangling/legacy.rs @@ -116,6 +116,7 @@ fn get_symbol_hash<'tcx>( // also include any type parameters (for generic items) assert!(!substs.has_erasable_regions()); + assert!(!substs.needs_subst()); substs.hash_stable(&mut hcx, &mut hasher); if let Some(instantiating_crate) = instantiating_crate { diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index d53033ba3ba20..231ab1ea68ded 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -676,7 +676,6 @@ supported_targets! { ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks), ("mipsel-sony-psp", mipsel_sony_psp), - ("thumbv4t-none-eabi", thumbv4t_none_eabi), } /// Everything `rustc` knows about how to compile for a specific target. diff --git a/src/librustc_target/spec/thumbv4t_none_eabi.rs b/src/librustc_target/spec/thumbv4t_none_eabi.rs deleted file mode 100644 index 31417b0154759..0000000000000 --- a/src/librustc_target/spec/thumbv4t_none_eabi.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! Targets the ARMv4T, with code as `t32` code by default. -//! -//! Primarily of use for the GBA, but usable with other devices too. -//! -//! Please ping @Lokathor if changes are needed. -//! -//! This target profile assumes that you have the ARM binutils in your path (specifically the linker, `arm-none-eabi-ld`). They can be obtained for free for all major OSes from the ARM developer's website, and they may also be available in your system's package manager. Unfortunately, the standard linker that Rust uses (`lld`) only supports as far back as `ARMv5TE`, so we must use the GNU `ld` linker. -//! -//! **Important:** This target profile **does not** specify a linker script. You just get the default link script when you build a binary for this target. The default link script is very likely wrong, so you should use `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script. - -use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; - -pub fn target() -> TargetResult { - Ok(Target { - llvm_target: "thumbv4t-none-eabi".to_string(), - target_endian: "little".to_string(), - target_pointer_width: "32".to_string(), - target_c_int_width: "32".to_string(), - target_os: "none".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), - arch: "arm".to_string(), - /* Data layout args are '-' separated: - * little endian - * stack is 64-bit aligned (EABI) - * pointers are 32-bit - * i64 must be 64-bit aligned (EABI) - * mangle names with ELF style - * native integers are 32-bit - * All other elements are default - */ - data_layout: "e-S64-p:32:32-i64:64-m:e-n32".to_string(), - linker_flavor: LinkerFlavor::Ld, - options: TargetOptions { - linker: Some("arm-none-eabi-ld".to_string()), - linker_is_gnu: true, - - // extra args passed to the external assembler (assuming `arm-none-eabi-as`): - // * activate t32/a32 interworking - // * use arch ARMv4T - // * use little-endian - asm_args: vec![ - "-mthumb-interwork".to_string(), - "-march=armv4t".to_string(), - "-mlittle-endian".to_string(), - ], - - // minimum extra features, these cannot be disabled via -C - features: "+soft-float,+strict-align".to_string(), - - main_needs_argc_argv: false, - - // No thread-local storage (just use a static Cell) - has_elf_tls: false, - - // don't have atomic compare-and-swap - atomic_cas: false, - - ..super::thumb_base::opts() - }, - }) -} diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index 1c3755222495e..e8006129e3ef8 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -418,14 +418,15 @@ where Ok(resolved_value) } -/// Normalizes the predicates and checks whether they hold in an empty environment. If this -/// returns true, then either normalize encountered an error or one of the predicates did not -/// hold. Used when creating vtables to check for unsatisfiable methods. -pub fn impossible_predicates<'tcx>( +/// Normalizes the predicates and checks whether they hold in an empty +/// environment. If this returns false, then either normalize +/// encountered an error or one of the predicates did not hold. Used +/// when creating vtables to check for unsatisfiable methods. +pub fn normalize_and_test_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: Vec>, ) -> bool { - debug!("impossible_predicates(predicates={:?})", predicates); + debug!("normalize_and_test_predicates(predicates={:?})", predicates); let result = tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::reveal_all(); @@ -442,23 +443,22 @@ pub fn impossible_predicates<'tcx>( fulfill_cx.register_predicate_obligation(&infcx, obligation); } - fulfill_cx.select_all_or_error(&infcx).is_err() + fulfill_cx.select_all_or_error(&infcx).is_ok() }); - debug!("impossible_predicates(predicates={:?}) = {:?}", predicates, result); + debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result); result } -fn subst_and_check_impossible_predicates<'tcx>( +fn substitute_normalize_and_test_predicates<'tcx>( tcx: TyCtxt<'tcx>, key: (DefId, SubstsRef<'tcx>), ) -> bool { - debug!("subst_and_check_impossible_predicates(key={:?})", key); + debug!("substitute_normalize_and_test_predicates(key={:?})", key); - let mut predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates; - predicates.retain(|predicate| !predicate.needs_subst()); - let result = impossible_predicates(tcx, predicates); + let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates; + let result = normalize_and_test_predicates(tcx, predicates); - debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result); + debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result); result } @@ -510,7 +510,7 @@ fn vtable_methods<'tcx>( // Note that this method could then never be called, so we // do not want to try and codegen it, in that case (see #23435). let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); - if impossible_predicates(tcx, predicates.predicates) { + if !normalize_and_test_predicates(tcx, predicates.predicates) { debug!("vtable_methods: predicates do not hold"); return None; } @@ -558,8 +558,8 @@ pub fn provide(providers: &mut ty::query::Providers) { specializes: specialize::specializes, codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, vtable_methods, + substitute_normalize_and_test_predicates, type_implements_trait, - subst_and_check_impossible_predicates, ..*providers }; } diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 324ae4ec29e9b..0bc6c47097868 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::sym; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; @@ -67,19 +67,12 @@ fn inner_resolve_instance<'tcx>( let ty = substs.type_at(0); if ty.needs_drop(tcx, param_env) { - debug!(" => nontrivial drop glue"); - match ty.kind { - ty::Closure(..) - | ty::Generator(..) - | ty::Tuple(..) - | ty::Adt(..) - | ty::Dynamic(..) - | ty::Array(..) - | ty::Slice(..) => {} - // Drop shims can only be built from ADTs. - _ => return Ok(None), + // `DropGlue` requires a monomorphic aka concrete type. + if ty.needs_subst() { + return Ok(None); } + debug!(" => nontrivial drop glue"); ty::InstanceDef::DropGlue(def_id, Some(ty)) } else { debug!(" => trivial drop glue"); @@ -231,13 +224,17 @@ fn resolve_associated_item<'tcx>( trait_closure_kind, )) } - traits::ImplSourceFnPointer(ref data) => match data.fn_ty.kind { - ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { + traits::ImplSourceFnPointer(ref data) => { + // `FnPtrShim` requires a monomorphic aka concrete type. + if data.fn_ty.needs_subst() { + return Ok(None); + } + + Some(Instance { def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty), substs: rcvr_substs, - }), - _ => None, - }, + }) + } traits::ImplSourceObject(ref data) => { let index = traits::get_vtable_index_of_object_method(tcx, data, def_id); Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs }) @@ -249,12 +246,10 @@ fn resolve_associated_item<'tcx>( if name == sym::clone { let self_ty = trait_ref.self_ty(); - let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env); - match self_ty.kind { - _ if is_copy => (), - ty::Array(..) | ty::Closure(..) | ty::Tuple(..) => {} - _ => return Ok(None), - }; + // `CloneShim` requires a monomorphic aka concrete type. + if self_ty.needs_subst() { + return Ok(None); + } Some(Instance { def: ty::InstanceDef::CloneShim(def_id, self_ty), diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index a09edf575c807..944e02acd610a 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -386,7 +386,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { } sym::count_code_region => { - (0, vec![tcx.types.u64, tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit()) + (0, vec![tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit()) } sym::coverage_counter_add | sym::coverage_counter_subtract => ( diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index dabae6cbc4137..845a4fcafc224 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_trait_selection::opaque_types::may_define_opaque_type; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -142,8 +142,8 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { _ => unreachable!(), } } - hir::ItemKind::Fn(ref sig, ..) => { - check_item_fn(tcx, item.hir_id, item.ident, item.span, sig.decl); + hir::ItemKind::Fn(..) => { + check_item_fn(tcx, item); } hir::ItemKind::Static(ref ty, ..) => { check_item_type(tcx, item.hir_id, ty.span, false); @@ -153,14 +153,8 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { } hir::ItemKind::ForeignMod(ref module) => { for it in module.items.iter() { - match it.kind { - hir::ForeignItemKind::Fn(ref decl, ..) => { - check_item_fn(tcx, it.hir_id, it.ident, it.span, decl) - } - hir::ForeignItemKind::Static(ref ty, ..) => { - check_item_type(tcx, it.hir_id, ty.span, true) - } - hir::ForeignItemKind::Type => (), + if let hir::ForeignItemKind::Static(ref ty, ..) = it.kind { + check_item_type(tcx, it.hir_id, ty.span, true); } } } @@ -309,7 +303,7 @@ fn check_associated_item( fcx, item.ident.span, sig, - hir_sig.decl, + hir_sig, item.def_id, &mut implied_bounds, ); @@ -570,24 +564,22 @@ fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { } } -fn check_item_fn( - tcx: TyCtxt<'_>, - item_id: hir::HirId, - ident: Ident, - span: Span, - decl: &hir::FnDecl<'_>, -) { - for_id(tcx, item_id, span).with_fcx(|fcx, tcx| { - let def_id = fcx.tcx.hir().local_def_id(item_id); +fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { + for_item(tcx, item).with_fcx(|fcx, tcx| { + let def_id = fcx.tcx.hir().local_def_id(item.hir_id); let sig = fcx.tcx.fn_sig(def_id); - let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.normalize_associated_types_in(item.span, &sig); let mut implied_bounds = vec![]; + let hir_sig = match &item.kind { + ItemKind::Fn(sig, ..) => sig, + _ => bug!("expected `ItemKind::Fn`, found `{:?}`", item.kind), + }; check_fn_or_method( tcx, fcx, - ident.span, + item.ident.span, sig, - decl, + hir_sig, def_id.to_def_id(), &mut implied_bounds, ); @@ -843,28 +835,28 @@ fn check_fn_or_method<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, span: Span, sig: ty::PolyFnSig<'tcx>, - hir_decl: &hir::FnDecl<'_>, + hir_sig: &hir::FnSig<'_>, def_id: DefId, implied_bounds: &mut Vec>, ) { let sig = fcx.normalize_associated_types_in(span, &sig); let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig); - for (&input_ty, span) in sig.inputs().iter().zip(hir_decl.inputs.iter().map(|t| t.span)) { + for (&input_ty, span) in sig.inputs().iter().zip(hir_sig.decl.inputs.iter().map(|t| t.span)) { fcx.register_wf_obligation(input_ty.into(), span, ObligationCauseCode::MiscObligation); } implied_bounds.extend(sig.inputs()); fcx.register_wf_obligation( sig.output().into(), - hir_decl.output.span(), + hir_sig.decl.output.span(), ObligationCauseCode::ReturnType, ); // FIXME(#25759) return types should not be implied bounds implied_bounds.push(sig.output()); - check_where_clauses(tcx, fcx, span, def_id, Some((sig.output(), hir_decl.output.span()))); + check_where_clauses(tcx, fcx, span, def_id, Some((sig.output(), hir_sig.decl.output.span()))); } /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c3b54f1461426..ec534aa925d4f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1927,7 +1927,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let re_root_empty = tcx.lifetimes.re_root_empty; let predicate = ty::OutlivesPredicate(ty, re_root_empty); predicates.push(( - ty::PredicateKind::TypeOutlives(ty::Binder::bind(predicate)) + ty::PredicateKind::TypeOutlives(ty::Binder::dummy(predicate)) .to_predicate(tcx), span, )); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 1f576a17dd9d6..491daa80e5c85 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -346,11 +346,9 @@ pub fn build_impl( // such. This helps prevent dependencies of the standard library, for // example, from getting documented as "traits `u32` implements" which // isn't really too helpful. - if let Some(trait_did) = associated_trait { - if let Some(stab) = cx.tcx.lookup_stability(trait_did.def_id) { - if stab.level.is_unstable() { - return; - } + if let Some(stab) = cx.tcx.lookup_stability(did) { + if stab.level.is_unstable() { + return; } } } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 850a4b3cbc216..38709b445efae 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1511,11 +1511,6 @@ h4 > .important-traits { #main > .line-numbers { margin-top: 0; } - - .important-traits .important-traits-tooltiptext { - left: 0; - top: 100%; - } } @media print { diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index 96ba5c46a3cde..e0ab7170ea877 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -237,6 +237,16 @@ a { #crate-search+.search-input:focus { box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent; + color: #ffffff; + background-color: #141920; + box-shadow: none; + transition: box-shadow 150ms ease-in-out; + border-radius: 4px; + margin-left: 8px; +} + +#crate-search+.search-input:focus { + box-shadow: 0px 6px 20px 0px black; } .search-focus:disabled { @@ -308,12 +318,12 @@ a.test-arrow { font-size: 100%; color: #788797; border-radius: 4px; - background-color: rgba(57, 175, 215, 0.09); + background-color: rgba(255, 255, 255, 0); } a.test-arrow:hover { - background-color: rgba(57, 175, 215, 0.368); - color: #c5c5c5; + background-color: rgba(242, 151, 24, 0.05); + color: #ffb44c; } .toggle-label { diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 42403bdb1bcea..29893bd12f1f7 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -25,15 +25,11 @@ profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-dep-of-std'] } -# Dependencies of the `backtrace` crate -addr2line = { version = "0.13.0", optional = true, default-features = false } -rustc-demangle = { version = "0.1.4", features = ['rustc-dep-of-std'] } -miniz_oxide = { version = "0.4.0", optional = true, default-features = false } -[dependencies.object] -version = "0.20" -optional = true -default-features = false -features = ['read_core', 'elf', 'macho', 'pe'] +[dependencies.backtrace_rs] +package = "backtrace" +version = "0.3.46" +default-features = false # without the libstd `backtrace` feature, stub out everything +features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd [dev-dependencies] rand = "0.7" @@ -52,12 +48,11 @@ wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = [features] backtrace = [ - "gimli-symbolize", - 'addr2line/rustc-dep-of-std', - 'object/rustc-dep-of-std', - 'miniz_oxide/rustc-dep-of-std', + "backtrace_rs/dbghelp", # backtrace/symbolize on MSVC + "backtrace_rs/libbacktrace", # symbolize on most platforms + "backtrace_rs/libunwind", # backtrace on most platforms + "backtrace_rs/dladdr", # symbolize on platforms w/o libbacktrace ] -gimli-symbolize = [] panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index ecfaaeace513e..38d223d84e90f 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -59,7 +59,6 @@ //! The `#[global_allocator]` can only be used once in a crate //! or its recursive dependencies. -#![deny(unsafe_op_in_unsafe_fn)] #![stable(feature = "alloc_module", since = "1.28.0")] use core::intrinsics; @@ -159,9 +158,7 @@ unsafe impl AllocRef for System { #[inline] unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { if layout.size() != 0 { - // SAFETY: The safety guarantees are explained in the documentation - // for the `GlobalAlloc` trait and its `dealloc` method. - unsafe { GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) } + GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) } } @@ -187,36 +184,16 @@ unsafe impl AllocRef for System { match placement { ReallocPlacement::InPlace => Err(AllocErr), ReallocPlacement::MayMove if layout.size() == 0 => { - let new_layout = - // SAFETY: The new size and layout alignement guarantees - // are transfered to the caller (they come from parameters). - // - // See the preconditions for `Layout::from_size_align` to - // see what must be checked. - unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); self.alloc(new_layout, init) } ReallocPlacement::MayMove => { - // SAFETY: - // - // The safety guarantees are explained in the documentation - // for the `GlobalAlloc` trait and its `dealloc` method. - // - // `realloc` probably checks for `new_size > size` or something - // similar. - // - // For the guarantees about `init_offset`, see its documentation: - // `ptr` is assumed valid (and checked for non-NUL) and - // `memory.size` is set to `new_size` so the offset being `size` - // is valid. - let memory = unsafe { - intrinsics::assume(new_size > size); - let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size); - let memory = - MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }; - init.init_offset(memory, size); - memory - }; + // `realloc` probably checks for `new_size > size` or something similar. + intrinsics::assume(new_size > size); + let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size); + let memory = + MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }; + init.init_offset(memory, size); Ok(memory) } } @@ -243,28 +220,14 @@ unsafe impl AllocRef for System { match placement { ReallocPlacement::InPlace => Err(AllocErr), ReallocPlacement::MayMove if new_size == 0 => { - // SAFETY: see `GlobalAlloc::dealloc` for the guarantees that - // must be respected. `ptr` and `layout` are parameters and so - // those guarantees must be checked by the caller. - unsafe { self.dealloc(ptr, layout) }; + self.dealloc(ptr, layout); Ok(MemoryBlock { ptr: layout.dangling(), size: 0 }) } ReallocPlacement::MayMove => { - // SAFETY: - // - // See `GlobalAlloc::realloc` for more informations about the - // guarantees expected by this method. `ptr`, `layout` and - // `new_size` are parameters and the responsability for their - // correctness is left to the caller. - // - // `realloc` probably checks for `new_size < size` or something - // similar. - let memory = unsafe { - intrinsics::assume(new_size < size); - let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size); - MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size } - }; - Ok(memory) + // `realloc` probably checks for `new_size < size` or something similar. + intrinsics::assume(new_size < size); + let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size); + Ok(MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }) } } } @@ -337,19 +300,13 @@ pub mod __default_lib_allocator { #[rustc_std_internal_symbol] pub unsafe extern "C" fn __rdl_alloc(size: usize, align: usize) -> *mut u8 { - // SAFETY: see the guarantees expected by `Layout::from_size_align` and - // `GlobalAlloc::alloc`. - unsafe { - let layout = Layout::from_size_align_unchecked(size, align); - System.alloc(layout) - } + let layout = Layout::from_size_align_unchecked(size, align); + System.alloc(layout) } #[rustc_std_internal_symbol] pub unsafe extern "C" fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) { - // SAFETY: see the guarantees expected by `Layout::from_size_align` and - // `GlobalAlloc::dealloc`. - unsafe { System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) } + System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) } #[rustc_std_internal_symbol] @@ -359,21 +316,13 @@ pub mod __default_lib_allocator { align: usize, new_size: usize, ) -> *mut u8 { - // SAFETY: see the guarantees expected by `Layout::from_size_align` and - // `GlobalAlloc::realloc`. - unsafe { - let old_layout = Layout::from_size_align_unchecked(old_size, align); - System.realloc(ptr, old_layout, new_size) - } + let old_layout = Layout::from_size_align_unchecked(old_size, align); + System.realloc(ptr, old_layout, new_size) } #[rustc_std_internal_symbol] pub unsafe extern "C" fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 { - // SAFETY: see the guarantees expected by `Layout::from_size_align` and - // `GlobalAlloc::alloc_zeroed`. - unsafe { - let layout = Layout::from_size_align_unchecked(size, align); - System.alloc_zeroed(layout) - } + let layout = Layout::from_size_align_unchecked(size, align); + System.alloc_zeroed(layout) } } diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index e65775c1ced67..e10d466030f0b 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -91,7 +91,6 @@ // `Backtrace`, but that's a relatively small price to pay relative to capturing // a backtrace or actually symbolizing it. -use crate::backtrace_rs::{self, BytesOrWideString}; use crate::env; use crate::ffi::c_void; use crate::fmt; @@ -99,6 +98,8 @@ use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use crate::sync::Mutex; use crate::sys_common::backtrace::{lock, output_filename}; use crate::vec::Vec; +use backtrace::BytesOrWideString; +use backtrace_rs as backtrace; /// A captured OS thread stack backtrace. /// @@ -149,7 +150,7 @@ struct BacktraceFrame { } enum RawFrame { - Actual(backtrace_rs::Frame), + Actual(backtrace::Frame), #[cfg(test)] Fake, } @@ -196,7 +197,7 @@ impl fmt::Debug for BacktraceSymbol { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { write!(fmt, "{{ ")?; - if let Some(fn_name) = self.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)) { + if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) { write!(fmt, "fn: \"{:#}\"", fn_name)?; } else { write!(fmt, "fn: ")?; @@ -222,7 +223,7 @@ impl fmt::Debug for BytesOrWide { BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), }, - backtrace_rs::PrintFmt::Short, + backtrace::PrintFmt::Short, crate::env::current_dir().as_ref().ok(), ) } @@ -298,7 +299,7 @@ impl Backtrace { let mut frames = Vec::new(); let mut actual_start = None; unsafe { - backtrace_rs::trace_unsynchronized(|frame| { + backtrace::trace_unsynchronized(|frame| { frames.push(BacktraceFrame { frame: RawFrame::Actual(frame.clone()), symbols: Vec::new(), @@ -349,9 +350,9 @@ impl fmt::Display for Backtrace { let full = fmt.alternate(); let (frames, style) = if full { - (&capture.frames[..], backtrace_rs::PrintFmt::Full) + (&capture.frames[..], backtrace::PrintFmt::Full) } else { - (&capture.frames[capture.actual_start..], backtrace_rs::PrintFmt::Short) + (&capture.frames[capture.actual_start..], backtrace::PrintFmt::Short) }; // When printing paths we try to strip the cwd if it exists, otherwise @@ -363,7 +364,7 @@ impl fmt::Display for Backtrace { output_filename(fmt, path, style, cwd.as_ref().ok()) }; - let mut f = backtrace_rs::BacktraceFmt::new(fmt, style, &mut print_path); + let mut f = backtrace::BacktraceFmt::new(fmt, style, &mut print_path); f.add_context()?; for frame in frames { let mut f = f.frame(); @@ -373,7 +374,7 @@ impl fmt::Display for Backtrace { for symbol in frame.symbols.iter() { f.print_raw( frame.frame.ip(), - symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)), + symbol.name.as_ref().map(|b| backtrace::SymbolName::new(b)), symbol.filename.as_ref().map(|b| match b { BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), @@ -408,7 +409,7 @@ impl Capture { RawFrame::Fake => unimplemented!(), }; unsafe { - backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| { + backtrace::resolve_frame_unsynchronized(frame, |symbol| { symbols.push(BacktraceSymbol { name: symbol.name().map(|m| m.as_bytes().to_vec()), filename: symbol.filename_raw().map(|b| match b { diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 58fb6fda19aab..eb2753d62457a 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -87,5 +87,4 @@ fn main() { println!("cargo:rustc-cfg=feature=\"restricted-std\""); } println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); - println!("cargo:rustc-cfg=backtrace_in_libstd"); } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 7b48deee1abdf..5ba5eff44076b 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -148,11 +148,14 @@ use crate::sys; /// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`]. /// We must also derive [`PartialEq`]. /// -/// [`RefCell`]: crate::cell::RefCell -/// [`Cell`]: crate::cell::Cell -/// [`default`]: Default::default -/// [`with_hasher`]: Self::with_hasher -/// [`with_capacity_and_hasher`]: Self::with_capacity_and_hasher +/// [`Eq`]: ../../std/cmp/trait.Eq.html +/// [`Hash`]: ../../std/hash/trait.Hash.html +/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html +/// [`RefCell`]: ../../std/cell/struct.RefCell.html +/// [`Cell`]: ../../std/cell/struct.Cell.html +/// [`default`]: #method.default +/// [`with_hasher`]: #method.with_hasher +/// [`with_capacity_and_hasher`]: #method.with_capacity_and_hasher /// [`fnv`]: https://crates.io/crates/fnv /// /// ``` @@ -261,6 +264,8 @@ impl HashMap { /// let mut map = HashMap::with_hasher(s); /// map.insert(1, 2); /// ``` + /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_hasher(hash_builder: S) -> HashMap { @@ -291,6 +296,8 @@ impl HashMap { /// let mut map = HashMap::with_capacity_and_hasher(10, s); /// map.insert(1, 2); /// ``` + /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap { @@ -517,6 +524,8 @@ impl HashMap { /// Returns a reference to the map's [`BuildHasher`]. /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html + /// /// # Examples /// /// ``` @@ -547,6 +556,8 @@ where /// /// Panics if the new allocation size overflows [`usize`]. /// + /// [`usize`]: ../../std/primitive.usize.html + /// /// # Examples /// /// ``` @@ -665,6 +676,9 @@ where /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html + /// /// # Examples /// /// ``` @@ -691,6 +705,9 @@ where /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html + /// /// # Examples /// /// ``` @@ -717,6 +734,9 @@ where /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html + /// /// # Examples /// /// ``` @@ -743,6 +763,9 @@ where /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html + /// /// # Examples /// /// ``` @@ -774,7 +797,8 @@ where /// types that can be `==` without being identical. See the [module-level /// documentation] for more. /// - /// [module-level documentation]: crate::collections#insert-and-complex-keys + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [module-level documentation]: index.html#insert-and-complex-keys /// /// # Examples /// @@ -802,6 +826,9 @@ where /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html + /// /// # Examples /// /// ``` @@ -829,6 +856,9 @@ where /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for /// the key type. /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html + /// /// # Examples /// /// ``` @@ -1010,7 +1040,8 @@ where /// This `struct` is created by the [`iter`] method on [`HashMap`]. See its /// documentation for more. /// -/// [`iter`]: HashMap::iter +/// [`iter`]: struct.HashMap.html#method.iter +/// [`HashMap`]: struct.HashMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, K: 'a, V: 'a> { base: base::Iter<'a, K, V>, @@ -1037,7 +1068,8 @@ impl fmt::Debug for Iter<'_, K, V> { /// This `struct` is created by the [`iter_mut`] method on [`HashMap`]. See its /// documentation for more. /// -/// [`iter_mut`]: HashMap::iter_mut +/// [`iter_mut`]: struct.HashMap.html#method.iter_mut +/// [`HashMap`]: struct.HashMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, K: 'a, V: 'a> { base: base::IterMut<'a, K, V>, @@ -1056,7 +1088,8 @@ impl<'a, K, V> IterMut<'a, K, V> { /// This `struct` is created by the [`into_iter`] method on [`HashMap`] /// (provided by the `IntoIterator` trait). See its documentation for more. /// -/// [`into_iter`]: IntoIterator::into_iter +/// [`into_iter`]: struct.HashMap.html#method.into_iter +/// [`HashMap`]: struct.HashMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { base: base::IntoIter, @@ -1075,7 +1108,8 @@ impl IntoIter { /// This `struct` is created by the [`keys`] method on [`HashMap`]. See its /// documentation for more. /// -/// [`keys`]: HashMap::keys +/// [`keys`]: struct.HashMap.html#method.keys +/// [`HashMap`]: struct.HashMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Keys<'a, K: 'a, V: 'a> { inner: Iter<'a, K, V>, @@ -1102,7 +1136,8 @@ impl fmt::Debug for Keys<'_, K, V> { /// This `struct` is created by the [`values`] method on [`HashMap`]. See its /// documentation for more. /// -/// [`values`]: HashMap::values +/// [`values`]: struct.HashMap.html#method.values +/// [`HashMap`]: struct.HashMap.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K: 'a, V: 'a> { inner: Iter<'a, K, V>, @@ -1129,7 +1164,8 @@ impl fmt::Debug for Values<'_, K, V> { /// This `struct` is created by the [`drain`] method on [`HashMap`]. See its /// documentation for more. /// -/// [`drain`]: HashMap::drain +/// [`drain`]: struct.HashMap.html#method.drain +/// [`HashMap`]: struct.HashMap.html #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, K: 'a, V: 'a> { base: base::Drain<'a, K, V>, @@ -1148,7 +1184,8 @@ impl<'a, K, V> Drain<'a, K, V> { /// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its /// documentation for more. /// -/// [`values_mut`]: HashMap::values_mut +/// [`values_mut`]: struct.HashMap.html#method.values_mut +/// [`HashMap`]: struct.HashMap.html #[stable(feature = "map_values_mut", since = "1.10.0")] pub struct ValuesMut<'a, K: 'a, V: 'a> { inner: IterMut<'a, K, V>, @@ -1158,7 +1195,7 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { /// /// See the [`HashMap::raw_entry_mut`] docs for usage examples. /// -/// [`HashMap::raw_entry_mut`]: HashMap::raw_entry_mut +/// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut #[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { @@ -1172,8 +1209,9 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { /// This `enum` is constructed through the [`raw_entry_mut`] method on [`HashMap`], /// then calling one of the methods of that [`RawEntryBuilderMut`]. /// +/// [`HashMap`]: struct.HashMap.html /// [`Entry`]: enum.Entry.html -/// [`raw_entry_mut`]: HashMap::raw_entry_mut +/// [`raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut /// [`RawEntryBuilderMut`]: struct.RawEntryBuilderMut.html #[unstable(feature = "hash_raw_entry", issue = "56167")] pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { @@ -1185,6 +1223,8 @@ pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// A view into an occupied entry in a `HashMap`. /// It is part of the [`RawEntryMut`] enum. +/// +/// [`RawEntryMut`]: enum.RawEntryMut.html #[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> { base: base::RawOccupiedEntryMut<'a, K, V>, @@ -1192,6 +1232,8 @@ pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> { /// A view into a vacant entry in a `HashMap`. /// It is part of the [`RawEntryMut`] enum. +/// +/// [`RawEntryMut`]: enum.RawEntryMut.html #[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { base: base::RawVacantEntryMut<'a, K, V, S>, @@ -1201,7 +1243,7 @@ pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// /// See the [`HashMap::raw_entry`] docs for usage examples. /// -/// [`HashMap::raw_entry`]: HashMap::raw_entry +/// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry #[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> { map: &'a HashMap, @@ -1555,7 +1597,8 @@ impl Debug for RawEntryBuilder<'_, K, V, S> { /// /// This `enum` is constructed from the [`entry`] method on [`HashMap`]. /// -/// [`entry`]: HashMap::entry +/// [`HashMap`]: struct.HashMap.html +/// [`entry`]: struct.HashMap.html#method.entry #[stable(feature = "rust1", since = "1.0.0")] pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied entry. @@ -2113,7 +2156,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { /// If you need a reference to the `OccupiedEntry` which may outlive the /// destruction of the `Entry` value, see [`into_mut`]. /// - /// [`into_mut`]: Self::into_mut + /// [`into_mut`]: #method.into_mut /// /// # Examples /// @@ -2146,7 +2189,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { /// /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`]. /// - /// [`get_mut`]: Self::get_mut + /// [`get_mut`]: #method.get_mut /// /// # Examples /// @@ -2432,6 +2475,9 @@ where /// [`Hasher`], but the hashers created by two different `RandomState` /// instances are unlikely to produce the same result for the same values. /// +/// [`HashMap`]: struct.HashMap.html +/// [`Hasher`]: ../../hash/trait.Hasher.html +/// /// # Examples /// /// ``` @@ -2501,6 +2547,9 @@ impl BuildHasher for RandomState { /// /// The internal algorithm is not specified, and so it and its hashes should /// not be relied upon over releases. +/// +/// [`RandomState`]: struct.RandomState.html +/// [`Hasher`]: ../../hash/trait.Hasher.html #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[allow(deprecated)] #[derive(Clone, Debug)] diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 10bf917daea46..cb2f829803b85 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -98,8 +98,12 @@ use super::map::{self, HashMap, Keys, RandomState}; /// // use the values stored in the set /// ``` /// -/// [`RefCell`]: crate::cell::RefCell -/// [`Cell`]: crate::cell::Cell +/// [`Cell`]: ../../std/cell/struct.Cell.html +/// [`Eq`]: ../../std/cmp/trait.Eq.html +/// [`Hash`]: ../../std/hash/trait.Hash.html +/// [`HashMap`]: struct.HashMap.html +/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html +/// [`RefCell`]: ../../std/cell/struct.RefCell.html #[derive(Clone)] #[cfg_attr(not(test), rustc_diagnostic_item = "hashset_type")] #[stable(feature = "rust1", since = "1.0.0")] @@ -282,6 +286,8 @@ impl HashSet { /// let mut set = HashSet::with_hasher(s); /// set.insert(2); /// ``` + /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_hasher(hasher: S) -> HashSet { @@ -312,6 +318,8 @@ impl HashSet { /// let mut set = HashSet::with_capacity_and_hasher(10, s); /// set.insert(1); /// ``` + /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet { @@ -320,6 +328,8 @@ impl HashSet { /// Returns a reference to the set's [`BuildHasher`]. /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html + /// /// # Examples /// /// ``` @@ -567,6 +577,9 @@ where /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` + /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn contains(&self, value: &Q) -> bool @@ -592,6 +605,9 @@ where /// assert_eq!(set.get(&2), Some(&2)); /// assert_eq!(set.get(&4), None); /// ``` + /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html #[inline] #[stable(feature = "set_recovery", since = "1.9.0")] pub fn get(&self, value: &Q) -> Option<&T> @@ -833,6 +849,9 @@ where /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` + /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, value: &Q) -> bool @@ -858,6 +877,9 @@ where /// assert_eq!(set.take(&2), Some(2)); /// assert_eq!(set.take(&2), None); /// ``` + /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html #[inline] #[stable(feature = "set_recovery", since = "1.9.0")] pub fn take(&mut self, value: &Q) -> Option @@ -1131,7 +1153,8 @@ where /// This `struct` is created by the [`iter`] method on [`HashSet`]. /// See its documentation for more. /// -/// [`iter`]: HashSet::iter +/// [`HashSet`]: struct.HashSet.html +/// [`iter`]: struct.HashSet.html#method.iter #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, K: 'a> { iter: Keys<'a, K, ()>, @@ -1142,7 +1165,8 @@ pub struct Iter<'a, K: 'a> { /// This `struct` is created by the [`into_iter`] method on [`HashSet`] /// (provided by the `IntoIterator` trait). See its documentation for more. /// -/// [`into_iter`]: IntoIterator::into_iter +/// [`HashSet`]: struct.HashSet.html +/// [`into_iter`]: struct.HashSet.html#method.into_iter #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { iter: map::IntoIter, @@ -1153,7 +1177,8 @@ pub struct IntoIter { /// This `struct` is created by the [`drain`] method on [`HashSet`]. /// See its documentation for more. /// -/// [`drain`]: HashSet::drain +/// [`HashSet`]: struct.HashSet.html +/// [`drain`]: struct.HashSet.html#method.drain #[stable(feature = "rust1", since = "1.0.0")] pub struct Drain<'a, K: 'a> { iter: map::Drain<'a, K, ()>, @@ -1164,7 +1189,8 @@ pub struct Drain<'a, K: 'a> { /// This `struct` is created by the [`intersection`] method on [`HashSet`]. /// See its documentation for more. /// -/// [`intersection`]: HashSet::intersection +/// [`HashSet`]: struct.HashSet.html +/// [`intersection`]: struct.HashSet.html#method.intersection #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection<'a, T: 'a, S: 'a> { // iterator of the first set @@ -1178,7 +1204,8 @@ pub struct Intersection<'a, T: 'a, S: 'a> { /// This `struct` is created by the [`difference`] method on [`HashSet`]. /// See its documentation for more. /// -/// [`difference`]: HashSet::difference +/// [`HashSet`]: struct.HashSet.html +/// [`difference`]: struct.HashSet.html#method.difference #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference<'a, T: 'a, S: 'a> { // iterator of the first set @@ -1192,7 +1219,8 @@ pub struct Difference<'a, T: 'a, S: 'a> { /// This `struct` is created by the [`symmetric_difference`] method on /// [`HashSet`]. See its documentation for more. /// -/// [`symmetric_difference`]: HashSet::symmetric_difference +/// [`HashSet`]: struct.HashSet.html +/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference #[stable(feature = "rust1", since = "1.0.0")] pub struct SymmetricDifference<'a, T: 'a, S: 'a> { iter: Chain, Difference<'a, T, S>>, @@ -1203,7 +1231,8 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> { /// This `struct` is created by the [`union`] method on [`HashSet`]. /// See its documentation for more. /// -/// [`union`]: HashSet::union +/// [`HashSet`]: struct.HashSet.html +/// [`union`]: struct.HashSet.html#method.union #[stable(feature = "rust1", since = "1.0.0")] pub struct Union<'a, T: 'a, S: 'a> { iter: Chain, Difference<'a, T, S>>, diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index b6488ae61b153..cc6663bebd3d4 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -86,7 +86,7 @@ //! cost are suffixed with a `~`. //! //! All amortized costs are for the potential need to resize when capacity is -//! exhausted. If a resize occurs it will take *O*(*n*) time. Our collections never +//! exhausted. If a resize occurs it will take O(n) time. Our collections never //! automatically shrink, so removal operations aren't amortized. Over a //! sufficiently large series of operations, the average cost per operation will //! deterministically equal the given cost. diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index da25a0ede729d..dca1fdde48242 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1551,27 +1551,6 @@ impl ops::Index for CString { } } -#[stable(feature = "cstr_range_from", since = "1.47.0")] -impl ops::Index> for CStr { - type Output = CStr; - - fn index(&self, index: ops::RangeFrom) -> &CStr { - let bytes = self.to_bytes_with_nul(); - // we need to manually check the starting index to account for the null - // byte, since otherwise we could get an empty string that doesn't end - // in a null. - if index.start < bytes.len() { - unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) } - } else { - panic!( - "index out of bounds: the len is {} but the index is {}", - bytes.len(), - index.start - ); - } - } -} - #[stable(feature = "cstring_asref", since = "1.7.0")] impl AsRef for CStr { #[inline] @@ -1768,21 +1747,4 @@ mod tests { assert_eq!(CSTR.to_str().unwrap(), "Hello, world!"); } - - #[test] - fn cstr_index_from() { - let original = b"Hello, world!\0"; - let cstr = CStr::from_bytes_with_nul(original).unwrap(); - let result = CStr::from_bytes_with_nul(&original[7..]).unwrap(); - - assert_eq!(&cstr[7..], result); - } - - #[test] - #[should_panic] - fn cstr_index_from_empty() { - let original = b"Hello, world!\0"; - let cstr = CStr::from_bytes_with_nul(original).unwrap(); - let _ = &cstr[original.len()..]; - } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 797318d95b777..d5af4f25102d1 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -238,14 +238,25 @@ //! contract. The implementation of many of these functions are subject to change over //! time and may call fewer or more syscalls/library functions. //! -//! [`File`]: crate::fs::File -//! [`TcpStream`]: crate::net::TcpStream -//! [`Vec`]: crate::vec::Vec -//! [`io::stdout`]: stdout -//! [`io::Result`]: crate::io::Result +//! [`Read`]: trait.Read.html +//! [`Write`]: trait.Write.html +//! [`Seek`]: trait.Seek.html +//! [`BufRead`]: trait.BufRead.html +//! [`File`]: ../fs/struct.File.html +//! [`TcpStream`]: ../net/struct.TcpStream.html +//! [`Vec`]: ../vec/struct.Vec.html +//! [`BufReader`]: struct.BufReader.html +//! [`BufWriter`]: struct.BufWriter.html +//! [`Write::write`]: trait.Write.html#tymethod.write +//! [`io::stdout`]: fn.stdout.html +//! [`println!`]: ../macro.println.html +//! [`Lines`]: struct.Lines.html +//! [`io::Result`]: type.Result.html //! [`?` operator]: ../../book/appendix-02-operators.html -//! [`Result`]: crate::result::Result -//! [`.unwrap()`]: crate::result::Result::unwrap +//! [`Read::read`]: trait.Read.html#tymethod.read +//! [`Result`]: ../result/enum.Result.html +//! [`.unwrap()`]: ../result/enum.Result.html#method.unwrap +// ignore-tidy-filelength #![stable(feature = "rust1", since = "1.0.0")] @@ -480,10 +491,12 @@ where /// } /// ``` /// -/// [`read()`]: Read::read -/// [`&str`]: str -/// [`std::io`]: self -/// [`File`]: crate::fs::File +/// [`read()`]: trait.Read.html#tymethod.read +/// [`std::io`]: ../../std/io/index.html +/// [`File`]: ../fs/struct.File.html +/// [`BufRead`]: trait.BufRead.html +/// [`BufReader`]: struct.BufReader.html +/// [`&str`]: ../../std/primitive.str.html /// [slice]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] #[doc(spotlight)] @@ -522,7 +535,7 @@ pub trait Read { /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one /// obtains via [`MaybeUninit`]) is not safe, and can lead to undefined behavior. /// - /// [`MaybeUninit`]: crate::mem::MaybeUninit + /// [`MaybeUninit`]: ../mem/union.MaybeUninit.html /// /// # Errors /// @@ -537,8 +550,10 @@ pub trait Read { /// /// [`File`]s implement `Read`: /// - /// [`Ok(n)`]: Ok - /// [`File`]: crate::fs::File + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`File`]: ../fs/struct.File.html /// /// ```no_run /// use std::io; @@ -605,6 +620,9 @@ pub trait Read { /// This method is unsafe because a `Read`er could otherwise return a /// non-zeroing `Initializer` from another `Read` type without an `unsafe` /// block. + /// + /// [`Initializer::nop()`]: ../../std/io/struct.Initializer.html#method.nop + /// [`Initializer`]: ../../std/io/struct.Initializer.html #[unstable(feature = "read_initializer", issue = "42788")] #[inline] unsafe fn initializer(&self) -> Initializer { @@ -634,9 +652,10 @@ pub trait Read { /// /// [`File`]s implement `Read`: /// - /// [`read()`]: Read::read - /// [`Ok(0)`]: Ok - /// [`File`]: crate::fs::File + /// [`read()`]: trait.Read.html#tymethod.read + /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`File`]: ../fs/struct.File.html /// /// ```no_run /// use std::io; @@ -656,7 +675,7 @@ pub trait Read { /// (See also the [`std::fs::read`] convenience function for reading from a /// file.) /// - /// [`std::fs::read`]: crate::fs::read + /// [`std::fs::read`]: ../fs/fn.read.html #[stable(feature = "rust1", since = "1.0.0")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { read_to_end(self, buf) @@ -674,13 +693,13 @@ pub trait Read { /// /// See [`read_to_end`][readtoend] for other error semantics. /// - /// [readtoend]: Self::read_to_end + /// [readtoend]: #method.read_to_end /// /// # Examples /// /// [`File`][file]s implement `Read`: /// - /// [file]: crate::fs::File + /// [file]: ../fs/struct.File.html /// /// ```no_run /// use std::io; @@ -699,7 +718,7 @@ pub trait Read { /// (See also the [`std::fs::read_to_string`] convenience function for /// reading from a file.) /// - /// [`std::fs::read_to_string`]: crate::fs::read_to_string + /// [`std::fs::read_to_string`]: ../fs/fn.read_to_string.html #[stable(feature = "rust1", since = "1.0.0")] fn read_to_string(&mut self, buf: &mut String) -> Result { // Note that we do *not* call `.read_to_end()` here. We are passing @@ -722,9 +741,7 @@ pub trait Read { /// No guarantees are provided about the contents of `buf` when this /// function is called, implementations cannot rely on any property of the /// contents of `buf` being true. It is recommended that implementations - /// only write data to `buf` instead of reading its contents. The - /// documentation on [`read`] has a more detailed explanation on this - /// subject. + /// only write data to `buf` instead of reading its contents. /// /// # Errors /// @@ -747,8 +764,9 @@ pub trait Read { /// /// [`File`]s implement `Read`: /// - /// [`read`]: Read::read - /// [`File`]: crate::fs::File + /// [`File`]: ../fs/struct.File.html + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof /// /// ```no_run /// use std::io; @@ -793,7 +811,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: crate::fs::File + /// [file]: ../fs/struct.File.html /// /// ```no_run /// use std::io; @@ -837,10 +855,14 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: crate::fs::File - /// [`Iterator`]: crate::iter::Iterator - /// [`Result`]: crate::result::Result - /// [`io::Error`]: self::Error + /// [file]: ../fs/struct.File.html + /// [`Iterator`]: ../../std/iter/trait.Iterator.html + /// [`Result`]: ../../std/result/enum.Result.html + /// [`io::Error`]: ../../std/io/struct.Error.html + /// [`u8`]: ../../std/primitive.u8.html + /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// ```no_run /// use std::io; @@ -874,7 +896,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: crate::fs::File + /// [file]: ../fs/struct.File.html /// /// ```no_run /// use std::io; @@ -913,9 +935,9 @@ pub trait Read { /// /// [`File`]s implement `Read`: /// - /// [`File`]: crate::fs::File - /// [`Ok(0)`]: Ok - /// [`read()`]: Read::read + /// [`File`]: ../fs/struct.File.html + /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`read()`]: trait.Read.html#tymethod.read /// /// ```no_run /// use std::io; @@ -1211,8 +1233,8 @@ impl Initializer { /// throughout [`std::io`] take and provide types which implement the `Write` /// trait. /// -/// [`write`]: Self::write -/// [`flush`]: Self::flush +/// [`write`]: #tymethod.write +/// [`flush`]: #tymethod.flush /// [`std::io`]: index.html /// /// # Examples @@ -1238,7 +1260,7 @@ impl Initializer { /// The trait also provides convenience methods like [`write_all`], which calls /// `write` in a loop until its entire input has been written. /// -/// [`write_all`]: Self::write_all +/// [`write_all`]: #method.write_all #[stable(feature = "rust1", since = "1.0.0")] #[doc(spotlight)] pub trait Write { @@ -1270,6 +1292,10 @@ pub trait Write { /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the /// write operation should be retried if there is nothing else to do. /// + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// /// # Examples /// /// ```no_run @@ -1355,7 +1381,8 @@ pub trait Write { /// This function will return the first error of /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns. /// - /// [`write`]: Self::write + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`write`]: #tymethod.write /// /// # Examples /// @@ -1396,7 +1423,8 @@ pub trait Write { /// /// If the buffer contains no data, this will never call [`write_vectored`]. /// - /// [`write_vectored`]: Self::write_vectored + /// [`write_vectored`]: #method.write_vectored + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// /// # Notes /// @@ -1452,16 +1480,19 @@ pub trait Write { /// encountered. /// /// This method is primarily used to interface with the - /// [`format_args!()`] macro, but it is rare that this should - /// explicitly be called. The [`write!()`] macro should be favored to + /// [`format_args!`][formatargs] macro, but it is rare that this should + /// explicitly be called. The [`write!`][write] macro should be favored to /// invoke this method instead. /// + /// [formatargs]: ../macro.format_args.html + /// [write]: ../macro.write.html + /// /// This function internally uses the [`write_all`][writeall] method on /// this trait and hence will continuously write data so long as no errors /// are received. This also means that partial writes are not indicated in /// this signature. /// - /// [writeall]: Self::write_all + /// [writeall]: #method.write_all /// /// # Errors /// @@ -1558,7 +1589,7 @@ pub trait Write { /// /// [`File`][file]s implement `Seek`: /// -/// [file]: crate::fs::File +/// [file]: ../fs/struct.File.html /// /// ```no_run /// use std::io; @@ -1758,9 +1789,9 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) -> R /// [`BufReader`] to the rescue! /// /// [`BufReader`]: struct.BufReader.html -/// [`File`]: crate::fs::File -/// [`read_line`]: Self::read_line -/// [`lines`]: Self::lines +/// [`File`]: ../fs/struct.File.html +/// [`read_line`]: #method.read_line +/// [`lines`]: #method.lines /// [`Read`]: trait.Read.html /// /// ```no_run @@ -1792,7 +1823,7 @@ pub trait BufRead: Read { /// be called with the number of bytes that are consumed from this buffer to /// ensure that the bytes are never returned twice. /// - /// [`consume`]: Self::consume + /// [`consume`]: #tymethod.consume /// /// An empty buffer returned indicates that the stream has reached EOF. /// @@ -1842,7 +1873,7 @@ pub trait BufRead: Read { /// Since `consume()` is meant to be used with [`fill_buf`], /// that method's example includes an example of `consume()`. /// - /// [`fill_buf`]: Self::fill_buf + /// [`fill_buf`]: #tymethod.fill_buf #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); @@ -1866,7 +1897,7 @@ pub trait BufRead: Read { /// If an I/O error is encountered then all bytes read so far will be /// present in `buf` and its length will have been adjusted appropriately. /// - /// [`fill_buf`]: Self::fill_buf + /// [`fill_buf`]: #tymethod.fill_buf /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted /// /// # Examples @@ -1931,7 +1962,7 @@ pub trait BufRead: Read { /// error is encountered then `buf` may contain some bytes already read in /// the event that all data read so far was valid UTF-8. /// - /// [`read_until`]: Self::read_until + /// [`read_until`]: #method.read_until /// /// # Examples /// @@ -1984,9 +2015,9 @@ pub trait BufRead: Read { /// This function will yield errors whenever [`read_until`] would have /// also yielded an error. /// - /// [`io::Result`]: self::Result - /// [`Vec`]: crate::vec::Vec - /// [`read_until`]: Self::read_until + /// [`io::Result`]: type.Result.html + /// [`Vec`]: ../vec/struct.Vec.html + /// [`read_until`]: #method.read_until /// /// # Examples /// @@ -2021,7 +2052,8 @@ pub trait BufRead: Read { /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. /// - /// [`io::Result`]: self::Result + /// [`io::Result`]: type.Result.html + /// [`String`]: ../string/struct.String.html /// /// # Examples /// @@ -2029,6 +2061,8 @@ pub trait BufRead: Read { /// this example, we use [`Cursor`] to iterate over all the lines in a byte /// slice. /// + /// [`Cursor`]: struct.Cursor.html + /// /// ``` /// use std::io::{self, BufRead}; /// @@ -2219,6 +2253,8 @@ impl Take { /// This instance may reach `EOF` after reading fewer bytes than indicated by /// this method if the underlying [`Read`] instance reaches EOF. /// + /// [`Read`]: ../../std/io/trait.Read.html + /// /// # Examples /// /// ```no_run diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index a62987891b99b..a53e7f5cf57aa 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -387,11 +387,10 @@ mod extern_keyword {} // /// A value of type [`bool`] representing logical **false**. /// -/// `false` is the logical opposite of [`true`]. -/// -/// See the documentation for [`true`] for more information. +/// The documentation for this keyword is [not yet complete]. Pull requests welcome! /// -/// [`true`]: keyword.true.html +/// [`bool`]: primitive.bool.html +/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod false_keyword {} #[doc(keyword = "fn")] @@ -474,8 +473,8 @@ mod fn_keyword {} /// * `for` is also used for [higher-ranked trait bounds] as in `for<'a> &'a T: PartialEq`. /// /// for-in-loops, or to be more precise, iterator loops, are a simple syntactic sugar over a common -/// practice within Rust, which is to loop over anything that implements [`IntoIterator`] until the -/// iterator returned by `.into_iter()` returns `None` (or the loop body uses `break`). +/// practice within Rust, which is to loop over an iterator until that iterator returns `None` (or +/// `break` is called). /// /// ```rust /// for i in 0..5 { @@ -681,7 +680,7 @@ mod impl_keyword {} // /// Iterate over a series of values with [`for`]. /// -/// The expression immediately following `in` must implement the [`IntoIterator`] trait. +/// The expression immediately following `in` must implement the [`Iterator`] trait. /// /// ## Literal Examples: /// @@ -690,7 +689,7 @@ mod impl_keyword {} /// /// (Read more about [range patterns]) /// -/// [`IntoIterator`]: ../book/ch13-04-performance.html +/// [`Iterator`]: ../book/ch13-04-performance.html /// [range patterns]: ../reference/patterns.html?highlight=range#range-patterns /// [`for`]: keyword.for.html mod in_keyword {} @@ -1498,188 +1497,11 @@ mod super_keyword {} #[doc(keyword = "trait")] // -/// A common interface for a group of types. -/// -/// A `trait` is like an interface that data types can implement. When a type -/// implements a trait it can be treated abstractly as that trait using generics -/// or trait objects. -/// -/// Traits can be made up of three varieties of associated items: -/// -/// - functions and methods -/// - types -/// - constants -/// -/// Traits may also contain additional type parameters. Those type parameters -/// or the trait itself can be constrained by other traits. -/// -/// Traits can serve as markers or carry other logical semantics that -/// aren't expressed through their items. When a type implements that -/// trait it is promising to uphold its contract. [`Send`] and [`Sync`] are two -/// such marker traits present in the standard library. -/// -/// See the [Reference][Ref-Traits] for a lot more information on traits. -/// -/// # Examples -/// -/// Traits are declared using the `trait` keyword. Types can implement them -/// using [`impl`] `Trait` [`for`] `Type`: -/// -/// ```rust -/// trait Zero { -/// const ZERO: Self; -/// fn is_zero(&self) -> bool; -/// } -/// -/// impl Zero for i32 { -/// const ZERO: Self = 0; -/// -/// fn is_zero(&self) -> bool { -/// *self == Self::ZERO -/// } -/// } -/// -/// assert_eq!(i32::ZERO, 0); -/// assert!(i32::ZERO.is_zero()); -/// assert!(!4.is_zero()); -/// ``` -/// -/// With an associated type: -/// -/// ```rust -/// trait Builder { -/// type Built; -/// -/// fn build(&self) -> Self::Built; -/// } -/// ``` -/// -/// Traits can be generic, with constraints or without: -/// -/// ```rust -/// trait MaybeFrom { -/// fn maybe_from(value: T) -> Option -/// where -/// Self: Sized; -/// } -/// ``` -/// -/// Traits can build upon the requirements of other traits. In the example -/// below `Iterator` is a **supertrait** and `ThreeIterator` is a **subtrait**: -/// -/// ```rust -/// trait ThreeIterator: std::iter::Iterator { -/// fn next_three(&mut self) -> Option<[Self::Item; 3]>; -/// } -/// ``` -/// -/// Traits can be used in functions, as parameters: -/// -/// ```rust -/// # #![allow(dead_code)] -/// fn debug_iter(it: I) where I::Item: std::fmt::Debug { -/// for elem in it { -/// println!("{:#?}", elem); -/// } -/// } -/// -/// // u8_len_1, u8_len_2 and u8_len_3 are equivalent -/// -/// fn u8_len_1(val: impl Into>) -> usize { -/// val.into().len() -/// } +/// A common interface for a class of types. /// -/// fn u8_len_2>>(val: T) -> usize { -/// val.into().len() -/// } -/// -/// fn u8_len_3(val: T) -> usize -/// where -/// T: Into>, -/// { -/// val.into().len() -/// } -/// ``` -/// -/// Or as return types: -/// -/// ```rust -/// # #![allow(dead_code)] -/// fn from_zero_to(v: u8) -> impl Iterator { -/// (0..v).into_iter() -/// } -/// ``` -/// -/// The use of the [`impl`] keyword in this position allows the function writer -/// to hide the concrete type as an implementation detail which can change -/// without breaking user's code. -/// -/// # Trait objects -/// -/// A *trait object* is an opaque value of another type that implements a set of -/// traits. A trait object implements all specified traits as well as their -/// supertraits (if any). -/// -/// The syntax is the following: `dyn BaseTrait + AutoTrait1 + ... AutoTraitN`. -/// Only one `BaseTrait` can be used so this will not compile: -/// -/// ```rust,compile_fail,E0225 -/// trait A {} -/// trait B {} -/// -/// let _: Box; -/// ``` -/// -/// Neither will this, which is a syntax error: -/// -/// ```rust,compile_fail -/// trait A {} -/// trait B {} -/// -/// let _: Box; -/// ``` -/// -/// On the other hand, this is correct: -/// -/// ```rust -/// trait A {} -/// -/// let _: Box; -/// ``` -/// -/// The [Reference][Ref-Trait-Objects] has more information about trait objects, -/// their limitations and the differences between editions. -/// -/// # Unsafe traits -/// -/// Some traits may be unsafe to implement. Using the [`unsafe`] keyword in -/// front of the trait's declaration is used to mark this: -/// -/// ```rust -/// unsafe trait UnsafeTrait {} -/// -/// unsafe impl UnsafeTrait for i32 {} -/// ``` -/// -/// # Differences between the 2015 and 2018 editions -/// -/// In the 2015 edition parameters pattern where not needed for traits: -/// -/// ```rust,edition2015 -/// trait Tr { -/// fn f(i32); -/// } -/// ``` -/// -/// This behavior is no longer valid in edition 2018. +/// The documentation for this keyword is [not yet complete]. Pull requests welcome! /// -/// [`for`]: keyword.for.html -/// [`impl`]: keyword.impl.html -/// [`unsafe`]: keyword.unsafe.html -/// [`Send`]: marker/trait.Send.html -/// [`Sync`]: marker/trait.Sync.html -/// [Ref-Traits]: ../reference/items/traits.html -/// [Ref-Trait-Objects]: ../reference/types/trait-object.html +/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod trait_keyword {} #[doc(keyword = "true")] diff --git a/src/libstd/lazy.rs b/src/libstd/lazy.rs deleted file mode 100644 index 86e1cfae582e8..0000000000000 --- a/src/libstd/lazy.rs +++ /dev/null @@ -1,844 +0,0 @@ -//! Lazy values and one-time initialization of static data. - -use crate::{ - cell::{Cell, UnsafeCell}, - fmt, - mem::{self, MaybeUninit}, - ops::{Deref, Drop}, - panic::{RefUnwindSafe, UnwindSafe}, - sync::Once, -}; - -#[doc(inline)] -#[unstable(feature = "once_cell", issue = "74465")] -pub use core::lazy::*; - -/// A synchronization primitive which can be written to only once. -/// -/// This type is a thread-safe `OnceCell`. -/// -/// # Examples -/// -/// ``` -/// #![feature(once_cell)] -/// -/// use std::lazy::SyncOnceCell; -/// -/// static CELL: SyncOnceCell = SyncOnceCell::new(); -/// assert!(CELL.get().is_none()); -/// -/// std::thread::spawn(|| { -/// let value: &String = CELL.get_or_init(|| { -/// "Hello, World!".to_string() -/// }); -/// assert_eq!(value, "Hello, World!"); -/// }).join().unwrap(); -/// -/// let value: Option<&String> = CELL.get(); -/// assert!(value.is_some()); -/// assert_eq!(value.unwrap().as_str(), "Hello, World!"); -/// ``` -#[unstable(feature = "once_cell", issue = "74465")] -pub struct SyncOnceCell { - once: Once, - // Whether or not the value is initialized is tracked by `state_and_queue`. - value: UnsafeCell>, -} - -// Why do we need `T: Send`? -// Thread A creates a `SyncOnceCell` and shares it with -// scoped thread B, which fills the cell, which is -// then destroyed by A. That is, destructor observes -// a sent value. -#[unstable(feature = "once_cell", issue = "74465")] -unsafe impl Sync for SyncOnceCell {} -#[unstable(feature = "once_cell", issue = "74465")] -unsafe impl Send for SyncOnceCell {} - -#[unstable(feature = "once_cell", issue = "74465")] -impl RefUnwindSafe for SyncOnceCell {} -#[unstable(feature = "once_cell", issue = "74465")] -impl UnwindSafe for SyncOnceCell {} - -#[unstable(feature = "once_cell", issue = "74465")] -impl Default for SyncOnceCell { - fn default() -> SyncOnceCell { - SyncOnceCell::new() - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl fmt::Debug for SyncOnceCell { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.get() { - Some(v) => f.debug_tuple("Once").field(v).finish(), - None => f.write_str("Once(Uninit)"), - } - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl Clone for SyncOnceCell { - fn clone(&self) -> SyncOnceCell { - let cell = Self::new(); - if let Some(value) = self.get() { - match cell.set(value.clone()) { - Ok(()) => (), - Err(_) => unreachable!(), - } - } - cell - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl From for SyncOnceCell { - fn from(value: T) -> Self { - let cell = Self::new(); - match cell.set(value) { - Ok(()) => cell, - Err(_) => unreachable!(), - } - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl PartialEq for SyncOnceCell { - fn eq(&self, other: &SyncOnceCell) -> bool { - self.get() == other.get() - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl Eq for SyncOnceCell {} - -impl SyncOnceCell { - /// Creates a new empty cell. - #[unstable(feature = "once_cell", issue = "74465")] - pub const fn new() -> SyncOnceCell { - SyncOnceCell { once: Once::new(), value: UnsafeCell::new(MaybeUninit::uninit()) } - } - - /// Gets the reference to the underlying value. - /// - /// Returns `None` if the cell is empty, or being initialized. This - /// method never blocks. - #[unstable(feature = "once_cell", issue = "74465")] - pub fn get(&self) -> Option<&T> { - if self.is_initialized() { - // Safe b/c checked is_initialized - Some(unsafe { self.get_unchecked() }) - } else { - None - } - } - - /// Gets the mutable reference to the underlying value. - /// - /// Returns `None` if the cell is empty. This method never blocks. - #[unstable(feature = "once_cell", issue = "74465")] - pub fn get_mut(&mut self) -> Option<&mut T> { - if self.is_initialized() { - // Safe b/c checked is_initialized and we have a unique access - Some(unsafe { self.get_unchecked_mut() }) - } else { - None - } - } - - /// Sets the contents of this cell to `value`. - /// - /// Returns `Ok(())` if the cell's value was updated. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::SyncOnceCell; - /// - /// static CELL: SyncOnceCell = SyncOnceCell::new(); - /// - /// fn main() { - /// assert!(CELL.get().is_none()); - /// - /// std::thread::spawn(|| { - /// assert_eq!(CELL.set(92), Ok(())); - /// }).join().unwrap(); - /// - /// assert_eq!(CELL.set(62), Err(62)); - /// assert_eq!(CELL.get(), Some(&92)); - /// } - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn set(&self, value: T) -> Result<(), T> { - let mut value = Some(value); - self.get_or_init(|| value.take().unwrap()); - match value { - None => Ok(()), - Some(value) => Err(value), - } - } - - /// Gets the contents of the cell, initializing it with `f` if the cell - /// was empty. - /// - /// Many threads may call `get_or_init` concurrently with different - /// initializing functions, but it is guaranteed that only one function - /// will be executed. - /// - /// # Panics - /// - /// If `f` panics, the panic is propagated to the caller, and the cell - /// remains uninitialized. - /// - /// It is an error to reentrantly initialize the cell from `f`. The - /// exact outcome is unspecified. Current implementation deadlocks, but - /// this may be changed to a panic in the future. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::SyncOnceCell; - /// - /// let cell = SyncOnceCell::new(); - /// let value = cell.get_or_init(|| 92); - /// assert_eq!(value, &92); - /// let value = cell.get_or_init(|| unreachable!()); - /// assert_eq!(value, &92); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn get_or_init(&self, f: F) -> &T - where - F: FnOnce() -> T, - { - match self.get_or_try_init(|| Ok::(f())) { - Ok(val) => val, - } - } - - /// Gets the contents of the cell, initializing it with `f` if - /// the cell was empty. If the cell was empty and `f` failed, an - /// error is returned. - /// - /// # Panics - /// - /// If `f` panics, the panic is propagated to the caller, and - /// the cell remains uninitialized. - /// - /// It is an error to reentrantly initialize the cell from `f`. - /// The exact outcome is unspecified. Current implementation - /// deadlocks, but this may be changed to a panic in the future. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::SyncOnceCell; - /// - /// let cell = SyncOnceCell::new(); - /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); - /// assert!(cell.get().is_none()); - /// let value = cell.get_or_try_init(|| -> Result { - /// Ok(92) - /// }); - /// assert_eq!(value, Ok(&92)); - /// assert_eq!(cell.get(), Some(&92)) - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn get_or_try_init(&self, f: F) -> Result<&T, E> - where - F: FnOnce() -> Result, - { - // Fast path check - // NOTE: We need to perform an acquire on the state in this method - // in order to correctly synchronize `SyncLazy::force`. This is - // currently done by calling `self.get()`, which in turn calls - // `self.is_initialized()`, which in turn performs the acquire. - if let Some(value) = self.get() { - return Ok(value); - } - self.initialize(f)?; - - debug_assert!(self.is_initialized()); - - // Safety: The inner value has been initialized - Ok(unsafe { self.get_unchecked() }) - } - - /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns - /// `None` if the cell was empty. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::SyncOnceCell; - /// - /// let cell: SyncOnceCell = SyncOnceCell::new(); - /// assert_eq!(cell.into_inner(), None); - /// - /// let cell = SyncOnceCell::new(); - /// cell.set("hello".to_string()).unwrap(); - /// assert_eq!(cell.into_inner(), Some("hello".to_string())); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn into_inner(mut self) -> Option { - // Safety: Safe because we immediately free `self` without dropping - let inner = unsafe { self.take_inner() }; - - // Don't drop this `SyncOnceCell`. We just moved out one of the fields, but didn't set - // the state to uninitialized. - mem::ManuallyDrop::new(self); - inner - } - - /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state. - /// - /// Has no effect and returns `None` if the `SyncOnceCell` hasn't been initialized. - /// - /// Safety is guaranteed by requiring a mutable reference. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::SyncOnceCell; - /// - /// let mut cell: SyncOnceCell = SyncOnceCell::new(); - /// assert_eq!(cell.take(), None); - /// - /// let mut cell = SyncOnceCell::new(); - /// cell.set("hello".to_string()).unwrap(); - /// assert_eq!(cell.take(), Some("hello".to_string())); - /// assert_eq!(cell.get(), None); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn take(&mut self) -> Option { - mem::take(self).into_inner() - } - - /// Takes the wrapped value out of a `SyncOnceCell`. - /// Afterwards the cell is no longer initialized. - /// - /// Safety: The cell must now be free'd WITHOUT dropping. No other usages of the cell - /// are valid. Only used by `into_inner` and `drop`. - unsafe fn take_inner(&mut self) -> Option { - // The mutable reference guarantees there are no other threads that can observe us - // taking out the wrapped value. - // Right after this function `self` is supposed to be freed, so it makes little sense - // to atomically set the state to uninitialized. - if self.is_initialized() { - let value = mem::replace(&mut self.value, UnsafeCell::new(MaybeUninit::uninit())); - Some(value.into_inner().assume_init()) - } else { - None - } - } - - #[inline] - fn is_initialized(&self) -> bool { - self.once.is_completed() - } - - #[cold] - fn initialize(&self, f: F) -> Result<(), E> - where - F: FnOnce() -> Result, - { - let mut res: Result<(), E> = Ok(()); - let slot = &self.value; - - // Ignore poisoning from other threads - // If another thread panics, then we'll be able to run our closure - self.once.call_once_force(|p| { - match f() { - Ok(value) => { - unsafe { (&mut *slot.get()).write(value) }; - } - Err(e) => { - res = Err(e); - - // Treat the underlying `Once` as poisoned since we - // failed to initialize our value. Calls - p.poison(); - } - } - }); - res - } - - /// Safety: The value must be initialized - unsafe fn get_unchecked(&self) -> &T { - debug_assert!(self.is_initialized()); - (&*self.value.get()).get_ref() - } - - /// Safety: The value must be initialized - unsafe fn get_unchecked_mut(&mut self) -> &mut T { - debug_assert!(self.is_initialized()); - (&mut *self.value.get()).get_mut() - } -} - -impl Drop for SyncOnceCell { - fn drop(&mut self) { - // Safety: The cell is being dropped, so it can't be accessed again - unsafe { self.take_inner() }; - } -} - -/// A value which is initialized on the first access. -/// -/// This type is a thread-safe `Lazy`, and can be used in statics. -/// -/// # Examples -/// -/// ``` -/// #![feature(once_cell)] -/// -/// use std::collections::HashMap; -/// -/// use std::lazy::SyncLazy; -/// -/// static HASHMAP: SyncLazy> = SyncLazy::new(|| { -/// println!("initializing"); -/// let mut m = HashMap::new(); -/// m.insert(13, "Spica".to_string()); -/// m.insert(74, "Hoyten".to_string()); -/// m -/// }); -/// -/// fn main() { -/// println!("ready"); -/// std::thread::spawn(|| { -/// println!("{:?}", HASHMAP.get(&13)); -/// }).join().unwrap(); -/// println!("{:?}", HASHMAP.get(&74)); -/// -/// // Prints: -/// // ready -/// // initializing -/// // Some("Spica") -/// // Some("Hoyten") -/// } -/// ``` -#[unstable(feature = "once_cell", issue = "74465")] -pub struct SyncLazy T> { - cell: SyncOnceCell, - init: Cell>, -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl fmt::Debug for SyncLazy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() - } -} - -// We never create a `&F` from a `&SyncLazy` so it is fine -// to not impl `Sync` for `F` -// we do create a `&mut Option` in `force`, but this is -// properly synchronized, so it only happens once -// so it also does not contribute to this impl. -#[unstable(feature = "once_cell", issue = "74465")] -unsafe impl Sync for SyncLazy where SyncOnceCell: Sync {} -// auto-derived `Send` impl is OK. - -#[unstable(feature = "once_cell", issue = "74465")] -impl RefUnwindSafe for SyncLazy where SyncOnceCell: RefUnwindSafe {} - -impl SyncLazy { - /// Creates a new lazy value with the given initializing - /// function. - #[unstable(feature = "once_cell", issue = "74465")] - pub const fn new(f: F) -> SyncLazy { - SyncLazy { cell: SyncOnceCell::new(), init: Cell::new(Some(f)) } - } -} - -impl T> SyncLazy { - /// Forces the evaluation of this lazy value and - /// returns a reference to result. This is equivalent - /// to the `Deref` impl, but is explicit. - /// - /// # Examples - /// - /// ``` - /// #![feature(once_cell)] - /// - /// use std::lazy::SyncLazy; - /// - /// let lazy = SyncLazy::new(|| 92); - /// - /// assert_eq!(SyncLazy::force(&lazy), &92); - /// assert_eq!(&*lazy, &92); - /// ``` - #[unstable(feature = "once_cell", issue = "74465")] - pub fn force(this: &SyncLazy) -> &T { - this.cell.get_or_init(|| match this.init.take() { - Some(f) => f(), - None => panic!("Lazy instance has previously been poisoned"), - }) - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl T> Deref for SyncLazy { - type Target = T; - fn deref(&self) -> &T { - SyncLazy::force(self) - } -} - -#[unstable(feature = "once_cell", issue = "74465")] -impl Default for SyncLazy { - /// Creates a new lazy value using `Default` as the initializing function. - fn default() -> SyncLazy { - SyncLazy::new(T::default) - } -} - -#[cfg(test)] -mod tests { - use crate::{ - lazy::{Lazy, SyncLazy, SyncOnceCell}, - panic, - sync::{ - atomic::{AtomicUsize, Ordering::SeqCst}, - mpsc::channel, - Mutex, - }, - }; - - #[test] - fn lazy_default() { - static CALLED: AtomicUsize = AtomicUsize::new(0); - - struct Foo(u8); - impl Default for Foo { - fn default() -> Self { - CALLED.fetch_add(1, SeqCst); - Foo(42) - } - } - - let lazy: Lazy> = <_>::default(); - - assert_eq!(CALLED.load(SeqCst), 0); - - assert_eq!(lazy.lock().unwrap().0, 42); - assert_eq!(CALLED.load(SeqCst), 1); - - lazy.lock().unwrap().0 = 21; - - assert_eq!(lazy.lock().unwrap().0, 21); - assert_eq!(CALLED.load(SeqCst), 1); - } - - #[test] - fn lazy_poisoning() { - let x: Lazy = Lazy::new(|| panic!("kaboom")); - for _ in 0..2 { - let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len())); - assert!(res.is_err()); - } - } - - // miri doesn't support threads - #[cfg(not(miri))] - fn spawn_and_wait(f: impl FnOnce() -> R + Send + 'static) -> R { - crate::thread::spawn(f).join().unwrap() - } - - #[cfg(not(miri))] - fn spawn(f: impl FnOnce() + Send + 'static) { - let _ = crate::thread::spawn(f); - } - - // "stub threads" for Miri - #[cfg(miri)] - fn spawn_and_wait(f: impl FnOnce() -> R + Send + 'static) -> R { - f(()) - } - - #[cfg(miri)] - fn spawn(f: impl FnOnce() + Send + 'static) { - f(()) - } - - #[test] - fn sync_once_cell() { - static ONCE_CELL: SyncOnceCell = SyncOnceCell::new(); - - assert!(ONCE_CELL.get().is_none()); - - spawn_and_wait(|| { - ONCE_CELL.get_or_init(|| 92); - assert_eq!(ONCE_CELL.get(), Some(&92)); - }); - - ONCE_CELL.get_or_init(|| panic!("Kabom!")); - assert_eq!(ONCE_CELL.get(), Some(&92)); - } - - #[test] - fn sync_once_cell_get_mut() { - let mut c = SyncOnceCell::new(); - assert!(c.get_mut().is_none()); - c.set(90).unwrap(); - *c.get_mut().unwrap() += 2; - assert_eq!(c.get_mut(), Some(&mut 92)); - } - - #[test] - fn sync_once_cell_get_unchecked() { - let c = SyncOnceCell::new(); - c.set(92).unwrap(); - unsafe { - assert_eq!(c.get_unchecked(), &92); - } - } - - #[test] - fn sync_once_cell_drop() { - static DROP_CNT: AtomicUsize = AtomicUsize::new(0); - struct Dropper; - impl Drop for Dropper { - fn drop(&mut self) { - DROP_CNT.fetch_add(1, SeqCst); - } - } - - let x = SyncOnceCell::new(); - spawn_and_wait(move || { - x.get_or_init(|| Dropper); - assert_eq!(DROP_CNT.load(SeqCst), 0); - drop(x); - }); - - assert_eq!(DROP_CNT.load(SeqCst), 1); - } - - #[test] - fn sync_once_cell_drop_empty() { - let x = SyncOnceCell::::new(); - drop(x); - } - - #[test] - fn clone() { - let s = SyncOnceCell::new(); - let c = s.clone(); - assert!(c.get().is_none()); - - s.set("hello".to_string()).unwrap(); - let c = s.clone(); - assert_eq!(c.get().map(String::as_str), Some("hello")); - } - - #[test] - fn get_or_try_init() { - let cell: SyncOnceCell = SyncOnceCell::new(); - assert!(cell.get().is_none()); - - let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); - assert!(res.is_err()); - assert!(!cell.is_initialized()); - assert!(cell.get().is_none()); - - assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); - - assert_eq!( - cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), - Ok(&"hello".to_string()) - ); - assert_eq!(cell.get(), Some(&"hello".to_string())); - } - - #[test] - fn from_impl() { - assert_eq!(SyncOnceCell::from("value").get(), Some(&"value")); - assert_ne!(SyncOnceCell::from("foo").get(), Some(&"bar")); - } - - #[test] - fn partialeq_impl() { - assert!(SyncOnceCell::from("value") == SyncOnceCell::from("value")); - assert!(SyncOnceCell::from("foo") != SyncOnceCell::from("bar")); - - assert!(SyncOnceCell::::new() == SyncOnceCell::new()); - assert!(SyncOnceCell::::new() != SyncOnceCell::from("value".to_owned())); - } - - #[test] - fn into_inner() { - let cell: SyncOnceCell = SyncOnceCell::new(); - assert_eq!(cell.into_inner(), None); - let cell = SyncOnceCell::new(); - cell.set("hello".to_string()).unwrap(); - assert_eq!(cell.into_inner(), Some("hello".to_string())); - } - - #[test] - fn sync_lazy_new() { - static CALLED: AtomicUsize = AtomicUsize::new(0); - static SYNC_LAZY: SyncLazy = SyncLazy::new(|| { - CALLED.fetch_add(1, SeqCst); - 92 - }); - - assert_eq!(CALLED.load(SeqCst), 0); - - spawn_and_wait(|| { - let y = *SYNC_LAZY - 30; - assert_eq!(y, 62); - assert_eq!(CALLED.load(SeqCst), 1); - }); - - let y = *SYNC_LAZY - 30; - assert_eq!(y, 62); - assert_eq!(CALLED.load(SeqCst), 1); - } - - #[test] - fn sync_lazy_default() { - static CALLED: AtomicUsize = AtomicUsize::new(0); - - struct Foo(u8); - impl Default for Foo { - fn default() -> Self { - CALLED.fetch_add(1, SeqCst); - Foo(42) - } - } - - let lazy: SyncLazy> = <_>::default(); - - assert_eq!(CALLED.load(SeqCst), 0); - - assert_eq!(lazy.lock().unwrap().0, 42); - assert_eq!(CALLED.load(SeqCst), 1); - - lazy.lock().unwrap().0 = 21; - - assert_eq!(lazy.lock().unwrap().0, 21); - assert_eq!(CALLED.load(SeqCst), 1); - } - - #[test] - #[cfg_attr(miri, ignore)] // leaks memory - fn static_sync_lazy() { - static XS: SyncLazy> = SyncLazy::new(|| { - let mut xs = Vec::new(); - xs.push(1); - xs.push(2); - xs.push(3); - xs - }); - - spawn_and_wait(|| { - assert_eq!(&*XS, &vec![1, 2, 3]); - }); - - assert_eq!(&*XS, &vec![1, 2, 3]); - } - - #[test] - #[cfg_attr(miri, ignore)] // leaks memory - fn static_sync_lazy_via_fn() { - fn xs() -> &'static Vec { - static XS: SyncOnceCell> = SyncOnceCell::new(); - XS.get_or_init(|| { - let mut xs = Vec::new(); - xs.push(1); - xs.push(2); - xs.push(3); - xs - }) - } - assert_eq!(xs(), &vec![1, 2, 3]); - } - - #[test] - fn sync_lazy_poisoning() { - let x: SyncLazy = SyncLazy::new(|| panic!("kaboom")); - for _ in 0..2 { - let res = panic::catch_unwind(|| x.len()); - assert!(res.is_err()); - } - } - - #[test] - fn is_sync_send() { - fn assert_traits() {} - assert_traits::>(); - assert_traits::>(); - } - - #[test] - fn eval_once_macro() { - macro_rules! eval_once { - (|| -> $ty:ty { - $($body:tt)* - }) => {{ - static ONCE_CELL: SyncOnceCell<$ty> = SyncOnceCell::new(); - fn init() -> $ty { - $($body)* - } - ONCE_CELL.get_or_init(init) - }}; - } - - let fib: &'static Vec = eval_once! { - || -> Vec { - let mut res = vec![1, 1]; - for i in 0..10 { - let next = res[i] + res[i + 1]; - res.push(next); - } - res - } - }; - assert_eq!(fib[5], 8) - } - - #[test] - #[cfg_attr(miri, ignore)] // deadlocks without real threads - fn sync_once_cell_does_not_leak_partially_constructed_boxes() { - static ONCE_CELL: SyncOnceCell = SyncOnceCell::new(); - - let n_readers = 10; - let n_writers = 3; - const MSG: &str = "Hello, World"; - - let (tx, rx) = channel(); - - for _ in 0..n_readers { - let tx = tx.clone(); - spawn(move || { - loop { - if let Some(msg) = ONCE_CELL.get() { - tx.send(msg).unwrap(); - break; - } - } - }); - } - for _ in 0..n_writers { - spawn(move || { - let _ = ONCE_CELL.set(MSG.to_owned()); - }); - } - - for _ in 0..n_readers { - let msg = rx.recv().unwrap(); - assert_eq!(msg, MSG); - } - } -} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 02de3fff29f87..54fc35b20f7c9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -224,7 +224,10 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform, ptr_wrapping_offset_from) )] -#![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))] +#![cfg_attr( + all(test, target_vendor = "fortanix", target_env = "sgx"), + feature(fixed_size_array, maybe_uninit_extra) +)] // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. @@ -284,7 +287,6 @@ #![feature(linkage)] #![feature(llvm_asm)] #![feature(log_syntax)] -#![feature(maybe_uninit_extra)] #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(min_specialization)] @@ -292,7 +294,6 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(nll)] -#![feature(once_cell)] #![feature(optin_builtin_traits)] #![feature(or_patterns)] #![feature(panic_info_message)] @@ -302,7 +303,6 @@ #![feature(ptr_internals)] #![feature(raw)] #![feature(raw_ref_macros)] -#![feature(ready_macro)] #![feature(renamed_spin_loop)] #![feature(rustc_attrs)] #![feature(rustc_private)] @@ -477,9 +477,6 @@ pub mod process; pub mod sync; pub mod time; -#[unstable(feature = "once_cell", issue = "74465")] -pub mod lazy; - #[stable(feature = "futures_api", since = "1.36.0")] pub mod task { //! Types and Traits for working with asynchronous tasks. @@ -511,10 +508,6 @@ mod panicking; // compiler pub mod rt; -#[path = "../backtrace/src/lib.rs"] -#[allow(dead_code, unused_attributes)] -mod backtrace_rs; - // Pull in the `std_detect` crate directly into libstd. The contents of // `std_detect` are in a different repository: rust-lang/stdarch. // diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index ab2a60103069d..9542e7209b4cf 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -171,7 +171,7 @@ fn default_hook(info: &PanicInfo<'_>) { // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. let backtrace_env = if panic_count::get() >= 2 { - RustBacktrace::Print(crate::backtrace_rs::PrintFmt::Full) + RustBacktrace::Print(backtrace_rs::PrintFmt::Full) } else { backtrace::rust_backtrace_env() }; diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 64260990824b8..7dc822db3d027 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -132,7 +132,6 @@ unsafe impl Send for Once {} #[derive(Debug)] pub struct OnceState { poisoned: bool, - set_state_on_drop_to: Cell, } /// Initialization value for static [`Once`] values. @@ -322,7 +321,7 @@ impl Once { } let mut f = Some(f); - self.call_inner(true, &mut |p| f.take().unwrap()(p)); + self.call_inner(true, &mut |p| f.take().unwrap()(&OnceState { poisoned: p })); } /// Returns `true` if some `call_once` call has completed @@ -386,7 +385,7 @@ impl Once { // currently no way to take an `FnOnce` and call it via virtual dispatch // without some allocation overhead. #[cold] - fn call_inner(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&OnceState)) { + fn call_inner(&self, ignore_poisoning: bool, init: &mut dyn FnMut(bool)) { let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire); loop { match state_and_queue { @@ -414,12 +413,8 @@ impl Once { }; // Run the initialization function, letting it know if we're // poisoned or not. - let init_state = OnceState { - poisoned: state_and_queue == POISONED, - set_state_on_drop_to: Cell::new(COMPLETE), - }; - init(&init_state); - waiter_queue.set_state_on_drop_to = init_state.set_state_on_drop_to.get(); + init(state_and_queue == POISONED); + waiter_queue.set_state_on_drop_to = COMPLETE; break; } _ => { @@ -559,14 +554,6 @@ impl OnceState { pub fn poisoned(&self) -> bool { self.poisoned } - - /// Poison the associated [`Once`] without explicitly panicking. - /// - /// [`Once`]: struct.Once.html - // NOTE: This is currently only exposed for the `lazy` module - pub(crate) fn poison(&self) { - self.set_state_on_drop_to.set(POISONED); - } } #[cfg(all(test, not(target_os = "emscripten")))] diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 0f349dfa30216..371291b9f76ab 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -84,12 +84,12 @@ impl Command { Ok(0) => return Ok((p, ours)), Ok(8) => { let (errno, footer) = bytes.split_at(4); - assert_eq!( - CLOEXEC_MSG_FOOTER, footer, + assert!( + combine(CLOEXEC_MSG_FOOTER) == combine(footer.try_into().unwrap()), "Validation on the CLOEXEC pipe failed: {:?}", bytes ); - let errno = i32::from_be_bytes(errno.try_into().unwrap()); + let errno = combine(errno.try_into().unwrap()); assert!(p.wait().is_ok(), "wait() should either return Ok or panic"); return Err(Error::from_raw_os_error(errno)); } @@ -105,6 +105,10 @@ impl Command { } } } + + fn combine(arr: [u8; 4]) -> i32 { + i32::from_be_bytes(arr) + } } pub fn exec(&mut self, default: Stdio) -> io::Error { diff --git a/src/libstd/sys/wasi/ext/mod.rs b/src/libstd/sys/wasi/ext/mod.rs index 58c8c46c969c1..5f8b1cbfa0b53 100644 --- a/src/libstd/sys/wasi/ext/mod.rs +++ b/src/libstd/sys/wasi/ext/mod.rs @@ -18,5 +18,5 @@ pub mod prelude { pub use crate::sys::ext::fs::{DirEntryExt, FileExt, MetadataExt, OpenOptionsExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use crate::sys::ext::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; + pub use crate::sys::ext::io::{AsRawFd, FromRawFd, IntoRawFd}; } diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index d386a656e4ffd..e9b1e86d7ae49 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -1,4 +1,3 @@ -use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt}; use crate::borrow::Cow; /// Common code for printing the backtrace in the same way across the different /// supported platforms. @@ -10,6 +9,8 @@ use crate::path::{self, Path, PathBuf}; use crate::sync::atomic::{self, Ordering}; use crate::sys::mutex::Mutex; +use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt}; + /// Max number of frames to print. const MAX_NB_FRAMES: usize = 100; diff --git a/src/rustllvm/CoverageMappingWrapper.cpp b/src/rustllvm/CoverageMappingWrapper.cpp deleted file mode 100644 index c6c4cdb5562f8..0000000000000 --- a/src/rustllvm/CoverageMappingWrapper.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "rustllvm.h" -#include "llvm/ProfileData/Coverage/CoverageMapping.h" -#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ADT/ArrayRef.h" - -#include - -using namespace llvm; - -extern "C" SmallVectorTemplateBase - *LLVMRustCoverageSmallVectorCounterExpressionCreate() { - return new SmallVector(); -} - -extern "C" void LLVMRustCoverageSmallVectorCounterExpressionDispose( - SmallVectorTemplateBase *Vector) { - delete Vector; -} - -extern "C" void LLVMRustCoverageSmallVectorCounterExpressionAdd( - SmallVectorTemplateBase *Expressions, - coverage::CounterExpression::ExprKind Kind, - unsigned LeftIndex, - unsigned RightIndex) { - auto LHS = coverage::Counter::getCounter(LeftIndex); - auto RHS = coverage::Counter::getCounter(RightIndex); - Expressions->push_back(coverage::CounterExpression { Kind, LHS, RHS }); -} - -extern "C" SmallVectorTemplateBase - *LLVMRustCoverageSmallVectorCounterMappingRegionCreate() { - return new SmallVector(); -} - -extern "C" void LLVMRustCoverageSmallVectorCounterMappingRegionDispose( - SmallVectorTemplateBase *Vector) { - delete Vector; -} - -extern "C" void LLVMRustCoverageSmallVectorCounterMappingRegionAdd( - SmallVectorTemplateBase *MappingRegions, - unsigned Index, - unsigned FileID, - unsigned LineStart, - unsigned ColumnStart, - unsigned LineEnd, - unsigned ColumnEnd) { - auto Counter = coverage::Counter::getCounter(Index); - MappingRegions->push_back(coverage::CounterMappingRegion::makeRegion( - Counter, FileID, LineStart, - ColumnStart, LineEnd, ColumnEnd)); - - // FIXME(richkadel): As applicable, implement additional CounterMappingRegion types using the - // static method alternatives to `coverage::CounterMappingRegion::makeRegion`: - // - // makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, - // unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { - // makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, - // unsigned LineEnd, unsigned ColumnEnd) { - // makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, - // unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { -} - -extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( - const char* const Filenames[], - size_t FilenamesLen, - RustStringRef BufferOut) { - SmallVector FilenameRefs; - for (size_t i = 0; i < FilenamesLen; i++) { - FilenameRefs.push_back(StringRef(Filenames[i])); - } - auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter( - makeArrayRef(FilenameRefs)); - RawRustStringOstream OS(BufferOut); - FilenamesWriter.write(OS); -} - -extern "C" void LLVMRustCoverageWriteMappingToBuffer( - const unsigned *VirtualFileMappingIDs, - unsigned NumVirtualFileMappingIDs, - const SmallVectorImpl *Expressions, - SmallVectorImpl *MappingRegions, - RustStringRef BufferOut) { - auto CoverageMappingWriter = coverage::CoverageMappingWriter( - makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs), - makeArrayRef(*Expressions), - MutableArrayRef { *MappingRegions }); - RawRustStringOstream OS(BufferOut); - CoverageMappingWriter.write(OS); -} - -extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) { - StringRef NameRef(Name); - return IndexedInstrProf::ComputeHash(NameRef); -} - -extern "C" void LLVMRustCoverageWriteSectionNameToString(LLVMModuleRef M, - RustStringRef Str) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - auto name = getInstrProfSectionName(IPSK_covmap, - TargetTriple.getObjectFormat()); - RawRustStringOstream OS(Str); - OS << name; -} - -extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { - auto name = getCoverageMappingVarName(); - RawRustStringOstream OS(Str); - OS << name; -} - -extern "C" uint32_t LLVMRustCoverageMappingVersion() { - return coverage::CovMapVersion::CurrentVersion; -} diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 667bf4a2ded37..c92cf65f98af7 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1395,7 +1395,7 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles)); } -extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { +extern "C" LLVMValueRef LLVMRustGetInstrprofIncrementIntrinsic(LLVMModuleRef M) { return wrap(llvm::Intrinsic::getDeclaration(unwrap(M), (llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment)); } diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 57b8664d3b605..da48048113bc2 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -3,7 +3,6 @@ #include "llvm-c/Object.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/Lint.h" #include "llvm/Analysis/Passes.h" diff --git a/src/test/codegen-units/item-collection/static-init.rs b/src/test/codegen-units/item-collection/static-init.rs index aebccff01fc69..f6005eed43c7d 100644 --- a/src/test/codegen-units/item-collection/static-init.rs +++ b/src/test/codegen-units/item-collection/static-init.rs @@ -6,7 +6,7 @@ pub static FN : fn() = foo::; pub fn foo() { } -//~ MONO_ITEM fn static_init::foo[0] +//~ MONO_ITEM fn static_init::foo[0] //~ MONO_ITEM static static_init::FN[0] //~ MONO_ITEM fn static_init::start[0] diff --git a/src/test/codegen-units/item-collection/trait-method-default-impl.rs b/src/test/codegen-units/item-collection/trait-method-default-impl.rs index abe2d108eae7d..11f6cc62d49e3 100644 --- a/src/test/codegen-units/item-collection/trait-method-default-impl.rs +++ b/src/test/codegen-units/item-collection/trait-method-default-impl.rs @@ -27,7 +27,7 @@ impl SomeGenericTrait for i32 { // For the non-generic foo(), we should generate a codegen-item even if it // is not called anywhere - //~ MONO_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0] + //~ MONO_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0] } // Non-generic impl of generic trait diff --git a/src/test/codegen-units/polymorphization/unused_type_parameters.rs b/src/test/codegen-units/polymorphization/unused_type_parameters.rs deleted file mode 100644 index dc2ad0559b34f..0000000000000 --- a/src/test/codegen-units/polymorphization/unused_type_parameters.rs +++ /dev/null @@ -1,323 +0,0 @@ -// compile-flags:-Zprint-mono-items=lazy -Copt-level=1 -// ignore-tidy-linelength - -#![crate_type = "rlib"] - -// This test checks that the polymorphization analysis correctly reduces the -// generated mono items. - -mod functions { - // Function doesn't have any type parameters to be unused. - pub fn no_parameters() {} - -//~ MONO_ITEM fn unused_type_parameters::functions[0]::no_parameters[0] - - // Function has an unused type parameter. - pub fn unused() { - } - -//~ MONO_ITEM fn unused_type_parameters::functions[0]::unused[0] - - // Function uses type parameter in value of a binding. - pub fn used_binding_value() { - let _: T = Default::default(); - } - -//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_binding_value[0] -//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_binding_value[0] - - // Function uses type parameter in type of a binding. - pub fn used_binding_type() { - let _: Option = None; - } - -//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_binding_type[0] -//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_binding_type[0] - - // Function uses type parameter in argument. - pub fn used_argument(_: T) { - } - -//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_argument[0] -//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_argument[0] -// - // Function uses type parameter in substitutions to another function. - pub fn used_substs() { - unused::() - } - -//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_substs[0] -//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_substs[0] -} - - -mod closures { - // Function doesn't have any type parameters to be unused. - pub fn no_parameters() { - let _ = || {}; - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::no_parameters[0] - - // Function has an unused type parameter in parent and closure. - pub fn unused() -> u32 { - let add_one = |x: u32| x + 1; - add_one(3) - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::unused[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::unused[0] - - // Function has an unused type parameter in closure, but not in parent. - pub fn used_parent() -> u32 { - let _: T = Default::default(); - let add_one = |x: u32| x + 1; - add_one(3) - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_parent[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_parent[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_parent[0] - - // Function uses type parameter in value of a binding in closure. - pub fn used_binding_value() -> T { - let x = || { - let y: T = Default::default(); - y - }; - - x() - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_value[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_value[0]::{{closure}}[0] u64, ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_value[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_value[0] - - // Function uses type parameter in type of a binding in closure. - pub fn used_binding_type() -> Option { - let x = || { - let y: Option = None; - y - }; - - x() - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_type[0]::{{closure}}[0] core::option[0]::Option[0], ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_type[0]::{{closure}}[0] core::option[0]::Option[0], ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_type[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_type[0] - - // Function and closure uses type parameter in argument. - pub fn used_argument(t: T) -> u32 { - let x = |_: T| 3; - x(t) - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument[0] - - // Closure uses type parameter in argument. - pub fn used_argument_closure() -> u32 { - let t: T = Default::default(); - let x = |_: T| 3; - x(t) - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument_closure[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument_closure[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument_closure[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument_closure[0] - - // Closure uses type parameter as upvar. - pub fn used_upvar() -> T { - let x: T = Default::default(); - let y = || x; - y() - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_upvar[0]::{{closure}}[0] u32, (u32)> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_upvar[0]::{{closure}}[0] u64, (u64)> -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_upvar[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_upvar[0] - - // Closure uses type parameter in substitutions to another function. - pub fn used_substs() { - let x = || super::functions::unused::(); - x() - } - -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_substs[0]::{{closure}}[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_substs[0]::{{closure}}[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_substs[0] -//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_substs[0] -} - -mod methods { - pub struct Foo(F); - - impl Foo { - // Function has an unused type parameter from impl. - pub fn unused_impl() { - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::unused_impl[0] - - // Function has an unused type parameter from impl and fn. - pub fn unused_both() { - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::unused_both[0] - - // Function uses type parameter from impl. - pub fn used_impl() { - let _: F = Default::default(); - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_impl[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_impl[0] - - // Function uses type parameter from impl. - pub fn used_fn() { - let _: G = Default::default(); - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_fn[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_fn[0] - - // Function uses type parameter from impl. - pub fn used_both() { - let _: F = Default::default(); - let _: G = Default::default(); - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_both[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_both[0] - - // Function uses type parameter in substitutions to another function. - pub fn used_substs() { - super::functions::unused::() - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_substs[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_substs[0] - - // Function has an unused type parameter from impl and fn. - pub fn closure_unused_all() -> u32 { - let add_one = |x: u32| x + 1; - add_one(3) - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_unused_all[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_unused_all[0] - - // Function uses type parameter from impl and fn in closure. - pub fn closure_used_both() -> u32 { - let add_one = |x: u32| { - let _: F = Default::default(); - let _: G = Default::default(); - x + 1 - }; - - add_one(3) - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_both[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_both[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_both[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_both[0] - - // Function uses type parameter from fn in closure. - pub fn closure_used_fn() -> u32 { - let add_one = |x: u32| { - let _: G = Default::default(); - x + 1 - }; - - add_one(3) - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_fn[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_fn[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_fn[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_fn[0] - - // Function uses type parameter from impl in closure. - pub fn closure_used_impl() -> u32 { - let add_one = |x: u32| { - let _: F = Default::default(); - x + 1 - }; - - add_one(3) - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_impl[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_impl[0]::{{closure}}[0] u32, ()> -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_impl[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_impl[0] - - // Closure uses type parameter in substitutions to another function. - pub fn closure_used_substs() { - let x = || super::functions::unused::(); - x() - } - -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_substs[0]::{{closure}}[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_substs[0]::{{closure}}[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_substs[0] -//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_substs[0] - } -} - - - -fn dispatch() { - functions::no_parameters(); - functions::unused::(); - functions::used_binding_value::(); - functions::used_binding_type::(); - functions::used_argument::(Default::default()); - functions::used_substs::(); - - closures::no_parameters(); - let _ = closures::unused::(); - let _ = closures::used_parent::(); - let _ = closures::used_binding_value::(); - let _ = closures::used_binding_type::(); - let _ = closures::used_argument::(Default::default()); - let _ = closures::used_argument_closure::(); - let _ = closures::used_upvar::(); - let _ = closures::used_substs::(); - - methods::Foo::::unused_impl(); - methods::Foo::::unused_both::(); - methods::Foo::::used_impl(); - methods::Foo::::used_fn::(); - methods::Foo::::used_both::(); - methods::Foo::::used_substs(); - let _ = methods::Foo::::closure_unused_all::(); - let _ = methods::Foo::::closure_used_both::(); - let _ = methods::Foo::::closure_used_impl::(); - let _ = methods::Foo::::closure_used_fn::(); - let _ = methods::Foo::::closure_used_substs(); -} - -//~ MONO_ITEM fn unused_type_parameters::dispatch[0] -//~ MONO_ITEM fn unused_type_parameters::dispatch[0] - -pub fn foo() { - // Generate two copies of each function to check that where the type parameter is unused, - // there is only a single copy. - dispatch::(); - dispatch::(); -} - -//~ MONO_ITEM fn unused_type_parameters::foo[0] @@ unused_type_parameters-cgu.0[External] - -// These are all the items that aren't relevant to the test. -//~ MONO_ITEM fn core::default[0]::{{impl}}[6]::default[0] -//~ MONO_ITEM fn core::default[0]::{{impl}}[7]::default[0] diff --git a/src/test/codegen/atomic-operations.rs b/src/test/codegen/atomic-operations.rs deleted file mode 100644 index ff94ac8543f8b..0000000000000 --- a/src/test/codegen/atomic-operations.rs +++ /dev/null @@ -1,60 +0,0 @@ -// Code generation of atomic operations. -// -// compile-flags: -O -#![crate_type = "lib"] - -use std::sync::atomic::{AtomicI32, Ordering::*}; - -// CHECK-LABEL: @compare_exchange -#[no_mangle] -pub fn compare_exchange(a: &AtomicI32) { - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 10 monotonic monotonic - let _ = a.compare_exchange(0, 10, Relaxed, Relaxed); - - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 20 release monotonic - let _ = a.compare_exchange(0, 20, Release, Relaxed); - - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 30 acquire monotonic - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 31 acquire acquire - let _ = a.compare_exchange(0, 30, Acquire, Relaxed); - let _ = a.compare_exchange(0, 31, Acquire, Acquire); - - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 40 acq_rel monotonic - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 41 acq_rel acquire - let _ = a.compare_exchange(0, 40, AcqRel, Relaxed); - let _ = a.compare_exchange(0, 41, AcqRel, Acquire); - - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 50 seq_cst monotonic - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 51 seq_cst acquire - // CHECK: cmpxchg i32* %{{.*}}, i32 0, i32 52 seq_cst seq_cst - let _ = a.compare_exchange(0, 50, SeqCst, Relaxed); - let _ = a.compare_exchange(0, 51, SeqCst, Acquire); - let _ = a.compare_exchange(0, 52, SeqCst, SeqCst); -} - -// CHECK-LABEL: @compare_exchange_weak -#[no_mangle] -pub fn compare_exchange_weak(w: &AtomicI32) { - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 10 monotonic monotonic - let _ = w.compare_exchange_weak(1, 10, Relaxed, Relaxed); - - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 20 release monotonic - let _ = w.compare_exchange_weak(1, 20, Release, Relaxed); - - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 30 acquire monotonic - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 31 acquire acquire - let _ = w.compare_exchange_weak(1, 30, Acquire, Relaxed); - let _ = w.compare_exchange_weak(1, 31, Acquire, Acquire); - - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 40 acq_rel monotonic - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 41 acq_rel acquire - let _ = w.compare_exchange_weak(1, 40, AcqRel, Relaxed); - let _ = w.compare_exchange_weak(1, 41, AcqRel, Acquire); - - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 50 seq_cst monotonic - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 51 seq_cst acquire - // CHECK: cmpxchg weak i32* %{{.*}}, i32 1, i32 52 seq_cst seq_cst - let _ = w.compare_exchange_weak(1, 50, SeqCst, Relaxed); - let _ = w.compare_exchange_weak(1, 51, SeqCst, Acquire); - let _ = w.compare_exchange_weak(1, 52, SeqCst, SeqCst); -} diff --git a/src/test/compile-fail/empty-extern-arg.rs b/src/test/compile-fail/empty-extern-arg.rs index d3cb5aaaeba89..ae28fcad903be 100644 --- a/src/test/compile-fail/empty-extern-arg.rs +++ b/src/test/compile-fail/empty-extern-arg.rs @@ -1,4 +1,4 @@ // compile-flags: --extern std= -// error-pattern: extern location for std does not exist +// error-pattern: can't find crate for `std` fn main() {} diff --git a/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff index e7fef4622b1c6..af2899c887a94 100644 --- a/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff +++ b/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff @@ -3,40 +3,34 @@ fn bar() -> bool { let mut _0: bool; // return place in scope 0 at $DIR/instrument_coverage.rs:18:13: 18:17 -+ let mut _1: (); // in scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18 ++ let mut _1: (); // in scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2 bb0: { -+ StorageLive(_1); // scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18 -+ _1 = const std::intrinsics::count_code_region(const 10208505205182607101_u64, const 0_u32, const 501_u32, const 513_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18 ++ StorageLive(_1); // scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2 ++ _1 = const std::intrinsics::count_code_region(const 0_u32, const 484_u32, const 513_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2 + // ty::Const -+ // + ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region} ++ // + ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region} + // + val: Value(Scalar()) + // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18 -+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar()) } -+ // ty::Const -+ // + ty: u64 -+ // + val: Value(Scalar(0x8dabe565aaa2aefd)) -+ // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18 -+ // + literal: Const { ty: u64, val: Value(Scalar(0x8dabe565aaa2aefd)) } ++ // + span: $DIR/instrument_coverage.rs:18:1: 18:1 ++ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar()) } + // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18 ++ // + span: $DIR/instrument_coverage.rs:18:1: 18:1 + // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) } + // ty::Const + // + ty: u32 -+ // + val: Value(Scalar(0x000001f5)) ++ // + val: Value(Scalar(0x000001e4)) + // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18 -+ // + literal: Const { ty: u32, val: Value(Scalar(0x000001f5)) } ++ // + span: $DIR/instrument_coverage.rs:18:1: 18:1 ++ // + literal: Const { ty: u32, val: Value(Scalar(0x000001e4)) } + // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x00000201)) + // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:18:18: 18:18 ++ // + span: $DIR/instrument_coverage.rs:18:1: 18:1 + // + literal: Const { ty: u32, val: Value(Scalar(0x00000201)) } + } + diff --git a/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff index 51378c216da64..4a300230f8a97 100644 --- a/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff +++ b/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff @@ -6,41 +6,35 @@ let mut _1: (); // in scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2 let mut _2: bool; // in scope 0 at $DIR/instrument_coverage.rs:11:12: 11:17 let mut _3: !; // in scope 0 at $DIR/instrument_coverage.rs:11:18: 13:10 -+ let mut _4: (); // in scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11 ++ let mut _4: (); // in scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2 bb0: { - falseUnwind -> [real: bb1, cleanup: bb2]; // scope 0 at $DIR/instrument_coverage.rs:10:5: 14:6 -+ StorageLive(_4); // scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11 -+ _4 = const std::intrinsics::count_code_region(const 16004455475339839479_u64, const 0_u32, const 397_u32, const 465_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11 ++ StorageLive(_4); // scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2 ++ _4 = const std::intrinsics::count_code_region(const 0_u32, const 387_u32, const 465_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2 + // ty::Const -+ // + ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region} ++ // + ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region} + // + val: Value(Scalar()) + // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11 -+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar()) } -+ // ty::Const -+ // + ty: u64 -+ // + val: Value(Scalar(0xde1b3f75a72fc7f7)) -+ // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11 -+ // + literal: Const { ty: u64, val: Value(Scalar(0xde1b3f75a72fc7f7)) } ++ // + span: $DIR/instrument_coverage.rs:9:1: 9:1 ++ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar()) } + // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11 ++ // + span: $DIR/instrument_coverage.rs:9:1: 9:1 + // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) } + // ty::Const + // + ty: u32 -+ // + val: Value(Scalar(0x0000018d)) ++ // + val: Value(Scalar(0x00000183)) + // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11 -+ // + literal: Const { ty: u32, val: Value(Scalar(0x0000018d)) } ++ // + span: $DIR/instrument_coverage.rs:9:1: 9:1 ++ // + literal: Const { ty: u32, val: Value(Scalar(0x00000183)) } + // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x000001d1)) + // mir::Constant -+ // + span: $DIR/instrument_coverage.rs:9:11: 9:11 ++ // + span: $DIR/instrument_coverage.rs:9:1: 9:1 + // + literal: Const { ty: u32, val: Value(Scalar(0x000001d1)) } } diff --git a/src/test/run-make-fulldeps/instrument-coverage/Makefile b/src/test/run-make-fulldeps/instrument-coverage/Makefile deleted file mode 100644 index df47305b547a8..0000000000000 --- a/src/test/run-make-fulldeps/instrument-coverage/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# needs-profiler-support -# ignore-msvc - -# FIXME(richkadel): Debug the following problem, and reenable on Windows (by -# removing the `# ignore-msvc` directive above). The current implementation -# generates a segfault when running the instrumented `main` executable, -# after the `main` program code executes, but before the process terminates. -# This most likely points to a problem generating the LLVM "main.profraw" -# file. - --include ../tools.mk - -# This test makes sure that LLVM coverage maps are genereated in LLVM IR. - -COMMON_FLAGS=-Zinstrument-coverage - -all: - # Compile the test program with instrumentation, and also generate LLVM IR - $(RUSTC) $(COMMON_FLAGS) main.rs - - # Run it in order to generate some profiling data, - # with `LLVM_PROFILE_FILE=` environment variable set to - # output the coverage stats for this run. - LLVM_PROFILE_FILE="$(TMPDIR)"/main.profraw \ - $(call RUN,main) - - # Postprocess the profiling data so it can be used by the llvm-cov tool - "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \ - "$(TMPDIR)"/main.profraw \ - -o "$(TMPDIR)"/main.profdata - - # Generate a coverage report using `llvm-cov show`. The output ordering - # can be non-deterministic, so ignore the return status. If the test fails - # when comparing the JSON `export`, the `show` output may be useful when - # debugging. - "$(LLVM_BIN_DIR)"/llvm-cov show \ - --Xdemangler="$(RUST_DEMANGLER)" \ - --show-line-counts-or-regions \ - --instr-profile="$(TMPDIR)"/main.profdata \ - $(call BIN,"$(TMPDIR)"/main) \ - > "$(TMPDIR)"/actual_show_coverage.txt - - # Compare the show coverage output - $(DIFF) typical_show_coverage.txt "$(TMPDIR)"/actual_show_coverage.txt || \ - >&2 echo 'diff failed for `llvm-cov show` (might not be an error)' - - # Generate a coverage report in JSON, using `llvm-cov export`, and fail if - # there are differences from the expected output. - "$(LLVM_BIN_DIR)"/llvm-cov export \ - --summary-only \ - --instr-profile="$(TMPDIR)"/main.profdata \ - $(call BIN,"$(TMPDIR)"/main) \ - | "$(PYTHON)" prettify_json.py \ - > "$(TMPDIR)"/actual_export_coverage.json - - # Check that the exported JSON coverage data matches what we expect - $(DIFF) expected_export_coverage.json "$(TMPDIR)"/actual_export_coverage.json diff --git a/src/test/run-make-fulldeps/instrument-coverage/expected_export_coverage.json b/src/test/run-make-fulldeps/instrument-coverage/expected_export_coverage.json deleted file mode 100644 index 9d739a89114e2..0000000000000 --- a/src/test/run-make-fulldeps/instrument-coverage/expected_export_coverage.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "data": [ - { - "files": [ - { - "filename": "main.rs", - "summary": { - "functions": { - "count": 7, - "covered": 5, - "percent": 71.42857142857143 - }, - "instantiations": { - "count": 8, - "covered": 6, - "percent": 75 - }, - "lines": { - "count": 30, - "covered": 25, - "percent": 83.33333333333334 - }, - "regions": { - "count": 7, - "covered": 5, - "notcovered": 2, - "percent": 71.42857142857143 - } - } - } - ], - "totals": { - "functions": { - "count": 7, - "covered": 5, - "percent": 71.42857142857143 - }, - "instantiations": { - "count": 8, - "covered": 6, - "percent": 75 - }, - "lines": { - "count": 30, - "covered": 25, - "percent": 83.33333333333334 - }, - "regions": { - "count": 7, - "covered": 5, - "notcovered": 2, - "percent": 71.42857142857143 - } - } - } - ], - "type": "llvm.coverage.json.export", - "version": "2.0.0" -} diff --git a/src/test/run-make-fulldeps/instrument-coverage/main.rs b/src/test/run-make-fulldeps/instrument-coverage/main.rs deleted file mode 100644 index 358c25677ae1d..0000000000000 --- a/src/test/run-make-fulldeps/instrument-coverage/main.rs +++ /dev/null @@ -1,38 +0,0 @@ -pub fn will_be_called() -> &'static str { - let val = "called"; - println!("{}", val); - val -} - -pub fn will_not_be_called() -> bool { - println!("should not have been called"); - false -} - -pub fn print(left: &str, value: T, right: &str) -where - T: std::fmt::Display, -{ - println!("{}{}{}", left, value, right); -} - -pub fn wrap_with(inner: T, should_wrap: bool, wrapper: F) -where - F: FnOnce(&T) -{ - if should_wrap { - wrapper(&inner) - } -} - -fn main() { - let less = 1; - let more = 100; - - if less < more { - wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** ")); - wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** ")); - } else { - wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, "")); - } -} diff --git a/src/test/run-make-fulldeps/instrument-coverage/prettify_json.py b/src/test/run-make-fulldeps/instrument-coverage/prettify_json.py deleted file mode 100644 index ed9279841f70e..0000000000000 --- a/src/test/run-make-fulldeps/instrument-coverage/prettify_json.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python - -import sys -import json - -# Try to decode line in order to ensure it is a valid JSON document -for line in sys.stdin: - parsed = json.loads(line) - print (json.dumps(parsed, indent=2, separators=(',', ': '), sort_keys=True)) diff --git a/src/test/run-make-fulldeps/instrument-coverage/typical_show_coverage.txt b/src/test/run-make-fulldeps/instrument-coverage/typical_show_coverage.txt deleted file mode 100644 index 9c593d0809d48..0000000000000 --- a/src/test/run-make-fulldeps/instrument-coverage/typical_show_coverage.txt +++ /dev/null @@ -1,55 +0,0 @@ - 1| 2|pub fn will_be_called() -> &'static str { - 2| 2| let val = "called"; - 3| 2| println!("{}", val); - 4| 2| val - 5| 2|} - 6| | - 7| 0|pub fn will_not_be_called() -> bool { - 8| 0| println!("should not have been called"); - 9| 0| false - 10| 0|} - 11| | - 12| |pub fn print(left: &str, value: T, right: &str) - 13| |where - 14| | T: std::fmt::Display, - 15| 1|{ - 16| 1| println!("{}{}{}", left, value, right); - 17| 1|} - 18| | - 19| |pub fn wrap_with(inner: T, should_wrap: bool, wrapper: F) - 20| |where - 21| | F: FnOnce(&T) - 22| 2|{ - 23| 2| if should_wrap { - 24| 2| wrapper(&inner) - 25| 2| } - 26| 2|} - ------------------ - | main[317d481089b8c8fe]::wrap_with::: - | 22| 1|{ - | 23| 1| if should_wrap { - | 24| 1| wrapper(&inner) - | 25| 1| } - | 26| 1|} - ------------------ - | main[317d481089b8c8fe]::wrap_with::: - | 22| 1|{ - | 23| 1| if should_wrap { - | 24| 1| wrapper(&inner) - | 25| 1| } - | 26| 1|} - ------------------ - 27| | - 28| 1|fn main() { - 29| 1| let less = 1; - 30| 1| let more = 100; - 31| 1| - 32| 1| if less < more { - 33| 1| wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** ")); - 34| 1| wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** ")); - ^0 - 35| 1| } else { - 36| 1| wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, "")); - 37| 1| } - 38| 1|} - diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index 8b885f1dc6d58..1effa46e101eb 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -18,9 +18,6 @@ endif HTMLDOCCK := '$(PYTHON)' '$(S)/src/etc/htmldocck.py' CGREP := "$(S)/src/etc/cat-and-grep.sh" -# diff with common flags for multi-platform diffs against text output -DIFF := diff -u --strip-trailing-cr - # This is the name of the binary we will generate and run; use this # e.g. for `$(CC) -o $(RUN_BINFILE)`. RUN_BINFILE = $(TMPDIR)/$(1) diff --git a/src/test/rustdoc/auxiliary/unstable-trait.rs b/src/test/rustdoc/auxiliary/unstable-trait.rs deleted file mode 100644 index 6f06a6e2656d7..0000000000000 --- a/src/test/rustdoc/auxiliary/unstable-trait.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![feature(staged_api)] -#![stable(feature = "private_general", since = "1.0.0")] - -#[unstable(feature = "private_trait", issue = "none")] -pub trait Bar {} - -#[stable(feature = "private_general", since = "1.0.0")] -pub struct Foo { - // nothing -} - -impl Foo { - #[stable(feature = "private_general", since = "1.0.0")] - pub fn stable_impl() {} -} - -impl Foo { - #[unstable(feature = "private_trait", issue = "none")] - pub fn bar() {} - - #[stable(feature = "private_general", since = "1.0.0")] - pub fn bar2() {} -} - -#[stable(feature = "private_general", since = "1.0.0")] -impl Bar for Foo {} diff --git a/src/test/rustdoc/hide-unstable-trait.rs b/src/test/rustdoc/hide-unstable-trait.rs deleted file mode 100644 index c30d6ed7b5220..0000000000000 --- a/src/test/rustdoc/hide-unstable-trait.rs +++ /dev/null @@ -1,11 +0,0 @@ -// aux-build:unstable-trait.rs - -#![crate_name = "foo"] -#![feature(private_trait)] - -extern crate unstable_trait; - -// @has foo/struct.Foo.html 'bar' -// @has foo/struct.Foo.html 'bar2' -#[doc(inline)] -pub use unstable_trait::Foo; diff --git a/src/test/ui-fulldeps/macro-crate-rlib.rs b/src/test/ui-fulldeps/macro-crate-rlib.rs index 1fd514c617329..b5038a58249d2 100644 --- a/src/test/ui-fulldeps/macro-crate-rlib.rs +++ b/src/test/ui-fulldeps/macro-crate-rlib.rs @@ -1,8 +1,10 @@ // aux-build:rlib-crate-test.rs +// ignore-tidy-linelength // ignore-cross-compile gives a different error message #![feature(plugin)] #![plugin(rlib_crate_test)] -//~^ ERROR: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib +//~^ ERROR: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib format +//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated fn main() {} diff --git a/src/test/ui-fulldeps/macro-crate-rlib.stderr b/src/test/ui-fulldeps/macro-crate-rlib.stderr index 7b31f28a26e7d..342663312a853 100644 --- a/src/test/ui-fulldeps/macro-crate-rlib.stderr +++ b/src/test/ui-fulldeps/macro-crate-rlib.stderr @@ -1,8 +1,16 @@ error[E0457]: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib format - --> $DIR/macro-crate-rlib.rs:5:11 + --> $DIR/macro-crate-rlib.rs:6:11 | LL | #![plugin(rlib_crate_test)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 + --> $DIR/macro-crate-rlib.rs:6:1 + | +LL | #![plugin(rlib_crate_test)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version + | + = note: `#[warn(deprecated)]` on by default + +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/const-argument-non-static-lifetime.rs b/src/test/ui/const-generics/const-argument-non-static-lifetime.rs deleted file mode 100644 index bc09ba2ab553b..0000000000000 --- a/src/test/ui/const-generics/const-argument-non-static-lifetime.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-pass - -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete -#![allow(dead_code)] - -fn test() {} - -fn wow<'a>() -> &'a () { - test::<{ - let _: &'a (); - 3 - }>(); - &() -} - -fn main() {} diff --git a/src/test/ui/const-generics/const-argument-non-static-lifetime.stderr b/src/test/ui/const-generics/const-argument-non-static-lifetime.stderr deleted file mode 100644 index 53a7550090d44..0000000000000 --- a/src/test/ui/const-generics/const-argument-non-static-lifetime.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-argument-non-static-lifetime.rs:3:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs index ea75a3d040358..db15ececfa436 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -1,6 +1,3 @@ -// compile-flags: -Zsave-analysis -// Regression test for #69414 ^ - use std::marker::PhantomData; struct B(PhantomData<[T; N]>); //~ ERROR const generics are unstable diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr index 616f0fa8f1af0..35996e833610d 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -1,11 +1,11 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/const-param-type-depends-on-type-param-ungated.rs:6:22 + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 | LL | struct B(PhantomData<[T; N]>); | ^ the type must not depend on the parameter `T` error[E0658]: const generics are unstable - --> $DIR/const-param-type-depends-on-type-param-ungated.rs:6:19 + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19 | LL | struct B(PhantomData<[T; N]>); | ^ diff --git a/src/test/ui/const-generics/issues/issue-62878.rs b/src/test/ui/const-generics/issues/issue-62878.rs deleted file mode 100644 index ccc05fdf100e7..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62878.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete - -fn foo() {} -//~^ ERROR the type of const parameters must not - -fn main() { - foo::<_, {[1]}>(); - //~^ ERROR wrong number of const arguments - //~| ERROR wrong number of type arguments - //~| ERROR mismatched types -} diff --git a/src/test/ui/const-generics/issues/issue-62878.stderr b/src/test/ui/const-generics/issues/issue-62878.stderr deleted file mode 100644 index fe0990d8241fa..0000000000000 --- a/src/test/ui/const-generics/issues/issue-62878.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/issue-62878.rs:3:38 - | -LL | fn foo() {} - | ^ the type must not depend on the parameter `N` - -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-62878.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -error[E0107]: wrong number of const arguments: expected 2, found 1 - --> $DIR/issue-62878.rs:7:5 - | -LL | foo::<_, {[1]}>(); - | ^^^^^^^^^^^^^^^ expected 2 const arguments - -error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/issue-62878.rs:7:11 - | -LL | foo::<_, {[1]}>(); - | ^ unexpected type argument - -error[E0308]: mismatched types - --> $DIR/issue-62878.rs:7:15 - | -LL | foo::<_, {[1]}>(); - | ^^^ expected `usize`, found array `[{integer}; 1]` - -error: aborting due to 4 previous errors; 1 warning emitted - -Some errors have detailed explanations: E0107, E0308, E0770. -For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/consts/const_unsafe_unreachable.rs b/src/test/ui/consts/const_unsafe_unreachable.rs deleted file mode 100644 index cfed6e5deb999..0000000000000 --- a/src/test/ui/consts/const_unsafe_unreachable.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-pass - -#![feature(const_fn)] -#![feature(const_unreachable_unchecked)] - -const unsafe fn foo(x: bool) -> bool { - match x { - true => true, - false => std::hint::unreachable_unchecked(), - } -} - -const BAR: bool = unsafe { foo(true) }; - -fn main() { - assert_eq!(BAR, true); -} diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.rs b/src/test/ui/consts/const_unsafe_unreachable_ub.rs deleted file mode 100644 index 11920d852e02f..0000000000000 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.rs +++ /dev/null @@ -1,20 +0,0 @@ -// build-fail - -#![feature(const_fn)] -#![feature(const_unreachable_unchecked)] - -const unsafe fn foo(x: bool) -> bool { - match x { - true => true, - false => std::hint::unreachable_unchecked(), - } -} - -#[warn(const_err)] -const BAR: bool = unsafe { foo(false) }; - -fn main() { - assert_eq!(BAR, true); - //~^ ERROR E0080 - //~| ERROR erroneous constant -} diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr deleted file mode 100644 index 3ef8043a54d88..0000000000000 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr +++ /dev/null @@ -1,44 +0,0 @@ -warning: any use of this value will cause an error - --> $SRC_DIR/libcore/hint.rs:LL:COL - | -LL | unsafe { intrinsics::unreachable() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | entering unreachable code - | inside `std::hint::unreachable_unchecked` at $SRC_DIR/libcore/hint.rs:LL:COL - | inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:9:18 - | inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:14:28 - | - ::: $DIR/const_unsafe_unreachable_ub.rs:14:1 - | -LL | const BAR: bool = unsafe { foo(false) }; - | ---------------------------------------- - | -note: the lint level is defined here - --> $DIR/const_unsafe_unreachable_ub.rs:13:8 - | -LL | #[warn(const_err)] - | ^^^^^^^^^ - -error[E0080]: evaluation of constant expression failed - --> $DIR/const_unsafe_unreachable_ub.rs:17:3 - | -LL | assert_eq!(BAR, true); - | ^^^^^^^^^^^---^^^^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: erroneous constant used - --> $DIR/const_unsafe_unreachable_ub.rs:17:3 - | -LL | assert_eq!(BAR, true); - | ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors - | - = note: `#[deny(const_err)]` on by default - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/error-codes/E0771.rs b/src/test/ui/error-codes/E0771.rs deleted file mode 100644 index ba3592719408c..0000000000000 --- a/src/test/ui/error-codes/E0771.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete - -fn function_with_str<'a, const STRING: &'a str>() {} //~ ERROR E0771 - -fn main() { - function_with_str::<"Hello, world!">() -} diff --git a/src/test/ui/error-codes/E0771.stderr b/src/test/ui/error-codes/E0771.stderr deleted file mode 100644 index 60220be6b57ba..0000000000000 --- a/src/test/ui/error-codes/E0771.stderr +++ /dev/null @@ -1,20 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/E0771.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -error[E0771]: use of non-static lifetime `'a` in const generic - --> $DIR/E0771.rs:4:41 - | -LL | fn function_with_str<'a, const STRING: &'a str>() {} - | ^^ - | - = note: for more information, see issue #74052 - -error: aborting due to previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0771`. diff --git a/src/test/ui/extern/extern-prelude-no-speculative.rs b/src/test/ui/extern/extern-prelude-no-speculative.rs index 3ba124159e000..cc00737ab591d 100644 --- a/src/test/ui/extern/extern-prelude-no-speculative.rs +++ b/src/test/ui/extern/extern-prelude-no-speculative.rs @@ -1,6 +1,6 @@ // run-pass #![allow(unused_variables)] -// compile-flags: --extern LooksLikeExternCrate=/path/to/nowhere +// compile-flags: --extern LooksLikeExternCrate mod m { pub struct LooksLikeExternCrate; diff --git a/src/test/ui/issues/issue-74539.rs b/src/test/ui/issues/issue-74539.rs deleted file mode 100644 index 75632d11c1df0..0000000000000 --- a/src/test/ui/issues/issue-74539.rs +++ /dev/null @@ -1,12 +0,0 @@ -enum E { - A(u8, u8), -} - -fn main() { - let e = E::A(2, 3); - match e { - E::A(x @ ..) => { //~ ERROR `x @` is not allowed in a tuple - x //~ ERROR cannot find value `x` in this scope - } - }; -} diff --git a/src/test/ui/issues/issue-74539.stderr b/src/test/ui/issues/issue-74539.stderr deleted file mode 100644 index 94526dcd7cb39..0000000000000 --- a/src/test/ui/issues/issue-74539.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0425]: cannot find value `x` in this scope - --> $DIR/issue-74539.rs:9:13 - | -LL | x - | ^ help: a local variable with a similar name exists: `e` - -error: `x @` is not allowed in a tuple struct - --> $DIR/issue-74539.rs:8:14 - | -LL | E::A(x @ ..) => { - | ^^^^^^ this is only allowed in slice patterns - | - = help: remove this and bind each tuple field independently -help: if you don't need to use the contents of x, discard the tuple's remaining fields - | -LL | E::A(..) => { - | ^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/lint/lint-ctypes-fn.rs b/src/test/ui/lint/lint-ctypes-fn.rs index aa02e57866328..67dd7abcf79ef 100644 --- a/src/test/ui/lint/lint-ctypes-fn.rs +++ b/src/test/ui/lint/lint-ctypes-fn.rs @@ -71,8 +71,7 @@ pub extern "C" fn str_type(p: &str) { } //~^ ERROR: uses type `str` pub extern "C" fn box_type(p: Box) { } - -pub extern "C" fn opt_box_type(p: Option>) { } +//~^ ERROR uses type `std::boxed::Box` pub extern "C" fn char_type(p: char) { } //~^ ERROR uses type `char` @@ -107,6 +106,7 @@ pub extern "C" fn fn_type2(p: fn()) { } //~^ ERROR uses type `fn()` pub extern "C" fn fn_contained(p: RustBadRet) { } +//~^ ERROR: uses type `std::boxed::Box` pub extern "C" fn transparent_i128(p: TransparentI128) { } //~^ ERROR: uses type `i128` @@ -115,6 +115,7 @@ pub extern "C" fn transparent_str(p: TransparentStr) { } //~^ ERROR: uses type `str` pub extern "C" fn transparent_fn(p: TransparentBadFn) { } +//~^ ERROR: uses type `std::boxed::Box` pub extern "C" fn good3(fptr: Option) { } diff --git a/src/test/ui/lint/lint-ctypes-fn.stderr b/src/test/ui/lint/lint-ctypes-fn.stderr index d0a449514e50e..66cf195327890 100644 --- a/src/test/ui/lint/lint-ctypes-fn.stderr +++ b/src/test/ui/lint/lint-ctypes-fn.stderr @@ -21,8 +21,17 @@ LL | pub extern "C" fn str_type(p: &str) { } = help: consider using `*const u8` and a length instead = note: string slices have no C equivalent +error: `extern` fn uses type `std::boxed::Box`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:73:31 + | +LL | pub extern "C" fn box_type(p: Box) { } + | ^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + error: `extern` fn uses type `char`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:77:32 + --> $DIR/lint-ctypes-fn.rs:76:32 | LL | pub extern "C" fn char_type(p: char) { } | ^^^^ not FFI-safe @@ -31,7 +40,7 @@ LL | pub extern "C" fn char_type(p: char) { } = note: the `char` type has no C equivalent error: `extern` fn uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:80:32 + --> $DIR/lint-ctypes-fn.rs:79:32 | LL | pub extern "C" fn i128_type(p: i128) { } | ^^^^ not FFI-safe @@ -39,7 +48,7 @@ LL | pub extern "C" fn i128_type(p: i128) { } = note: 128-bit integers don't currently have a known stable ABI error: `extern` fn uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:83:32 + --> $DIR/lint-ctypes-fn.rs:82:32 | LL | pub extern "C" fn u128_type(p: u128) { } | ^^^^ not FFI-safe @@ -47,7 +56,7 @@ LL | pub extern "C" fn u128_type(p: u128) { } = note: 128-bit integers don't currently have a known stable ABI error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:86:33 + --> $DIR/lint-ctypes-fn.rs:85:33 | LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } | ^^^^^^^^^^ not FFI-safe @@ -56,7 +65,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } = note: tuples have unspecified layout error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:89:34 + --> $DIR/lint-ctypes-fn.rs:88:34 | LL | pub extern "C" fn tuple_type2(p: I32Pair) { } | ^^^^^^^ not FFI-safe @@ -65,7 +74,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { } = note: tuples have unspecified layout error: `extern` fn uses type `ZeroSize`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:92:32 + --> $DIR/lint-ctypes-fn.rs:91:32 | LL | pub extern "C" fn zero_size(p: ZeroSize) { } | ^^^^^^^^ not FFI-safe @@ -79,7 +88,7 @@ LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:95:40 + --> $DIR/lint-ctypes-fn.rs:94:40 | LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -92,7 +101,7 @@ LL | pub struct ZeroSizeWithPhantomData(PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `std::marker::PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:98:51 + --> $DIR/lint-ctypes-fn.rs:97:51 | LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { | ^^^^^^^^^^^^^^^^^ not FFI-safe @@ -100,7 +109,7 @@ LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { = note: composed only of `PhantomData` error: `extern` fn uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:103:30 + --> $DIR/lint-ctypes-fn.rs:102:30 | LL | pub extern "C" fn fn_type(p: RustFn) { } | ^^^^^^ not FFI-safe @@ -109,7 +118,7 @@ LL | pub extern "C" fn fn_type(p: RustFn) { } = note: this function pointer has Rust-specific calling convention error: `extern` fn uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:106:31 + --> $DIR/lint-ctypes-fn.rs:105:31 | LL | pub extern "C" fn fn_type2(p: fn()) { } | ^^^^ not FFI-safe @@ -117,6 +126,15 @@ LL | pub extern "C" fn fn_type2(p: fn()) { } = help: consider using an `extern fn(...) -> ...` function pointer instead = note: this function pointer has Rust-specific calling convention +error: `extern` fn uses type `std::boxed::Box`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:108:35 + | +LL | pub extern "C" fn fn_contained(p: RustBadRet) { } + | ^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + error: `extern` fn uses type `i128`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:111:39 | @@ -134,8 +152,17 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { } = help: consider using `*const u8` and a length instead = note: string slices have no C equivalent +error: `extern` fn uses type `std::boxed::Box`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:117:37 + | +LL | pub extern "C" fn transparent_fn(p: TransparentBadFn) { } + | ^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + error: `extern` fn uses type `std::marker::PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:160:43 + --> $DIR/lint-ctypes-fn.rs:161:43 | LL | pub extern "C" fn unused_generic2() -> PhantomData { | ^^^^^^^^^^^^^^^^^ not FFI-safe @@ -143,7 +170,7 @@ LL | pub extern "C" fn unused_generic2() -> PhantomData { = note: composed only of `PhantomData` error: `extern` fn uses type `std::vec::Vec`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:173:39 + --> $DIR/lint-ctypes-fn.rs:174:39 | LL | pub extern "C" fn used_generic4(x: Vec) { } | ^^^^^^ not FFI-safe @@ -152,7 +179,7 @@ LL | pub extern "C" fn used_generic4(x: Vec) { } = note: this struct has unspecified layout error: `extern` fn uses type `std::vec::Vec`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:176:41 + --> $DIR/lint-ctypes-fn.rs:177:41 | LL | pub extern "C" fn used_generic5() -> Vec { | ^^^^^^ not FFI-safe @@ -160,5 +187,5 @@ LL | pub extern "C" fn used_generic5() -> Vec { = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout -error: aborting due to 17 previous errors +error: aborting due to 20 previous errors diff --git a/src/test/ui/lint/lint-ctypes.rs b/src/test/ui/lint/lint-ctypes.rs index f485766bcd34e..a439a1f339aea 100644 --- a/src/test/ui/lint/lint-ctypes.rs +++ b/src/test/ui/lint/lint-ctypes.rs @@ -7,7 +7,6 @@ extern crate libc; use std::marker::PhantomData; -trait Bar { } trait Mirror { type It: ?Sized; } impl Mirror for T { type It = Self; } #[repr(C)] @@ -49,12 +48,10 @@ extern { pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]` pub fn str_type(p: &str); //~ ERROR: uses type `str` pub fn box_type(p: Box); //~ ERROR uses type `std::boxed::Box` - pub fn opt_box_type(p: Option>); - //~^ ERROR uses type `std::option::Option>` pub fn char_type(p: char); //~ ERROR uses type `char` pub fn i128_type(p: i128); //~ ERROR uses type `i128` pub fn u128_type(p: u128); //~ ERROR uses type `u128` - pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `dyn Bar` + pub fn trait_type(p: &dyn Clone); //~ ERROR uses type `dyn std::clone::Clone` pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)` pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)` pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize` diff --git a/src/test/ui/lint/lint-ctypes.stderr b/src/test/ui/lint/lint-ctypes.stderr index a54226a7fc4a2..9821f858d9caf 100644 --- a/src/test/ui/lint/lint-ctypes.stderr +++ b/src/test/ui/lint/lint-ctypes.stderr @@ -1,5 +1,5 @@ error: `extern` block uses type `Foo`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:47:28 + --> $DIR/lint-ctypes.rs:46:28 | LL | pub fn ptr_type1(size: *const Foo); | ^^^^^^^^^^ not FFI-safe @@ -12,13 +12,13 @@ LL | #![deny(improper_ctypes)] = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes.rs:25:1 + --> $DIR/lint-ctypes.rs:24:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^^ error: `extern` block uses type `Foo`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:48:28 + --> $DIR/lint-ctypes.rs:47:28 | LL | pub fn ptr_type2(size: *const Foo); | ^^^^^^^^^^ not FFI-safe @@ -26,13 +26,13 @@ LL | pub fn ptr_type2(size: *const Foo); = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes.rs:25:1 + --> $DIR/lint-ctypes.rs:24:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^^ error: `extern` block uses type `[u32]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:49:26 + --> $DIR/lint-ctypes.rs:48:26 | LL | pub fn slice_type(p: &[u32]); | ^^^^^^ not FFI-safe @@ -41,7 +41,7 @@ LL | pub fn slice_type(p: &[u32]); = note: slices have no C equivalent error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:50:24 + --> $DIR/lint-ctypes.rs:49:24 | LL | pub fn str_type(p: &str); | ^^^^ not FFI-safe @@ -50,7 +50,7 @@ LL | pub fn str_type(p: &str); = note: string slices have no C equivalent error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:51:24 + --> $DIR/lint-ctypes.rs:50:24 | LL | pub fn box_type(p: Box); | ^^^^^^^^ not FFI-safe @@ -58,17 +58,8 @@ LL | pub fn box_type(p: Box); = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout -error: `extern` block uses type `std::option::Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:52:28 - | -LL | pub fn opt_box_type(p: Option>); - | ^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum - = note: enum has no representation hint - error: `extern` block uses type `char`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:54:25 + --> $DIR/lint-ctypes.rs:51:25 | LL | pub fn char_type(p: char); | ^^^^ not FFI-safe @@ -77,7 +68,7 @@ LL | pub fn char_type(p: char); = note: the `char` type has no C equivalent error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:55:25 + --> $DIR/lint-ctypes.rs:52:25 | LL | pub fn i128_type(p: i128); | ^^^^ not FFI-safe @@ -85,23 +76,23 @@ LL | pub fn i128_type(p: i128); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:56:25 + --> $DIR/lint-ctypes.rs:53:25 | LL | pub fn u128_type(p: u128); | ^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `dyn Bar`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:57:26 +error: `extern` block uses type `dyn std::clone::Clone`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:54:26 | -LL | pub fn trait_type(p: &dyn Bar); - | ^^^^^^^^ not FFI-safe +LL | pub fn trait_type(p: &dyn Clone); + | ^^^^^^^^^^ not FFI-safe | = note: trait objects have no C equivalent error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:58:26 + --> $DIR/lint-ctypes.rs:55:26 | LL | pub fn tuple_type(p: (i32, i32)); | ^^^^^^^^^^ not FFI-safe @@ -110,7 +101,7 @@ LL | pub fn tuple_type(p: (i32, i32)); = note: tuples have unspecified layout error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:59:27 + --> $DIR/lint-ctypes.rs:56:27 | LL | pub fn tuple_type2(p: I32Pair); | ^^^^^^^ not FFI-safe @@ -119,7 +110,7 @@ LL | pub fn tuple_type2(p: I32Pair); = note: tuples have unspecified layout error: `extern` block uses type `ZeroSize`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:60:25 + --> $DIR/lint-ctypes.rs:57:25 | LL | pub fn zero_size(p: ZeroSize); | ^^^^^^^^ not FFI-safe @@ -127,26 +118,26 @@ LL | pub fn zero_size(p: ZeroSize); = help: consider adding a member to this struct = note: this struct has no fields note: the type is defined here - --> $DIR/lint-ctypes.rs:21:1 + --> $DIR/lint-ctypes.rs:20:1 | LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:61:33 + --> $DIR/lint-ctypes.rs:58:33 | LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: composed only of `PhantomData` note: the type is defined here - --> $DIR/lint-ctypes.rs:44:1 + --> $DIR/lint-ctypes.rs:43:1 | LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `std::marker::PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:64:12 + --> $DIR/lint-ctypes.rs:61:12 | LL | -> ::std::marker::PhantomData; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -154,7 +145,7 @@ LL | -> ::std::marker::PhantomData; = note: composed only of `PhantomData` error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:65:23 + --> $DIR/lint-ctypes.rs:62:23 | LL | pub fn fn_type(p: RustFn); | ^^^^^^ not FFI-safe @@ -163,7 +154,7 @@ LL | pub fn fn_type(p: RustFn); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:66:24 + --> $DIR/lint-ctypes.rs:63:24 | LL | pub fn fn_type2(p: fn()); | ^^^^ not FFI-safe @@ -172,7 +163,7 @@ LL | pub fn fn_type2(p: fn()); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:67:28 + --> $DIR/lint-ctypes.rs:64:28 | LL | pub fn fn_contained(p: RustBadRet); | ^^^^^^^^^^ not FFI-safe @@ -181,7 +172,7 @@ LL | pub fn fn_contained(p: RustBadRet); = note: this struct has unspecified layout error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:68:32 + --> $DIR/lint-ctypes.rs:65:32 | LL | pub fn transparent_i128(p: TransparentI128); | ^^^^^^^^^^^^^^^ not FFI-safe @@ -189,7 +180,7 @@ LL | pub fn transparent_i128(p: TransparentI128); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:69:31 + --> $DIR/lint-ctypes.rs:66:31 | LL | pub fn transparent_str(p: TransparentStr); | ^^^^^^^^^^^^^^ not FFI-safe @@ -198,7 +189,7 @@ LL | pub fn transparent_str(p: TransparentStr); = note: string slices have no C equivalent error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:70:30 + --> $DIR/lint-ctypes.rs:67:30 | LL | pub fn transparent_fn(p: TransparentBadFn); | ^^^^^^^^^^^^^^^^ not FFI-safe @@ -207,7 +198,7 @@ LL | pub fn transparent_fn(p: TransparentBadFn); = note: this struct has unspecified layout error: `extern` block uses type `[u8; 8]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:71:27 + --> $DIR/lint-ctypes.rs:68:27 | LL | pub fn raw_array(arr: [u8; 8]); | ^^^^^^^ not FFI-safe @@ -216,7 +207,7 @@ LL | pub fn raw_array(arr: [u8; 8]); = note: passing raw arrays by value is not FFI-safe error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:73:34 + --> $DIR/lint-ctypes.rs:70:34 | LL | pub static static_u128_type: u128; | ^^^^ not FFI-safe @@ -224,12 +215,12 @@ LL | pub static static_u128_type: u128; = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:74:40 + --> $DIR/lint-ctypes.rs:71:40 | LL | pub static static_u128_array_type: [u128; 16]; | ^^^^^^^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI -error: aborting due to 24 previous errors +error: aborting due to 23 previous errors diff --git a/src/test/ui/polymorphization/const_parameters/closures.rs b/src/test/ui/polymorphization/const_parameters/closures.rs deleted file mode 100644 index 7bbcaebea0125..0000000000000 --- a/src/test/ui/polymorphization/const_parameters/closures.rs +++ /dev/null @@ -1,66 +0,0 @@ -// build-fail -#![feature(const_generics, rustc_attrs)] -//~^ WARN the feature `const_generics` is incomplete - -// This test checks that the polymorphization analysis correctly detects unused const -// parameters in closures. - -// Function doesn't have any generic parameters to be unused. -#[rustc_polymorphize_error] -pub fn no_parameters() { - let _ = || {}; -} - -// Function has an unused generic parameter in parent and closure. -#[rustc_polymorphize_error] -pub fn unused() -> usize { - //~^ ERROR item has unused generic parameters - let add_one = |x: usize| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) -} - -// Function has an unused generic parameter in closure, but not in parent. -#[rustc_polymorphize_error] -pub fn used_parent() -> usize { - let x: usize = T; - let add_one = |x: usize| x + 1; - //~^ ERROR item has unused generic parameters - x + add_one(3) -} - -// Function uses generic parameter in value of a binding in closure. -#[rustc_polymorphize_error] -pub fn used_binding() -> usize { - let x = || { - let y: usize = T; - y - }; - - x() -} - -// Closure uses a value as an upvar, which used the generic parameter. -#[rustc_polymorphize_error] -pub fn unused_upvar() -> usize { - let x: usize = T; - let y = || x; - //~^ ERROR item has unused generic parameters - y() -} - -// Closure uses generic parameter in substitutions to another function. -#[rustc_polymorphize_error] -pub fn used_substs() -> usize { - let x = || unused::(); - x() -} - -fn main() { - no_parameters(); - let _ = unused::<1>(); - let _ = used_parent::<1>(); - let _ = used_binding::<1>(); - let _ = unused_upvar::<1>(); - let _ = used_substs::<1>(); -} diff --git a/src/test/ui/polymorphization/const_parameters/closures.stderr b/src/test/ui/polymorphization/const_parameters/closures.stderr deleted file mode 100644 index eb872eac74c91..0000000000000 --- a/src/test/ui/polymorphization/const_parameters/closures.stderr +++ /dev/null @@ -1,44 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closures.rs:2:12 - | -LL | #![feature(const_generics, rustc_attrs)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -error: item has unused generic parameters - --> $DIR/closures.rs:18:19 - | -LL | pub fn unused() -> usize { - | - generic parameter `T` is unused -LL | -LL | let add_one = |x: usize| x + 1; - | ^^^^^^^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:16:8 - | -LL | pub fn unused() -> usize { - | ^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/closures.rs:27:19 - | -LL | pub fn used_parent() -> usize { - | - generic parameter `T` is unused -LL | let x: usize = T; -LL | let add_one = |x: usize| x + 1; - | ^^^^^^^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:47:13 - | -LL | pub fn unused_upvar() -> usize { - | - generic parameter `T` is unused -LL | let x: usize = T; -LL | let y = || x; - | ^^^^ - -error: aborting due to 4 previous errors; 1 warning emitted - diff --git a/src/test/ui/polymorphization/const_parameters/functions.rs b/src/test/ui/polymorphization/const_parameters/functions.rs deleted file mode 100644 index 77539b94e489a..0000000000000 --- a/src/test/ui/polymorphization/const_parameters/functions.rs +++ /dev/null @@ -1,36 +0,0 @@ -// build-fail -#![feature(const_generics, rustc_attrs)] -//~^ WARN the feature `const_generics` is incomplete - -// This test checks that the polymorphization analysis correctly detects unused const -// parameters in functions. - -// Function doesn't have any generic parameters to be unused. -#[rustc_polymorphize_error] -pub fn no_parameters() {} - -// Function has an unused generic parameter. -#[rustc_polymorphize_error] -pub fn unused() { - //~^ ERROR item has unused generic parameters -} - -// Function uses generic parameter in value of a binding. -#[rustc_polymorphize_error] -pub fn used_binding() -> usize { - let x: usize = T; - x -} - -// Function uses generic parameter in substitutions to another function. -#[rustc_polymorphize_error] -pub fn used_substs() { - unused::() -} - -fn main() { - no_parameters(); - unused::<1>(); - used_binding::<1>(); - used_substs::<1>(); -} diff --git a/src/test/ui/polymorphization/const_parameters/functions.stderr b/src/test/ui/polymorphization/const_parameters/functions.stderr deleted file mode 100644 index c99a9b788ebc5..0000000000000 --- a/src/test/ui/polymorphization/const_parameters/functions.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/functions.rs:2:12 - | -LL | #![feature(const_generics, rustc_attrs)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -error: item has unused generic parameters - --> $DIR/functions.rs:14:8 - | -LL | pub fn unused() { - | ^^^^^^ - generic parameter `T` is unused - -error: aborting due to previous error; 1 warning emitted - diff --git a/src/test/ui/polymorphization/drop_shims/simple.rs b/src/test/ui/polymorphization/drop_shims/simple.rs deleted file mode 100644 index ce56b7a358861..0000000000000 --- a/src/test/ui/polymorphization/drop_shims/simple.rs +++ /dev/null @@ -1,21 +0,0 @@ -// check-pass - -pub struct OnDrop(pub F); - -impl Drop for OnDrop { - fn drop(&mut self) { } -} - -fn foo( - _: R, - _: S, -) { - let bar = || { - let _ = OnDrop(|| ()); - }; - let _ = bar(); -} - -fn main() { - foo(3u32, || {}); -} diff --git a/src/test/ui/polymorphization/drop_shims/transitive.rs b/src/test/ui/polymorphization/drop_shims/transitive.rs deleted file mode 100644 index b7ea07b6bc653..0000000000000 --- a/src/test/ui/polymorphization/drop_shims/transitive.rs +++ /dev/null @@ -1,26 +0,0 @@ -// check-pass - -pub struct OnDrop(pub F); - -impl Drop for OnDrop { - fn drop(&mut self) { } -} - -fn bar(f: F) { - let _ = OnDrop(|| ()); - f() -} - -fn foo( - _: R, - _: S, -) { - let bar = || { - bar(|| {}) - }; - let _ = bar(); -} - -fn main() { - foo(3u32, || {}); -} diff --git a/src/test/ui/polymorphization/generators.rs b/src/test/ui/polymorphization/generators.rs deleted file mode 100644 index 1acba7c8bf14c..0000000000000 --- a/src/test/ui/polymorphization/generators.rs +++ /dev/null @@ -1,93 +0,0 @@ -// build-fail -#![feature(const_generics, generators, generator_trait, rustc_attrs)] -//~^ WARN the feature `const_generics` is incomplete - -use std::marker::Unpin; -use std::ops::{Generator, GeneratorState}; -use std::pin::Pin; - -enum YieldOrReturn { - Yield(Y), - Return(R), -} - -fn finish(mut t: T) -> Vec> -where - T: Generator<(), Yield = Y, Return = R> + Unpin, -{ - let mut results = Vec::new(); - loop { - match Pin::new(&mut t).resume(()) { - GeneratorState::Yielded(yielded) => results.push(YieldOrReturn::Yield(yielded)), - GeneratorState::Complete(returned) => { - results.push(YieldOrReturn::Return(returned)); - return results; - } - } - } -} - -// This test checks that the polymorphization analysis functions on generators. - -#[rustc_polymorphize_error] -pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - //~^ ERROR item has unused generic parameters - || { - //~^ ERROR item has unused generic parameters - yield 1; - 2 - } -} - -#[rustc_polymorphize_error] -pub fn used_type_in_yield() -> impl Generator<(), Yield = Y, Return = u32> + Unpin { - || { - yield Y::default(); - 2 - } -} - -#[rustc_polymorphize_error] -pub fn used_type_in_return() -> impl Generator<(), Yield = u32, Return = R> + Unpin { - || { - yield 3; - R::default() - } -} - -#[rustc_polymorphize_error] -pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - //~^ ERROR item has unused generic parameters - || { - //~^ ERROR item has unused generic parameters - yield 1; - 2 - } -} - -#[rustc_polymorphize_error] -pub fn used_const_in_yield() -> impl Generator<(), Yield = u32, Return = u32> + Unpin -{ - || { - yield Y; - 2 - } -} - -#[rustc_polymorphize_error] -pub fn used_const_in_return() -> impl Generator<(), Yield = u32, Return = u32> + Unpin -{ - || { - yield 4; - R - } -} - -fn main() { - finish(unused_type::()); - finish(used_type_in_yield::()); - finish(used_type_in_return::()); - finish(unused_const::<1u32>()); - finish(used_const_in_yield::<1u32>()); - finish(used_const_in_return::<1u32>()); -} diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr deleted file mode 100644 index b3e5a2de0270a..0000000000000 --- a/src/test/ui/polymorphization/generators.stderr +++ /dev/null @@ -1,49 +0,0 @@ -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/generators.rs:2:12 - | -LL | #![feature(const_generics, generators, generator_trait, rustc_attrs)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information - -error: item has unused generic parameters - --> $DIR/generators.rs:35:5 - | -LL | pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | - generic parameter `T` is unused -LL | -LL | / || { -LL | | -LL | | yield 1; -LL | | 2 -LL | | } - | |_____^ - -error: item has unused generic parameters - --> $DIR/generators.rs:33:8 - | -LL | pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | ^^^^^^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/generators.rs:61:5 - | -LL | pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | - generic parameter `T` is unused -LL | -LL | / || { -LL | | -LL | | yield 1; -LL | | 2 -LL | | } - | |_____^ - -error: item has unused generic parameters - --> $DIR/generators.rs:59:8 - | -LL | pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | ^^^^^^^^^^^^ - generic parameter `T` is unused - -error: aborting due to 4 previous errors; 1 warning emitted - diff --git a/src/test/ui/polymorphization/lifetimes.rs b/src/test/ui/polymorphization/lifetimes.rs deleted file mode 100644 index 4bde349a336ea..0000000000000 --- a/src/test/ui/polymorphization/lifetimes.rs +++ /dev/null @@ -1,24 +0,0 @@ -// build-fail -#![feature(rustc_attrs)] - -// This test checks that the polymorphization analysis doesn't break when the -// function/closure doesn't just have generic parameters. - -// Function has an unused generic parameter. -#[rustc_polymorphize_error] -pub fn unused<'a, T>(_: &'a u32) { - //~^ ERROR item has unused generic parameters -} - -#[rustc_polymorphize_error] -pub fn used<'a, T: Default>(_: &'a u32) -> u32 { - let _: T = Default::default(); - let add_one = |x: u32| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) -} - -fn main() { - unused::(&3); - used::(&3); -} diff --git a/src/test/ui/polymorphization/lifetimes.stderr b/src/test/ui/polymorphization/lifetimes.stderr deleted file mode 100644 index 6c85e4f291611..0000000000000 --- a/src/test/ui/polymorphization/lifetimes.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: item has unused generic parameters - --> $DIR/lifetimes.rs:9:8 - | -LL | pub fn unused<'a, T>(_: &'a u32) { - | ^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/lifetimes.rs:16:19 - | -LL | pub fn used<'a, T: Default>(_: &'a u32) -> u32 { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/polymorphization/normalized_sig_types.rs b/src/test/ui/polymorphization/normalized_sig_types.rs deleted file mode 100644 index fa76b7201e8c3..0000000000000 --- a/src/test/ui/polymorphization/normalized_sig_types.rs +++ /dev/null @@ -1,25 +0,0 @@ -// build-pass - -pub trait ParallelIterator: Sized { - fn drive>(_: C) { - C::into_folder(); - } -} - -pub trait Consumer: Sized { - type Result; - fn into_folder() -> Self::Result; -} - -impl ParallelIterator for () {} - -impl Consumer for F { - type Result = (); - fn into_folder() -> Self::Result { - unimplemented!() - } -} - -fn main() { - <()>::drive(|| ()); -} diff --git a/src/test/ui/polymorphization/predicates.rs b/src/test/ui/polymorphization/predicates.rs deleted file mode 100644 index 390ac983aa007..0000000000000 --- a/src/test/ui/polymorphization/predicates.rs +++ /dev/null @@ -1,23 +0,0 @@ -// build-fail -#![feature(rustc_attrs)] - -// This test checks that `T` is considered used in `foo`, because it is used in a predicate for -// `I`, which is used. - -#[rustc_polymorphize_error] -fn bar() { - //~^ ERROR item has unused generic parameters -} - -#[rustc_polymorphize_error] -fn foo(_: I) -where - I: Iterator, -{ - bar::() -} - -fn main() { - let x = &[2u32]; - foo(x.iter()); -} diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr deleted file mode 100644 index 1b266083463a2..0000000000000 --- a/src/test/ui/polymorphization/predicates.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: item has unused generic parameters - --> $DIR/predicates.rs:8:4 - | -LL | fn bar() { - | ^^^ - generic parameter `I` is unused - -error: aborting due to previous error - diff --git a/src/test/ui/polymorphization/too-many-generic-params.rs b/src/test/ui/polymorphization/too-many-generic-params.rs deleted file mode 100644 index ec6244630fd1f..0000000000000 --- a/src/test/ui/polymorphization/too-many-generic-params.rs +++ /dev/null @@ -1,85 +0,0 @@ -// build-pass -#![feature(rustc_attrs)] - -// This test checks that the analysis doesn't panic when there are >64 generic parameters, but -// instead considers those parameters used. - -#[rustc_polymorphize_error] -fn bar() -{ - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option

= None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; - let _: Option = None; -} - -fn main() { - bar::(); -} diff --git a/src/test/ui/polymorphization/type_parameters/closures.rs b/src/test/ui/polymorphization/type_parameters/closures.rs deleted file mode 100644 index 1fbe13380b5b9..0000000000000 --- a/src/test/ui/polymorphization/type_parameters/closures.rs +++ /dev/null @@ -1,160 +0,0 @@ -// build-fail -#![feature(stmt_expr_attributes, rustc_attrs)] - -// This test checks that the polymorphization analysis correctly detects unused type -// parameters in closures. - -// Function doesn't have any generic parameters to be unused. -#[rustc_polymorphize_error] -pub fn no_parameters() { - let _ = || {}; -} - -// Function has an unused generic parameter in parent and closure. -#[rustc_polymorphize_error] -pub fn unused() -> u32 { - //~^ ERROR item has unused generic parameters - - let add_one = |x: u32| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) -} - -// Function has an unused generic parameter in closure, but not in parent. -#[rustc_polymorphize_error] -pub fn used_parent() -> u32 { - let _: T = Default::default(); - let add_one = |x: u32| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) -} - -// Function uses generic parameter in value of a binding in closure. -#[rustc_polymorphize_error] -pub fn used_binding_value() -> T { - let x = || { - let y: T = Default::default(); - y - }; - - x() -} - -// Function uses generic parameter in generic of a binding in closure. -#[rustc_polymorphize_error] -pub fn used_binding_generic() -> Option { - let x = || { - let y: Option = None; - y - }; - - x() -} - -// Function and closure uses generic parameter in argument. -#[rustc_polymorphize_error] -pub fn used_argument(t: T) -> u32 { - let x = |_: T| 3; - x(t) -} - -// Closure uses generic parameter in argument. -#[rustc_polymorphize_error] -pub fn used_argument_closure() -> u32 { - let t: T = Default::default(); - - let x = |_: T| 3; - x(t) -} - -// Closure uses generic parameter as upvar. -#[rustc_polymorphize_error] -pub fn used_upvar() -> T { - let x: T = Default::default(); - - let y = || x; - y() -} - -// Closure uses generic parameter in substitutions to another function. -#[rustc_polymorphize_error] -pub fn used_substs() -> u32 { - let x = || unused::(); - x() -} - -struct Foo(F); - -impl Foo { - // Function has an unused generic parameter from impl and fn. - #[rustc_polymorphize_error] - pub fn unused_all() -> u32 { - //~^ ERROR item has unused generic parameters - let add_one = |x: u32| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) - } - - // Function uses generic parameter from impl and fn in closure. - #[rustc_polymorphize_error] - pub fn used_both() -> u32 { - let add_one = |x: u32| { - let _: F = Default::default(); - let _: G = Default::default(); - x + 1 - }; - - add_one(3) - } - - // Function uses generic parameter from fn in closure. - #[rustc_polymorphize_error] - pub fn used_fn() -> u32 { - //~^ ERROR item has unused generic parameters - let add_one = |x: u32| { - //~^ ERROR item has unused generic parameters - let _: G = Default::default(); - x + 1 - }; - - add_one(3) - } - - // Function uses generic parameter from impl in closure. - #[rustc_polymorphize_error] - pub fn used_impl() -> u32 { - //~^ ERROR item has unused generic parameters - let add_one = |x: u32| { - //~^ ERROR item has unused generic parameters - let _: F = Default::default(); - x + 1 - }; - - add_one(3) - } - - // Closure uses generic parameter in substitutions to another function. - #[rustc_polymorphize_error] - pub fn used_substs() -> u32 { - let x = || unused::(); - x() - } -} - -fn main() { - no_parameters(); - let _ = unused::(); - let _ = used_parent::(); - let _ = used_binding_value::(); - let _ = used_binding_generic::(); - let _ = used_argument(3u32); - let _ = used_argument_closure::(); - let _ = used_upvar::(); - let _ = used_substs::(); - - let _ = Foo::::unused_all::(); - let _ = Foo::::used_both::(); - let _ = Foo::::used_impl::(); - let _ = Foo::::used_fn::(); - let _ = Foo::::used_substs(); -} diff --git a/src/test/ui/polymorphization/type_parameters/closures.stderr b/src/test/ui/polymorphization/type_parameters/closures.stderr deleted file mode 100644 index d68e6e25a1eb9..0000000000000 --- a/src/test/ui/polymorphization/type_parameters/closures.stderr +++ /dev/null @@ -1,90 +0,0 @@ -error: item has unused generic parameters - --> $DIR/closures.rs:18:19 - | -LL | pub fn unused() -> u32 { - | - generic parameter `T` is unused -... -LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:15:8 - | -LL | pub fn unused() -> u32 { - | ^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/closures.rs:27:19 - | -LL | pub fn used_parent() -> u32 { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:93:23 - | -LL | impl Foo { - | - generic parameter `F` is unused -... -LL | pub fn unused_all() -> u32 { - | - generic parameter `G` is unused -LL | -LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:91:12 - | -LL | impl Foo { - | - generic parameter `F` is unused -... -LL | pub fn unused_all() -> u32 { - | ^^^^^^^^^^ - generic parameter `G` is unused - -error: item has unused generic parameters - --> $DIR/closures.rs:127:23 - | -LL | pub fn used_impl() -> u32 { - | - generic parameter `G` is unused -LL | -LL | let add_one = |x: u32| { - | _______________________^ -LL | | -LL | | let _: F = Default::default(); -LL | | x + 1 -LL | | }; - | |_________^ - -error: item has unused generic parameters - --> $DIR/closures.rs:125:12 - | -LL | pub fn used_impl() -> u32 { - | ^^^^^^^^^ - generic parameter `G` is unused - -error: item has unused generic parameters - --> $DIR/closures.rs:114:23 - | -LL | impl Foo { - | - generic parameter `F` is unused -... -LL | let add_one = |x: u32| { - | _______________________^ -LL | | -LL | | let _: G = Default::default(); -LL | | x + 1 -LL | | }; - | |_________^ - -error: item has unused generic parameters - --> $DIR/closures.rs:112:12 - | -LL | impl Foo { - | - generic parameter `F` is unused -... -LL | pub fn used_fn() -> u32 { - | ^^^^^^^ - -error: aborting due to 9 previous errors - diff --git a/src/test/ui/polymorphization/type_parameters/functions.rs b/src/test/ui/polymorphization/type_parameters/functions.rs deleted file mode 100644 index 38f10148c2c52..0000000000000 --- a/src/test/ui/polymorphization/type_parameters/functions.rs +++ /dev/null @@ -1,95 +0,0 @@ -// build-fail -#![feature(rustc_attrs)] - -// This test checks that the polymorphization analysis correctly detects unused type -// parameters in functions. - -// Function doesn't have any generic parameters to be unused. -#[rustc_polymorphize_error] -pub fn no_parameters() {} - -// Function has an unused generic parameter. -#[rustc_polymorphize_error] -pub fn unused() { - //~^ ERROR item has unused generic parameters -} - -// Function uses generic parameter in value of a binding. -#[rustc_polymorphize_error] -pub fn used_binding_value() { - let _: T = Default::default(); -} - -// Function uses generic parameter in generic of a binding. -#[rustc_polymorphize_error] -pub fn used_binding_generic() { - let _: Option = None; -} - -// Function uses generic parameter in argument. -#[rustc_polymorphize_error] -pub fn used_argument(_: T) {} - -// Function uses generic parameter in substitutions to another function. -#[rustc_polymorphize_error] -pub fn used_substs() { - unused::() -} - -struct Foo(F); - -impl Foo { - // Function has an unused generic parameter from impl. - #[rustc_polymorphize_error] - pub fn unused_impl() { - //~^ ERROR item has unused generic parameters - } - - // Function has an unused generic parameter from impl and fn. - #[rustc_polymorphize_error] - pub fn unused_both() { - //~^ ERROR item has unused generic parameters - } - - // Function uses generic parameter from impl. - #[rustc_polymorphize_error] - pub fn used_impl() { - let _: F = Default::default(); - } - - // Function uses generic parameter from impl. - #[rustc_polymorphize_error] - pub fn used_fn() { - //~^ ERROR item has unused generic parameters - let _: G = Default::default(); - } - - // Function uses generic parameter from impl. - #[rustc_polymorphize_error] - pub fn used_both() { - let _: F = Default::default(); - let _: G = Default::default(); - } - - // Function uses generic parameter in substitutions to another function. - #[rustc_polymorphize_error] - pub fn used_substs() { - unused::() - } -} - -fn main() { - no_parameters(); - unused::(); - used_binding_value::(); - used_binding_generic::(); - used_argument(3u32); - used_substs::(); - - Foo::::unused_impl(); - Foo::::unused_both::(); - Foo::::used_impl(); - Foo::::used_fn::(); - Foo::::used_both::(); - Foo::::used_substs(); -} diff --git a/src/test/ui/polymorphization/type_parameters/functions.stderr b/src/test/ui/polymorphization/type_parameters/functions.stderr deleted file mode 100644 index be4c6576e9645..0000000000000 --- a/src/test/ui/polymorphization/type_parameters/functions.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error: item has unused generic parameters - --> $DIR/functions.rs:13:8 - | -LL | pub fn unused() { - | ^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/functions.rs:44:12 - | -LL | impl Foo { - | - generic parameter `F` is unused -... -LL | pub fn unused_impl() { - | ^^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/functions.rs:50:12 - | -LL | impl Foo { - | - generic parameter `F` is unused -... -LL | pub fn unused_both() { - | ^^^^^^^^^^^ - generic parameter `G` is unused - -error: item has unused generic parameters - --> $DIR/functions.rs:62:12 - | -LL | impl Foo { - | - generic parameter `F` is unused -... -LL | pub fn used_fn() { - | ^^^^^^^ - -error: aborting due to 4 previous errors - diff --git a/src/test/ui/polymorphization/unsized_cast.rs b/src/test/ui/polymorphization/unsized_cast.rs deleted file mode 100644 index d2f3d4f13cdcc..0000000000000 --- a/src/test/ui/polymorphization/unsized_cast.rs +++ /dev/null @@ -1,28 +0,0 @@ -// build-fail -#![feature(fn_traits, rustc_attrs, unboxed_closures)] - -// This test checks that the polymorphization analysis considers a closure -// as using all generic parameters if it does an unsizing cast. - -#[rustc_polymorphize_error] -fn foo() { - let _: T = Default::default(); - (|| Box::new(|| {}) as Box)(); - //~^ ERROR item has unused generic parameters - //~^^ ERROR item has unused generic parameters -} - -#[rustc_polymorphize_error] -fn foo2() { - let _: T = Default::default(); - (|| { - let call: extern "rust-call" fn(_, _) = Fn::call; - call(&|| {}, ()); - //~^ ERROR item has unused generic parameters - })(); -} - -fn main() { - foo::(); - foo2::(); -} diff --git a/src/test/ui/polymorphization/unsized_cast.stderr b/src/test/ui/polymorphization/unsized_cast.stderr deleted file mode 100644 index b8b96bbdf15a6..0000000000000 --- a/src/test/ui/polymorphization/unsized_cast.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error: item has unused generic parameters - --> $DIR/unsized_cast.rs:10:18 - | -LL | fn foo() { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | (|| Box::new(|| {}) as Box)(); - | ^^^^^ - -error: item has unused generic parameters - --> $DIR/unsized_cast.rs:10:5 - | -LL | fn foo() { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | (|| Box::new(|| {}) as Box)(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/unsized_cast.rs:20:15 - | -LL | fn foo2() { - | - generic parameter `T` is unused -... -LL | call(&|| {}, ()); - | ^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/print_type_sizes/niche-filling.stdout b/src/test/ui/print_type_sizes/niche-filling.stdout index 1894cd218ee34..301edc0d086b1 100644 --- a/src/test/ui/print_type_sizes/niche-filling.stdout +++ b/src/test/ui/print_type_sizes/niche-filling.stdout @@ -8,12 +8,12 @@ print-type-size variant `Some`: 12 bytes print-type-size field `.0`: 12 bytes print-type-size variant `None`: 0 bytes print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes -print-type-size discriminant: 1 bytes print-type-size variant `Record`: 7 bytes -print-type-size field `.pre`: 1 bytes -print-type-size field `.post`: 2 bytes print-type-size field `.val`: 4 bytes +print-type-size field `.post`: 2 bytes +print-type-size field `.pre`: 1 bytes print-type-size variant `None`: 0 bytes +print-type-size end padding: 1 bytes print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes print-type-size discriminant: 4 bytes print-type-size variant `Some`: 4 bytes diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs index 310545b92d549..3fb1cf9f557b2 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs @@ -1,5 +1,6 @@ #![feature(non_ascii_idents)] extern crate ьаг; //~ ERROR cannot load a crate with a non-ascii name `ьаг` +//~| ERROR can't find crate for `ьаг` fn main() {} diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr index 11108f2fb8678..1e424237fd238 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr @@ -4,5 +4,12 @@ error: cannot load a crate with a non-ascii name `ьаг` LL | extern crate ьаг; | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0463]: can't find crate for `ьаг` + --> $DIR/crate_name_nonascii_forbidden-1.rs:3:1 + | +LL | extern crate ьаг; + | ^^^^^^^^^^^^^^^^^ can't find crate + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs index 0249848b35ac0..e1acdbff06189 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs @@ -3,5 +3,7 @@ #![feature(non_ascii_idents)] use му_сгате::baz; //~ ERROR cannot load a crate with a non-ascii name `му_сгате` + //~| can't find crate for `му_сгате` + fn main() {} diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr index 8d3548ed33dcf..c06405ebb37ec 100644 --- a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr @@ -4,5 +4,12 @@ error: cannot load a crate with a non-ascii name `му_сгате` LL | use му_сгате::baz; | ^^^^^^^^ -error: aborting due to previous error +error[E0463]: can't find crate for `му_сгате` + --> $DIR/crate_name_nonascii_forbidden-2.rs:5:5 + | +LL | use му_сгате::baz; + | ^^^^^^^^ can't find crate + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/specialization/min_specialization/impl-on-nonexisting.rs b/src/test/ui/specialization/min_specialization/impl-on-nonexisting.rs deleted file mode 100644 index 77a64320d6f37..0000000000000 --- a/src/test/ui/specialization/min_specialization/impl-on-nonexisting.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(min_specialization)] - -trait Trait {} -impl Trait for NonExistent {} -//~^ ERROR cannot find type `NonExistent` in this scope - -fn main() {} diff --git a/src/test/ui/specialization/min_specialization/impl-on-nonexisting.stderr b/src/test/ui/specialization/min_specialization/impl-on-nonexisting.stderr deleted file mode 100644 index b032ccbe53ffc..0000000000000 --- a/src/test/ui/specialization/min_specialization/impl-on-nonexisting.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0412]: cannot find type `NonExistent` in this scope - --> $DIR/impl-on-nonexisting.rs:4:16 - | -LL | impl Trait for NonExistent {} - | ^^^^^^^^^^^ not found in this scope - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/traits/issue-72410.rs b/src/test/ui/traits/issue-72410.rs deleted file mode 100644 index c95f1dfdca53a..0000000000000 --- a/src/test/ui/traits/issue-72410.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Regression test for #72410, this should be used with debug assertion enabled. - -// should be fine -pub trait Foo { - fn map() - where - Self: Sized, - for<'a> &'a mut [u8]: ; -} - -// should fail -pub trait Bar { - fn map() - where for<'a> &'a mut [dyn Bar]: ; - //~^ ERROR: the trait `Bar` cannot be made into an object -} - -fn main() {} diff --git a/src/test/ui/traits/issue-72410.stderr b/src/test/ui/traits/issue-72410.stderr deleted file mode 100644 index 1db2320841ff7..0000000000000 --- a/src/test/ui/traits/issue-72410.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-72410.rs:14:19 - | -LL | pub trait Bar { - | --- this trait cannot be made into an object... -LL | fn map() - | --- ...because associated function `map` has no `self` parameter -LL | where for<'a> &'a mut [dyn Bar]: ; - | ^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object - | -help: consider turning `map` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects - | -LL | where for<'a> &'a mut [dyn Bar]:, Self: Sized ; - | ^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/type-sizes.rs b/src/test/ui/type-sizes.rs index 73a11a5e743f6..6a3f3c98f127a 100644 --- a/src/test/ui/type-sizes.rs +++ b/src/test/ui/type-sizes.rs @@ -5,7 +5,6 @@ #![feature(never_type)] use std::mem::size_of; -use std::num::NonZeroU8; struct t {a: u8, b: i8} struct u {a: u8, b: i8, c: u8} @@ -103,23 +102,6 @@ enum Option2 { None } -// Two layouts are considered for `CanBeNicheFilledButShouldnt`: -// Niche-filling: -// { u32 (4 bytes), NonZeroU8 + tag in niche (1 byte), padding (3 bytes) } -// Tagged: -// { tag (1 byte), NonZeroU8 (1 byte), padding (2 bytes), u32 (4 bytes) } -// Both are the same size (due to padding), -// but the tagged layout is better as the tag creates a niche with 254 invalid values, -// allowing types like `Option>` to fit into 8 bytes. -pub enum CanBeNicheFilledButShouldnt { - A(NonZeroU8, u32), - B -} -pub enum AlwaysTaggedBecauseItHasNoNiche { - A(u8, u32), - B -} - pub fn main() { assert_eq!(size_of::(), 1 as usize); assert_eq!(size_of::(), 4 as usize); @@ -163,11 +145,4 @@ pub fn main() { assert_eq!(size_of::>>(), size_of::<(bool, &())>()); assert_eq!(size_of::>>(), size_of::<(bool, &())>()); assert_eq!(size_of::>>(), size_of::<(bool, &())>()); - - assert_eq!(size_of::(), 8); - assert_eq!(size_of::>(), 8); - assert_eq!(size_of::>>(), 8); - assert_eq!(size_of::(), 8); - assert_eq!(size_of::>(), 8); - assert_eq!(size_of::>>(), 8); } diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.rs b/src/test/ui/wf/wf-foreign-fn-decl-ret.rs deleted file mode 100644 index b9d956c056869..0000000000000 --- a/src/test/ui/wf/wf-foreign-fn-decl-ret.rs +++ /dev/null @@ -1,18 +0,0 @@ -pub trait Unsatisfied {} - -#[repr(transparent)] -pub struct Bar(T); - -pub trait Foo { - type Assoc; -} - -extern "C" { - pub fn lint_me() -> <() as Foo>::Assoc; - //~^ ERROR: the trait bound `(): Foo` is not satisfied [E0277] - - pub fn lint_me_aswell() -> Bar; - //~^ ERROR: the trait bound `u32: Unsatisfied` is not satisfied [E0277] -} - -fn main() {} diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr deleted file mode 100644 index 9081b7929d935..0000000000000 --- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/wf-foreign-fn-decl-ret.rs:11:5 - | -LL | pub fn lint_me() -> <() as Foo>::Assoc; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` - -error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied - --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 - | -LL | pub struct Bar(T); - | ----------- required by this bound in `Bar` -... -LL | pub fn lint_me_aswell() -> Bar; - | ^^^^^^^^ the trait `Unsatisfied` is not implemented for `u32` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index a4bee1c278059..4b163fba52890 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -1346,7 +1346,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { .predicates .iter() .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); - traits::impossible_predicates( + !traits::normalize_and_test_predicates( cx.tcx, traits::elaborate_predicates(cx.tcx, predicates) .map(|o| o.predicate) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 5f7373be65946..703b87634cec3 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -186,9 +186,6 @@ pub struct Config { /// The rustdoc executable. pub rustdoc_path: Option, - /// The rust-demangler executable. - pub rust_demangler_path: Option, - /// The Python executable to use for LLDB. pub lldb_python: String, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 07eba22c6eeb3..97272f1a9c1b6 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -53,7 +53,6 @@ pub fn parse_config(args: Vec) -> Config { .reqopt("", "run-lib-path", "path to target shared libraries", "PATH") .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH") .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") - .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH") .reqopt("", "lldb-python", "path to python to use for doc tests", "PATH") .reqopt("", "docck-python", "path to python to use for doc tests", "PATH") .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM") @@ -183,7 +182,6 @@ pub fn parse_config(args: Vec) -> Config { run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), rustc_path: opt_path(matches, "rustc-path"), rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from), - rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from), lldb_python: matches.opt_str("lldb-python").unwrap(), docck_python: matches.opt_str("docck-python").unwrap(), valgrind_path: matches.opt_str("valgrind-path"), @@ -248,7 +246,6 @@ pub fn log_config(config: &Config) { logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); - logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path)); logv(c, format!("src_base: {:?}", config.src_base.display())); logv(c, format!("build_base: {:?}", config.build_base.display())); logv(c, format!("stage_id: {}", config.stage_id)); @@ -482,8 +479,6 @@ fn common_inputs_stamp(config: &Config) -> Stamp { stamp.add_path(&rustdoc_path); stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py")); } - // FIXME(richkadel): Do I need to add an `if let Some(rust_demangler_path) contribution to the - // stamp here as well? // Compiletest itself. stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/")); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f09f7621aa170..dd0c68ecd4965 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2739,10 +2739,6 @@ impl<'test> TestCx<'test> { cmd.env("RUSTDOC", cwd.join(rustdoc)); } - if let Some(ref rust_demangler) = self.config.rust_demangler_path { - cmd.env("RUST_DEMANGLER", cwd.join(rust_demangler)); - } - if let Some(ref node) = self.config.nodejs { cmd.env("NODE", node); } diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 194318d7a59b5..74601f9e4c679 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -23,32 +23,6 @@ use std::rc::Rc; use crate::Redirect::*; -// Add linkcheck exceptions here -// If at all possible you should use intra-doc links to avoid linkcheck issues. These -// are cases where that does not work -// [(generated_documentation_page, &[broken_links])] -const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[ - // These are methods on slice, and `Self` does not work on primitive impls - // in intra-doc links (primitive impls are weird) - // https://github.com/rust-lang/rust/issues/62834 is necessary to be - // able to link to slices - ( - "std/io/struct.IoSlice.html", - &[ - "#method.as_mut_ptr", - "#method.sort_by_key", - "#method.make_ascii_uppercase", - "#method.make_ascii_lowercase", - ], - ), - // These try to link to std::collections, but are defined in alloc - // https://github.com/rust-lang/rust/issues/74481 - ("std/collections/btree_map/struct.BTreeMap.html", &["#insert-and-complex-keys"]), - ("std/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]), - ("alloc/collections/btree_map/struct.BTreeMap.html", &["#insert-and-complex-keys"]), - ("alloc/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]), -]; - macro_rules! t { ($e:expr) => { match $e { @@ -137,20 +111,35 @@ fn walk(cache: &mut Cache, root: &Path, dir: &Path, errors: &mut bool) { } } -fn is_exception(file: &Path, link: &str) -> bool { - if let Some(entry) = LINKCHECK_EXCEPTIONS.iter().find(|&(f, _)| file.ends_with(f)) { - entry.1.contains(&link) - } else { - false - } -} - fn check(cache: &mut Cache, root: &Path, file: &Path, errors: &mut bool) -> Option { // Ignore non-HTML files. if file.extension().and_then(|s| s.to_str()) != Some("html") { return None; } + // Unfortunately we're not 100% full of valid links today to we need a few + // exceptions to get this past `make check` today. + // FIXME(#32129) + if file.ends_with("std/io/struct.IoSlice.html") + || file.ends_with("std/string/struct.String.html") + { + return None; + } + // FIXME(#32553) + if file.ends_with("alloc/string/struct.String.html") { + return None; + } + // FIXME(#32130) + if file.ends_with("alloc/collections/btree_map/struct.BTreeMap.html") + || file.ends_with("alloc/collections/btree_set/struct.BTreeSet.html") + || file.ends_with("std/collections/btree_map/struct.BTreeMap.html") + || file.ends_with("std/collections/btree_set/struct.BTreeSet.html") + || file.ends_with("std/collections/hash_map/struct.HashMap.html") + || file.ends_with("std/collections/hash_set/struct.HashSet.html") + { + return None; + } + let res = load_file(cache, root, file, SkipRedirect); let (pretty_file, contents) = match res { Ok(res) => res, @@ -265,20 +254,17 @@ fn check(cache: &mut Cache, root: &Path, file: &Path, errors: &mut bool) -> Opti let entry = &mut cache.get_mut(&pretty_path).unwrap(); entry.parse_ids(&pretty_path, &contents, errors); - if !entry.ids.contains(*fragment) && !is_exception(file, &format!("#{}", fragment)) - { + if !entry.ids.contains(*fragment) { *errors = true; print!("{}:{}: broken link fragment ", pretty_file.display(), i + 1); println!("`#{}` pointing to `{}`", fragment, pretty_path.display()); }; } } else { + *errors = true; + print!("{}:{}: broken link - ", pretty_file.display(), i + 1); let pretty_path = path.strip_prefix(root).unwrap_or(&path); - if !is_exception(file, pretty_path.to_str().unwrap()) { - *errors = true; - print!("{}:{}: broken link - ", pretty_file.display(), i + 1); - println!("{}", pretty_path.display()); - } + println!("{}", pretty_path.display()); } }); Some(pretty_file) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index c0631fcedd349..72437e070044c 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -26,7 +26,7 @@ MAINTAINERS = { 'miri': {'oli-obk', 'RalfJung', 'eddyb'}, 'rls': {'Xanewok'}, - 'rustfmt': {'topecongiro', 'calebcartwright'}, + 'rustfmt': {'topecongiro'}, 'book': {'carols10cents', 'steveklabnik'}, 'nomicon': {'frewsxcv', 'Gankra'}, 'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'}, diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index c9c518e5e9761..8b0983e89ad9a 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit c9c518e5e9761bf35d466c47c57c3a1358b56b3c +Subproject commit 8b0983e89ad9a28b142eccf3755a8c9aaeb37852 diff --git a/src/tools/rust-demangler/Cargo.toml b/src/tools/rust-demangler/Cargo.toml deleted file mode 100644 index 0b8d974d2558a..0000000000000 --- a/src/tools/rust-demangler/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "rust-demangler" -version = "0.0.0" -edition = "2018" - -[dependencies] -rustc-demangle = "0.1" - -[[bin]] -name = "rust-demangler" -path = "main.rs" diff --git a/src/tools/rust-demangler/main.rs b/src/tools/rust-demangler/main.rs deleted file mode 100644 index a9f1011c450a9..0000000000000 --- a/src/tools/rust-demangler/main.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! Demangles rustc mangled names. -//! -//! This tool uses https://crates.io/crates/rustc-demangle to convert an input buffer of -//! newline-separated mangled names into their demangled translations. -//! -//! This tool can be leveraged by other applications that support third-party demanglers. -//! It takes a list of mangled names (one per line) on standard input, and prints a corresponding -//! list of demangled names. The tool is designed to support other programs that can leverage a -//! third-party demangler, such as `llvm-cov`, via the `-Xdemangler=` option. -//! -//! To use `rust-demangler`, first build the tool with: -//! -//! ```shell -//! $ ./x.py build rust-demangler -//! ``` -//! -//! Then, with `llvm-cov` for example, add the `-Xdemangler=...` option: -//! -//! ```shell -//! $ TARGET="${PWD}/build/x86_64-unknown-linux-gnu" -//! $ "${TARGET}"/llvm/bin/llvm-cov show --Xdemangler="${TARGET}"/stage0-tools-bin/rust-demangler \ -//! --instr-profile=main.profdata ./main --show-line-counts-or-regions -//! ``` - -use rustc_demangle::demangle; -use std::io::{self, Read, Write}; - -fn main() -> io::Result<()> { - let mut buffer = String::new(); - io::stdin().read_to_string(&mut buffer)?; - let lines = buffer.lines(); - let mut demangled = Vec::new(); - for mangled in lines { - demangled.push(demangle(mangled).to_string()); - } - demangled.push("".to_string()); - io::stdout().write_all(demangled.join("\n").as_bytes())?; - Ok(()) -} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 36bd1ab6c1078..b7d3d428cd283 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -17,7 +17,6 @@ const LICENSES: &[&str] = &[ "MIT", "Unlicense/MIT", "Unlicense OR MIT", - "0BSD OR MIT OR Apache-2.0", // adler license ]; /// These are exceptions to Rust's permissive licensing policy, and @@ -37,6 +36,7 @@ const EXCEPTIONS: &[(&str, &str)] = &[ ("ryu", "Apache-2.0 OR BSL-1.0"), // rls/cargo/... (because of serde) ("bytesize", "Apache-2.0"), // cargo ("im-rc", "MPL-2.0+"), // cargo + ("adler32", "BSD-3-Clause AND Zlib"), // cargo dep that isn't used ("constant_time_eq", "CC0-1.0"), // rustfmt ("sized-chunks", "MPL-2.0+"), // cargo via im-rc ("bitmaps", "MPL-2.0+"), // cargo via im-rc @@ -57,8 +57,7 @@ const RESTRICTED_DEPENDENCY_CRATES: &[&str] = &["rustc_middle", "rustc_codegen_l /// This list is here to provide a speed-bump to adding a new dependency to /// rustc. Please check with the compiler team before adding an entry. const PERMITTED_DEPENDENCIES: &[&str] = &[ - "addr2line", - "adler", + "adler32", "aho-corasick", "annotate-snippets", "ansi_term", @@ -66,6 +65,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "atty", "autocfg", "backtrace", + "backtrace-sys", "bitflags", "block-buffer", "block-padding", @@ -98,7 +98,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "generic-array", "getopts", "getrandom", - "gimli", "hashbrown", "hermit-abi", "humantime", @@ -120,12 +119,10 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "miniz_oxide", "nodrop", "num_cpus", - "object", "once_cell", "opaque-debug", "parking_lot", "parking_lot_core", - "pathdiff", "pkg-config", "polonius-engine", "ppv-lite86", diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs index 51f135d376161..3af71f69d2457 100644 --- a/src/tools/tidy/src/error_codes_check.rs +++ b/src/tools/tidy/src/error_codes_check.rs @@ -8,11 +8,11 @@ use std::path::Path; // A few of those error codes can't be tested but all the others can and *should* be tested! const EXEMPTED_FROM_TEST: &[&str] = &[ - "E0183", "E0227", "E0279", "E0280", "E0311", "E0313", "E0314", "E0315", "E0377", "E0461", - "E0462", "E0464", "E0465", "E0472", "E0473", "E0474", "E0475", "E0476", "E0479", "E0480", - "E0481", "E0482", "E0483", "E0484", "E0485", "E0486", "E0487", "E0488", "E0489", "E0514", - "E0519", "E0523", "E0553", "E0554", "E0570", "E0629", "E0630", "E0640", "E0717", "E0727", - "E0729", + "E0183", "E0227", "E0279", "E0280", "E0311", "E0313", "E0314", "E0315", "E0377", "E0456", + "E0461", "E0462", "E0464", "E0465", "E0472", "E0473", "E0474", "E0475", "E0476", "E0479", + "E0480", "E0481", "E0482", "E0483", "E0484", "E0485", "E0486", "E0487", "E0488", "E0489", + "E0514", "E0519", "E0523", "E0553", "E0554", "E0570", "E0629", "E0630", "E0640", "E0717", + "E0727", "E0729", ]; // Some error codes don't have any tests apparently... diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index c0671596e19f1..b4aafb815fc6b 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -60,7 +60,6 @@ fn filter_dirs(path: &Path) -> bool { "src/tools/rust-installer", "src/tools/rustfmt", "src/doc/book", - "src/backtrace", // Filter RLS output directories "target/rls", ];