mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-26 13:54:06 +00:00
Auto merge of #74408 - Manishearth:rollup-9gxn4od, r=Manishearth
Rollup of 21 pull requests Successful merges: - #73566 (Don't run `everybody_loops` for rustdoc; instead ignore resolution errors) - #73771 (Don't pollute docs/suggestions with libstd deps) - #73794 (Small cleanup for E0705 explanation) - #73807 (rustdoc: glue tokens before highlighting) - #73835 (Clean up E0710 explanation) - #73926 (Ignoring test case: [codegen] repr-transparent-aggregates-1.rs for aarch64) - #73981 (Remove some `ignore-stage1` annotations.) - #73998 (add regression test for #61216) - #74140 (Make hir ProjectionKind more precise) - #74148 (Move #[doc(alias)] check in rustc) - #74159 (forbid generic params in the type of const params) - #74171 (Fix 44056 test with debug on macos.) - #74221 (Don't panic if the lhs of a div by zero is not statically known) - #74325 (Focus on the current file in the source file sidebar) - #74359 (rustdoc: Rename internal API fns to `into_string`) - #74370 (Reintroduce spotlight / "important traits" feature) - #74390 (Fix typo in std::mem::transmute documentation) - #74391 (BtreeMap: superficially refactor root access) - #74392 (const generics triage) - #74397 (Fix typo in the latest release note) - #74406 (Set shell for github actions CI) Failed merges: r? @ghost
This commit is contained in:
commit
5c9e5df3a0
77
.github/workflows/ci.yml
vendored
77
.github/workflows/ci.yml
vendored
@ -66,59 +66,77 @@ jobs:
|
|||||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||||
- name: add extra environment variables
|
- name: add extra environment variables
|
||||||
run: src/ci/scripts/setup-environment.sh
|
run: src/ci/scripts/setup-environment.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: decide whether to skip this job
|
- name: decide whether to skip this job
|
||||||
run: src/ci/scripts/should-skip-this.sh
|
run: src/ci/scripts/should-skip-this.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: collect CPU statistics
|
- name: collect CPU statistics
|
||||||
run: src/ci/scripts/collect-cpu-stats.sh
|
run: src/ci/scripts/collect-cpu-stats.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: show the current environment
|
- name: show the current environment
|
||||||
run: src/ci/scripts/dump-environment.sh
|
run: src/ci/scripts/dump-environment.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install awscli
|
- name: install awscli
|
||||||
run: src/ci/scripts/install-awscli.sh
|
run: src/ci/scripts/install-awscli.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install sccache
|
- name: install sccache
|
||||||
run: src/ci/scripts/install-sccache.sh
|
run: src/ci/scripts/install-sccache.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install clang
|
- name: install clang
|
||||||
run: src/ci/scripts/install-clang.sh
|
run: src/ci/scripts/install-clang.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install WIX
|
- name: install WIX
|
||||||
run: src/ci/scripts/install-wix.sh
|
run: src/ci/scripts/install-wix.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: ensure the build happens on a partition with enough space
|
- name: ensure the build happens on a partition with enough space
|
||||||
run: src/ci/scripts/symlink-build-dir.sh
|
run: src/ci/scripts/symlink-build-dir.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install MSYS2
|
- name: install MSYS2
|
||||||
run: src/ci/scripts/install-msys2.sh
|
run: src/ci/scripts/install-msys2.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install MinGW
|
- name: install MinGW
|
||||||
run: src/ci/scripts/install-mingw.sh
|
run: src/ci/scripts/install-mingw.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install ninja
|
- name: install ninja
|
||||||
run: src/ci/scripts/install-ninja.sh
|
run: src/ci/scripts/install-ninja.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: enable ipv6 on Docker
|
- name: enable ipv6 on Docker
|
||||||
run: src/ci/scripts/enable-docker-ipv6.sh
|
run: src/ci/scripts/enable-docker-ipv6.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: checkout submodules
|
- name: checkout submodules
|
||||||
run: src/ci/scripts/checkout-submodules.sh
|
run: src/ci/scripts/checkout-submodules.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: ensure line endings are correct
|
- name: ensure line endings are correct
|
||||||
run: src/ci/scripts/verify-line-endings.sh
|
run: src/ci/scripts/verify-line-endings.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: run the build
|
- name: run the build
|
||||||
run: src/ci/scripts/run-build-from-ci.sh
|
run: src/ci/scripts/run-build-from-ci.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
|
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)] }}"
|
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
|
||||||
@ -126,6 +144,7 @@ jobs:
|
|||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: upload artifacts to S3
|
- name: upload artifacts to S3
|
||||||
run: src/ci/scripts/upload-artifacts.sh
|
run: src/ci/scripts/upload-artifacts.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
|
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)] }}"
|
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||||
@ -166,59 +185,77 @@ jobs:
|
|||||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||||
- name: add extra environment variables
|
- name: add extra environment variables
|
||||||
run: src/ci/scripts/setup-environment.sh
|
run: src/ci/scripts/setup-environment.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: decide whether to skip this job
|
- name: decide whether to skip this job
|
||||||
run: src/ci/scripts/should-skip-this.sh
|
run: src/ci/scripts/should-skip-this.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: collect CPU statistics
|
- name: collect CPU statistics
|
||||||
run: src/ci/scripts/collect-cpu-stats.sh
|
run: src/ci/scripts/collect-cpu-stats.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: show the current environment
|
- name: show the current environment
|
||||||
run: src/ci/scripts/dump-environment.sh
|
run: src/ci/scripts/dump-environment.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install awscli
|
- name: install awscli
|
||||||
run: src/ci/scripts/install-awscli.sh
|
run: src/ci/scripts/install-awscli.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install sccache
|
- name: install sccache
|
||||||
run: src/ci/scripts/install-sccache.sh
|
run: src/ci/scripts/install-sccache.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install clang
|
- name: install clang
|
||||||
run: src/ci/scripts/install-clang.sh
|
run: src/ci/scripts/install-clang.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install WIX
|
- name: install WIX
|
||||||
run: src/ci/scripts/install-wix.sh
|
run: src/ci/scripts/install-wix.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: ensure the build happens on a partition with enough space
|
- name: ensure the build happens on a partition with enough space
|
||||||
run: src/ci/scripts/symlink-build-dir.sh
|
run: src/ci/scripts/symlink-build-dir.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install MSYS2
|
- name: install MSYS2
|
||||||
run: src/ci/scripts/install-msys2.sh
|
run: src/ci/scripts/install-msys2.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install MinGW
|
- name: install MinGW
|
||||||
run: src/ci/scripts/install-mingw.sh
|
run: src/ci/scripts/install-mingw.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install ninja
|
- name: install ninja
|
||||||
run: src/ci/scripts/install-ninja.sh
|
run: src/ci/scripts/install-ninja.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: enable ipv6 on Docker
|
- name: enable ipv6 on Docker
|
||||||
run: src/ci/scripts/enable-docker-ipv6.sh
|
run: src/ci/scripts/enable-docker-ipv6.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: checkout submodules
|
- name: checkout submodules
|
||||||
run: src/ci/scripts/checkout-submodules.sh
|
run: src/ci/scripts/checkout-submodules.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: ensure line endings are correct
|
- name: ensure line endings are correct
|
||||||
run: src/ci/scripts/verify-line-endings.sh
|
run: src/ci/scripts/verify-line-endings.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: run the build
|
- name: run the build
|
||||||
run: src/ci/scripts/run-build-from-ci.sh
|
run: src/ci/scripts/run-build-from-ci.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
|
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)] }}"
|
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
|
||||||
@ -226,6 +263,7 @@ jobs:
|
|||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: upload artifacts to S3
|
- name: upload artifacts to S3
|
||||||
run: src/ci/scripts/upload-artifacts.sh
|
run: src/ci/scripts/upload-artifacts.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
|
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)] }}"
|
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||||
@ -484,59 +522,77 @@ jobs:
|
|||||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||||
- name: add extra environment variables
|
- name: add extra environment variables
|
||||||
run: src/ci/scripts/setup-environment.sh
|
run: src/ci/scripts/setup-environment.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: decide whether to skip this job
|
- name: decide whether to skip this job
|
||||||
run: src/ci/scripts/should-skip-this.sh
|
run: src/ci/scripts/should-skip-this.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: collect CPU statistics
|
- name: collect CPU statistics
|
||||||
run: src/ci/scripts/collect-cpu-stats.sh
|
run: src/ci/scripts/collect-cpu-stats.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: show the current environment
|
- name: show the current environment
|
||||||
run: src/ci/scripts/dump-environment.sh
|
run: src/ci/scripts/dump-environment.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install awscli
|
- name: install awscli
|
||||||
run: src/ci/scripts/install-awscli.sh
|
run: src/ci/scripts/install-awscli.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install sccache
|
- name: install sccache
|
||||||
run: src/ci/scripts/install-sccache.sh
|
run: src/ci/scripts/install-sccache.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install clang
|
- name: install clang
|
||||||
run: src/ci/scripts/install-clang.sh
|
run: src/ci/scripts/install-clang.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install WIX
|
- name: install WIX
|
||||||
run: src/ci/scripts/install-wix.sh
|
run: src/ci/scripts/install-wix.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: ensure the build happens on a partition with enough space
|
- name: ensure the build happens on a partition with enough space
|
||||||
run: src/ci/scripts/symlink-build-dir.sh
|
run: src/ci/scripts/symlink-build-dir.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install MSYS2
|
- name: install MSYS2
|
||||||
run: src/ci/scripts/install-msys2.sh
|
run: src/ci/scripts/install-msys2.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install MinGW
|
- name: install MinGW
|
||||||
run: src/ci/scripts/install-mingw.sh
|
run: src/ci/scripts/install-mingw.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install ninja
|
- name: install ninja
|
||||||
run: src/ci/scripts/install-ninja.sh
|
run: src/ci/scripts/install-ninja.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: enable ipv6 on Docker
|
- name: enable ipv6 on Docker
|
||||||
run: src/ci/scripts/enable-docker-ipv6.sh
|
run: src/ci/scripts/enable-docker-ipv6.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: checkout submodules
|
- name: checkout submodules
|
||||||
run: src/ci/scripts/checkout-submodules.sh
|
run: src/ci/scripts/checkout-submodules.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: ensure line endings are correct
|
- name: ensure line endings are correct
|
||||||
run: src/ci/scripts/verify-line-endings.sh
|
run: src/ci/scripts/verify-line-endings.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: run the build
|
- name: run the build
|
||||||
run: src/ci/scripts/run-build-from-ci.sh
|
run: src/ci/scripts/run-build-from-ci.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
|
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)] }}"
|
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
|
||||||
@ -544,6 +600,7 @@ jobs:
|
|||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: upload artifacts to S3
|
- name: upload artifacts to S3
|
||||||
run: src/ci/scripts/upload-artifacts.sh
|
run: src/ci/scripts/upload-artifacts.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
|
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)] }}"
|
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||||
@ -610,59 +667,77 @@ jobs:
|
|||||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||||
- name: add extra environment variables
|
- name: add extra environment variables
|
||||||
run: src/ci/scripts/setup-environment.sh
|
run: src/ci/scripts/setup-environment.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: decide whether to skip this job
|
- name: decide whether to skip this job
|
||||||
run: src/ci/scripts/should-skip-this.sh
|
run: src/ci/scripts/should-skip-this.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: collect CPU statistics
|
- name: collect CPU statistics
|
||||||
run: src/ci/scripts/collect-cpu-stats.sh
|
run: src/ci/scripts/collect-cpu-stats.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: show the current environment
|
- name: show the current environment
|
||||||
run: src/ci/scripts/dump-environment.sh
|
run: src/ci/scripts/dump-environment.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install awscli
|
- name: install awscli
|
||||||
run: src/ci/scripts/install-awscli.sh
|
run: src/ci/scripts/install-awscli.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install sccache
|
- name: install sccache
|
||||||
run: src/ci/scripts/install-sccache.sh
|
run: src/ci/scripts/install-sccache.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install clang
|
- name: install clang
|
||||||
run: src/ci/scripts/install-clang.sh
|
run: src/ci/scripts/install-clang.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install WIX
|
- name: install WIX
|
||||||
run: src/ci/scripts/install-wix.sh
|
run: src/ci/scripts/install-wix.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: ensure the build happens on a partition with enough space
|
- name: ensure the build happens on a partition with enough space
|
||||||
run: src/ci/scripts/symlink-build-dir.sh
|
run: src/ci/scripts/symlink-build-dir.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install MSYS2
|
- name: install MSYS2
|
||||||
run: src/ci/scripts/install-msys2.sh
|
run: src/ci/scripts/install-msys2.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install MinGW
|
- name: install MinGW
|
||||||
run: src/ci/scripts/install-mingw.sh
|
run: src/ci/scripts/install-mingw.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: install ninja
|
- name: install ninja
|
||||||
run: src/ci/scripts/install-ninja.sh
|
run: src/ci/scripts/install-ninja.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: enable ipv6 on Docker
|
- name: enable ipv6 on Docker
|
||||||
run: src/ci/scripts/enable-docker-ipv6.sh
|
run: src/ci/scripts/enable-docker-ipv6.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: checkout submodules
|
- name: checkout submodules
|
||||||
run: src/ci/scripts/checkout-submodules.sh
|
run: src/ci/scripts/checkout-submodules.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: ensure line endings are correct
|
- name: ensure line endings are correct
|
||||||
run: src/ci/scripts/verify-line-endings.sh
|
run: src/ci/scripts/verify-line-endings.sh
|
||||||
|
shell: bash
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: run the build
|
- name: run the build
|
||||||
run: src/ci/scripts/run-build-from-ci.sh
|
run: src/ci/scripts/run-build-from-ci.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
|
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)] }}"
|
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
|
||||||
@ -670,6 +745,7 @@ jobs:
|
|||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
- name: upload artifacts to S3
|
- name: upload artifacts to S3
|
||||||
run: src/ci/scripts/upload-artifacts.sh
|
run: src/ci/scripts/upload-artifacts.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
|
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)] }}"
|
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||||
@ -694,6 +770,7 @@ jobs:
|
|||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: publish toolstate
|
- name: publish toolstate
|
||||||
run: src/ci/publish_toolstate.sh
|
run: src/ci/publish_toolstate.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}"
|
TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}"
|
||||||
if: success() && !env.SKIP_JOB
|
if: success() && !env.SKIP_JOB
|
||||||
|
@ -47,7 +47,7 @@ Libraries
|
|||||||
// Prints "abcdefghijklmnopqrstuvwxyz"
|
// Prints "abcdefghijklmnopqrstuvwxyz"
|
||||||
```
|
```
|
||||||
- [`OsString` now implements `FromStr`.][71662]
|
- [`OsString` now implements `FromStr`.][71662]
|
||||||
- [The `saturating_neg` method as been added to all signed integer primitive
|
- [The `saturating_neg` method has been added to all signed integer primitive
|
||||||
types, and the `saturating_abs` method has been added for all integer
|
types, and the `saturating_abs` method has been added for all integer
|
||||||
primitive types.][71886]
|
primitive types.][71886]
|
||||||
- [`Arc<T>`, `Rc<T>` now implement `From<Cow<'_, T>>`, and `Box` now
|
- [`Arc<T>`, `Rc<T>` now implement `From<Cow<'_, T>>`, and `Box` now
|
||||||
|
@ -95,6 +95,7 @@ x--expand-yaml-anchors--remove:
|
|||||||
|
|
||||||
- name: add extra environment variables
|
- name: add extra environment variables
|
||||||
run: src/ci/scripts/setup-environment.sh
|
run: src/ci/scripts/setup-environment.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
# Since it's not possible to merge `${{ matrix.env }}` with the other
|
# Since it's not possible to merge `${{ matrix.env }}` with the other
|
||||||
# variables in `job.<name>.env`, the variables defined in the matrix
|
# variables in `job.<name>.env`, the variables defined in the matrix
|
||||||
@ -105,54 +106,67 @@ x--expand-yaml-anchors--remove:
|
|||||||
|
|
||||||
- name: decide whether to skip this job
|
- name: decide whether to skip this job
|
||||||
run: src/ci/scripts/should-skip-this.sh
|
run: src/ci/scripts/should-skip-this.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: collect CPU statistics
|
- name: collect CPU statistics
|
||||||
run: src/ci/scripts/collect-cpu-stats.sh
|
run: src/ci/scripts/collect-cpu-stats.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: show the current environment
|
- name: show the current environment
|
||||||
run: src/ci/scripts/dump-environment.sh
|
run: src/ci/scripts/dump-environment.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: install awscli
|
- name: install awscli
|
||||||
run: src/ci/scripts/install-awscli.sh
|
run: src/ci/scripts/install-awscli.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: install sccache
|
- name: install sccache
|
||||||
run: src/ci/scripts/install-sccache.sh
|
run: src/ci/scripts/install-sccache.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: install clang
|
- name: install clang
|
||||||
run: src/ci/scripts/install-clang.sh
|
run: src/ci/scripts/install-clang.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: install WIX
|
- name: install WIX
|
||||||
run: src/ci/scripts/install-wix.sh
|
run: src/ci/scripts/install-wix.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: ensure the build happens on a partition with enough space
|
- name: ensure the build happens on a partition with enough space
|
||||||
run: src/ci/scripts/symlink-build-dir.sh
|
run: src/ci/scripts/symlink-build-dir.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: install MSYS2
|
- name: install MSYS2
|
||||||
run: src/ci/scripts/install-msys2.sh
|
run: src/ci/scripts/install-msys2.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: install MinGW
|
- name: install MinGW
|
||||||
run: src/ci/scripts/install-mingw.sh
|
run: src/ci/scripts/install-mingw.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: install ninja
|
- name: install ninja
|
||||||
run: src/ci/scripts/install-ninja.sh
|
run: src/ci/scripts/install-ninja.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: enable ipv6 on Docker
|
- name: enable ipv6 on Docker
|
||||||
run: src/ci/scripts/enable-docker-ipv6.sh
|
run: src/ci/scripts/enable-docker-ipv6.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
# Disable automatic line ending conversion (again). On Windows, when we're
|
# Disable automatic line ending conversion (again). On Windows, when we're
|
||||||
@ -162,18 +176,22 @@ x--expand-yaml-anchors--remove:
|
|||||||
# appropriate line endings.
|
# appropriate line endings.
|
||||||
- name: disable git crlf conversion
|
- name: disable git crlf conversion
|
||||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: checkout submodules
|
- name: checkout submodules
|
||||||
run: src/ci/scripts/checkout-submodules.sh
|
run: src/ci/scripts/checkout-submodules.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: ensure line endings are correct
|
- name: ensure line endings are correct
|
||||||
run: src/ci/scripts/verify-line-endings.sh
|
run: src/ci/scripts/verify-line-endings.sh
|
||||||
|
shell: bash
|
||||||
<<: *step
|
<<: *step
|
||||||
|
|
||||||
- name: run the build
|
- name: run the build
|
||||||
run: src/ci/scripts/run-build-from-ci.sh
|
run: src/ci/scripts/run-build-from-ci.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: ${{ env.CACHES_AWS_ACCESS_KEY_ID }}
|
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)] }}
|
AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}
|
||||||
@ -182,6 +200,7 @@ x--expand-yaml-anchors--remove:
|
|||||||
|
|
||||||
- name: upload artifacts to S3
|
- name: upload artifacts to S3
|
||||||
run: src/ci/scripts/upload-artifacts.sh
|
run: src/ci/scripts/upload-artifacts.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: ${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}
|
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)] }}
|
AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}
|
||||||
@ -620,6 +639,7 @@ jobs:
|
|||||||
|
|
||||||
- name: publish toolstate
|
- name: publish toolstate
|
||||||
run: src/ci/publish_toolstate.sh
|
run: src/ci/publish_toolstate.sh
|
||||||
|
shell: bash
|
||||||
env:
|
env:
|
||||||
TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}
|
TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}
|
||||||
<<: *step
|
<<: *step
|
||||||
|
@ -150,6 +150,27 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
|
|||||||
[unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
|
[unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
|
||||||
[issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
|
[issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
|
||||||
|
|
||||||
|
### Adding your trait to the "Important Traits" dialog
|
||||||
|
|
||||||
|
Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when
|
||||||
|
implemented on it. These traits are intended to be the primary interface for their types, and are
|
||||||
|
often the only thing available to be documented on their types. For this reason, Rustdoc will track
|
||||||
|
when a given type implements one of these traits and call special attention to it when a function
|
||||||
|
returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next
|
||||||
|
to the function, which, when clicked, shows the dialog.
|
||||||
|
|
||||||
|
In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and
|
||||||
|
`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a
|
||||||
|
special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this
|
||||||
|
attribute to your own trait to include it in the "Important Traits" dialog in documentation.
|
||||||
|
|
||||||
|
The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate.
|
||||||
|
For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking
|
||||||
|
issue][issue-spotlight].
|
||||||
|
|
||||||
|
[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html
|
||||||
|
[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040
|
||||||
|
|
||||||
### Exclude certain dependencies from documentation
|
### Exclude certain dependencies from documentation
|
||||||
|
|
||||||
The standard library uses several dependencies which, in turn, use several types and traits from the
|
The standard library uses several dependencies which, in turn, use several types and traits from the
|
||||||
|
30
src/doc/unstable-book/src/language-features/doc-spotlight.md
Normal file
30
src/doc/unstable-book/src/language-features/doc-spotlight.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# `doc_spotlight`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#45040]
|
||||||
|
|
||||||
|
The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute,
|
||||||
|
to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]`
|
||||||
|
attribute to a trait definition will make rustdoc print extra information for functions which return
|
||||||
|
a type that implements that trait. This attribute is applied to the `Iterator`, `io::Read`, and
|
||||||
|
`io::Write` traits in the standard library.
|
||||||
|
|
||||||
|
You can do this on your own traits, like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
#![feature(doc_spotlight)]
|
||||||
|
|
||||||
|
#[doc(spotlight)]
|
||||||
|
pub trait MyTrait {}
|
||||||
|
|
||||||
|
pub struct MyStruct;
|
||||||
|
impl MyTrait for MyStruct {}
|
||||||
|
|
||||||
|
/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`,
|
||||||
|
/// without having to write that yourself!
|
||||||
|
pub fn my_fn() -> MyStruct { MyStruct }
|
||||||
|
```
|
||||||
|
|
||||||
|
This feature was originally implemented in PR [#45039].
|
||||||
|
|
||||||
|
[#45040]: https://github.com/rust-lang/rust/issues/45040
|
||||||
|
[#45039]: https://github.com/rust-lang/rust/pull/45039
|
@ -151,7 +151,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
|||||||
let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 };
|
let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 };
|
||||||
|
|
||||||
{
|
{
|
||||||
let root = out_tree.root.as_mut().unwrap();
|
let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped
|
||||||
let mut out_node = match root.as_mut().force() {
|
let mut out_node = match root.as_mut().force() {
|
||||||
Leaf(leaf) => leaf,
|
Leaf(leaf) => leaf,
|
||||||
Internal(_) => unreachable!(),
|
Internal(_) => unreachable!(),
|
||||||
@ -171,14 +171,10 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
|||||||
}
|
}
|
||||||
Internal(internal) => {
|
Internal(internal) => {
|
||||||
let mut out_tree = clone_subtree(internal.first_edge().descend());
|
let mut out_tree = clone_subtree(internal.first_edge().descend());
|
||||||
out_tree.ensure_root_is_owned();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Ideally we'd use the return of ensure_root_is_owned
|
let out_root = BTreeMap::ensure_is_owned(&mut out_tree.root);
|
||||||
// instead of re-unwrapping here but unfortunately that
|
let mut out_node = out_root.push_level();
|
||||||
// borrows all of out_tree and we need access to the
|
|
||||||
// length below.
|
|
||||||
let mut out_node = out_tree.root.as_mut().unwrap().push_level();
|
|
||||||
let mut in_edge = internal.first_edge();
|
let mut in_edge = internal.first_edge();
|
||||||
while let Ok(kv) = in_edge.right_kv() {
|
while let Ok(kv) = in_edge.right_kv() {
|
||||||
let (k, v) = kv.into_kv();
|
let (k, v) = kv.into_kv();
|
||||||
@ -212,7 +208,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
|||||||
// Ord` constraint, which this method lacks.
|
// Ord` constraint, which this method lacks.
|
||||||
BTreeMap { root: None, length: 0 }
|
BTreeMap { root: None, length: 0 }
|
||||||
} else {
|
} else {
|
||||||
clone_subtree(self.root.as_ref().unwrap().as_ref())
|
clone_subtree(self.root.as_ref().unwrap().as_ref()) // unwrap succeeds because not empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,8 +239,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn replace(&mut self, key: K) -> Option<K> {
|
fn replace(&mut self, key: K) -> Option<K> {
|
||||||
self.ensure_root_is_owned();
|
let root = Self::ensure_is_owned(&mut self.root);
|
||||||
match search::search_tree::<marker::Mut<'_>, K, (), K>(self.root.as_mut()?.as_mut(), &key) {
|
match search::search_tree::<marker::Mut<'_>, K, (), K>(root.as_mut(), &key) {
|
||||||
Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
|
Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
|
||||||
GoDown(handle) => {
|
GoDown(handle) => {
|
||||||
VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
|
VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
|
||||||
@ -943,7 +939,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
|
|
||||||
// Second, we build a tree from the sorted sequence in linear time.
|
// Second, we build a tree from the sorted sequence in linear time.
|
||||||
self.from_sorted_iter(iter);
|
self.from_sorted_iter(iter);
|
||||||
self.fix_right_edge();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a double-ended iterator over a sub-range of elements in the map.
|
/// Constructs a double-ended iterator over a sub-range of elements in the map.
|
||||||
@ -1058,8 +1053,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
|
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
|
||||||
// FIXME(@porglezomp) Avoid allocating if we don't insert
|
// FIXME(@porglezomp) Avoid allocating if we don't insert
|
||||||
self.ensure_root_is_owned();
|
let root = Self::ensure_is_owned(&mut self.root);
|
||||||
match search::search_tree(self.root.as_mut().unwrap().as_mut(), &key) {
|
match search::search_tree(root.as_mut(), &key) {
|
||||||
Found(handle) => {
|
Found(handle) => {
|
||||||
Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
|
Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
|
||||||
}
|
}
|
||||||
@ -1070,8 +1065,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
|
fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
|
||||||
self.ensure_root_is_owned();
|
let root = Self::ensure_is_owned(&mut self.root);
|
||||||
let mut cur_node = self.root.as_mut().unwrap().as_mut().last_leaf_edge().into_node();
|
let mut cur_node = root.as_mut().last_leaf_edge().into_node();
|
||||||
// Iterate through all key-value pairs, pushing them into nodes at the right level.
|
// Iterate through all key-value pairs, pushing them into nodes at the right level.
|
||||||
for (key, value) in iter {
|
for (key, value) in iter {
|
||||||
// Try to push key-value pair into the current leaf node.
|
// Try to push key-value pair into the current leaf node.
|
||||||
@ -1116,11 +1111,12 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
|
|
||||||
self.length += 1;
|
self.length += 1;
|
||||||
}
|
}
|
||||||
|
Self::fix_right_edge(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fix_right_edge(&mut self) {
|
fn fix_right_edge(root: &mut node::Root<K, V>) {
|
||||||
// Handle underfull nodes, start from the top.
|
// Handle underfull nodes, start from the top.
|
||||||
let mut cur_node = self.root.as_mut().unwrap().as_mut();
|
let mut cur_node = root.as_mut();
|
||||||
while let Internal(internal) = cur_node.force() {
|
while let Internal(internal) = cur_node.force() {
|
||||||
// Check if right-most child is underfull.
|
// Check if right-most child is underfull.
|
||||||
let mut last_edge = internal.last_edge();
|
let mut last_edge = internal.last_edge();
|
||||||
@ -1179,16 +1175,17 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let total_num = self.len();
|
let total_num = self.len();
|
||||||
|
let left_root = self.root.as_mut().unwrap(); // unwrap succeeds because not empty
|
||||||
|
|
||||||
let mut right = Self::new();
|
let mut right = Self::new();
|
||||||
let right_root = right.ensure_root_is_owned();
|
let right_root = Self::ensure_is_owned(&mut right.root);
|
||||||
for _ in 0..(self.root.as_ref().unwrap().as_ref().height()) {
|
for _ in 0..left_root.height() {
|
||||||
right_root.push_level();
|
right_root.push_level();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut left_node = self.root.as_mut().unwrap().as_mut();
|
let mut left_node = left_root.as_mut();
|
||||||
let mut right_node = right.root.as_mut().unwrap().as_mut();
|
let mut right_node = right_root.as_mut();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut split_edge = match search::search_node(left_node, key) {
|
let mut split_edge = match search::search_node(left_node, key) {
|
||||||
@ -1214,12 +1211,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fix_right_border();
|
left_root.fix_right_border();
|
||||||
right.fix_left_border();
|
right_root.fix_left_border();
|
||||||
|
|
||||||
if self.root.as_ref().unwrap().as_ref().height()
|
if left_root.height() < right_root.height() {
|
||||||
< right.root.as_ref().unwrap().as_ref().height()
|
|
||||||
{
|
|
||||||
self.recalc_length();
|
self.recalc_length();
|
||||||
right.length = total_num - self.len();
|
right.length = total_num - self.len();
|
||||||
} else {
|
} else {
|
||||||
@ -1301,69 +1296,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
|
|
||||||
self.length = dfs(self.root.as_ref().unwrap().as_ref());
|
self.length = dfs(self.root.as_ref().unwrap().as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes empty levels on the top.
|
|
||||||
fn fix_top(&mut self) {
|
|
||||||
loop {
|
|
||||||
{
|
|
||||||
let node = self.root.as_ref().unwrap().as_ref();
|
|
||||||
if node.height() == 0 || node.len() > 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.root.as_mut().unwrap().pop_level();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fix_right_border(&mut self) {
|
|
||||||
self.fix_top();
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut cur_node = self.root.as_mut().unwrap().as_mut();
|
|
||||||
|
|
||||||
while let Internal(node) = cur_node.force() {
|
|
||||||
let mut last_kv = node.last_kv();
|
|
||||||
|
|
||||||
if last_kv.can_merge() {
|
|
||||||
cur_node = last_kv.merge().descend();
|
|
||||||
} else {
|
|
||||||
let right_len = last_kv.reborrow().right_edge().descend().len();
|
|
||||||
// `MINLEN + 1` to avoid readjust if merge happens on the next level.
|
|
||||||
if right_len < node::MIN_LEN + 1 {
|
|
||||||
last_kv.bulk_steal_left(node::MIN_LEN + 1 - right_len);
|
|
||||||
}
|
|
||||||
cur_node = last_kv.right_edge().descend();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.fix_top();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The symmetric clone of `fix_right_border`.
|
|
||||||
fn fix_left_border(&mut self) {
|
|
||||||
self.fix_top();
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut cur_node = self.root.as_mut().unwrap().as_mut();
|
|
||||||
|
|
||||||
while let Internal(node) = cur_node.force() {
|
|
||||||
let mut first_kv = node.first_kv();
|
|
||||||
|
|
||||||
if first_kv.can_merge() {
|
|
||||||
cur_node = first_kv.merge().descend();
|
|
||||||
} else {
|
|
||||||
let left_len = first_kv.reborrow().left_edge().descend().len();
|
|
||||||
if left_len < node::MIN_LEN + 1 {
|
|
||||||
first_kv.bulk_steal_right(node::MIN_LEN + 1 - left_len);
|
|
||||||
}
|
|
||||||
cur_node = first_kv.left_edge().descend();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.fix_top();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -2321,9 +2253,9 @@ impl<K, V> BTreeMap<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If the root node is the empty (non-allocated) root node, allocate our
|
/// If the root node is the empty (non-allocated) root node, allocate our
|
||||||
/// own node.
|
/// own node. Is an associated function to avoid borrowing the entire BTreeMap.
|
||||||
fn ensure_root_is_owned(&mut self) -> &mut node::Root<K, V> {
|
fn ensure_is_owned(root: &mut Option<node::Root<K, V>>) -> &mut node::Root<K, V> {
|
||||||
self.root.get_or_insert_with(node::Root::new_leaf)
|
root.get_or_insert_with(node::Root::new_leaf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2825,6 +2757,65 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<K, V> node::Root<K, V> {
|
||||||
|
/// Removes empty levels on the top, but keep an empty leaf if the entire tree is empty.
|
||||||
|
fn fix_top(&mut self) {
|
||||||
|
while self.height() > 0 && self.as_ref().len() == 0 {
|
||||||
|
self.pop_level();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fix_right_border(&mut self) {
|
||||||
|
self.fix_top();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut cur_node = self.as_mut();
|
||||||
|
|
||||||
|
while let Internal(node) = cur_node.force() {
|
||||||
|
let mut last_kv = node.last_kv();
|
||||||
|
|
||||||
|
if last_kv.can_merge() {
|
||||||
|
cur_node = last_kv.merge().descend();
|
||||||
|
} else {
|
||||||
|
let right_len = last_kv.reborrow().right_edge().descend().len();
|
||||||
|
// `MINLEN + 1` to avoid readjust if merge happens on the next level.
|
||||||
|
if right_len < node::MIN_LEN + 1 {
|
||||||
|
last_kv.bulk_steal_left(node::MIN_LEN + 1 - right_len);
|
||||||
|
}
|
||||||
|
cur_node = last_kv.right_edge().descend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fix_top();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The symmetric clone of `fix_right_border`.
|
||||||
|
fn fix_left_border(&mut self) {
|
||||||
|
self.fix_top();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut cur_node = self.as_mut();
|
||||||
|
|
||||||
|
while let Internal(node) = cur_node.force() {
|
||||||
|
let mut first_kv = node.first_kv();
|
||||||
|
|
||||||
|
if first_kv.can_merge() {
|
||||||
|
cur_node = first_kv.merge().descend();
|
||||||
|
} else {
|
||||||
|
let left_len = first_kv.reborrow().left_edge().descend().len();
|
||||||
|
if left_len < node::MIN_LEN + 1 {
|
||||||
|
first_kv.bulk_steal_right(node::MIN_LEN + 1 - left_len);
|
||||||
|
}
|
||||||
|
cur_node = first_kv.left_edge().descend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fix_top();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum UnderflowResult<'a, K, V> {
|
enum UnderflowResult<'a, K, V> {
|
||||||
AtRoot,
|
AtRoot,
|
||||||
Merged(Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge>, bool, usize),
|
Merged(Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge>, bool, usize),
|
||||||
|
@ -153,6 +153,11 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
|
|||||||
unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
|
unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
|
||||||
|
|
||||||
impl<K, V> Root<K, V> {
|
impl<K, V> Root<K, V> {
|
||||||
|
/// Returns the number of levels below the root.
|
||||||
|
pub fn height(&self) -> usize {
|
||||||
|
self.height
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a new owned tree, with its own root node that is initially empty.
|
/// Returns a new owned tree, with its own root node that is initially empty.
|
||||||
pub fn new_leaf() -> Self {
|
pub fn new_leaf() -> Self {
|
||||||
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
|
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
|
||||||
|
@ -24,6 +24,7 @@ use crate::task::{Context, Poll};
|
|||||||
/// `.await` the value.
|
/// `.await` the value.
|
||||||
///
|
///
|
||||||
/// [`Waker`]: ../task/struct.Waker.html
|
/// [`Waker`]: ../task/struct.Waker.html
|
||||||
|
#[doc(spotlight)]
|
||||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||||
#[lang = "future_trait"]
|
#[lang = "future_trait"]
|
||||||
|
@ -1126,7 +1126,7 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// // use `u32::from_ne_bytes` instead
|
/// // use `u32::from_ne_bytes` instead
|
||||||
/// let num = u32::from_ne_bytes(raw_bytes);
|
/// let num = u32::from_ne_bytes(raw_bytes);
|
||||||
/// // or use `u32::from_le_bytes` or `u32::from_ge_bytes` to specify the endianness
|
/// // or use `u32::from_le_bytes` or `u32::from_be_bytes` to specify the endianness
|
||||||
/// let num = u32::from_le_bytes(raw_bytes);
|
/// let num = u32::from_le_bytes(raw_bytes);
|
||||||
/// assert_eq!(num, 0x12345678);
|
/// assert_eq!(num, 0x12345678);
|
||||||
/// let num = u32::from_be_bytes(raw_bytes);
|
/// let num = u32::from_be_bytes(raw_bytes);
|
||||||
|
@ -92,6 +92,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
|
|||||||
label = "`{Self}` is not an iterator",
|
label = "`{Self}` is not an iterator",
|
||||||
message = "`{Self}` is not an iterator"
|
message = "`{Self}` is not an iterator"
|
||||||
)]
|
)]
|
||||||
|
#[doc(spotlight)]
|
||||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||||
pub trait Iterator {
|
pub trait Iterator {
|
||||||
/// The type of the elements being iterated over.
|
/// The type of the elements being iterated over.
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
#![feature(custom_inner_attributes)]
|
#![feature(custom_inner_attributes)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(doc_cfg)]
|
#![feature(doc_cfg)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(doc_spotlight))]
|
||||||
#![feature(duration_consts_2)]
|
#![feature(duration_consts_2)]
|
||||||
#![feature(extern_types)]
|
#![feature(extern_types)]
|
||||||
#![feature(fundamental)]
|
#![feature(fundamental)]
|
||||||
|
@ -253,6 +253,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
include => external_doc
|
include => external_doc
|
||||||
cfg => doc_cfg
|
cfg => doc_cfg
|
||||||
masked => doc_masked
|
masked => doc_masked
|
||||||
|
spotlight => doc_spotlight
|
||||||
alias => doc_alias
|
alias => doc_alias
|
||||||
keyword => doc_keyword
|
keyword => doc_keyword
|
||||||
);
|
);
|
||||||
|
@ -452,6 +452,7 @@ E0766: include_str!("./error_codes/E0766.md"),
|
|||||||
E0767: include_str!("./error_codes/E0767.md"),
|
E0767: include_str!("./error_codes/E0767.md"),
|
||||||
E0768: include_str!("./error_codes/E0768.md"),
|
E0768: include_str!("./error_codes/E0768.md"),
|
||||||
E0769: include_str!("./error_codes/E0769.md"),
|
E0769: include_str!("./error_codes/E0769.md"),
|
||||||
|
E0770: include_str!("./error_codes/E0770.md"),
|
||||||
;
|
;
|
||||||
// E0006, // merged with E0005
|
// E0006, // merged with E0005
|
||||||
// E0008, // cannot bind by-move into a pattern guard
|
// E0008, // cannot bind by-move into a pattern guard
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
Const parameters cannot depend on type parameters.
|
Const parameters cannot depend on type parameters.
|
||||||
The following is therefore invalid:
|
The following is therefore invalid:
|
||||||
|
|
||||||
```compile_fail,E0741
|
```compile_fail,E0770
|
||||||
#![feature(const_generics)]
|
#![feature(const_generics)]
|
||||||
|
|
||||||
fn const_id<T, const N: T>() -> T { // error
|
fn const_id<T, const N: T>() -> T { // error
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
A `#![feature]` attribute was declared for a feature that is stable in
|
A `#![feature]` attribute was declared for a feature that is stable in the
|
||||||
the current edition, but not in all editions.
|
current edition, but not in all editions.
|
||||||
|
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
An unknown tool name found in scoped lint
|
An unknown tool name was found in a scoped lint.
|
||||||
|
|
||||||
Erroneous code examples:
|
Erroneous code examples:
|
||||||
|
|
||||||
|
15
src/librustc_error_codes/error_codes/E0770.md
Normal file
15
src/librustc_error_codes/error_codes/E0770.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
The type of a const parameter references other generic parameters.
|
||||||
|
|
||||||
|
Erroneous code example:
|
||||||
|
|
||||||
|
```compile_fail,E0770
|
||||||
|
#![feature(const_generics)]
|
||||||
|
fn foo<T, const N: T>() {} // error!
|
||||||
|
```
|
||||||
|
|
||||||
|
To fix this error, use a concrete type for the const parameter:
|
||||||
|
|
||||||
|
```
|
||||||
|
#![feature(const_generics)]
|
||||||
|
fn foo<T, const N: usize>() {}
|
||||||
|
```
|
@ -368,6 +368,9 @@ declare_features! (
|
|||||||
/// Allows `#[doc(masked)]`.
|
/// Allows `#[doc(masked)]`.
|
||||||
(active, doc_masked, "1.21.0", Some(44027), None),
|
(active, doc_masked, "1.21.0", Some(44027), None),
|
||||||
|
|
||||||
|
/// Allows `#[doc(spotlight)]`.
|
||||||
|
(active, doc_spotlight, "1.22.0", Some(45040), None),
|
||||||
|
|
||||||
/// Allows `#[doc(include = "some-file")]`.
|
/// Allows `#[doc(include = "some-file")]`.
|
||||||
(active, external_doc, "1.22.0", Some(44732), None),
|
(active, external_doc, "1.22.0", Some(44732), None),
|
||||||
|
|
||||||
|
@ -2687,7 +2687,7 @@ pub enum Node<'hir> {
|
|||||||
Crate(&'hir CrateItem<'hir>),
|
Crate(&'hir CrateItem<'hir>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node<'_> {
|
impl<'hir> Node<'hir> {
|
||||||
pub fn ident(&self) -> Option<Ident> {
|
pub fn ident(&self) -> Option<Ident> {
|
||||||
match self {
|
match self {
|
||||||
Node::TraitItem(TraitItem { ident, .. })
|
Node::TraitItem(TraitItem { ident, .. })
|
||||||
@ -2698,7 +2698,7 @@ impl Node<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fn_decl(&self) -> Option<&FnDecl<'_>> {
|
pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> {
|
||||||
match self {
|
match self {
|
||||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||||
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||||
@ -2722,7 +2722,7 @@ impl Node<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generics(&self) -> Option<&Generics<'_>> {
|
pub fn generics(&self) -> Option<&'hir Generics<'hir>> {
|
||||||
match self {
|
match self {
|
||||||
Node::TraitItem(TraitItem { generics, .. })
|
Node::TraitItem(TraitItem { generics, .. })
|
||||||
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
|
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
|
||||||
|
@ -354,13 +354,7 @@ fn configure_and_expand_inner<'a>(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// If we're actually rustdoc then there's no need to actually compile
|
|
||||||
// anything, so switch everything to just looping
|
|
||||||
let mut should_loop = sess.opts.actually_rustdoc;
|
|
||||||
if let Some(PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops)) = sess.opts.pretty {
|
if let Some(PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops)) = sess.opts.pretty {
|
||||||
should_loop |= true;
|
|
||||||
}
|
|
||||||
if should_loop {
|
|
||||||
log::debug!("replacing bodies with loop {{}}");
|
log::debug!("replacing bodies with loop {{}}");
|
||||||
util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
|
util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||||||
lint: &'static lint::Lint,
|
lint: &'static lint::Lint,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
message: &'static str,
|
message: &'static str,
|
||||||
panic: AssertKind<ConstInt>,
|
panic: AssertKind<impl std::fmt::Debug>,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let lint_root = self.lint_root(source_info)?;
|
let lint_root = self.lint_root(source_info)?;
|
||||||
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
|
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
|
||||||
@ -1004,11 +1004,27 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
|||||||
let expected = ScalarMaybeUninit::from(Scalar::from_bool(*expected));
|
let expected = ScalarMaybeUninit::from(Scalar::from_bool(*expected));
|
||||||
let value_const = self.ecx.read_scalar(value).unwrap();
|
let value_const = self.ecx.read_scalar(value).unwrap();
|
||||||
if expected != value_const {
|
if expected != value_const {
|
||||||
|
enum DbgVal<T> {
|
||||||
|
Val(T),
|
||||||
|
Underscore,
|
||||||
|
}
|
||||||
|
impl<T: std::fmt::Debug> std::fmt::Debug for DbgVal<T> {
|
||||||
|
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Val(val) => val.fmt(fmt),
|
||||||
|
Self::Underscore => fmt.write_str("_"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let mut eval_to_int = |op| {
|
let mut eval_to_int = |op| {
|
||||||
let op = self
|
// This can be `None` if the lhs wasn't const propagated and we just
|
||||||
.eval_operand(op, source_info)
|
// triggered the assert on the value of the rhs.
|
||||||
.expect("if we got here, it must be const");
|
match self.eval_operand(op, source_info) {
|
||||||
self.ecx.read_immediate(op).unwrap().to_const_int()
|
Some(op) => {
|
||||||
|
DbgVal::Val(self.ecx.read_immediate(op).unwrap().to_const_int())
|
||||||
|
}
|
||||||
|
None => DbgVal::Underscore,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let msg = match msg {
|
let msg = match msg {
|
||||||
AssertKind::DivisionByZero(op) => {
|
AssertKind::DivisionByZero(op) => {
|
||||||
|
@ -70,6 +70,8 @@ impl CheckAttrVisitor<'tcx> {
|
|||||||
self.check_target_feature(attr, span, target)
|
self.check_target_feature(attr, span, target)
|
||||||
} else if attr.check_name(sym::track_caller) {
|
} else if attr.check_name(sym::track_caller) {
|
||||||
self.check_track_caller(&attr.span, attrs, span, target)
|
self.check_track_caller(&attr.span, attrs, span, target)
|
||||||
|
} else if attr.check_name(sym::doc) {
|
||||||
|
self.check_doc_alias(attr)
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
@ -216,6 +218,34 @@ impl CheckAttrVisitor<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_doc_alias(&self, attr: &Attribute) -> bool {
|
||||||
|
if let Some(mi) = attr.meta() {
|
||||||
|
if let Some(list) = mi.meta_item_list() {
|
||||||
|
for meta in list {
|
||||||
|
if meta.check_name(sym::alias) {
|
||||||
|
if !meta.is_value_str()
|
||||||
|
|| meta
|
||||||
|
.value_str()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.unwrap_or_else(String::new)
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
|
self.tcx
|
||||||
|
.sess
|
||||||
|
.struct_span_err(
|
||||||
|
meta.span(),
|
||||||
|
"doc alias attribute expects a string: #[doc(alias = \"0\")]",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks if the `#[repr]` attributes on `item` are valid.
|
/// Checks if the `#[repr]` attributes on `item` are valid.
|
||||||
fn check_repr(
|
fn check_repr(
|
||||||
&self,
|
&self,
|
||||||
|
@ -442,6 +442,19 @@ impl<'a> Resolver<'a> {
|
|||||||
);
|
);
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
ResolutionError::ParamInTyOfConstArg(name) => {
|
||||||
|
let mut err = struct_span_err!(
|
||||||
|
self.session,
|
||||||
|
span,
|
||||||
|
E0770,
|
||||||
|
"the type of const parameters must not depend on other generic parameters"
|
||||||
|
);
|
||||||
|
err.span_label(
|
||||||
|
span,
|
||||||
|
format!("the type must not depend on the parameter `{}`", name),
|
||||||
|
);
|
||||||
|
err
|
||||||
|
}
|
||||||
ResolutionError::SelfInTyParamDefault => {
|
ResolutionError::SelfInTyParamDefault => {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.session,
|
self.session,
|
||||||
|
@ -123,6 +123,10 @@ crate enum RibKind<'a> {
|
|||||||
/// from the default of a type parameter because they're not declared
|
/// from the default of a type parameter because they're not declared
|
||||||
/// before said type parameter. Also see the `visit_generics` override.
|
/// before said type parameter. Also see the `visit_generics` override.
|
||||||
ForwardTyParamBanRibKind,
|
ForwardTyParamBanRibKind,
|
||||||
|
|
||||||
|
/// We are inside of the type of a const parameter. Can't refer to any
|
||||||
|
/// parameters.
|
||||||
|
ConstParamTyRibKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RibKind<'_> {
|
impl RibKind<'_> {
|
||||||
@ -135,7 +139,8 @@ impl RibKind<'_> {
|
|||||||
| FnItemRibKind
|
| FnItemRibKind
|
||||||
| ConstantItemRibKind
|
| ConstantItemRibKind
|
||||||
| ModuleRibKind(_)
|
| ModuleRibKind(_)
|
||||||
| MacroDefinition(_) => false,
|
| MacroDefinition(_)
|
||||||
|
| ConstParamTyRibKind => false,
|
||||||
AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true,
|
AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,13 +399,23 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
|
|
||||||
/// Fields used to add information to diagnostic errors.
|
/// Fields used to add information to diagnostic errors.
|
||||||
diagnostic_metadata: DiagnosticMetadata<'ast>,
|
diagnostic_metadata: DiagnosticMetadata<'ast>,
|
||||||
|
|
||||||
|
/// State used to know whether to ignore resolution errors for function bodies.
|
||||||
|
///
|
||||||
|
/// In particular, rustdoc uses this to avoid giving errors for `cfg()` items.
|
||||||
|
/// In most cases this will be `None`, in which case errors will always be reported.
|
||||||
|
/// If it is `Some(_)`, then it will be updated when entering a nested function or trait body.
|
||||||
|
in_func_body: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
|
/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
|
||||||
impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
fn visit_item(&mut self, item: &'ast Item) {
|
fn visit_item(&mut self, item: &'ast Item) {
|
||||||
let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item));
|
let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item));
|
||||||
|
// Always report errors in items we just entered.
|
||||||
|
let old_ignore = replace(&mut self.in_func_body, false);
|
||||||
self.resolve_item(item);
|
self.resolve_item(item);
|
||||||
|
self.in_func_body = old_ignore;
|
||||||
self.diagnostic_metadata.current_item = prev;
|
self.diagnostic_metadata.current_item = prev;
|
||||||
}
|
}
|
||||||
fn visit_arm(&mut self, arm: &'ast Arm) {
|
fn visit_arm(&mut self, arm: &'ast Arm) {
|
||||||
@ -497,6 +512,9 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||||||
|
|
||||||
visit::walk_fn_ret_ty(this, &declaration.output);
|
visit::walk_fn_ret_ty(this, &declaration.output);
|
||||||
|
|
||||||
|
// Ignore errors in function bodies if this is rustdoc
|
||||||
|
// Be sure not to set this until the function signature has been resolved.
|
||||||
|
let previous_state = replace(&mut this.in_func_body, true);
|
||||||
// Resolve the function body, potentially inside the body of an async closure
|
// Resolve the function body, potentially inside the body of an async closure
|
||||||
match fn_kind {
|
match fn_kind {
|
||||||
FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
|
FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
|
||||||
@ -504,6 +522,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
debug!("(resolving function) leaving function");
|
debug!("(resolving function) leaving function");
|
||||||
|
this.in_func_body = previous_state;
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
self.diagnostic_metadata.current_function = previous_value;
|
self.diagnostic_metadata.current_function = previous_value;
|
||||||
@ -562,7 +581,11 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||||||
for bound in ¶m.bounds {
|
for bound in ¶m.bounds {
|
||||||
self.visit_param_bound(bound);
|
self.visit_param_bound(bound);
|
||||||
}
|
}
|
||||||
|
self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
|
||||||
|
self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
|
||||||
self.visit_ty(ty);
|
self.visit_ty(ty);
|
||||||
|
self.ribs[TypeNS].pop().unwrap();
|
||||||
|
self.ribs[ValueNS].pop().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -644,6 +667,8 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
label_ribs: Vec::new(),
|
label_ribs: Vec::new(),
|
||||||
current_trait_ref: None,
|
current_trait_ref: None,
|
||||||
diagnostic_metadata: DiagnosticMetadata::default(),
|
diagnostic_metadata: DiagnosticMetadata::default(),
|
||||||
|
// errors at module scope should always be reported
|
||||||
|
in_func_body: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,7 +782,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
return if self.is_label_valid_from_rib(i) {
|
return if self.is_label_valid_from_rib(i) {
|
||||||
Some(*id)
|
Some(*id)
|
||||||
} else {
|
} else {
|
||||||
self.r.report_error(
|
self.report_error(
|
||||||
original_span,
|
original_span,
|
||||||
ResolutionError::UnreachableLabel {
|
ResolutionError::UnreachableLabel {
|
||||||
name: label.name,
|
name: label.name,
|
||||||
@ -775,7 +800,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
|
suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.r.report_error(
|
self.report_error(
|
||||||
original_span,
|
original_span,
|
||||||
ResolutionError::UndeclaredLabel { name: label.name, suggestion },
|
ResolutionError::UndeclaredLabel { name: label.name, suggestion },
|
||||||
);
|
);
|
||||||
@ -798,7 +823,8 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
| ItemRibKind(..)
|
| ItemRibKind(..)
|
||||||
| ConstantItemRibKind
|
| ConstantItemRibKind
|
||||||
| ModuleRibKind(..)
|
| ModuleRibKind(..)
|
||||||
| ForwardTyParamBanRibKind => {
|
| ForwardTyParamBanRibKind
|
||||||
|
| ConstParamTyRibKind => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -833,7 +859,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
};
|
};
|
||||||
let report_error = |this: &Self, ns| {
|
let report_error = |this: &Self, ns| {
|
||||||
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
|
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
|
||||||
this.r.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
|
if this.should_report_errs() {
|
||||||
|
this.r
|
||||||
|
.session
|
||||||
|
.span_err(ident.span, &format!("imports cannot refer to {}", what));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for &ns in nss {
|
for &ns in nss {
|
||||||
@ -1008,7 +1038,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
if seen_bindings.contains_key(&ident) {
|
if seen_bindings.contains_key(&ident) {
|
||||||
let span = seen_bindings.get(&ident).unwrap();
|
let span = seen_bindings.get(&ident).unwrap();
|
||||||
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, *span);
|
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, *span);
|
||||||
self.r.report_error(param.ident.span, err);
|
self.report_error(param.ident.span, err);
|
||||||
}
|
}
|
||||||
seen_bindings.entry(ident).or_insert(param.ident.span);
|
seen_bindings.entry(ident).or_insert(param.ident.span);
|
||||||
|
|
||||||
@ -1274,7 +1304,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
|
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
|
||||||
self.r.report_error(span, err(ident.name, &path_names_to_string(path)));
|
self.report_error(span, err(ident.name, &path_names_to_string(path)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1289,6 +1319,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_local(&mut self, local: &'ast Local) {
|
fn resolve_local(&mut self, local: &'ast Local) {
|
||||||
|
debug!("resolving local ({:?})", local);
|
||||||
// Resolve the type.
|
// Resolve the type.
|
||||||
walk_list!(self, visit_ty, &local.ty);
|
walk_list!(self, visit_ty, &local.ty);
|
||||||
|
|
||||||
@ -1390,7 +1421,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
if inconsistent_vars.contains_key(name) {
|
if inconsistent_vars.contains_key(name) {
|
||||||
v.could_be_path = false;
|
v.could_be_path = false;
|
||||||
}
|
}
|
||||||
self.r.report_error(
|
self.report_error(
|
||||||
*v.origin.iter().next().unwrap(),
|
*v.origin.iter().next().unwrap(),
|
||||||
ResolutionError::VariableNotBoundInPattern(v),
|
ResolutionError::VariableNotBoundInPattern(v),
|
||||||
);
|
);
|
||||||
@ -1400,7 +1431,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
|
let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
|
||||||
inconsistent_vars.sort();
|
inconsistent_vars.sort();
|
||||||
for (name, v) in inconsistent_vars {
|
for (name, v) in inconsistent_vars {
|
||||||
self.r.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
|
self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5) Finally bubble up all the binding maps.
|
// 5) Finally bubble up all the binding maps.
|
||||||
@ -1550,7 +1581,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
// `Variant(a, a)`:
|
// `Variant(a, a)`:
|
||||||
_ => IdentifierBoundMoreThanOnceInSamePattern,
|
_ => IdentifierBoundMoreThanOnceInSamePattern,
|
||||||
};
|
};
|
||||||
self.r.report_error(ident.span, error(ident.name));
|
self.report_error(ident.span, error(ident.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record as bound if it's valid:
|
// Record as bound if it's valid:
|
||||||
@ -1624,7 +1655,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
// to something unusable as a pattern (e.g., constructor function),
|
// to something unusable as a pattern (e.g., constructor function),
|
||||||
// but we still conservatively report an error, see
|
// but we still conservatively report an error, see
|
||||||
// issues/33118#issuecomment-233962221 for one reason why.
|
// issues/33118#issuecomment-233962221 for one reason why.
|
||||||
self.r.report_error(
|
self.report_error(
|
||||||
ident.span,
|
ident.span,
|
||||||
ResolutionError::BindingShadowsSomethingUnacceptable(
|
ResolutionError::BindingShadowsSomethingUnacceptable(
|
||||||
pat_src.descr(),
|
pat_src.descr(),
|
||||||
@ -1677,18 +1708,27 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
source: PathSource<'ast>,
|
source: PathSource<'ast>,
|
||||||
crate_lint: CrateLint,
|
crate_lint: CrateLint,
|
||||||
) -> PartialRes {
|
) -> PartialRes {
|
||||||
|
log::debug!("smart_resolve_path_fragment(id={:?},qself={:?},path={:?}", id, qself, path);
|
||||||
let ns = source.namespace();
|
let ns = source.namespace();
|
||||||
let is_expected = &|res| source.is_expected(res);
|
let is_expected = &|res| source.is_expected(res);
|
||||||
|
|
||||||
let report_errors = |this: &mut Self, res: Option<Res>| {
|
let report_errors = |this: &mut Self, res: Option<Res>| {
|
||||||
let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
|
if this.should_report_errs() {
|
||||||
|
let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
|
||||||
|
|
||||||
let def_id = this.parent_scope.module.normal_ancestor_id;
|
let def_id = this.parent_scope.module.normal_ancestor_id;
|
||||||
let instead = res.is_some();
|
let instead = res.is_some();
|
||||||
let suggestion =
|
let suggestion =
|
||||||
if res.is_none() { this.report_missing_type_error(path) } else { None };
|
if res.is_none() { this.report_missing_type_error(path) } else { None };
|
||||||
|
|
||||||
this.r.use_injections.push(UseError { err, candidates, def_id, instead, suggestion });
|
this.r.use_injections.push(UseError {
|
||||||
|
err,
|
||||||
|
candidates,
|
||||||
|
def_id,
|
||||||
|
instead,
|
||||||
|
suggestion,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
PartialRes::new(Res::Err)
|
PartialRes::new(Res::Err)
|
||||||
};
|
};
|
||||||
@ -1746,13 +1786,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
|
|
||||||
let def_id = this.parent_scope.module.normal_ancestor_id;
|
let def_id = this.parent_scope.module.normal_ancestor_id;
|
||||||
|
|
||||||
this.r.use_injections.push(UseError {
|
if this.should_report_errs() {
|
||||||
err,
|
this.r.use_injections.push(UseError {
|
||||||
candidates,
|
err,
|
||||||
def_id,
|
candidates,
|
||||||
instead: false,
|
def_id,
|
||||||
suggestion: None,
|
instead: false,
|
||||||
});
|
suggestion: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
err.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
// We don't return `Some(parent_err)` here, because the error will
|
// We don't return `Some(parent_err)` here, because the error will
|
||||||
// be already printed as part of the `use` injections
|
// be already printed as part of the `use` injections
|
||||||
@ -1809,7 +1853,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let Some(err) = report_errors_for_call(self, err) {
|
if let Some(err) = report_errors_for_call(self, err) {
|
||||||
self.r.report_error(err.span, err.node);
|
self.report_error(err.span, err.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
PartialRes::new(Res::Err)
|
PartialRes::new(Res::Err)
|
||||||
@ -1843,6 +1887,21 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
|
if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A wrapper around [`Resolver::report_error`].
|
||||||
|
///
|
||||||
|
/// This doesn't emit errors for function bodies if this is rustdoc.
|
||||||
|
fn report_error(&self, span: Span, resolution_error: ResolutionError<'_>) {
|
||||||
|
if self.should_report_errs() {
|
||||||
|
self.r.report_error(span, resolution_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items.
|
||||||
|
fn should_report_errs(&self) -> bool {
|
||||||
|
!(self.r.session.opts.actually_rustdoc && self.in_func_body)
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve in alternative namespaces if resolution in the primary namespace fails.
|
// Resolve in alternative namespaces if resolution in the primary namespace fails.
|
||||||
fn resolve_qpath_anywhere(
|
fn resolve_qpath_anywhere(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -214,6 +214,8 @@ enum ResolutionError<'a> {
|
|||||||
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
|
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
|
||||||
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
|
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
|
||||||
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
|
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
|
||||||
|
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
|
||||||
|
ParamInTyOfConstArg(Symbol),
|
||||||
/// Error E0735: type parameters with a default cannot use `Self`
|
/// Error E0735: type parameters with a default cannot use `Self`
|
||||||
SelfInTyParamDefault,
|
SelfInTyParamDefault,
|
||||||
/// Error E0767: use of unreachable label
|
/// Error E0767: use of unreachable label
|
||||||
@ -2480,6 +2482,12 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
return Res::Err;
|
return Res::Err;
|
||||||
}
|
}
|
||||||
|
ConstParamTyRibKind => {
|
||||||
|
if record_used {
|
||||||
|
self.report_error(span, ParamInTyOfConstArg(rib_ident.name));
|
||||||
|
}
|
||||||
|
return Res::Err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(res_err) = res_err {
|
if let Some(res_err) = res_err {
|
||||||
@ -2503,6 +2511,15 @@ impl<'a> Resolver<'a> {
|
|||||||
// This was an attempt to use a type parameter outside its scope.
|
// This was an attempt to use a type parameter outside its scope.
|
||||||
ItemRibKind(has_generic_params) => has_generic_params,
|
ItemRibKind(has_generic_params) => has_generic_params,
|
||||||
FnItemRibKind => HasGenericParams::Yes,
|
FnItemRibKind => HasGenericParams::Yes,
|
||||||
|
ConstParamTyRibKind => {
|
||||||
|
if record_used {
|
||||||
|
self.report_error(
|
||||||
|
span,
|
||||||
|
ResolutionError::ParamInTyOfConstArg(rib_ident.name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Res::Err;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if record_used {
|
if record_used {
|
||||||
@ -2527,9 +2544,24 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
for rib in ribs {
|
for rib in ribs {
|
||||||
let has_generic_params = match rib.kind {
|
let has_generic_params = match rib.kind {
|
||||||
|
NormalRibKind
|
||||||
|
| ClosureOrAsyncRibKind
|
||||||
|
| AssocItemRibKind
|
||||||
|
| ModuleRibKind(..)
|
||||||
|
| MacroDefinition(..)
|
||||||
|
| ForwardTyParamBanRibKind
|
||||||
|
| ConstantItemRibKind => continue,
|
||||||
ItemRibKind(has_generic_params) => has_generic_params,
|
ItemRibKind(has_generic_params) => has_generic_params,
|
||||||
FnItemRibKind => HasGenericParams::Yes,
|
FnItemRibKind => HasGenericParams::Yes,
|
||||||
_ => continue,
|
ConstParamTyRibKind => {
|
||||||
|
if record_used {
|
||||||
|
self.report_error(
|
||||||
|
span,
|
||||||
|
ResolutionError::ParamInTyOfConstArg(rib_ident.name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Res::Err;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This was an attempt to use a const parameter outside its scope.
|
// This was an attempt to use a const parameter outside its scope.
|
||||||
|
@ -400,6 +400,7 @@ symbols! {
|
|||||||
doc_cfg,
|
doc_cfg,
|
||||||
doc_keyword,
|
doc_keyword,
|
||||||
doc_masked,
|
doc_masked,
|
||||||
|
doc_spotlight,
|
||||||
doctest,
|
doctest,
|
||||||
document_private_items,
|
document_private_items,
|
||||||
dotdot_in_tuple_patterns,
|
dotdot_in_tuple_patterns,
|
||||||
@ -968,6 +969,7 @@ symbols! {
|
|||||||
soft,
|
soft,
|
||||||
specialization,
|
specialization,
|
||||||
speed,
|
speed,
|
||||||
|
spotlight,
|
||||||
sqrtf32,
|
sqrtf32,
|
||||||
sqrtf64,
|
sqrtf64,
|
||||||
sse4a_target_feature,
|
sse4a_target_feature,
|
||||||
|
@ -937,6 +937,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// legal to implement.
|
// legal to implement.
|
||||||
let mut candidates = all_traits(self.tcx)
|
let mut candidates = all_traits(self.tcx)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
// Don't issue suggestions for unstable traits since they're
|
||||||
|
// unlikely to be implementable anyway
|
||||||
|
.filter(|info| match self.tcx.lookup_stability(info.def_id) {
|
||||||
|
Some(attr) => attr.level.is_stable(),
|
||||||
|
None => true,
|
||||||
|
})
|
||||||
.filter(|info| {
|
.filter(|info| {
|
||||||
// We approximate the coherence rules to only suggest
|
// We approximate the coherence rules to only suggest
|
||||||
// traits that are legal to implement by requiring that
|
// traits that are legal to implement by requiring that
|
||||||
|
@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
|
|||||||
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::weak_lang_items;
|
use rustc_hir::weak_lang_items;
|
||||||
use rustc_hir::{GenericParamKind, Node};
|
use rustc_hir::{GenericParamKind, HirId, Node};
|
||||||
use rustc_middle::hir::map::blocks::FnLikeNode;
|
use rustc_middle::hir::map::blocks::FnLikeNode;
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||||
@ -1155,6 +1155,35 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AnonConstInParamListDetector {
|
||||||
|
in_param_list: bool,
|
||||||
|
found_anon_const_in_list: bool,
|
||||||
|
ct: HirId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'v> Visitor<'v> for AnonConstInParamListDetector {
|
||||||
|
type Map = intravisit::ErasedMap<'v>;
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||||
|
NestedVisitorMap::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
|
||||||
|
let prev = self.in_param_list;
|
||||||
|
self.in_param_list = true;
|
||||||
|
intravisit::walk_generic_param(self, p);
|
||||||
|
self.in_param_list = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
|
||||||
|
if self.in_param_list && self.ct == c.hir_id {
|
||||||
|
self.found_anon_const_in_list = true;
|
||||||
|
} else {
|
||||||
|
intravisit::walk_anon_const(self, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
||||||
use rustc_hir::*;
|
use rustc_hir::*;
|
||||||
|
|
||||||
@ -1176,10 +1205,32 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||||||
let parent_id = tcx.hir().get_parent_item(hir_id);
|
let parent_id = tcx.hir().get_parent_item(hir_id);
|
||||||
let parent_def_id = tcx.hir().local_def_id(parent_id);
|
let parent_def_id = tcx.hir().local_def_id(parent_id);
|
||||||
|
|
||||||
// HACK(eddyb) this provides the correct generics when
|
let mut in_param_list = false;
|
||||||
// `feature(const_generics)` is enabled, so that const expressions
|
for (_parent, node) in tcx.hir().parent_iter(hir_id) {
|
||||||
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
|
if let Some(generics) = node.generics() {
|
||||||
if tcx.lazy_normalization() {
|
let mut visitor = AnonConstInParamListDetector {
|
||||||
|
in_param_list: false,
|
||||||
|
found_anon_const_in_list: false,
|
||||||
|
ct: hir_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
visitor.visit_generics(generics);
|
||||||
|
in_param_list = visitor.found_anon_const_in_list;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if in_param_list {
|
||||||
|
// We do not allow generic parameters in anon consts if we are inside
|
||||||
|
// of a param list.
|
||||||
|
//
|
||||||
|
// This affects both default type bindings, e.g. `struct<T, U = [u8; std::mem::size_of::<T>()]>(T, U)`,
|
||||||
|
// and the types of const parameters, e.g. `struct V<const N: usize, const M: [u8; N]>();`.
|
||||||
|
None
|
||||||
|
} else if tcx.lazy_normalization() {
|
||||||
|
// HACK(eddyb) this provides the correct generics when
|
||||||
|
// `feature(const_generics)` is enabled, so that const expressions
|
||||||
|
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
|
||||||
Some(parent_def_id.to_def_id())
|
Some(parent_def_id.to_def_id())
|
||||||
} else {
|
} else {
|
||||||
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
|
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
|
||||||
|
@ -11,8 +11,10 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::PatKind;
|
use rustc_hir::PatKind;
|
||||||
|
use rustc_index::vec::Idx;
|
||||||
use rustc_infer::infer::InferCtxt;
|
use rustc_infer::infer::InferCtxt;
|
||||||
use rustc_middle::ty::{self, adjustment, TyCtxt};
|
use rustc_middle::ty::{self, adjustment, TyCtxt};
|
||||||
|
use rustc_target::abi::VariantIdx;
|
||||||
|
|
||||||
use crate::mem_categorization as mc;
|
use crate::mem_categorization as mc;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -396,6 +398,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||||||
&*with_expr,
|
&*with_expr,
|
||||||
with_place.clone(),
|
with_place.clone(),
|
||||||
with_field.ty(self.tcx(), substs),
|
with_field.ty(self.tcx(), substs),
|
||||||
|
mc::ProjectionKind::Field(f_index as u32, VariantIdx::new(0)),
|
||||||
);
|
);
|
||||||
self.delegate_consume(&field_place);
|
self.delegate_consume(&field_place);
|
||||||
}
|
}
|
||||||
|
@ -54,11 +54,14 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
|
|||||||
|
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
|
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
||||||
use rustc_hir::PatKind;
|
use rustc_hir::PatKind;
|
||||||
|
use rustc_index::vec::Idx;
|
||||||
use rustc_infer::infer::InferCtxt;
|
use rustc_infer::infer::InferCtxt;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use rustc_target::abi::VariantIdx;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -77,8 +80,20 @@ pub enum PlaceBase {
|
|||||||
pub enum ProjectionKind {
|
pub enum ProjectionKind {
|
||||||
/// A dereference of a pointer, reference or `Box<T>` of the given type
|
/// A dereference of a pointer, reference or `Box<T>` of the given type
|
||||||
Deref,
|
Deref,
|
||||||
/// An index or a field
|
|
||||||
Other,
|
/// `B.F` where `B` is the base expression and `F` is
|
||||||
|
/// the field. The field is identified by which variant
|
||||||
|
/// it appears in along with a field index. The variant
|
||||||
|
/// is used for enums.
|
||||||
|
Field(u32, VariantIdx),
|
||||||
|
|
||||||
|
/// Some index like `B[x]`, where `B` is the base
|
||||||
|
/// expression. We don't preserve the index `x` because
|
||||||
|
/// we won't need it.
|
||||||
|
Index,
|
||||||
|
|
||||||
|
/// A subslice covering a range of values like `B[x..y]`.
|
||||||
|
Subslice,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -406,7 +421,20 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||||||
hir::ExprKind::Field(ref base, _) => {
|
hir::ExprKind::Field(ref base, _) => {
|
||||||
let base = self.cat_expr(&base)?;
|
let base = self.cat_expr(&base)?;
|
||||||
debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.hir_id, expr, base);
|
debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.hir_id, expr, base);
|
||||||
Ok(self.cat_projection(expr, base, expr_ty))
|
|
||||||
|
let field_idx = self
|
||||||
|
.tables
|
||||||
|
.field_indices()
|
||||||
|
.get(expr.hir_id)
|
||||||
|
.cloned()
|
||||||
|
.expect("Field index not found");
|
||||||
|
|
||||||
|
Ok(self.cat_projection(
|
||||||
|
expr,
|
||||||
|
base,
|
||||||
|
expr_ty,
|
||||||
|
ProjectionKind::Field(field_idx as u32, VariantIdx::new(0)),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Index(ref base, _) => {
|
hir::ExprKind::Index(ref base, _) => {
|
||||||
@ -419,7 +447,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||||||
self.cat_overloaded_place(expr, base)
|
self.cat_overloaded_place(expr, base)
|
||||||
} else {
|
} else {
|
||||||
let base = self.cat_expr(&base)?;
|
let base = self.cat_expr(&base)?;
|
||||||
Ok(self.cat_projection(expr, base, expr_ty))
|
Ok(self.cat_projection(expr, base, expr_ty, ProjectionKind::Index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,9 +561,10 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||||||
node: &N,
|
node: &N,
|
||||||
base_place: PlaceWithHirId<'tcx>,
|
base_place: PlaceWithHirId<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
|
kind: ProjectionKind,
|
||||||
) -> PlaceWithHirId<'tcx> {
|
) -> PlaceWithHirId<'tcx> {
|
||||||
let mut projections = base_place.place.projections;
|
let mut projections = base_place.place.projections;
|
||||||
projections.push(Projection { kind: ProjectionKind::Other, ty: ty });
|
projections.push(Projection { kind: kind, ty: ty });
|
||||||
let ret = PlaceWithHirId::new(
|
let ret = PlaceWithHirId::new(
|
||||||
node.hir_id(),
|
node.hir_id(),
|
||||||
base_place.place.base_ty,
|
base_place.place.base_ty,
|
||||||
@ -609,6 +638,75 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||||||
self.cat_pattern_(place, pat, &mut op)
|
self.cat_pattern_(place, pat, &mut op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
|
||||||
|
/// Here `pat_hir_id` is the HirId of the pattern itself.
|
||||||
|
fn variant_index_for_adt(
|
||||||
|
&self,
|
||||||
|
qpath: &hir::QPath<'_>,
|
||||||
|
pat_hir_id: hir::HirId,
|
||||||
|
span: Span,
|
||||||
|
) -> McResult<VariantIdx> {
|
||||||
|
let res = self.tables.qpath_res(qpath, pat_hir_id);
|
||||||
|
let ty = self.tables.node_type(pat_hir_id);
|
||||||
|
let adt_def = match ty.kind {
|
||||||
|
ty::Adt(adt_def, _) => adt_def,
|
||||||
|
_ => {
|
||||||
|
self.tcx()
|
||||||
|
.sess
|
||||||
|
.delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT");
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Res::Def(DefKind::Variant, variant_id) => Ok(adt_def.variant_index_with_id(variant_id)),
|
||||||
|
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
|
||||||
|
Ok(adt_def.variant_index_with_ctor_id(variant_ctor_id))
|
||||||
|
}
|
||||||
|
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
|
||||||
|
| Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
|
||||||
|
| Res::SelfCtor(..)
|
||||||
|
| Res::SelfTy(..) => {
|
||||||
|
// Structs and Unions have only have one variant.
|
||||||
|
Ok(VariantIdx::new(0))
|
||||||
|
}
|
||||||
|
_ => bug!("expected ADT path, found={:?}", res),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the total number of fields in an ADT variant used within a pattern.
|
||||||
|
/// Here `pat_hir_id` is the HirId of the pattern itself.
|
||||||
|
fn total_fields_in_adt_variant(
|
||||||
|
&self,
|
||||||
|
pat_hir_id: hir::HirId,
|
||||||
|
variant_index: VariantIdx,
|
||||||
|
span: Span,
|
||||||
|
) -> McResult<usize> {
|
||||||
|
let ty = self.tables.node_type(pat_hir_id);
|
||||||
|
match ty.kind {
|
||||||
|
ty::Adt(adt_def, _) => Ok(adt_def.variants[variant_index].fields.len()),
|
||||||
|
_ => {
|
||||||
|
self.tcx()
|
||||||
|
.sess
|
||||||
|
.delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT");
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the total number of fields in a tuple used within a Tuple pattern.
|
||||||
|
/// Here `pat_hir_id` is the HirId of the pattern itself.
|
||||||
|
fn total_fields_in_tuple(&self, pat_hir_id: hir::HirId, span: Span) -> McResult<usize> {
|
||||||
|
let ty = self.tables.node_type(pat_hir_id);
|
||||||
|
match ty.kind {
|
||||||
|
ty::Tuple(substs) => Ok(substs.len()),
|
||||||
|
_ => {
|
||||||
|
self.tcx().sess.delay_span_bug(span, "tuple pattern not applied to a tuple");
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(#19596) This is a workaround, but there should be a better way to do this
|
// FIXME(#19596) This is a workaround, but there should be a better way to do this
|
||||||
fn cat_pattern_<F>(
|
fn cat_pattern_<F>(
|
||||||
&self,
|
&self,
|
||||||
@ -679,20 +777,54 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||||||
op(&place_with_id, pat);
|
op(&place_with_id, pat);
|
||||||
|
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
PatKind::TupleStruct(_, ref subpats, _) | PatKind::Tuple(ref subpats, _) => {
|
PatKind::Tuple(ref subpats, dots_pos) => {
|
||||||
// S(p1, ..., pN) or (p1, ..., pN)
|
// (p1, ..., pN)
|
||||||
for subpat in subpats.iter() {
|
let total_fields = self.total_fields_in_tuple(pat.hir_id, pat.span)?;
|
||||||
|
|
||||||
|
for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
|
||||||
let subpat_ty = self.pat_ty_adjusted(&subpat)?;
|
let subpat_ty = self.pat_ty_adjusted(&subpat)?;
|
||||||
let sub_place = self.cat_projection(pat, place_with_id.clone(), subpat_ty);
|
let projection_kind = ProjectionKind::Field(i as u32, VariantIdx::new(0));
|
||||||
|
let sub_place =
|
||||||
|
self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
|
||||||
self.cat_pattern_(sub_place, &subpat, op)?;
|
self.cat_pattern_(sub_place, &subpat, op)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Struct(_, field_pats, _) => {
|
PatKind::TupleStruct(ref qpath, ref subpats, dots_pos) => {
|
||||||
|
// S(p1, ..., pN)
|
||||||
|
let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
|
||||||
|
let total_fields =
|
||||||
|
self.total_fields_in_adt_variant(pat.hir_id, variant_index, pat.span)?;
|
||||||
|
|
||||||
|
for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
|
||||||
|
let subpat_ty = self.pat_ty_adjusted(&subpat)?;
|
||||||
|
let projection_kind = ProjectionKind::Field(i as u32, variant_index);
|
||||||
|
let sub_place =
|
||||||
|
self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
|
||||||
|
self.cat_pattern_(sub_place, &subpat, op)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PatKind::Struct(ref qpath, field_pats, _) => {
|
||||||
// S { f1: p1, ..., fN: pN }
|
// S { f1: p1, ..., fN: pN }
|
||||||
|
|
||||||
|
let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
|
||||||
|
|
||||||
for fp in field_pats {
|
for fp in field_pats {
|
||||||
let field_ty = self.pat_ty_adjusted(&fp.pat)?;
|
let field_ty = self.pat_ty_adjusted(&fp.pat)?;
|
||||||
let field_place = self.cat_projection(pat, place_with_id.clone(), field_ty);
|
let field_index = self
|
||||||
|
.tables
|
||||||
|
.field_indices()
|
||||||
|
.get(fp.hir_id)
|
||||||
|
.cloned()
|
||||||
|
.expect("no index for a field");
|
||||||
|
|
||||||
|
let field_place = self.cat_projection(
|
||||||
|
pat,
|
||||||
|
place_with_id.clone(),
|
||||||
|
field_ty,
|
||||||
|
ProjectionKind::Field(field_index as u32, variant_index),
|
||||||
|
);
|
||||||
self.cat_pattern_(field_place, &fp.pat, op)?;
|
self.cat_pattern_(field_place, &fp.pat, op)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -723,13 +855,23 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let elt_place = self.cat_projection(pat, place_with_id.clone(), element_ty);
|
let elt_place = self.cat_projection(
|
||||||
|
pat,
|
||||||
|
place_with_id.clone(),
|
||||||
|
element_ty,
|
||||||
|
ProjectionKind::Index,
|
||||||
|
);
|
||||||
for before_pat in before {
|
for before_pat in before {
|
||||||
self.cat_pattern_(elt_place.clone(), &before_pat, op)?;
|
self.cat_pattern_(elt_place.clone(), &before_pat, op)?;
|
||||||
}
|
}
|
||||||
if let Some(ref slice_pat) = *slice {
|
if let Some(ref slice_pat) = *slice {
|
||||||
let slice_pat_ty = self.pat_ty_adjusted(&slice_pat)?;
|
let slice_pat_ty = self.pat_ty_adjusted(&slice_pat)?;
|
||||||
let slice_place = self.cat_projection(pat, place_with_id, slice_pat_ty);
|
let slice_place = self.cat_projection(
|
||||||
|
pat,
|
||||||
|
place_with_id,
|
||||||
|
slice_pat_ty,
|
||||||
|
ProjectionKind::Subslice,
|
||||||
|
);
|
||||||
self.cat_pattern_(slice_place, &slice_pat, op)?;
|
self.cat_pattern_(slice_place, &slice_pat, op)?;
|
||||||
}
|
}
|
||||||
for after_pat in after {
|
for after_pat in after {
|
||||||
|
@ -12,7 +12,7 @@ use rustc_metadata::creader::LoadedMacro;
|
|||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_mir::const_eval::is_min_const_fn;
|
use rustc_mir::const_eval::is_min_const_fn;
|
||||||
use rustc_span::hygiene::MacroKind;
|
use rustc_span::hygiene::MacroKind;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::clean::{self, GetDefId, ToSource, TypeKind};
|
use crate::clean::{self, GetDefId, ToSource, TypeKind};
|
||||||
@ -194,6 +194,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
|
|||||||
let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
|
let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
|
||||||
let generics = filter_non_trait_generics(did, generics);
|
let generics = filter_non_trait_generics(did, generics);
|
||||||
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
|
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
|
||||||
|
let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight);
|
||||||
let is_auto = cx.tcx.trait_is_auto(did);
|
let is_auto = cx.tcx.trait_is_auto(did);
|
||||||
clean::Trait {
|
clean::Trait {
|
||||||
auto: auto_trait,
|
auto: auto_trait,
|
||||||
@ -201,6 +202,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
|
|||||||
generics,
|
generics,
|
||||||
items: trait_items,
|
items: trait_items,
|
||||||
bounds: supertrait_bounds,
|
bounds: supertrait_bounds,
|
||||||
|
is_spotlight,
|
||||||
is_auto,
|
is_auto,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,6 +341,16 @@ pub fn build_impl(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip foreign unstable traits from lists of trait implementations and
|
||||||
|
// 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(stab) = cx.tcx.lookup_stability(did) {
|
||||||
|
if stab.level.is_unstable() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let for_ = if let Some(did) = did.as_local() {
|
let for_ = if let Some(did) = did.as_local() {
|
||||||
|
@ -1007,6 +1007,7 @@ impl Clean<FnRetTy> for hir::FnRetTy<'_> {
|
|||||||
impl Clean<Item> for doctree::Trait<'_> {
|
impl Clean<Item> for doctree::Trait<'_> {
|
||||||
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||||
let attrs = self.attrs.clean(cx);
|
let attrs = self.attrs.clean(cx);
|
||||||
|
let is_spotlight = attrs.has_doc_flag(sym::spotlight);
|
||||||
Item {
|
Item {
|
||||||
name: Some(self.name.clean(cx)),
|
name: Some(self.name.clean(cx)),
|
||||||
attrs,
|
attrs,
|
||||||
@ -1021,6 +1022,7 @@ impl Clean<Item> for doctree::Trait<'_> {
|
|||||||
items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
|
items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
|
||||||
generics: self.generics.clean(cx),
|
generics: self.generics.clean(cx),
|
||||||
bounds: self.bounds.clean(cx),
|
bounds: self.bounds.clean(cx),
|
||||||
|
is_spotlight,
|
||||||
is_auto: self.is_auto.clean(cx),
|
is_auto: self.is_auto.clean(cx),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -486,33 +486,6 @@ impl Attributes {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enforce the format of attributes inside `#[doc(...)]`.
|
|
||||||
pub fn check_doc_attributes(
|
|
||||||
diagnostic: &::rustc_errors::Handler,
|
|
||||||
mi: &ast::MetaItem,
|
|
||||||
) -> Option<(String, String)> {
|
|
||||||
mi.meta_item_list().and_then(|list| {
|
|
||||||
for meta in list {
|
|
||||||
if meta.check_name(sym::alias) {
|
|
||||||
if !meta.is_value_str()
|
|
||||||
|| meta
|
|
||||||
.value_str()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.unwrap_or_else(String::new)
|
|
||||||
.is_empty()
|
|
||||||
{
|
|
||||||
diagnostic.span_err(
|
|
||||||
meta.span(),
|
|
||||||
"doc alias attribute expects a string: #[doc(alias = \"0\")]",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_doc_flag(&self, flag: Symbol) -> bool {
|
pub fn has_doc_flag(&self, flag: Symbol) -> bool {
|
||||||
for attr in &self.other_attrs {
|
for attr in &self.other_attrs {
|
||||||
if !attr.check_name(sym::doc) {
|
if !attr.check_name(sym::doc) {
|
||||||
@ -556,7 +529,6 @@ impl Attributes {
|
|||||||
} else {
|
} else {
|
||||||
if attr.check_name(sym::doc) {
|
if attr.check_name(sym::doc) {
|
||||||
if let Some(mi) = attr.meta() {
|
if let Some(mi) = attr.meta() {
|
||||||
Attributes::check_doc_attributes(&diagnostic, &mi);
|
|
||||||
if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
|
if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
|
||||||
// Extracted #[doc(cfg(...))]
|
// Extracted #[doc(cfg(...))]
|
||||||
match Cfg::parse(cfg_mi) {
|
match Cfg::parse(cfg_mi) {
|
||||||
@ -995,6 +967,7 @@ pub struct Trait {
|
|||||||
pub items: Vec<Item>,
|
pub items: Vec<Item>,
|
||||||
pub generics: Generics,
|
pub generics: Generics,
|
||||||
pub bounds: Vec<GenericBound>,
|
pub bounds: Vec<GenericBound>,
|
||||||
|
pub is_spotlight: bool,
|
||||||
pub is_auto: bool,
|
pub is_auto: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,15 @@ use rustc_driver::abort_on_err;
|
|||||||
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
||||||
use rustc_errors::json::JsonEmitter;
|
use rustc_errors::json::JsonEmitter;
|
||||||
use rustc_feature::UnstableFeatures;
|
use rustc_feature::UnstableFeatures;
|
||||||
use rustc_hir::def::Namespace::TypeNS;
|
use rustc_hir::def::{Namespace::TypeNS, Res};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
|
use rustc_hir::{
|
||||||
|
intravisit::{self, NestedVisitorMap, Visitor},
|
||||||
|
Path,
|
||||||
|
};
|
||||||
use rustc_interface::interface;
|
use rustc_interface::interface;
|
||||||
|
use rustc_middle::hir::map::Map;
|
||||||
use rustc_middle::middle::cstore::CrateStore;
|
use rustc_middle::middle::cstore::CrateStore;
|
||||||
use rustc_middle::middle::privacy::AccessLevels;
|
use rustc_middle::middle::privacy::AccessLevels;
|
||||||
use rustc_middle::ty::{Ty, TyCtxt};
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
@ -372,7 +377,35 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||||||
crate_name,
|
crate_name,
|
||||||
lint_caps,
|
lint_caps,
|
||||||
register_lints: None,
|
register_lints: None,
|
||||||
override_queries: None,
|
override_queries: Some(|_sess, providers, _external_providers| {
|
||||||
|
// Most lints will require typechecking, so just don't run them.
|
||||||
|
providers.lint_mod = |_, _| {};
|
||||||
|
// Prevent `rustc_typeck::check_crate` from calling `typeck_tables_of` on all bodies.
|
||||||
|
providers.typeck_item_bodies = |_, _| {};
|
||||||
|
// hack so that `used_trait_imports` won't try to call typeck_tables_of
|
||||||
|
providers.used_trait_imports = |_, _| {
|
||||||
|
lazy_static! {
|
||||||
|
static ref EMPTY_SET: FxHashSet<LocalDefId> = FxHashSet::default();
|
||||||
|
}
|
||||||
|
&EMPTY_SET
|
||||||
|
};
|
||||||
|
// In case typeck does end up being called, don't ICE in case there were name resolution errors
|
||||||
|
providers.typeck_tables_of = move |tcx, def_id| {
|
||||||
|
// Closures' tables come from their outermost function,
|
||||||
|
// as they are part of the same "inference environment".
|
||||||
|
// This avoids emitting errors for the parent twice (see similar code in `typeck_tables_of_with_fallback`)
|
||||||
|
let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
|
||||||
|
if outer_def_id != def_id {
|
||||||
|
return tcx.typeck_tables_of(outer_def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let hir = tcx.hir();
|
||||||
|
let body = hir.body(hir.body_owned_by(hir.as_local_hir_id(def_id)));
|
||||||
|
debug!("visiting body for {:?}", def_id);
|
||||||
|
EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
|
||||||
|
(rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck_tables_of)(tcx, def_id)
|
||||||
|
};
|
||||||
|
}),
|
||||||
registry: rustc_driver::diagnostics_registry(),
|
registry: rustc_driver::diagnostics_registry(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -416,10 +449,17 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||||||
let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take();
|
let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take();
|
||||||
|
|
||||||
global_ctxt.enter(|tcx| {
|
global_ctxt.enter(|tcx| {
|
||||||
tcx.analysis(LOCAL_CRATE).ok();
|
// Certain queries assume that some checks were run elsewhere
|
||||||
|
// (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
|
||||||
// Abort if there were any errors so far
|
// so type-check everything other than function bodies in this crate before running lints.
|
||||||
sess.abort_if_errors();
|
// NOTE: this does not call `tcx.analysis()` so that we won't
|
||||||
|
// typeck function bodies or run the default rustc lints.
|
||||||
|
// (see `override_queries` in the `config`)
|
||||||
|
let _ = rustc_typeck::check_crate(tcx);
|
||||||
|
tcx.sess.abort_if_errors();
|
||||||
|
sess.time("missing_docs", || {
|
||||||
|
rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
|
||||||
|
});
|
||||||
|
|
||||||
let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
|
let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
|
||||||
// Convert from a HirId set to a DefId set since we don't always have easy access
|
// Convert from a HirId set to a DefId set since we don't always have easy access
|
||||||
@ -570,6 +610,62 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Due to https://github.com/rust-lang/rust/pull/73566,
|
||||||
|
/// the name resolution pass may find errors that are never emitted.
|
||||||
|
/// If typeck is called after this happens, then we'll get an ICE:
|
||||||
|
/// 'Res::Error found but not reported'. To avoid this, emit the errors now.
|
||||||
|
struct EmitIgnoredResolutionErrors<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> EmitIgnoredResolutionErrors<'tcx> {
|
||||||
|
fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||||
|
Self { tcx }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
|
||||||
|
type Map = Map<'tcx>;
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||||
|
// We need to recurse into nested closures,
|
||||||
|
// since those will fallback to the parent for type checking.
|
||||||
|
NestedVisitorMap::OnlyBodies(self.tcx.hir())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_path(&mut self, path: &'tcx Path<'_>, _id: HirId) {
|
||||||
|
debug!("visiting path {:?}", path);
|
||||||
|
if path.res == Res::Err {
|
||||||
|
// We have less context here than in rustc_resolve,
|
||||||
|
// so we can only emit the name and span.
|
||||||
|
// However we can give a hint that rustc_resolve will have more info.
|
||||||
|
let label = format!(
|
||||||
|
"could not resolve path `{}`",
|
||||||
|
path.segments
|
||||||
|
.iter()
|
||||||
|
.map(|segment| segment.ident.as_str().to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("::")
|
||||||
|
);
|
||||||
|
let mut err = rustc_errors::struct_span_err!(
|
||||||
|
self.tcx.sess,
|
||||||
|
path.span,
|
||||||
|
E0433,
|
||||||
|
"failed to resolve: {}",
|
||||||
|
label
|
||||||
|
);
|
||||||
|
err.span_label(path.span, label);
|
||||||
|
err.note("this error was originally ignored because you are running `rustdoc`");
|
||||||
|
err.note("try running again with `rustc` or `cargo check` and you may get a more detailed error");
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
// We could have an outer resolution that succeeded,
|
||||||
|
// but with generic parameters that failed.
|
||||||
|
// Recurse into the segments so we catch those too.
|
||||||
|
intravisit::walk_path(self, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
|
/// `DefId` or parameter index (`ty::ParamTy.index`) of a synthetic type parameter
|
||||||
/// for `impl Trait` in argument position.
|
/// for `impl Trait` in argument position.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
@ -37,14 +37,14 @@ impl ExternalHtml {
|
|||||||
let bc = format!(
|
let bc = format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
bc,
|
bc,
|
||||||
Markdown(&m_bc, &[], id_map, codes, edition, playground).to_string()
|
Markdown(&m_bc, &[], id_map, codes, edition, playground).into_string()
|
||||||
);
|
);
|
||||||
let ac = load_external_files(after_content, diag)?;
|
let ac = load_external_files(after_content, diag)?;
|
||||||
let m_ac = load_external_files(md_after_content, diag)?;
|
let m_ac = load_external_files(md_after_content, diag)?;
|
||||||
let ac = format!(
|
let ac = format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
ac,
|
ac,
|
||||||
Markdown(&m_ac, &[], id_map, codes, edition, playground).to_string()
|
Markdown(&m_ac, &[], id_map, codes, edition, playground).into_string()
|
||||||
);
|
);
|
||||||
Some(ExternalHtml { in_header: ih, before_content: bc, after_content: ac })
|
Some(ExternalHtml { in_header: ih, before_content: bc, after_content: ac })
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,22 @@ impl Buffer {
|
|||||||
Buffer { for_html: false, buffer: String::new() }
|
Buffer { for_html: false, buffer: String::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn is_empty(&self) -> bool {
|
||||||
|
self.buffer.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
crate fn into_inner(self) -> String {
|
crate fn into_inner(self) -> String {
|
||||||
self.buffer
|
self.buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn insert_str(&mut self, idx: usize, s: &str) {
|
||||||
|
self.buffer.insert_str(idx, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
crate fn push_str(&mut self, s: &str) {
|
||||||
|
self.buffer.push_str(s);
|
||||||
|
}
|
||||||
|
|
||||||
// Intended for consumption by write! and writeln! (std::fmt) but without
|
// Intended for consumption by write! and writeln! (std::fmt) but without
|
||||||
// the fmt::Result return type imposed by fmt::Write (and avoiding the trait
|
// the fmt::Result return type imposed by fmt::Write (and avoiding the trait
|
||||||
// import).
|
// import).
|
||||||
|
@ -12,15 +12,17 @@ use std::io;
|
|||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
use rustc_ast::token::{self, Token};
|
use rustc_ast::token::{self, Token};
|
||||||
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_parse::lexer;
|
use rustc_parse::lexer;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
|
use rustc_span::hygiene::SyntaxContext;
|
||||||
use rustc_span::source_map::SourceMap;
|
use rustc_span::source_map::SourceMap;
|
||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::{kw, sym};
|
||||||
use rustc_span::{FileName, Span};
|
use rustc_span::{BytePos, FileName, SourceFile, Span};
|
||||||
|
|
||||||
/// Highlights `src`, returning the HTML output.
|
/// Highlights `src`, returning the HTML output.
|
||||||
pub fn render_with_highlighting(
|
pub fn render_with_highlighting(
|
||||||
src: &str,
|
src: String,
|
||||||
class: Option<&str>,
|
class: Option<&str>,
|
||||||
playground_button: Option<&str>,
|
playground_button: Option<&str>,
|
||||||
tooltip: Option<(&str, &str)>,
|
tooltip: Option<(&str, &str)>,
|
||||||
@ -38,12 +40,13 @@ pub fn render_with_highlighting(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let sess = ParseSess::with_silent_emitter();
|
let sess = ParseSess::with_silent_emitter();
|
||||||
let sf = sess
|
let source_file = sess
|
||||||
.source_map()
|
.source_map()
|
||||||
.new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned());
|
.new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src);
|
||||||
|
|
||||||
|
let classifier_source_file = Lrc::clone(&source_file);
|
||||||
let highlight_result = rustc_driver::catch_fatal_errors(|| {
|
let highlight_result = rustc_driver::catch_fatal_errors(|| {
|
||||||
let lexer = lexer::StringReader::new(&sess, sf, None);
|
let mut classifier = Classifier::new(&sess, classifier_source_file);
|
||||||
let mut classifier = Classifier::new(lexer, sess.source_map());
|
|
||||||
|
|
||||||
let mut highlighted_source = vec![];
|
let mut highlighted_source = vec![];
|
||||||
if classifier.write_source(&mut highlighted_source).is_err() {
|
if classifier.write_source(&mut highlighted_source).is_err() {
|
||||||
@ -61,9 +64,17 @@ pub fn render_with_highlighting(
|
|||||||
write_footer(&mut out, playground_button).unwrap();
|
write_footer(&mut out, playground_button).unwrap();
|
||||||
}
|
}
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
|
// Get the source back out of the source map to avoid a copy in the happy path.
|
||||||
|
let span =
|
||||||
|
Span::new(BytePos(0), BytePos(source_file.byte_length()), SyntaxContext::root());
|
||||||
|
let src = sess
|
||||||
|
.source_map()
|
||||||
|
.span_to_snippet(span)
|
||||||
|
.expect("could not retrieve snippet from artificial source file");
|
||||||
|
|
||||||
// If errors are encountered while trying to highlight, just emit
|
// If errors are encountered while trying to highlight, just emit
|
||||||
// the unhighlighted source.
|
// the unhighlighted source.
|
||||||
write!(out, "<pre><code>{}</code></pre>", Escape(src)).unwrap();
|
write!(out, "<pre><code>{}</code></pre>", Escape(&src)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,10 +84,10 @@ pub fn render_with_highlighting(
|
|||||||
/// Processes a program (nested in the internal `lexer`), classifying strings of
|
/// Processes a program (nested in the internal `lexer`), classifying strings of
|
||||||
/// text by highlighting category (`Class`). Calls out to a `Writer` to write
|
/// text by highlighting category (`Class`). Calls out to a `Writer` to write
|
||||||
/// each span of text in sequence.
|
/// each span of text in sequence.
|
||||||
struct Classifier<'a> {
|
struct Classifier<'sess> {
|
||||||
lexer: lexer::StringReader<'a>,
|
lexer: lexer::StringReader<'sess>,
|
||||||
peek_token: Option<Token>,
|
peek_token: Option<Token>,
|
||||||
source_map: &'a SourceMap,
|
source_map: &'sess SourceMap,
|
||||||
|
|
||||||
// State of the classifier.
|
// State of the classifier.
|
||||||
in_attribute: bool,
|
in_attribute: bool,
|
||||||
@ -154,6 +165,7 @@ impl<U: Write> Writer for U {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
enum HighlightError {
|
enum HighlightError {
|
||||||
LexError,
|
LexError,
|
||||||
IoError(io::Error),
|
IoError(io::Error),
|
||||||
@ -165,12 +177,14 @@ impl From<io::Error> for HighlightError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Classifier<'a> {
|
impl<'sess> Classifier<'sess> {
|
||||||
fn new(lexer: lexer::StringReader<'a>, source_map: &'a SourceMap) -> Classifier<'a> {
|
fn new(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Classifier<'_> {
|
||||||
|
let lexer = lexer::StringReader::new(sess, source_file, None);
|
||||||
|
|
||||||
Classifier {
|
Classifier {
|
||||||
lexer,
|
lexer,
|
||||||
peek_token: None,
|
peek_token: None,
|
||||||
source_map,
|
source_map: sess.source_map(),
|
||||||
in_attribute: false,
|
in_attribute: false,
|
||||||
in_macro: false,
|
in_macro: false,
|
||||||
in_macro_nonterminal: false,
|
in_macro_nonterminal: false,
|
||||||
@ -209,11 +223,17 @@ impl<'a> Classifier<'a> {
|
|||||||
/// source.
|
/// source.
|
||||||
fn write_source<W: Writer>(&mut self, out: &mut W) -> Result<(), HighlightError> {
|
fn write_source<W: Writer>(&mut self, out: &mut W) -> Result<(), HighlightError> {
|
||||||
loop {
|
loop {
|
||||||
let next = self.try_next_token()?;
|
let mut next = self.try_next_token()?;
|
||||||
if next == token::Eof {
|
if next == token::Eof {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Glue any tokens that need to be glued.
|
||||||
|
if let Some(joint) = next.glue(self.peek()?) {
|
||||||
|
next = joint;
|
||||||
|
let _ = self.try_next_token()?;
|
||||||
|
}
|
||||||
|
|
||||||
self.write_token(out, next)?;
|
self.write_token(out, next)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,3 +449,6 @@ fn write_header(class: Option<&str>, out: &mut dyn Write) -> io::Result<()> {
|
|||||||
fn write_footer(out: &mut dyn Write, playground_button: Option<&str>) -> io::Result<()> {
|
fn write_footer(out: &mut dyn Write, playground_button: Option<&str>) -> io::Result<()> {
|
||||||
write!(out, "</pre>{}</div>\n", if let Some(button) = playground_button { button } else { "" })
|
write!(out, "</pre>{}</div>\n", if let Some(button) = playground_button { button } else { "" })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
82
src/librustdoc/html/highlight/tests.rs
Normal file
82
src/librustdoc/html/highlight/tests.rs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
use rustc_ast::attr::with_session_globals;
|
||||||
|
use rustc_session::parse::ParseSess;
|
||||||
|
use rustc_span::edition::Edition;
|
||||||
|
use rustc_span::FileName;
|
||||||
|
|
||||||
|
use super::Classifier;
|
||||||
|
|
||||||
|
fn highlight(src: &str) -> String {
|
||||||
|
let mut out = vec![];
|
||||||
|
|
||||||
|
with_session_globals(Edition::Edition2018, || {
|
||||||
|
let sess = ParseSess::with_silent_emitter();
|
||||||
|
let source_file = sess.source_map().new_source_file(
|
||||||
|
FileName::Custom(String::from("rustdoc-highlighting")),
|
||||||
|
src.to_owned(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut classifier = Classifier::new(&sess, source_file);
|
||||||
|
classifier.write_source(&mut out).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
String::from_utf8(out).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function() {
|
||||||
|
assert_eq!(
|
||||||
|
highlight("fn main() {}"),
|
||||||
|
r#"<span class="kw">fn</span> <span class="ident">main</span>() {}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn statement() {
|
||||||
|
assert_eq!(
|
||||||
|
highlight("let foo = true;"),
|
||||||
|
concat!(
|
||||||
|
r#"<span class="kw">let</span> <span class="ident">foo</span> "#,
|
||||||
|
r#"<span class="op">=</span> <span class="bool-val">true</span>;"#,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inner_attr() {
|
||||||
|
assert_eq!(
|
||||||
|
highlight(r##"#![crate_type = "lib"]"##),
|
||||||
|
concat!(
|
||||||
|
r##"<span class="attribute">#![<span class="ident">crate_type</span> "##,
|
||||||
|
r##"<span class="op">=</span> <span class="string">"lib"</span>]</span>"##,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn outer_attr() {
|
||||||
|
assert_eq!(
|
||||||
|
highlight(r##"#[cfg(target_os = "linux")]"##),
|
||||||
|
concat!(
|
||||||
|
r##"<span class="attribute">#[<span class="ident">cfg</span>("##,
|
||||||
|
r##"<span class="ident">target_os</span> <span class="op">=</span> "##,
|
||||||
|
r##"<span class="string">"linux"</span>)]</span>"##,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mac() {
|
||||||
|
assert_eq!(
|
||||||
|
highlight("mac!(foo bar)"),
|
||||||
|
concat!(
|
||||||
|
r#"<span class="macro">mac</span><span class="macro">!</span>("#,
|
||||||
|
r#"<span class="ident">foo</span> <span class="ident">bar</span>)"#,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regression test for #72684
|
||||||
|
#[test]
|
||||||
|
fn andand() {
|
||||||
|
assert_eq!(highlight("&&"), r#"<span class="op">&&</span>"#);
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
//! let s = "My *markdown* _text_";
|
//! let s = "My *markdown* _text_";
|
||||||
//! let mut id_map = IdMap::new();
|
//! let mut id_map = IdMap::new();
|
||||||
//! let md = Markdown(s, &[], &mut id_map, ErrorCodes::Yes, Edition::Edition2015, &None);
|
//! let md = Markdown(s, &[], &mut id_map, ErrorCodes::Yes, Edition::Edition2015, &None);
|
||||||
//! let html = md.to_string();
|
//! let html = md.into_string();
|
||||||
//! // ... something using html
|
//! // ... something using html
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
|||||||
|
|
||||||
if let Some((s1, s2)) = tooltip {
|
if let Some((s1, s2)) = tooltip {
|
||||||
s.push_str(&highlight::render_with_highlighting(
|
s.push_str(&highlight::render_with_highlighting(
|
||||||
&text,
|
text,
|
||||||
Some(&format!(
|
Some(&format!(
|
||||||
"rust-example-rendered{}",
|
"rust-example-rendered{}",
|
||||||
if ignore != Ignore::None {
|
if ignore != Ignore::None {
|
||||||
@ -313,7 +313,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
|||||||
Some(Event::Html(s.into()))
|
Some(Event::Html(s.into()))
|
||||||
} else {
|
} else {
|
||||||
s.push_str(&highlight::render_with_highlighting(
|
s.push_str(&highlight::render_with_highlighting(
|
||||||
&text,
|
text,
|
||||||
Some(&format!(
|
Some(&format!(
|
||||||
"rust-example-rendered{}",
|
"rust-example-rendered{}",
|
||||||
if ignore != Ignore::None {
|
if ignore != Ignore::None {
|
||||||
@ -848,7 +848,7 @@ impl LangString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Markdown<'_> {
|
impl Markdown<'_> {
|
||||||
pub fn to_string(self) -> String {
|
pub fn into_string(self) -> String {
|
||||||
let Markdown(md, links, mut ids, codes, edition, playground) = self;
|
let Markdown(md, links, mut ids, codes, edition, playground) = self;
|
||||||
|
|
||||||
// This is actually common enough to special-case
|
// This is actually common enough to special-case
|
||||||
@ -878,7 +878,7 @@ impl Markdown<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MarkdownWithToc<'_> {
|
impl MarkdownWithToc<'_> {
|
||||||
pub fn to_string(self) -> String {
|
pub fn into_string(self) -> String {
|
||||||
let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
|
let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
|
||||||
|
|
||||||
let p = Parser::new_ext(md, opts());
|
let p = Parser::new_ext(md, opts());
|
||||||
@ -899,7 +899,7 @@ impl MarkdownWithToc<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MarkdownHtml<'_> {
|
impl MarkdownHtml<'_> {
|
||||||
pub fn to_string(self) -> String {
|
pub fn into_string(self) -> String {
|
||||||
let MarkdownHtml(md, mut ids, codes, edition, playground) = self;
|
let MarkdownHtml(md, mut ids, codes, edition, playground) = self;
|
||||||
|
|
||||||
// This is actually common enough to special-case
|
// This is actually common enough to special-case
|
||||||
@ -926,7 +926,7 @@ impl MarkdownHtml<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MarkdownSummaryLine<'_> {
|
impl MarkdownSummaryLine<'_> {
|
||||||
pub fn to_string(self) -> String {
|
pub fn into_string(self) -> String {
|
||||||
let MarkdownSummaryLine(md, links) = self;
|
let MarkdownSummaryLine(md, links) = self;
|
||||||
// This is actually common enough to special-case
|
// This is actually common enough to special-case
|
||||||
if md.is_empty() {
|
if md.is_empty() {
|
||||||
|
@ -134,7 +134,7 @@ fn test_header() {
|
|||||||
fn t(input: &str, expect: &str) {
|
fn t(input: &str, expect: &str) {
|
||||||
let mut map = IdMap::new();
|
let mut map = IdMap::new();
|
||||||
let output =
|
let output =
|
||||||
Markdown(input, &[], &mut map, ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string();
|
Markdown(input, &[], &mut map, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
|
||||||
assert_eq!(output, expect, "original: {}", input);
|
assert_eq!(output, expect, "original: {}", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +166,8 @@ fn test_header() {
|
|||||||
fn test_header_ids_multiple_blocks() {
|
fn test_header_ids_multiple_blocks() {
|
||||||
let mut map = IdMap::new();
|
let mut map = IdMap::new();
|
||||||
fn t(map: &mut IdMap, input: &str, expect: &str) {
|
fn t(map: &mut IdMap, input: &str, expect: &str) {
|
||||||
let output = Markdown(input, &[], map, ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string();
|
let output =
|
||||||
|
Markdown(input, &[], map, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
|
||||||
assert_eq!(output, expect, "original: {}", input);
|
assert_eq!(output, expect, "original: {}", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +229,7 @@ fn test_markdown_html_escape() {
|
|||||||
fn t(input: &str, expect: &str) {
|
fn t(input: &str, expect: &str) {
|
||||||
let mut idmap = IdMap::new();
|
let mut idmap = IdMap::new();
|
||||||
let output =
|
let output =
|
||||||
MarkdownHtml(input, &mut idmap, ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string();
|
MarkdownHtml(input, &mut idmap, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
|
||||||
assert_eq!(output, expect, "original: {}", input);
|
assert_eq!(output, expect, "original: {}", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1895,7 +1895,7 @@ fn render_markdown(
|
|||||||
cx.shared.edition,
|
cx.shared.edition,
|
||||||
&cx.shared.playground
|
&cx.shared.playground
|
||||||
)
|
)
|
||||||
.to_string()
|
.into_string()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2185,7 +2185,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
|
|||||||
</tr>",
|
</tr>",
|
||||||
name = *myitem.name.as_ref().unwrap(),
|
name = *myitem.name.as_ref().unwrap(),
|
||||||
stab_tags = stability_tags(myitem),
|
stab_tags = stability_tags(myitem),
|
||||||
docs = MarkdownSummaryLine(doc_value, &myitem.links()).to_string(),
|
docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
|
||||||
class = myitem.type_(),
|
class = myitem.type_(),
|
||||||
add = add,
|
add = add,
|
||||||
stab = stab.unwrap_or_else(String::new),
|
stab = stab.unwrap_or_else(String::new),
|
||||||
@ -2278,7 +2278,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
|||||||
cx.shared.edition,
|
cx.shared.edition,
|
||||||
&cx.shared.playground,
|
&cx.shared.playground,
|
||||||
);
|
);
|
||||||
message.push_str(&format!(": {}", html.to_string()));
|
message.push_str(&format!(": {}", html.into_string()));
|
||||||
}
|
}
|
||||||
stability.push(format!(
|
stability.push(format!(
|
||||||
"<div class='stab deprecated'><span class='emoji'>👎</span> {}</div>",
|
"<div class='stab deprecated'><span class='emoji'>👎</span> {}</div>",
|
||||||
@ -2332,7 +2332,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
|||||||
cx.shared.edition,
|
cx.shared.edition,
|
||||||
&cx.shared.playground,
|
&cx.shared.playground,
|
||||||
)
|
)
|
||||||
.to_string()
|
.into_string()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2415,7 +2415,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
|
|||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
|
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
|
||||||
{name}{generics}{decl}{where_clause}</pre>",
|
{name}{generics}{decl}{spotlight}{where_clause}</pre>",
|
||||||
vis = it.visibility.print_with_space(),
|
vis = it.visibility.print_with_space(),
|
||||||
constness = f.header.constness.print_with_space(),
|
constness = f.header.constness.print_with_space(),
|
||||||
asyncness = f.header.asyncness.print_with_space(),
|
asyncness = f.header.asyncness.print_with_space(),
|
||||||
@ -2425,7 +2425,8 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
|
|||||||
generics = f.generics.print(),
|
generics = f.generics.print(),
|
||||||
where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
|
where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
|
||||||
decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness }
|
decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness }
|
||||||
.print()
|
.print(),
|
||||||
|
spotlight = spotlight_decl(&f.decl),
|
||||||
);
|
);
|
||||||
document(w, cx, it)
|
document(w, cx, it)
|
||||||
}
|
}
|
||||||
@ -2612,7 +2613,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
|
|||||||
let name = m.name.as_ref().unwrap();
|
let name = m.name.as_ref().unwrap();
|
||||||
let item_type = m.type_();
|
let item_type = m.type_();
|
||||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||||
write!(w, "<h3 id='{id}' class='method'><code>", id = id);
|
write!(w, "<h3 id='{id}' class='method'><code>", id = id,);
|
||||||
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
|
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
|
||||||
write!(w, "</code>");
|
write!(w, "</code>");
|
||||||
render_stability_since(w, m, t);
|
render_stability_since(w, m, t);
|
||||||
@ -2926,7 +2927,7 @@ fn render_assoc_item(
|
|||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{}{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
|
"{}{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
|
||||||
{generics}{decl}{where_clause}",
|
{generics}{decl}{spotlight}{where_clause}",
|
||||||
if parent == ItemType::Trait { " " } else { "" },
|
if parent == ItemType::Trait { " " } else { "" },
|
||||||
meth.visibility.print_with_space(),
|
meth.visibility.print_with_space(),
|
||||||
header.constness.print_with_space(),
|
header.constness.print_with_space(),
|
||||||
@ -2938,6 +2939,7 @@ fn render_assoc_item(
|
|||||||
name = name,
|
name = name,
|
||||||
generics = g.print(),
|
generics = g.print(),
|
||||||
decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }.print(),
|
decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }.print(),
|
||||||
|
spotlight = spotlight_decl(&d),
|
||||||
where_clause = WhereClause { gens: g, indent, end_newline }
|
where_clause = WhereClause { gens: g, indent, end_newline }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -3559,6 +3561,62 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spotlight_decl(decl: &clean::FnDecl) -> String {
|
||||||
|
let mut out = Buffer::html();
|
||||||
|
let mut trait_ = String::new();
|
||||||
|
|
||||||
|
if let Some(did) = decl.output.def_id() {
|
||||||
|
let c = cache();
|
||||||
|
if let Some(impls) = c.impls.get(&did) {
|
||||||
|
for i in impls {
|
||||||
|
let impl_ = i.inner_impl();
|
||||||
|
if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
|
||||||
|
if out.is_empty() {
|
||||||
|
out.push_str(&format!(
|
||||||
|
"<h3 class=\"important\">Important traits for {}</h3>\
|
||||||
|
<code class=\"content\">",
|
||||||
|
impl_.for_.print()
|
||||||
|
));
|
||||||
|
trait_.push_str(&impl_.for_.print().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
//use the "where" class here to make it small
|
||||||
|
out.push_str(&format!(
|
||||||
|
"<span class=\"where fmt-newline\">{}</span>",
|
||||||
|
impl_.print()
|
||||||
|
));
|
||||||
|
let t_did = impl_.trait_.def_id().unwrap();
|
||||||
|
for it in &impl_.items {
|
||||||
|
if let clean::TypedefItem(ref tydef, _) = it.inner {
|
||||||
|
out.push_str("<span class=\"where fmt-newline\"> ");
|
||||||
|
assoc_type(
|
||||||
|
&mut out,
|
||||||
|
it,
|
||||||
|
&[],
|
||||||
|
Some(&tydef.type_),
|
||||||
|
AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
out.push_str(";</span>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !out.is_empty() {
|
||||||
|
out.insert_str(
|
||||||
|
0,
|
||||||
|
"<span class=\"important-traits\"><span class=\"important-traits-tooltip\">ⓘ<div class='important-traits-tooltiptext'><span class=\"docblock\">"
|
||||||
|
|
||||||
|
);
|
||||||
|
out.push_str("</code></span></div></span></span>");
|
||||||
|
}
|
||||||
|
|
||||||
|
out.into_inner()
|
||||||
|
}
|
||||||
|
|
||||||
fn render_impl(
|
fn render_impl(
|
||||||
w: &mut Buffer,
|
w: &mut Buffer,
|
||||||
cx: &Context,
|
cx: &Context,
|
||||||
@ -3632,7 +3690,7 @@ fn render_impl(
|
|||||||
cx.shared.edition,
|
cx.shared.edition,
|
||||||
&cx.shared.playground
|
&cx.shared.playground
|
||||||
)
|
)
|
||||||
.to_string()
|
.into_string()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3670,7 +3728,8 @@ fn render_impl(
|
|||||||
// Only render when the method is not static or we allow static methods
|
// Only render when the method is not static or we allow static methods
|
||||||
if render_method_item {
|
if render_method_item {
|
||||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||||
write!(w, "<h4 id='{}' class=\"{}{}\"><code>", id, item_type, extra_class);
|
write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
|
||||||
|
write!(w, "<code>");
|
||||||
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
|
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
|
||||||
write!(w, "</code>");
|
write!(w, "</code>");
|
||||||
render_stability_since_raw(w, item.stable_since(), outer_version);
|
render_stability_since_raw(w, item.stable_since(), outer_version);
|
||||||
@ -4526,7 +4585,12 @@ fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) {
|
|||||||
|
|
||||||
fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro) {
|
fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro) {
|
||||||
wrap_into_docblock(w, |w| {
|
wrap_into_docblock(w, |w| {
|
||||||
w.write_str(&highlight::render_with_highlighting(&t.source, Some("macro"), None, None))
|
w.write_str(&highlight::render_with_highlighting(
|
||||||
|
t.source.clone(),
|
||||||
|
Some("macro"),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
))
|
||||||
});
|
});
|
||||||
document(w, cx, it)
|
document(w, cx, it)
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ impl<'a> SourceCollector<'a> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let contents = match fs::read_to_string(&p) {
|
let mut contents = match fs::read_to_string(&p) {
|
||||||
Ok(contents) => contents,
|
Ok(contents) => contents,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(Error::new(e, &p));
|
return Err(Error::new(e, &p));
|
||||||
@ -83,8 +83,9 @@ impl<'a> SourceCollector<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Remove the utf-8 BOM if any
|
// Remove the utf-8 BOM if any
|
||||||
let contents =
|
if contents.starts_with("\u{feff}") {
|
||||||
if contents.starts_with("\u{feff}") { &contents[3..] } else { &contents[..] };
|
contents.drain(..3);
|
||||||
|
}
|
||||||
|
|
||||||
// Create the intermediate directories
|
// Create the intermediate directories
|
||||||
let mut cur = self.dst.clone();
|
let mut cur = self.dst.clone();
|
||||||
@ -122,7 +123,7 @@ impl<'a> SourceCollector<'a> {
|
|||||||
&self.scx.layout,
|
&self.scx.layout,
|
||||||
&page,
|
&page,
|
||||||
"",
|
"",
|
||||||
|buf: &mut _| print_src(buf, &contents),
|
|buf: &mut _| print_src(buf, contents),
|
||||||
&self.scx.style_files,
|
&self.scx.style_files,
|
||||||
);
|
);
|
||||||
self.scx.fs.write(&cur, v.as_bytes())?;
|
self.scx.fs.write(&cur, v.as_bytes())?;
|
||||||
@ -160,7 +161,7 @@ where
|
|||||||
|
|
||||||
/// Wrapper struct to render the source code of a file. This will do things like
|
/// Wrapper struct to render the source code of a file. This will do things like
|
||||||
/// adding line numbers to the left-hand side.
|
/// adding line numbers to the left-hand side.
|
||||||
fn print_src(buf: &mut Buffer, s: &str) {
|
fn print_src(buf: &mut Buffer, s: String) {
|
||||||
let lines = s.lines().count();
|
let lines = s.lines().count();
|
||||||
let mut cols = 0;
|
let mut cols = 0;
|
||||||
let mut tmp = lines;
|
let mut tmp = lines;
|
||||||
|
@ -2636,6 +2636,13 @@ function defocusSearchBar() {
|
|||||||
});
|
});
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
|
||||||
|
e.onclick = function() {
|
||||||
|
this.getElementsByClassName('important-traits-tooltiptext')[0]
|
||||||
|
.classList.toggle("force-tooltip");
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// In the search display, allows to switch between tabs.
|
// In the search display, allows to switch between tabs.
|
||||||
function printTab(nb) {
|
function printTab(nb) {
|
||||||
if (nb === 0 || nb === 1 || nb === 2) {
|
if (nb === 0 || nb === 1 || nb === 2) {
|
||||||
|
@ -146,9 +146,12 @@ code, pre, a.test-arrow {
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 0 0.1em;
|
padding: 0 0.1em;
|
||||||
}
|
}
|
||||||
.docblock pre code, .docblock-short pre code {
|
.docblock pre code, .docblock-short pre code, .docblock code.spotlight {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
.docblock code.spotlight :last-child {
|
||||||
|
padding-bottom: 0.6em;
|
||||||
|
}
|
||||||
pre {
|
pre {
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
}
|
}
|
||||||
@ -523,7 +526,7 @@ h4 > code, h3 > code, .invisible > code {
|
|||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content .methods > div {
|
.content .methods > div:not(.important-traits) {
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
@ -1079,10 +1082,6 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip:hover .tooltiptext {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip .tooltiptext::after {
|
.tooltip .tooltiptext::after {
|
||||||
content: " ";
|
content: " ";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -1098,13 +1097,52 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip .tooltiptext {
|
.important-traits-tooltip {
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.important-traits:hover .important-traits-tooltiptext,
|
||||||
|
.important-traits .important-traits-tooltiptext.force-tooltip {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.important-traits .important-traits-tooltiptext {
|
||||||
|
display: none;
|
||||||
|
padding: 5px 3px 3px 3px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-left: 5px;
|
||||||
|
z-index: 10;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: default;
|
||||||
|
position: absolute;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
font-weight: normal;
|
}
|
||||||
|
|
||||||
|
.important-traits-tooltip::after {
|
||||||
|
/* The margin on the tooltip does not capture hover events,
|
||||||
|
this extends the area of hover enough so that mouse hover is not
|
||||||
|
lost when moving the mouse to the tooltip */
|
||||||
|
content: "\00a0\00a0\00a0";
|
||||||
|
}
|
||||||
|
|
||||||
|
.important-traits .important, .important-traits .docblock {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.important-traits .docblock code.content{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Example code has the "Run" button that
|
||||||
|
needs to be positioned relative to the pre */
|
||||||
|
pre.rust.rust-example-rendered {
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre.rust {
|
pre.rust {
|
||||||
position: relative;
|
|
||||||
tab-size: 4;
|
tab-size: 4;
|
||||||
-moz-tab-size: 4;
|
-moz-tab-size: 4;
|
||||||
}
|
}
|
||||||
@ -1144,6 +1182,18 @@ pre.rust {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.important-traits {
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 2;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 > .important-traits {
|
||||||
|
position: absolute;
|
||||||
|
left: -44px;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
#all-types {
|
#all-types {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
@ -1370,6 +1420,12 @@ pre.rust {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h4 > .important-traits {
|
||||||
|
position: absolute;
|
||||||
|
left: -22px;
|
||||||
|
top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
#titles > div > div.count {
|
#titles > div > div.count {
|
||||||
float: left;
|
float: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -140,4 +140,9 @@ function createSourceSidebar() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
main.insertBefore(sidebar, main.firstChild);
|
main.insertBefore(sidebar, main.firstChild);
|
||||||
|
// Focus on the current file in the source files sidebar.
|
||||||
|
var selected_elem = sidebar.getElementsByClassName("selected")[0];
|
||||||
|
if (typeof selected_elem !== "undefined") {
|
||||||
|
selected_elem.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,6 +394,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
|
|||||||
border-color: transparent #314559 transparent transparent;
|
border-color: transparent #314559 transparent transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.important-traits-tooltiptext {
|
||||||
|
background-color: #314559;
|
||||||
|
border-color: #5c6773;
|
||||||
|
}
|
||||||
|
|
||||||
#titles > div.selected {
|
#titles > div.selected {
|
||||||
background-color: #141920 !important;
|
background-color: #141920 !important;
|
||||||
border-bottom: 1px solid #ffb44c !important;
|
border-bottom: 1px solid #ffb44c !important;
|
||||||
|
@ -337,6 +337,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
|
|||||||
border-color: transparent black transparent transparent;
|
border-color: transparent black transparent transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.important-traits-tooltiptext {
|
||||||
|
background-color: #111;
|
||||||
|
border-color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
#titles > div:not(.selected) {
|
#titles > div:not(.selected) {
|
||||||
background-color: #252525;
|
background-color: #252525;
|
||||||
border-top-color: #252525;
|
border-top-color: #252525;
|
||||||
|
@ -331,6 +331,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
|
|||||||
border-color: transparent black transparent transparent;
|
border-color: transparent black transparent transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.important-traits-tooltiptext {
|
||||||
|
background-color: #eee;
|
||||||
|
border-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
#titles > div:not(.selected) {
|
#titles > div:not(.selected) {
|
||||||
background-color: #e6e6e6;
|
background-color: #e6e6e6;
|
||||||
border-top-color: #e6e6e6;
|
border-top-color: #e6e6e6;
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
extern crate rustc_ast;
|
extern crate rustc_ast;
|
||||||
extern crate rustc_ast_pretty;
|
extern crate rustc_ast_pretty;
|
||||||
extern crate rustc_attr;
|
extern crate rustc_attr;
|
||||||
@ -94,6 +96,7 @@ pub fn main() {
|
|||||||
32_000_000 // 32MB on other platforms
|
32_000_000 // 32MB on other platforms
|
||||||
};
|
};
|
||||||
rustc_driver::set_sigpipe_handler();
|
rustc_driver::set_sigpipe_handler();
|
||||||
|
rustc_driver::install_ice_hook();
|
||||||
env_logger::init_from_env("RUSTDOC_LOG");
|
env_logger::init_from_env("RUSTDOC_LOG");
|
||||||
let res = std::thread::Builder::new()
|
let res = std::thread::Builder::new()
|
||||||
.stack_size(thread_stack_size)
|
.stack_size(thread_stack_size)
|
||||||
|
@ -68,9 +68,9 @@ pub fn render<P: AsRef<Path>>(
|
|||||||
let mut ids = IdMap::new();
|
let mut ids = IdMap::new();
|
||||||
let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
|
let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
|
||||||
let text = if !options.markdown_no_toc {
|
let text = if !options.markdown_no_toc {
|
||||||
MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).to_string()
|
MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).into_string()
|
||||||
} else {
|
} else {
|
||||||
Markdown(text, &[], &mut ids, error_codes, edition, &playground).to_string()
|
Markdown(text, &[], &mut ids, error_codes, edition, &playground).into_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
let err = write!(
|
let err = write!(
|
||||||
|
@ -499,6 +499,7 @@ where
|
|||||||
/// [`&str`]: ../../std/primitive.str.html
|
/// [`&str`]: ../../std/primitive.str.html
|
||||||
/// [slice]: ../../std/primitive.slice.html
|
/// [slice]: ../../std/primitive.slice.html
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[doc(spotlight)]
|
||||||
pub trait Read {
|
pub trait Read {
|
||||||
/// Pull some bytes from this source into the specified buffer, returning
|
/// Pull some bytes from this source into the specified buffer, returning
|
||||||
/// how many bytes were read.
|
/// how many bytes were read.
|
||||||
@ -1261,6 +1262,7 @@ impl Initializer {
|
|||||||
///
|
///
|
||||||
/// [`write_all`]: #method.write_all
|
/// [`write_all`]: #method.write_all
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[doc(spotlight)]
|
||||||
pub trait Write {
|
pub trait Write {
|
||||||
/// Write a buffer into this writer, returning how many bytes were written.
|
/// Write a buffer into this writer, returning how many bytes were written.
|
||||||
///
|
///
|
||||||
|
@ -261,6 +261,7 @@
|
|||||||
#![feature(doc_cfg)]
|
#![feature(doc_cfg)]
|
||||||
#![feature(doc_keyword)]
|
#![feature(doc_keyword)]
|
||||||
#![feature(doc_masked)]
|
#![feature(doc_masked)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(doc_spotlight))]
|
||||||
#![feature(dropck_eyepatch)]
|
#![feature(dropck_eyepatch)]
|
||||||
#![feature(duration_constants)]
|
#![feature(duration_constants)]
|
||||||
#![feature(exact_size_is_empty)]
|
#![feature(exact_size_is_empty)]
|
||||||
|
@ -6,12 +6,13 @@
|
|||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
#![feature(thread_local)]
|
#![feature(thread_local)]
|
||||||
|
|
||||||
// CHECK: @STATIC_VAR_1 = thread_local local_unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
|
// local_unnamed_addr does not appear when std is built with debug assertions.
|
||||||
|
// CHECK: @STATIC_VAR_1 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static mut STATIC_VAR_1: [u32; 8] = [0; 8];
|
static mut STATIC_VAR_1: [u32; 8] = [0; 8];
|
||||||
|
|
||||||
// CHECK: @STATIC_VAR_2 = thread_local local_unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
|
// CHECK: @STATIC_VAR_2 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static mut STATIC_VAR_2: [u32; 8] = [4; 8];
|
static mut STATIC_VAR_2: [u32; 8] = [4; 8];
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
// min-system-llvm-version: 9.0
|
// min-system-llvm-version: 9.0
|
||||||
// ignore-arm
|
// ignore-arm
|
||||||
|
// ignore-aarch64
|
||||||
// ignore-mips
|
// ignore-mips
|
||||||
// ignore-mips64
|
// ignore-mips64
|
||||||
// ignore-powerpc
|
// ignore-powerpc
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// WONTFIX(#20184) Needs landing pads (not present in stage1) or the compiler hangs.
|
|
||||||
// ignore-stage1
|
|
||||||
// compile-flags: -C codegen-units=2
|
// compile-flags: -C codegen-units=2
|
||||||
// ignore-emscripten
|
// ignore-emscripten
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
|
|
||||||
# ignore-stage1
|
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) a.rs && $(RUSTC) b.rs
|
$(RUSTC) a.rs && $(RUSTC) b.rs
|
||||||
$(BARE_RUSTC) c.rs -L dependency=$(TMPDIR) --extern b=$(TMPDIR)/libb.rlib \
|
$(BARE_RUSTC) c.rs -L dependency=$(TMPDIR) --extern b=$(TMPDIR)/libb.rlib \
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
|
|
||||||
# ignore-stage1
|
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs
|
$(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs
|
||||||
|
16
src/test/run-make-fulldeps/rustdoc-determinism/Makefile
Normal file
16
src/test/run-make-fulldeps/rustdoc-determinism/Makefile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-include ../tools.mk
|
||||||
|
|
||||||
|
# Assert that the search index is generated deterministically, regardless of the
|
||||||
|
# order that crates are documented in.
|
||||||
|
|
||||||
|
# ignore-windows
|
||||||
|
# Uses `diff`.
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(RUSTDOC) foo.rs -o $(TMPDIR)/foo_first
|
||||||
|
$(RUSTDOC) bar.rs -o $(TMPDIR)/foo_first
|
||||||
|
|
||||||
|
$(RUSTDOC) bar.rs -o $(TMPDIR)/bar_first
|
||||||
|
$(RUSTDOC) foo.rs -o $(TMPDIR)/bar_first
|
||||||
|
|
||||||
|
diff $(TMPDIR)/foo_first/search-index.js $(TMPDIR)/bar_first/search-index.js
|
1
src/test/run-make-fulldeps/rustdoc-determinism/bar.rs
Normal file
1
src/test/run-make-fulldeps/rustdoc-determinism/bar.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub struct Bar;
|
1
src/test/run-make-fulldeps/rustdoc-determinism/foo.rs
Normal file
1
src/test/run-make-fulldeps/rustdoc-determinism/foo.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub struct Foo;
|
7
src/test/rustdoc-ui/error-in-impl-trait/README.md
Normal file
7
src/test/rustdoc-ui/error-in-impl-trait/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Each of these needs to be in a separate file,
|
||||||
|
because the `delay_span_bug` ICE in rustdoc won't be triggerred
|
||||||
|
if even a single other error was emitted.
|
||||||
|
|
||||||
|
However, conceptually they are all testing basically the same thing.
|
||||||
|
See https://github.com/rust-lang/rust/pull/73566#issuecomment-653689128
|
||||||
|
for more details.
|
10
src/test/rustdoc-ui/error-in-impl-trait/async.rs
Normal file
10
src/test/rustdoc-ui/error-in-impl-trait/async.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// edition:2018
|
||||||
|
|
||||||
|
/// This used to work with ResolveBodyWithLoop.
|
||||||
|
/// However now that we ignore type checking instead of modifying the function body,
|
||||||
|
/// the return type is seen as `impl Future<Output = u32>`, not a `u32`.
|
||||||
|
/// So it no longer allows errors in the function body.
|
||||||
|
pub async fn a() -> u32 {
|
||||||
|
error::_in::async_fn()
|
||||||
|
//~^ ERROR failed to resolve
|
||||||
|
}
|
12
src/test/rustdoc-ui/error-in-impl-trait/async.stderr
Normal file
12
src/test/rustdoc-ui/error-in-impl-trait/async.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0433]: failed to resolve: could not resolve path `error::_in::async_fn`
|
||||||
|
--> $DIR/async.rs:8:5
|
||||||
|
|
|
||||||
|
LL | error::_in::async_fn()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::async_fn`
|
||||||
|
|
|
||||||
|
= note: this error was originally ignored because you are running `rustdoc`
|
||||||
|
= note: try running again with `rustc` or `cargo check` and you may get a more detailed error
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
5
src/test/rustdoc-ui/error-in-impl-trait/closure.rs
Normal file
5
src/test/rustdoc-ui/error-in-impl-trait/closure.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// manually desugared version of an `async fn` (but with a closure instead of a generator)
|
||||||
|
pub fn a() -> impl Fn() -> u32 {
|
||||||
|
|| content::doesnt::matter()
|
||||||
|
//~^ ERROR failed to resolve
|
||||||
|
}
|
12
src/test/rustdoc-ui/error-in-impl-trait/closure.stderr
Normal file
12
src/test/rustdoc-ui/error-in-impl-trait/closure.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0433]: failed to resolve: could not resolve path `content::doesnt::matter`
|
||||||
|
--> $DIR/closure.rs:3:8
|
||||||
|
|
|
||||||
|
LL | || content::doesnt::matter()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `content::doesnt::matter`
|
||||||
|
|
|
||||||
|
= note: this error was originally ignored because you are running `rustdoc`
|
||||||
|
= note: try running again with `rustc` or `cargo check` and you may get a more detailed error
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
@ -0,0 +1,7 @@
|
|||||||
|
trait ValidTrait {}
|
||||||
|
|
||||||
|
/// This has docs
|
||||||
|
pub fn f() -> impl ValidTrait {
|
||||||
|
Vec::<DoesNotExist>::new()
|
||||||
|
//~^ ERROR failed to resolve
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
error[E0433]: failed to resolve: could not resolve path `DoesNotExist`
|
||||||
|
--> $DIR/generic-argument.rs:5:11
|
||||||
|
|
|
||||||
|
LL | Vec::<DoesNotExist>::new()
|
||||||
|
| ^^^^^^^^^^^^ could not resolve path `DoesNotExist`
|
||||||
|
|
|
||||||
|
= note: this error was originally ignored because you are running `rustdoc`
|
||||||
|
= note: try running again with `rustc` or `cargo check` and you may get a more detailed error
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
@ -0,0 +1,6 @@
|
|||||||
|
pub trait ValidTrait {}
|
||||||
|
/// This returns impl trait
|
||||||
|
pub fn g() -> impl ValidTrait {
|
||||||
|
(|| error::_in::impl_trait::alias::nested::closure())()
|
||||||
|
//~^ ERROR failed to resolve
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias::nested::closure`
|
||||||
|
--> $DIR/impl-keyword-closure.rs:4:9
|
||||||
|
|
|
||||||
|
LL | (|| error::_in::impl_trait::alias::nested::closure())()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias::nested::closure`
|
||||||
|
|
|
||||||
|
= note: this error was originally ignored because you are running `rustdoc`
|
||||||
|
= note: try running again with `rustc` or `cargo check` and you may get a more detailed error
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
6
src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs
Normal file
6
src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
pub trait ValidTrait {}
|
||||||
|
/// This returns impl trait
|
||||||
|
pub fn g() -> impl ValidTrait {
|
||||||
|
error::_in::impl_trait()
|
||||||
|
//~^ ERROR failed to resolve
|
||||||
|
}
|
12
src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr
Normal file
12
src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait`
|
||||||
|
--> $DIR/impl-keyword.rs:4:5
|
||||||
|
|
|
||||||
|
LL | error::_in::impl_trait()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait`
|
||||||
|
|
|
||||||
|
= note: this error was originally ignored because you are running `rustdoc`
|
||||||
|
= note: try running again with `rustc` or `cargo check` and you may get a more detailed error
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
@ -0,0 +1,10 @@
|
|||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
pub trait ValidTrait {}
|
||||||
|
type ImplTrait = impl ValidTrait;
|
||||||
|
|
||||||
|
/// This returns impl trait, but using a type alias
|
||||||
|
pub fn h() -> ImplTrait {
|
||||||
|
(|| error::_in::impl_trait::alias::nested::closure())()
|
||||||
|
//~^ ERROR failed to resolve
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias::nested::closure`
|
||||||
|
--> $DIR/trait-alias-closure.rs:8:9
|
||||||
|
|
|
||||||
|
LL | (|| error::_in::impl_trait::alias::nested::closure())()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias::nested::closure`
|
||||||
|
|
|
||||||
|
= note: this error was originally ignored because you are running `rustdoc`
|
||||||
|
= note: try running again with `rustc` or `cargo check` and you may get a more detailed error
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
10
src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs
Normal file
10
src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
pub trait ValidTrait {}
|
||||||
|
type ImplTrait = impl ValidTrait;
|
||||||
|
|
||||||
|
/// This returns impl trait, but using a type alias
|
||||||
|
pub fn h() -> ImplTrait {
|
||||||
|
error::_in::impl_trait::alias()
|
||||||
|
//~^ ERROR failed to resolve
|
||||||
|
}
|
12
src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr
Normal file
12
src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias`
|
||||||
|
--> $DIR/trait-alias.rs:8:5
|
||||||
|
|
|
||||||
|
LL | error::_in::impl_trait::alias()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias`
|
||||||
|
|
|
||||||
|
= note: this error was originally ignored because you are running `rustdoc`
|
||||||
|
= note: try running again with `rustc` or `cargo check` and you may get a more detailed error
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
49
src/test/rustdoc-ui/impl-fn-nesting.rs
Normal file
49
src/test/rustdoc-ui/impl-fn-nesting.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Ensure that rustdoc gives errors for trait impls inside function bodies that don't resolve.
|
||||||
|
// See https://github.com/rust-lang/rust/pull/73566
|
||||||
|
pub struct ValidType;
|
||||||
|
pub trait ValidTrait {}
|
||||||
|
pub trait NeedsBody {
|
||||||
|
type Item;
|
||||||
|
fn f();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function has docs
|
||||||
|
pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
|
||||||
|
//~^ ERROR cannot find trait `UnknownBound` in this scope
|
||||||
|
//~| ERROR cannot find type `UnknownType` in this scope
|
||||||
|
impl UnknownTrait for ValidType {} //~ ERROR cannot find trait `UnknownTrait`
|
||||||
|
impl<T: UnknownBound> UnknownTrait for T {}
|
||||||
|
//~^ ERROR cannot find trait `UnknownBound` in this scope
|
||||||
|
//~| ERROR cannot find trait `UnknownTrait` in this scope
|
||||||
|
impl ValidTrait for UnknownType {}
|
||||||
|
//~^ ERROR cannot find type `UnknownType` in this scope
|
||||||
|
impl ValidTrait for ValidType where ValidTrait: UnknownBound {}
|
||||||
|
//~^ ERROR cannot find trait `UnknownBound` in this scope
|
||||||
|
|
||||||
|
/// This impl has documentation
|
||||||
|
impl NeedsBody for ValidType {
|
||||||
|
type Item = UnknownType;
|
||||||
|
//~^ ERROR cannot find type `UnknownType` in this scope
|
||||||
|
|
||||||
|
/// This function has documentation
|
||||||
|
fn f() {
|
||||||
|
<UnknownTypeShouldBeIgnored>::a();
|
||||||
|
content::shouldnt::matter();
|
||||||
|
unknown_macro!();
|
||||||
|
//~^ ERROR cannot find macro `unknown_macro` in this scope
|
||||||
|
|
||||||
|
/// This is documentation for a macro
|
||||||
|
macro_rules! can_define_macros_here_too {
|
||||||
|
() => {
|
||||||
|
this::content::should::also::be::ignored()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
can_define_macros_here_too!();
|
||||||
|
|
||||||
|
/// This also is documented.
|
||||||
|
pub fn doubly_nested(c: UnknownType) {
|
||||||
|
//~^ ERROR cannot find type `UnknownType` in this scope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
src/test/rustdoc-ui/impl-fn-nesting.stderr
Normal file
66
src/test/rustdoc-ui/impl-fn-nesting.stderr
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
error: cannot find macro `unknown_macro` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:32:13
|
||||||
|
|
|
||||||
|
LL | unknown_macro!();
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `UnknownBound` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:11:13
|
||||||
|
|
|
||||||
|
LL | pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
|
||||||
|
| ^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `UnknownType` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:11:30
|
||||||
|
|
|
||||||
|
LL | pub fn f<B: UnknownBound>(a: UnknownType, b: B) {
|
||||||
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `UnknownTrait` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:14:10
|
||||||
|
|
|
||||||
|
LL | impl UnknownTrait for ValidType {}
|
||||||
|
| ^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `UnknownTrait` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:15:27
|
||||||
|
|
|
||||||
|
LL | impl<T: UnknownBound> UnknownTrait for T {}
|
||||||
|
| ^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `UnknownBound` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:15:13
|
||||||
|
|
|
||||||
|
LL | impl<T: UnknownBound> UnknownTrait for T {}
|
||||||
|
| ^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `UnknownType` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:18:25
|
||||||
|
|
|
||||||
|
LL | impl ValidTrait for UnknownType {}
|
||||||
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0405]: cannot find trait `UnknownBound` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:20:53
|
||||||
|
|
|
||||||
|
LL | impl ValidTrait for ValidType where ValidTrait: UnknownBound {}
|
||||||
|
| ^^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `UnknownType` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:25:21
|
||||||
|
|
|
||||||
|
LL | type Item = UnknownType;
|
||||||
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `UnknownType` in this scope
|
||||||
|
--> $DIR/impl-fn-nesting.rs:44:37
|
||||||
|
|
|
||||||
|
LL | pub fn doubly_nested(c: UnknownType) {
|
||||||
|
| ^^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error: Compilation failed, aborting rustdoc
|
||||||
|
|
||||||
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0405, E0412.
|
||||||
|
For more information about an error, try `rustc --explain E0405`.
|
4
src/test/rustdoc-ui/infinite-recursive-type.rs
Normal file
4
src/test/rustdoc-ui/infinite-recursive-type.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
enum E {
|
||||||
|
//~^ ERROR recursive type `E` has infinite size
|
||||||
|
V(E),
|
||||||
|
}
|
17
src/test/rustdoc-ui/infinite-recursive-type.stderr
Normal file
17
src/test/rustdoc-ui/infinite-recursive-type.stderr
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
error[E0072]: recursive type `E` has infinite size
|
||||||
|
--> $DIR/infinite-recursive-type.rs:1:1
|
||||||
|
|
|
||||||
|
LL | enum E {
|
||||||
|
| ^^^^^^ recursive type has infinite size
|
||||||
|
LL |
|
||||||
|
LL | V(E),
|
||||||
|
| - recursive without indirection
|
||||||
|
|
|
||||||
|
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E` representable
|
||||||
|
|
|
||||||
|
LL | V(Box<E>),
|
||||||
|
| ^^^^ ^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0072`.
|
36
src/test/rustdoc/doc-spotlight.rs
Normal file
36
src/test/rustdoc/doc-spotlight.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#![feature(doc_spotlight)]
|
||||||
|
|
||||||
|
pub struct Wrapper<T> {
|
||||||
|
inner: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
|
||||||
|
|
||||||
|
#[doc(spotlight)]
|
||||||
|
pub trait SomeTrait {
|
||||||
|
// @has doc_spotlight/trait.SomeTrait.html
|
||||||
|
// @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
|
||||||
|
fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
|
||||||
|
Wrapper {
|
||||||
|
inner: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SomeStruct;
|
||||||
|
impl SomeTrait for SomeStruct {}
|
||||||
|
|
||||||
|
impl SomeStruct {
|
||||||
|
// @has doc_spotlight/struct.SomeStruct.html
|
||||||
|
// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
|
||||||
|
// @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
|
||||||
|
pub fn new() -> SomeStruct {
|
||||||
|
SomeStruct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has doc_spotlight/fn.bare_fn.html
|
||||||
|
// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
|
||||||
|
pub fn bare_fn() -> SomeStruct {
|
||||||
|
SomeStruct
|
||||||
|
}
|
14
src/test/rustdoc/impl-trait-alias.rs
Normal file
14
src/test/rustdoc/impl-trait-alias.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
trait MyTrait {}
|
||||||
|
impl MyTrait for i32 {}
|
||||||
|
|
||||||
|
// @has impl_trait_alias/type.Foo.html 'Foo'
|
||||||
|
/// debug type
|
||||||
|
pub type Foo = impl MyTrait;
|
||||||
|
|
||||||
|
// @has impl_trait_alias/fn.foo.html 'foo'
|
||||||
|
/// debug function
|
||||||
|
pub fn foo() -> Foo {
|
||||||
|
1
|
||||||
|
}
|
9
src/test/rustdoc/macro-in-async-block.rs
Normal file
9
src/test/rustdoc/macro-in-async-block.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Regression issue for rustdoc ICE encountered in PR #72088.
|
||||||
|
// edition:2018
|
||||||
|
#![feature(decl_macro)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
async {
|
||||||
|
macro m() {}
|
||||||
|
};
|
||||||
|
}
|
@ -6,4 +6,11 @@ fn main() {
|
|||||||
|| {
|
|| {
|
||||||
macro m() {}
|
macro m() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let _ = || {
|
||||||
|
macro n() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let cond = true;
|
||||||
|
let _ = || if cond { macro n() {} } else { panic!() };
|
||||||
}
|
}
|
||||||
|
15
src/test/rustdoc/return-impl-trait.rs
Normal file
15
src/test/rustdoc/return-impl-trait.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
pub trait Backend {}
|
||||||
|
|
||||||
|
impl Backend for () {}
|
||||||
|
|
||||||
|
pub struct Module<T>(T);
|
||||||
|
|
||||||
|
pub type BackendImpl = impl Backend;
|
||||||
|
|
||||||
|
// @has return_impl_trait/fn.make_module.html
|
||||||
|
/// Documentation
|
||||||
|
pub fn make_module() -> Module<BackendImpl> {
|
||||||
|
Module(())
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
#![crate_type = "lib"]
|
||||||
#![feature(doc_alias)]
|
#![feature(doc_alias)]
|
||||||
|
|
||||||
#[doc(alias = "foo")] // ok!
|
#[doc(alias = "foo")] // ok!
|
@ -1,17 +1,17 @@
|
|||||||
error: doc alias attribute expects a string: #[doc(alias = "0")]
|
error: doc alias attribute expects a string: #[doc(alias = "0")]
|
||||||
--> $DIR/check-doc-alias-attr.rs:6:7
|
--> $DIR/check-doc-alias-attr.rs:7:7
|
||||||
|
|
|
|
||||||
LL | #[doc(alias)]
|
LL | #[doc(alias)]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: doc alias attribute expects a string: #[doc(alias = "0")]
|
error: doc alias attribute expects a string: #[doc(alias = "0")]
|
||||||
--> $DIR/check-doc-alias-attr.rs:7:7
|
--> $DIR/check-doc-alias-attr.rs:8:7
|
||||||
|
|
|
|
||||||
LL | #[doc(alias = 0)]
|
LL | #[doc(alias = 0)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: doc alias attribute expects a string: #[doc(alias = "0")]
|
error: doc alias attribute expects a string: #[doc(alias = "0")]
|
||||||
--> $DIR/check-doc-alias-attr.rs:8:7
|
--> $DIR/check-doc-alias-attr.rs:9:7
|
||||||
|
|
|
|
||||||
LL | #[doc(alias("bar"))]
|
LL | #[doc(alias("bar"))]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
@ -0,0 +1,15 @@
|
|||||||
|
#![feature(const_generics)]
|
||||||
|
//~^ WARN the feature `const_generics` is incomplete
|
||||||
|
|
||||||
|
// Currently, const parameters cannot depend on other generic parameters,
|
||||||
|
// as our current implementation can't really support this.
|
||||||
|
//
|
||||||
|
// We may want to lift this restriction in the future.
|
||||||
|
|
||||||
|
pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
|
||||||
|
//~^ ERROR: the type of const parameters must not depend on other generic parameters
|
||||||
|
|
||||||
|
pub struct SelfDependent<const N: [u8; N]>;
|
||||||
|
//~^ ERROR: the type of const parameters must not depend on other generic parameters
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,24 @@
|
|||||||
|
error[E0770]: the type of const parameters must not depend on other generic parameters
|
||||||
|
--> $DIR/const-param-type-depends-on-const-param.rs:9:52
|
||||||
|
|
|
||||||
|
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
|
||||||
|
| ^ the type must not depend on the parameter `N`
|
||||||
|
|
||||||
|
error[E0770]: the type of const parameters must not depend on other generic parameters
|
||||||
|
--> $DIR/const-param-type-depends-on-const-param.rs:12:40
|
||||||
|
|
|
||||||
|
LL | pub struct SelfDependent<const N: [u8; N]>;
|
||||||
|
| ^ 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/const-param-type-depends-on-const-param.rs:1:12
|
||||||
|
|
|
||||||
|
LL | #![feature(const_generics)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0770`.
|
@ -1,6 +1,6 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
|
struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
|
||||||
//~^ ERROR `T` is not guaranteed to `#[derive(PartialEq, Eq)]`
|
//~^ ERROR the type of const parameters must not depend on other generic parameters
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
error[E0770]: the type of const parameters must not depend on other generic parameters
|
||||||
|
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
|
||||||
|
|
|
||||||
|
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
|
||||||
|
| ^ the type must not depend on the parameter `T`
|
||||||
|
|
||||||
error[E0658]: const generics are unstable
|
error[E0658]: const generics are unstable
|
||||||
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
|
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
|
||||||
|
|
|
|
||||||
@ -7,15 +13,7 @@ LL | struct B<T, const N: T>(PhantomData<[T; N]>);
|
|||||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter
|
|
||||||
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
|
|
||||||
|
|
|
||||||
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
|
|
||||||
| ^ `T` may not derive both `PartialEq` and `Eq`
|
|
||||||
|
|
|
||||||
= note: it is not currently possible to use a type parameter as the type of a const parameter
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0658, E0741.
|
Some errors have detailed explanations: E0658, E0770.
|
||||||
For more information about an error, try `rustc --explain E0658`.
|
For more information about an error, try `rustc --explain E0658`.
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#![feature(const_generics)]
|
#![feature(const_generics)]
|
||||||
//~^ WARN the feature `const_generics` is incomplete
|
//~^ WARN the feature `const_generics` is incomplete
|
||||||
|
|
||||||
// Currently, const parameters cannot depend on type parameters, because there is no way to
|
// Currently, const parameters cannot depend on other generic parameters,
|
||||||
// enforce the structural-match property on an arbitrary type parameter. This restriction
|
// as our current implementation can't really support this.
|
||||||
// may be relaxed in the future. See https://github.com/rust-lang/rfcs/pull/2000 for more
|
//
|
||||||
// details.
|
// We may want to lift this restriction in the future.
|
||||||
|
|
||||||
pub struct Dependent<T, const X: T>([(); X]);
|
pub struct Dependent<T, const X: T>([(); X]);
|
||||||
//~^ ERROR `T` is not guaranteed to `#[derive(PartialEq, Eq)]`
|
//~^ ERROR: the type of const parameters must not depend on other generic parameters
|
||||||
|
//~| ERROR: parameter `T` is never used
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
error[E0770]: the type of const parameters must not depend on other generic parameters
|
||||||
|
--> $DIR/const-param-type-depends-on-type-param.rs:9:34
|
||||||
|
|
|
||||||
|
LL | pub struct Dependent<T, const X: T>([(); X]);
|
||||||
|
| ^ the type must not depend on the parameter `T`
|
||||||
|
|
||||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/const-param-type-depends-on-type-param.rs:1:12
|
--> $DIR/const-param-type-depends-on-type-param.rs:1:12
|
||||||
|
|
|
|
||||||
@ -7,14 +13,15 @@ LL | #![feature(const_generics)]
|
|||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
|
|
||||||
error[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter
|
error[E0392]: parameter `T` is never used
|
||||||
--> $DIR/const-param-type-depends-on-type-param.rs:9:34
|
--> $DIR/const-param-type-depends-on-type-param.rs:9:22
|
||||||
|
|
|
|
||||||
LL | pub struct Dependent<T, const X: T>([(); X]);
|
LL | pub struct Dependent<T, const X: T>([(); X]);
|
||||||
| ^ `T` may not derive both `PartialEq` and `Eq`
|
| ^ unused parameter
|
||||||
|
|
|
|
||||||
= note: it is not currently possible to use a type parameter as the type of a const parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
|
||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0741`.
|
Some errors have detailed explanations: E0392, E0770.
|
||||||
|
For more information about an error, try `rustc --explain E0392`.
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
#![feature(const_generics)]
|
||||||
|
|
||||||
|
// All of these three items must be in `lib2` to reproduce the error
|
||||||
|
|
||||||
|
pub trait TypeFn {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GenericType<const B: i8>;
|
||||||
|
|
||||||
|
// Removing the braces around `42` resolves the crash
|
||||||
|
impl TypeFn for GenericType<{ 42 }> {
|
||||||
|
type Output = ();
|
||||||
|
}
|
18
src/test/ui/const-generics/issues/issue-68596.rs
Normal file
18
src/test/ui/const-generics/issues/issue-68596.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// check-pass
|
||||||
|
#![feature(const_generics)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
pub struct S(u8);
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
pub fn get<const A: u8>(&self) -> &u8 {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
const A: u8 = 5;
|
||||||
|
let s = S(0);
|
||||||
|
|
||||||
|
s.get::<A>();
|
||||||
|
}
|
10
src/test/ui/const-generics/issues/issue-71169.rs
Normal file
10
src/test/ui/const-generics/issues/issue-71169.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#![feature(const_generics)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
|
||||||
|
//~^ ERROR the type of const parameters must not
|
||||||
|
fn main() {
|
||||||
|
const DATA: [u8; 4] = *b"ABCD";
|
||||||
|
foo::<4, DATA>();
|
||||||
|
//~^ ERROR constant expression depends on
|
||||||
|
}
|
17
src/test/ui/const-generics/issues/issue-71169.stderr
Normal file
17
src/test/ui/const-generics/issues/issue-71169.stderr
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
error[E0770]: the type of const parameters must not depend on other generic parameters
|
||||||
|
--> $DIR/issue-71169.rs:4:43
|
||||||
|
|
|
||||||
|
LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
|
||||||
|
| ^^^ the type must not depend on the parameter `LEN`
|
||||||
|
|
||||||
|
error: constant expression depends on a generic parameter
|
||||||
|
--> $DIR/issue-71169.rs:8:14
|
||||||
|
|
|
||||||
|
LL | foo::<4, DATA>();
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
= note: this may fail depending on what value the parameter takes
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0770`.
|
@ -12,6 +12,7 @@ unsafe extern "C" fn pass(args: PassArg) {
|
|||||||
impl Test {
|
impl Test {
|
||||||
pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
|
pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
|
||||||
//~^ ERROR: using function pointers as const generic parameters is forbidden
|
//~^ ERROR: using function pointers as const generic parameters is forbidden
|
||||||
|
//~| ERROR: the type of const parameters must not depend on other generic parameters
|
||||||
self.0 = Self::trampiline::<Args, IDX, FN> as _
|
self.0 = Self::trampiline::<Args, IDX, FN> as _
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ impl Test {
|
|||||||
const IDX: usize,
|
const IDX: usize,
|
||||||
const FN: unsafe extern "C" fn(Args),
|
const FN: unsafe extern "C" fn(Args),
|
||||||
//~^ ERROR: using function pointers as const generic parameters is forbidden
|
//~^ ERROR: using function pointers as const generic parameters is forbidden
|
||||||
|
//~| ERROR: the type of const parameters must not depend on other generic parameters
|
||||||
>(
|
>(
|
||||||
args: Args,
|
args: Args,
|
||||||
) {
|
) {
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
|
error[E0770]: the type of const parameters must not depend on other generic parameters
|
||||||
|
--> $DIR/issue-71381.rs:13:82
|
||||||
|
|
|
||||||
|
LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
|
||||||
|
| ^^^^ the type must not depend on the parameter `Args`
|
||||||
|
|
||||||
|
error[E0770]: the type of const parameters must not depend on other generic parameters
|
||||||
|
--> $DIR/issue-71381.rs:22:40
|
||||||
|
|
|
||||||
|
LL | const FN: unsafe extern "C" fn(Args),
|
||||||
|
| ^^^^ the type must not depend on the parameter `Args`
|
||||||
|
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/issue-71381.rs:13:61
|
--> $DIR/issue-71381.rs:13:61
|
||||||
|
|
|
|
||||||
@ -5,10 +17,11 @@ LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/issue-71381.rs:21:19
|
--> $DIR/issue-71381.rs:22:19
|
||||||
|
|
|
|
||||||
LL | const FN: unsafe extern "C" fn(Args),
|
LL | const FN: unsafe extern "C" fn(Args),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0770`.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
fn func<A, const F: fn(inner: A)>(outer: A) {
|
fn func<A, const F: fn(inner: A)>(outer: A) {
|
||||||
//~^ ERROR: using function pointers as const generic parameters is forbidden
|
//~^ ERROR: using function pointers as const generic parameters is forbidden
|
||||||
|
//~| ERROR: the type of const parameters must not depend on other generic parameters
|
||||||
F(outer);
|
F(outer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
error[E0770]: the type of const parameters must not depend on other generic parameters
|
||||||
|
--> $DIR/issue-71611.rs:4:31
|
||||||
|
|
|
||||||
|
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
||||||
|
| ^ the type must not depend on the parameter `A`
|
||||||
|
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/issue-71611.rs:4:21
|
--> $DIR/issue-71611.rs:4:21
|
||||||
|
|
|
|
||||||
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0770`.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user