Merge remote-tracking branch 'origin/master' into mpk/add-long-error-message-for-E0311
This commit is contained in:
commit
24aab524cb
5269 changed files with 128288 additions and 36333 deletions
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
|
@ -25,11 +25,15 @@ name: CI
|
|||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
jobs:
|
||||
pr:
|
||||
permissions:
|
||||
actions: write
|
||||
name: PR
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
|
@ -142,6 +146,8 @@ jobs:
|
|||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||
if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
|
||||
auto:
|
||||
permissions:
|
||||
actions: write
|
||||
name: auto
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
|
@ -291,7 +297,7 @@ jobs:
|
|||
os: ubuntu-20.04-xl
|
||||
- name: dist-x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist --host=x86_64-apple-darwin --target=x86_64-apple-darwin"
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin"
|
||||
RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
|
@ -302,7 +308,7 @@ jobs:
|
|||
os: macos-latest
|
||||
- name: dist-apple-various
|
||||
env:
|
||||
SCRIPT: "./x.py dist --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
|
||||
RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
|
@ -312,7 +318,7 @@ jobs:
|
|||
os: macos-latest
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths"
|
||||
RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
|
@ -344,7 +350,7 @@ jobs:
|
|||
os: macos-latest
|
||||
- name: dist-aarch64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist --stage 2"
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2"
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --host=aarch64-apple-darwin --target=aarch64-apple-darwin --enable-full-tools --enable-sanitizers --enable-profiler --disable-docs --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
USE_XCODE_CLANG: 1
|
||||
|
@ -418,19 +424,19 @@ jobs:
|
|||
- name: dist-x86_64-msvc
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler"
|
||||
SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist
|
||||
SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: windows-latest-xl
|
||||
- name: dist-i686-msvc
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler"
|
||||
SCRIPT: python x.py dist
|
||||
SCRIPT: python x.py dist bootstrap --include-default-paths
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: windows-latest-xl
|
||||
- name: dist-aarch64-msvc
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler"
|
||||
SCRIPT: python x.py dist
|
||||
SCRIPT: python x.py dist bootstrap --include-default-paths
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
WINDOWS_SDK_20348_HACK: 1
|
||||
os: windows-latest-xl
|
||||
|
@ -438,13 +444,13 @@ jobs:
|
|||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --enable-full-tools --enable-profiler --set llvm.allow-old-toolchain"
|
||||
NO_DOWNLOAD_CI_LLVM: 1
|
||||
SCRIPT: python x.py dist
|
||||
SCRIPT: python x.py dist bootstrap --include-default-paths
|
||||
CUSTOM_MINGW: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: windows-latest-xl
|
||||
- name: dist-x86_64-mingw
|
||||
env:
|
||||
SCRIPT: python x.py dist
|
||||
SCRIPT: python x.py dist bootstrap --include-default-paths
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler --set llvm.allow-old-toolchain"
|
||||
NO_DOWNLOAD_CI_LLVM: 1
|
||||
CUSTOM_MINGW: 1
|
||||
|
@ -453,7 +459,7 @@ jobs:
|
|||
- name: dist-x86_64-msvc-alt
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-extended --enable-profiler"
|
||||
SCRIPT: python x.py dist
|
||||
SCRIPT: python x.py dist bootstrap --include-default-paths
|
||||
os: windows-latest-xl
|
||||
timeout-minutes: 600
|
||||
runs-on: "${{ matrix.os }}"
|
||||
|
@ -547,6 +553,8 @@ jobs:
|
|||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||
if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
|
||||
try:
|
||||
permissions:
|
||||
actions: write
|
||||
name: try
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -46,6 +46,7 @@ no_llvm_build
|
|||
/dist/
|
||||
/unicode-downloads
|
||||
/target
|
||||
/src/bootstrap/target
|
||||
/src/tools/x/target
|
||||
# Created by default with `src/ci/docker/run.sh`
|
||||
/obj/
|
||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -13,9 +13,6 @@
|
|||
[submodule "src/doc/book"]
|
||||
path = src/doc/book
|
||||
url = https://github.com/rust-lang/book.git
|
||||
[submodule "src/tools/miri"]
|
||||
path = src/tools/miri
|
||||
url = https://github.com/rust-lang/miri.git
|
||||
[submodule "src/doc/rust-by-example"]
|
||||
path = src/doc/rust-by-example
|
||||
url = https://github.com/rust-lang/rust-by-example.git
|
||||
|
|
321
Cargo.lock
321
Cargo.lock
|
@ -103,9 +103,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.60"
|
||||
version = "1.0.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"
|
||||
checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
|
||||
|
||||
[[package]]
|
||||
name = "array_tool"
|
||||
|
@ -209,34 +209,13 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"byte-tools",
|
||||
"byteorder",
|
||||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
||||
dependencies = [
|
||||
"byte-tools",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -277,12 +256,6 @@ dependencies = [
|
|||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "bytecount"
|
||||
version = "0.6.2"
|
||||
|
@ -292,12 +265,6 @@ dependencies = [
|
|||
"packed_simd_2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.0.1"
|
||||
|
@ -540,6 +507,10 @@ name = "cfg-if"
|
|||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chalk-derive"
|
||||
|
@ -610,9 +581,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.5"
|
||||
version = "3.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
|
||||
checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
|
@ -636,9 +607,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.2.5"
|
||||
version = "3.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
|
||||
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
|
@ -727,6 +698,7 @@ version = "0.1.65"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"if_chain",
|
||||
"itertools",
|
||||
"rustc-semver",
|
||||
]
|
||||
|
||||
|
@ -770,9 +742,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.3"
|
||||
version = "4.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062"
|
||||
checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"memchr",
|
||||
|
@ -1010,7 +982,7 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1035,16 +1007,6 @@ dependencies = [
|
|||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curl"
|
||||
version = "0.4.43"
|
||||
|
@ -1105,22 +1067,13 @@ version = "2.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
dependencies = [
|
||||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"
|
||||
dependencies = [
|
||||
"block-buffer 0.10.2",
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
|
@ -1268,7 +1221,7 @@ dependencies = [
|
|||
name = "error_index_generator"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustdoc",
|
||||
"mdbook",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1299,12 +1252,6 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
|
@ -1419,9 +1366,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fs-err"
|
||||
version = "2.5.0"
|
||||
version = "2.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcd1163ae48bda72a20ae26d66a04d3094135cadab911cff418ae5e33f253431"
|
||||
checksum = "64db3e262960f0662f43a6366788d5f10f7f244b8f7d7d987f560baf5ded5c50"
|
||||
|
||||
[[package]]
|
||||
name = "fs_extra"
|
||||
|
@ -1538,15 +1485,6 @@ dependencies = [
|
|||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
|
@ -1681,16 +1619,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "handlebars"
|
||||
version = "4.1.0"
|
||||
version = "4.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72a0ffab8c36d0436114310c7e10b59b3307e650ddfabf6d006028e29a70c6e6"
|
||||
checksum = "360d9740069b2f6cbb63ce2dbaa71a20d3185350cbb990d7bebeb9318415eb17"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"quick-error 2.0.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1722,12 +1660,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.0"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ab7905ea95c6d9af62940f9d7dd9596d54c334ae2c15300c482051292d5637f"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
|
@ -1780,7 +1719,7 @@ version = "1.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||
dependencies = [
|
||||
"quick-error 1.2.3",
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1826,13 +1765,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "im-rc"
|
||||
version = "15.0.0"
|
||||
version = "15.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
|
||||
checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
|
||||
dependencies = [
|
||||
"bitmaps",
|
||||
"rand_core 0.5.1",
|
||||
"rand_xoshiro 0.4.0",
|
||||
"rand_core 0.6.2",
|
||||
"rand_xoshiro",
|
||||
"sized-chunks",
|
||||
"typenum",
|
||||
"version_check",
|
||||
|
@ -1956,6 +1895,16 @@ dependencies = [
|
|||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsondoclint"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"fs-err",
|
||||
"rustdoc-json-types",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonpath_lib"
|
||||
version = "0.2.6"
|
||||
|
@ -1999,6 +1948,25 @@ dependencies = [
|
|||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libffi"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libffi-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libffi-sys"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
version = "0.14.0+1.5.0"
|
||||
|
@ -2169,7 +2137,7 @@ version = "0.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6a38fc55c8bbc10058782919516f88826e70320db6d206aebc49611d24216ae"
|
||||
dependencies = [
|
||||
"digest 0.10.2",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2293,6 +2261,8 @@ dependencies = [
|
|||
"getrandom 0.2.0",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"libffi",
|
||||
"libloading",
|
||||
"log",
|
||||
"measureme",
|
||||
"rand 0.8.5",
|
||||
|
@ -2395,12 +2365,6 @@ version = "1.12.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
|
||||
[[package]]
|
||||
name = "opener"
|
||||
version = "0.5.0"
|
||||
|
@ -2471,15 +2435,6 @@ version = "6.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
|
||||
[[package]]
|
||||
name = "output_vt100"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.4.0"
|
||||
|
@ -2590,18 +2545,19 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.1.3"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
||||
checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.1.0"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
|
||||
checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
|
@ -2609,9 +2565,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.1.3"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
|
||||
checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
|
@ -2622,13 +2578,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.1.3"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
|
||||
checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04"
|
||||
dependencies = [
|
||||
"maplit",
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha-1 0.8.2",
|
||||
"sha-1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2720,18 +2676,6 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"ctor",
|
||||
"diff",
|
||||
"output_vt100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pretty_env_logger"
|
||||
version = "0.4.0"
|
||||
|
@ -2830,12 +2774,6 @@ version = "1.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda"
|
||||
|
||||
[[package]]
|
||||
name = "quine-mc_cluskey"
|
||||
version = "0.2.4"
|
||||
|
@ -2931,15 +2869,6 @@ dependencies = [
|
|||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xoshiro"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xoshiro"
|
||||
version = "0.6.0"
|
||||
|
@ -3172,7 +3101,6 @@ dependencies = [
|
|||
"bstr",
|
||||
"clap",
|
||||
"libz-sys",
|
||||
"memchr",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"syn",
|
||||
|
@ -3207,6 +3135,7 @@ dependencies = [
|
|||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"smallvec",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -3228,6 +3157,7 @@ dependencies = [
|
|||
"rustc_span",
|
||||
"rustc_target",
|
||||
"smallvec",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -3322,6 +3252,7 @@ dependencies = [
|
|||
"rustc_span",
|
||||
"rustc_target",
|
||||
"smallvec",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -3332,7 +3263,6 @@ dependencies = [
|
|||
"bitflags",
|
||||
"cstr",
|
||||
"libc",
|
||||
"libloading",
|
||||
"measureme",
|
||||
"object 0.29.0",
|
||||
"rustc-demangle",
|
||||
|
@ -3446,6 +3376,7 @@ dependencies = [
|
|||
"stable_deref_trait",
|
||||
"stacker",
|
||||
"tempfile",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -3514,6 +3445,7 @@ dependencies = [
|
|||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"termcolor",
|
||||
|
@ -3807,7 +3739,7 @@ dependencies = [
|
|||
"gsgdt",
|
||||
"polonius-engine",
|
||||
"rand 0.8.5",
|
||||
"rand_xoshiro 0.6.0",
|
||||
"rand_xoshiro",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
"rustc_apfloat",
|
||||
|
@ -3828,6 +3760,7 @@ dependencies = [
|
|||
"rustc_target",
|
||||
"rustc_type_ir",
|
||||
"smallvec",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -4017,6 +3950,7 @@ dependencies = [
|
|||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -4038,7 +3972,9 @@ dependencies = [
|
|||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_type_ir",
|
||||
"smallvec",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -4094,6 +4030,7 @@ dependencies = [
|
|||
"indexmap",
|
||||
"rustc_macros",
|
||||
"smallvec",
|
||||
"thin-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4142,7 +4079,7 @@ dependencies = [
|
|||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"scoped-tls",
|
||||
"sha-1 0.10.0",
|
||||
"sha-1",
|
||||
"sha2",
|
||||
"tracing",
|
||||
"unicode-width",
|
||||
|
@ -4172,6 +4109,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"bitflags",
|
||||
"rustc_data_structures",
|
||||
"rustc_feature",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
|
@ -4234,6 +4172,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"itertools",
|
||||
"rustc_data_structures",
|
||||
"rustc_hir",
|
||||
"rustc_infer",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
|
@ -4330,6 +4269,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"smallvec",
|
||||
"tempfile",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
|
@ -4519,9 +4459,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.83"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
|
||||
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
|
@ -4529,18 +4469,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||
dependencies = [
|
||||
"block-buffer 0.7.3",
|
||||
"digest 0.8.1",
|
||||
"fake-simd",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.10.0"
|
||||
|
@ -4549,7 +4477,7 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
|
|||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest 0.10.2",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4560,7 +4488,7 @@ checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
|
|||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest 0.10.2",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4689,13 +4617,13 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"addr2line 0.16.0",
|
||||
"alloc",
|
||||
"cfg-if 0.1.10",
|
||||
"cfg-if 1.0.0",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"dlmalloc",
|
||||
"fortanix-sgx-abi",
|
||||
"hashbrown",
|
||||
"hermit-abi 0.2.0",
|
||||
"hermit-abi 0.2.6",
|
||||
"libc",
|
||||
"miniz_oxide 0.4.0",
|
||||
"object 0.26.2",
|
||||
|
@ -4713,7 +4641,7 @@ dependencies = [
|
|||
name = "std_detect"
|
||||
version = "0.1.5"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"cfg-if 1.0.0",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-alloc",
|
||||
|
@ -4884,19 +4812,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
name = "thin-vec"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
checksum = "104c2cb3180b6fb6d5b2278768e9b88b578d32ba751ea6e8d026688a40d7ed87"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4956,9 +4890,18 @@ checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1"
|
|||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "0.3.4"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
|
@ -5119,14 +5062,16 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
|||
|
||||
[[package]]
|
||||
name = "ui_test"
|
||||
version = "0.1.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d1f546a5883ae78da735bba529ec1116661e2f73582f23920d994dc97da3a22"
|
||||
dependencies = [
|
||||
"cargo_metadata 0.15.0",
|
||||
"color-eyre",
|
||||
"colored",
|
||||
"crossbeam",
|
||||
"diff",
|
||||
"lazy_static",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
|
@ -5244,24 +5189,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.13"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-script"
|
||||
version = "0.5.3"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "098ec66172ce21cd55f8bcc786ee209dd20e04eff70acfca30cb79924d173ae9"
|
||||
checksum = "7d817255e1bed6dfd4ca47258685d14d2bdcfbc64fdc9e3819bd5848057b8ecc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-security"
|
||||
version = "0.0.5"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d87c28edc5b263377e448d6cdcb935c06b95413d8013ba6fae470558ccab18f"
|
||||
checksum = "9ef5756b3097992b934b06608c69f48448a0fbe804bb1e72b982f6d7983e9e63"
|
||||
dependencies = [
|
||||
"unicode-normalization",
|
||||
"unicode-script",
|
||||
|
@ -5269,15 +5214,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
|
||||
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.8"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
|
@ -5286,9 +5231,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_categories"
|
||||
|
|
|
@ -33,6 +33,7 @@ members = [
|
|||
"src/tools/unicode-table-generator",
|
||||
"src/tools/expand-yaml-anchors",
|
||||
"src/tools/jsondocck",
|
||||
"src/tools/jsondoclint",
|
||||
"src/tools/html-checker",
|
||||
"src/tools/bump-stage0",
|
||||
"src/tools/replace-version-placeholder",
|
||||
|
|
23
README.md
23
README.md
|
@ -22,7 +22,7 @@ Read ["Installation"] from [The Book].
|
|||
## Installing from Source
|
||||
|
||||
The Rust build system uses a Python script called `x.py` to build the compiler,
|
||||
which manages the bootstrapping process. It lives in the root of the project.
|
||||
which manages the bootstrapping process. It lives at the root of the project.
|
||||
|
||||
The `x.py` command can be run directly on most systems in the following format:
|
||||
|
||||
|
@ -32,7 +32,7 @@ The `x.py` command can be run directly on most systems in the following format:
|
|||
|
||||
This is how the documentation and examples assume you are running `x.py`.
|
||||
|
||||
Systems such as Ubuntu 20.04 LTS do not create the necessary `python` command by default when Python is installed that allows `x.py` to be run directly. In that case you can either create a symlink for `python` (Ubuntu provides the `python-is-python3` package for this), or run `x.py` using Python itself:
|
||||
Systems such as Ubuntu 20.04 LTS do not create the necessary `python` command by default when Python is installed that allows `x.py` to be run directly. In that case, you can either create a symlink for `python` (Ubuntu provides the `python-is-python3` package for this), or run `x.py` using Python itself:
|
||||
|
||||
```sh
|
||||
# Python 3
|
||||
|
@ -103,11 +103,10 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide
|
|||
### Building on Windows
|
||||
|
||||
There are two prominent ABIs in use on Windows: the native (MSVC) ABI used by
|
||||
Visual Studio, and the GNU ABI used by the GCC toolchain. Which version of Rust
|
||||
you need depends largely on what C/C++ libraries you want to interoperate with:
|
||||
for interop with software produced by Visual Studio use the MSVC build of Rust;
|
||||
for interop with GNU software built using the MinGW/MSYS2 toolchain use the GNU
|
||||
build.
|
||||
Visual Studio and the GNU ABI used by the GCC toolchain. Which version of Rust
|
||||
you need depends largely on what C/C++ libraries you want to interoperate with.
|
||||
Use the MSVC build of Rust to interop with software produced by Visual Studio and
|
||||
the GNU build to interop with GNU software built using the MinGW/MSYS2 toolchain.
|
||||
|
||||
#### MinGW
|
||||
|
||||
|
@ -115,10 +114,10 @@ build.
|
|||
|
||||
[msys2]: https://www.msys2.org/
|
||||
|
||||
1. Grab the latest [MSYS2 installer][msys2] and go through the installer.
|
||||
1. Download the latest [MSYS2 installer][msys2] and go through the installer.
|
||||
|
||||
2. Run `mingw32_shell.bat` or `mingw64_shell.bat` from wherever you installed
|
||||
MSYS2 (i.e. `C:\msys64`), depending on whether you want 32-bit or 64-bit
|
||||
2. Run `mingw32_shell.bat` or `mingw64_shell.bat` from the MSYS2 installation
|
||||
directory (e.g. `C:\msys64`), depending on whether you want 32-bit or 64-bit
|
||||
Rust. (As of the latest version of MSYS2 you have to run `msys2_shell.cmd
|
||||
-mingw32` or `msys2_shell.cmd -mingw64` from the command line instead)
|
||||
|
||||
|
@ -168,7 +167,7 @@ shell with:
|
|||
python x.py build
|
||||
```
|
||||
|
||||
Currently, building Rust only works with some known versions of Visual Studio. If
|
||||
Right now, building Rust only works with some known versions of Visual Studio. If
|
||||
you have a more recent version installed and the build system doesn't understand,
|
||||
you may need to force rustbuild to use an older version. This can be done
|
||||
by manually calling the appropriate vcvars file before running the bootstrap.
|
||||
|
@ -225,7 +224,7 @@ the ABI used. I.e., if the ABI was `x86_64-pc-windows-msvc`, the directory will
|
|||
|
||||
Since the Rust compiler is written in Rust, it must be built by a
|
||||
precompiled "snapshot" version of itself (made in an earlier stage of
|
||||
development). As such, source builds require a connection to the Internet, to
|
||||
development). As such, source builds require an Internet connection to
|
||||
fetch snapshots, and an OS that can execute the available snapshot binaries.
|
||||
|
||||
Snapshot binaries are currently built and tested on several platforms:
|
||||
|
|
147
RELEASES.md
147
RELEASES.md
|
@ -1,3 +1,144 @@
|
|||
Version 1.64.0 (2022-09-22)
|
||||
===========================
|
||||
|
||||
Language
|
||||
--------
|
||||
- [Unions with mutable references or tuples of allowed types are now allowed](https://github.com/rust-lang/rust/pull/97995/)
|
||||
- It is now considered valid to deallocate memory pointed to by a shared reference `&T` [if every byte in `T` is inside an `UnsafeCell`](https://github.com/rust-lang/rust/pull/98017/)
|
||||
- Unused tuple struct fields are now warned against in an allow-by-default lint, [`unused_tuple_struct_fields`](https://github.com/rust-lang/rust/pull/95977/), similar to the existing warning for unused struct fields. This lint will become warn-by-default in the future.
|
||||
|
||||
Compiler
|
||||
--------
|
||||
- [Add Nintendo Switch as tier 3 target](https://github.com/rust-lang/rust/pull/88991/)
|
||||
- Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
- [Only compile `#[used]` as llvm.compiler.used for ELF targets](https://github.com/rust-lang/rust/pull/93718/)
|
||||
- [Add the `--diagnostic-width` compiler flag to define the terminal width.](https://github.com/rust-lang/rust/pull/95635/)
|
||||
- [Add support for link-flavor `rust-lld` for iOS, tvOS and watchOS](https://github.com/rust-lang/rust/pull/98771/)
|
||||
|
||||
Libraries
|
||||
---------
|
||||
- [Remove restrictions on compare-exchange memory ordering.](https://github.com/rust-lang/rust/pull/98383/)
|
||||
- You can now `write!` or `writeln!` into an `OsString`: [Implement `fmt::Write` for `OsString`](https://github.com/rust-lang/rust/pull/97915/)
|
||||
- [Make RwLockReadGuard covariant](https://github.com/rust-lang/rust/pull/96820/)
|
||||
- [Implement `FusedIterator` for `std::net::[Into]Incoming`](https://github.com/rust-lang/rust/pull/97300/)
|
||||
- [`impl<T: AsRawFd> AsRawFd for {Arc,Box}<T>`](https://github.com/rust-lang/rust/pull/97437/)
|
||||
- [`ptr::copy` and `ptr::swap` are doing untyped copies](https://github.com/rust-lang/rust/pull/97712/)
|
||||
- [Add cgroupv1 support to `available_parallelism`](https://github.com/rust-lang/rust/pull/97925/)
|
||||
- [Mitigate many incorrect uses of `mem::uninitialized`](https://github.com/rust-lang/rust/pull/99182/)
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
|
||||
- [`future::IntoFuture`](https://doc.rust-lang.org/stable/std/future/trait.IntoFuture.html)
|
||||
- [`future::poll_fn`](https://doc.rust-lang.org/stable/std/future/fn.poll_fn.html)
|
||||
- [`task::ready!`](https://doc.rust-lang.org/stable/std/task/macro.ready.html)
|
||||
- [`num::NonZero*::checked_mul`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_mul)
|
||||
- [`num::NonZero*::checked_pow`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_pow)
|
||||
- [`num::NonZero*::saturating_mul`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_mul)
|
||||
- [`num::NonZero*::saturating_pow`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_pow)
|
||||
- [`num::NonZeroI*::abs`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.abs)
|
||||
- [`num::NonZeroI*::checked_abs`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.checked_abs)
|
||||
- [`num::NonZeroI*::overflowing_abs`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.overflowing_abs)
|
||||
- [`num::NonZeroI*::saturating_abs`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.saturating_abs)
|
||||
- [`num::NonZeroI*::unsigned_abs`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.unsigned_abs)
|
||||
- [`num::NonZeroI*::wrapping_abs`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroIsize.html#method.wrapping_abs)
|
||||
- [`num::NonZeroU*::checked_add`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_add)
|
||||
- [`num::NonZeroU*::checked_next_power_of_two`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.checked_next_power_of_two)
|
||||
- [`num::NonZeroU*::saturating_add`](https://doc.rust-lang.org/stable/std/num/struct.NonZeroUsize.html#method.saturating_add)
|
||||
- [`os::unix::process::CommandExt::process_group`](https://doc.rust-lang.org/stable/std/os/unix/process/trait.CommandExt.html#tymethod.process_group)
|
||||
- [`os::windows::fs::FileTypeExt::is_symlink_dir`](https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTypeExt.html#tymethod.is_symlink_dir)
|
||||
- [`os::windows::fs::FileTypeExt::is_symlink_file`](https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTypeExt.html#tymethod.is_symlink_file)
|
||||
|
||||
These types were previously stable in `std::ffi`, but are now also available in `core` and `alloc`:
|
||||
|
||||
- [`core::ffi::CStr`](https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html)
|
||||
- [`core::ffi::FromBytesWithNulError`](https://doc.rust-lang.org/stable/core/ffi/struct.FromBytesWithNulError.html)
|
||||
- [`alloc::ffi::CString`](https://doc.rust-lang.org/stable/alloc/ffi/struct.CString.html)
|
||||
- [`alloc::ffi::FromVecWithNulError`](https://doc.rust-lang.org/stable/alloc/ffi/struct.FromVecWithNulError.html)
|
||||
- [`alloc::ffi::IntoStringError`](https://doc.rust-lang.org/stable/alloc/ffi/struct.IntoStringError.html)
|
||||
- [`alloc::ffi::NulError`](https://doc.rust-lang.org/stable/alloc/ffi/struct.NulError.html)
|
||||
|
||||
These types were previously stable in `std::os::raw`, but are now also available in `core::ffi` and `std::ffi`:
|
||||
|
||||
- [`ffi::c_char`](https://doc.rust-lang.org/stable/std/ffi/type.c_char.html)
|
||||
- [`ffi::c_double`](https://doc.rust-lang.org/stable/std/ffi/type.c_double.html)
|
||||
- [`ffi::c_float`](https://doc.rust-lang.org/stable/std/ffi/type.c_float.html)
|
||||
- [`ffi::c_int`](https://doc.rust-lang.org/stable/std/ffi/type.c_int.html)
|
||||
- [`ffi::c_long`](https://doc.rust-lang.org/stable/std/ffi/type.c_long.html)
|
||||
- [`ffi::c_longlong`](https://doc.rust-lang.org/stable/std/ffi/type.c_longlong.html)
|
||||
- [`ffi::c_schar`](https://doc.rust-lang.org/stable/std/ffi/type.c_schar.html)
|
||||
- [`ffi::c_short`](https://doc.rust-lang.org/stable/std/ffi/type.c_short.html)
|
||||
- [`ffi::c_uchar`](https://doc.rust-lang.org/stable/std/ffi/type.c_uchar.html)
|
||||
- [`ffi::c_uint`](https://doc.rust-lang.org/stable/std/ffi/type.c_uint.html)
|
||||
- [`ffi::c_ulong`](https://doc.rust-lang.org/stable/std/ffi/type.c_ulong.html)
|
||||
- [`ffi::c_ulonglong`](https://doc.rust-lang.org/stable/std/ffi/type.c_ulonglong.html)
|
||||
- [`ffi::c_ushort`](https://doc.rust-lang.org/stable/std/ffi/type.c_ushort.html)
|
||||
|
||||
These APIs are now usable in const contexts:
|
||||
|
||||
- [`slice::from_raw_parts`](https://doc.rust-lang.org/stable/core/slice/fn.from_raw_parts.html)
|
||||
|
||||
Cargo
|
||||
-----
|
||||
- [Packages can now inherit settings from the workspace so that the settings
|
||||
can be centralized in one place.](https://github.com/rust-lang/cargo/pull/10859) See
|
||||
[`workspace.package`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacepackage-table)
|
||||
and
|
||||
[`workspace.dependencies`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacedependencies-table)
|
||||
for more details on how to define these common settings.
|
||||
- [Cargo commands can now accept multiple `--target` flags to build for
|
||||
multiple targets at once](https://github.com/rust-lang/cargo/pull/10766), and the
|
||||
[`build.target`](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildtarget)
|
||||
config option may now take an array of multiple targets.
|
||||
- [The `--jobs` argument can now take a negative number to count backwards from
|
||||
the max CPUs.](https://github.com/rust-lang/cargo/pull/10844)
|
||||
- [`cargo add` will now update `Cargo.lock`.](https://github.com/rust-lang/cargo/pull/10902)
|
||||
- [Added](https://github.com/rust-lang/cargo/pull/10838) the
|
||||
[`--crate-type`](https://doc.rust-lang.org/nightly/cargo/commands/cargo-rustc.html#option-cargo-rustc---crate-type)
|
||||
flag to `cargo rustc` to override the crate type.
|
||||
- [Significantly improved the performance fetching git dependencies from GitHub
|
||||
when using a hash in the `rev` field.](https://github.com/rust-lang/cargo/pull/10079)
|
||||
|
||||
Misc
|
||||
----
|
||||
- [The `rust-analyzer` rustup component is now available on the stable channel.](https://github.com/rust-lang/rust/pull/98640/)
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
- The minimum required versions for all `-linux-gnu` targets are now at least kernel 3.2 and glibc 2.17, for targets that previously supported older versions: [Increase the minimum linux-gnu versions](https://github.com/rust-lang/rust/pull/95026/)
|
||||
- [Network primitives are now implemented with the ideal Rust layout, not the C system layout](https://github.com/rust-lang/rust/pull/78802/). This can cause problems when transmuting the types.
|
||||
- [Add assertion that `transmute_copy`'s `U` is not larger than `T`](https://github.com/rust-lang/rust/pull/98839/)
|
||||
- [A soundness bug in `BTreeMap` was fixed](https://github.com/rust-lang/rust/pull/99413/) that allowed data it was borrowing to be dropped before the container.
|
||||
- [The Drop behavior of C-like enums cast to ints has changed](https://github.com/rust-lang/rust/pull/96862/). These are already discouraged by a compiler warning.
|
||||
- [Relate late-bound closure lifetimes to parent fn in NLL](https://github.com/rust-lang/rust/pull/98835/)
|
||||
- [Errors at const-eval time are now in future incompatibility reports](https://github.com/rust-lang/rust/pull/97743/)
|
||||
- On the `thumbv6m-none-eabi` target, some incorrect `asm!` statements were erroneously accepted if they used the high registers (r8 to r14) as an input/output operand. [This is no longer accepted](https://github.com/rust-lang/rust/pull/99155/).
|
||||
- [`impl Trait` was accidentally accepted as the associated type value of return-position `impl Trait`](https://github.com/rust-lang/rust/pull/97346/), without fulfilling all the trait bounds of that associated type, as long as the hidden type satisfies said bounds. This has been fixed.
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
These changes do not affect any public interfaces of Rust, but they represent
|
||||
significant improvements to the performance or internals of rustc and related
|
||||
tools.
|
||||
|
||||
- Windows builds now use profile-guided optimization, providing 10-20% improvements to compiler performance: [Utilize PGO for windows x64 rustc dist builds](https://github.com/rust-lang/rust/pull/96978/)
|
||||
- [Stop keeping metadata in memory before writing it to disk](https://github.com/rust-lang/rust/pull/96544/)
|
||||
- [compiletest: strip debuginfo by default for mode=ui](https://github.com/rust-lang/rust/pull/98140/)
|
||||
- Many improvements to generated code for derives, including performance improvements:
|
||||
- [Don't use match-destructuring for derived ops on structs.](https://github.com/rust-lang/rust/pull/98446/)
|
||||
- [Many small deriving cleanups](https://github.com/rust-lang/rust/pull/98741/)
|
||||
- [More derive output improvements](https://github.com/rust-lang/rust/pull/98758/)
|
||||
- [Clarify deriving code](https://github.com/rust-lang/rust/pull/98915/)
|
||||
- [Final derive output improvements](https://github.com/rust-lang/rust/pull/99046/)
|
||||
- [Stop injecting `#[allow(unused_qualifications)]` in generated `derive` implementations](https://github.com/rust-lang/rust/pull/99485/)
|
||||
- [Improve `derive(Debug)`](https://github.com/rust-lang/rust/pull/98190/)
|
||||
- [Bump to clap 3](https://github.com/rust-lang/rust/pull/98213/)
|
||||
- [fully move dropck to mir](https://github.com/rust-lang/rust/pull/98641/)
|
||||
- [Optimize `Vec::insert` for the case where `index == len`.](https://github.com/rust-lang/rust/pull/98755/)
|
||||
- [Convert rust-analyzer to an in-tree tool](https://github.com/rust-lang/rust/pull/99603/)
|
||||
|
||||
Version 1.63.0 (2022-08-11)
|
||||
==========================
|
||||
|
||||
|
@ -217,6 +358,7 @@ Language
|
|||
- [Fix constants not getting dropped if part of a diverging expression][94775]
|
||||
- [Support unit struct/enum variant in destructuring assignment][95380]
|
||||
- [Remove mutable_borrow_reservation_conflict lint and allow the code pattern][96268]
|
||||
- [`const` functions may now specify `extern "C"` or `extern "Rust"`][95346]
|
||||
|
||||
Compiler
|
||||
--------
|
||||
|
@ -306,6 +448,7 @@ and related tools.
|
|||
[94872]: https://github.com/rust-lang/rust/pull/94872/
|
||||
[95006]: https://github.com/rust-lang/rust/pull/95006/
|
||||
[95035]: https://github.com/rust-lang/rust/pull/95035/
|
||||
[95346]: https://github.com/rust-lang/rust/pull/95346/
|
||||
[95372]: https://github.com/rust-lang/rust/pull/95372/
|
||||
[95380]: https://github.com/rust-lang/rust/pull/95380/
|
||||
[95431]: https://github.com/rust-lang/rust/pull/95431/
|
||||
|
@ -1442,7 +1585,7 @@ Compatibility Notes
|
|||
- [Mixing Option and Result via `?` is no longer permitted in closures for inferred types.][86831]
|
||||
- [Previously unsound code is no longer permitted where different constructors in branches
|
||||
could require different lifetimes.][85574]
|
||||
- As previously mentioned the [`std::arch` instrinsics now uses stricter const checking][83278]
|
||||
- As previously mentioned the [`std::arch` intrinsics now uses stricter const checking][83278]
|
||||
than before and may reject some previously accepted code.
|
||||
- [`i128` multiplication on Cortex M0+ platforms currently unconditionally causes overflow
|
||||
when compiled with `codegen-units = 1`.][86063]
|
||||
|
@ -2520,7 +2663,7 @@ Compatibility Notes
|
|||
- [Fixed a regression parsing `{} && false` in tail expressions.][74650]
|
||||
- [Added changes to how proc-macros are expanded in `macro_rules!` that should
|
||||
help to preserve more span information.][73084] These changes may cause
|
||||
compiliation errors if your macro was unhygenic or didn't correctly handle
|
||||
compilation errors if your macro was unhygenic or didn't correctly handle
|
||||
`Delimiter::None`.
|
||||
- [Moved support for the CloudABI target to tier 3.][75568]
|
||||
- [`linux-gnu` targets now require minimum kernel 2.6.32 and glibc 2.11.][74163]
|
||||
|
|
|
@ -7,12 +7,13 @@ edition = "2021"
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
tracing = "0.1"
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
bitflags = "1.2.1"
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
bitflags = "1.2.1"
|
||||
thin-vec = "0.2.8"
|
||||
tracing = "0.1"
|
||||
|
|
|
@ -24,22 +24,19 @@ pub use UnsafeSource::*;
|
|||
|
||||
use crate::ptr::P;
|
||||
use crate::token::{self, CommentKind, Delimiter};
|
||||
use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream};
|
||||
|
||||
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
use rustc_span::source_map::{respan, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
/// A "Label" is an identifier of some point in sources,
|
||||
/// e.g. in the following code:
|
||||
|
@ -94,7 +91,7 @@ pub struct Path {
|
|||
/// The segments in the path: the things separated by `::`.
|
||||
/// Global paths begin with `kw::PathRoot`.
|
||||
pub segments: Vec<PathSegment>,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
impl PartialEq<Symbol> for Path {
|
||||
|
@ -326,46 +323,17 @@ pub type GenericBounds = Vec<GenericBound>;
|
|||
/// Specifies the enforced ordering for generic parameters. In the future,
|
||||
/// if we wanted to relax this order, we could override `PartialEq` and
|
||||
/// `PartialOrd`, to allow the kinds to be unordered.
|
||||
#[derive(Hash, Clone, Copy)]
|
||||
#[derive(Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum ParamKindOrd {
|
||||
Lifetime,
|
||||
Type,
|
||||
Const,
|
||||
// `Infer` is not actually constructed directly from the AST, but is implicitly constructed
|
||||
// during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last.
|
||||
Infer,
|
||||
TypeOrConst,
|
||||
}
|
||||
|
||||
impl Ord for ParamKindOrd {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
use ParamKindOrd::*;
|
||||
let to_int = |v| match v {
|
||||
Lifetime => 0,
|
||||
Infer | Type | Const => 1,
|
||||
};
|
||||
|
||||
to_int(*self).cmp(&to_int(*other))
|
||||
}
|
||||
}
|
||||
impl PartialOrd for ParamKindOrd {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl PartialEq for ParamKindOrd {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.cmp(other) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
impl Eq for ParamKindOrd {}
|
||||
|
||||
impl fmt::Display for ParamKindOrd {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ParamKindOrd::Lifetime => "lifetime".fmt(f),
|
||||
ParamKindOrd::Type => "type".fmt(f),
|
||||
ParamKindOrd::Const { .. } => "const".fmt(f),
|
||||
ParamKindOrd::Infer => "infer".fmt(f),
|
||||
ParamKindOrd::TypeOrConst => "type and const".fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -566,7 +534,7 @@ pub struct Block {
|
|||
/// Distinguishes between `unsafe { ... }` and `{ ... }`.
|
||||
pub rules: BlockCheckMode,
|
||||
pub span: Span,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
/// The following *isn't* a parse error, but will cause multiple errors in following stages.
|
||||
/// ```compile_fail
|
||||
/// let x = {
|
||||
|
@ -585,7 +553,7 @@ pub struct Pat {
|
|||
pub id: NodeId,
|
||||
pub kind: PatKind,
|
||||
pub span: Span,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
impl Pat {
|
||||
|
@ -596,7 +564,7 @@ impl Pat {
|
|||
// In a type expression `_` is an inference variable.
|
||||
PatKind::Wild => TyKind::Infer,
|
||||
// An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
|
||||
PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
|
||||
PatKind::Ident(BindingAnnotation::NONE, ident, None) => {
|
||||
TyKind::Path(None, Path::from_ident(*ident))
|
||||
}
|
||||
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
|
||||
|
@ -683,10 +651,43 @@ pub struct PatField {
|
|||
pub is_placeholder: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
|
||||
pub enum BindingMode {
|
||||
ByRef(Mutability),
|
||||
ByValue(Mutability),
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[derive(Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum ByRef {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl From<bool> for ByRef {
|
||||
fn from(b: bool) -> ByRef {
|
||||
match b {
|
||||
false => ByRef::No,
|
||||
true => ByRef::Yes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Explicit binding annotations given in the HIR for a binding. Note
|
||||
/// that this is not the final binding *mode* that we infer after type
|
||||
/// inference.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[derive(Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct BindingAnnotation(pub ByRef, pub Mutability);
|
||||
|
||||
impl BindingAnnotation {
|
||||
pub const NONE: Self = Self(ByRef::No, Mutability::Not);
|
||||
pub const REF: Self = Self(ByRef::Yes, Mutability::Not);
|
||||
pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
|
||||
pub const REF_MUT: Self = Self(ByRef::Yes, Mutability::Mut);
|
||||
|
||||
pub fn prefix_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::NONE => "",
|
||||
Self::REF => "ref ",
|
||||
Self::MUT => "mut ",
|
||||
Self::REF_MUT => "ref mut ",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
|
@ -715,7 +716,7 @@ pub enum PatKind {
|
|||
/// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
|
||||
/// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
|
||||
/// during name resolution.
|
||||
Ident(BindingMode, Ident, Option<P<Pat>>),
|
||||
Ident(BindingAnnotation, Ident, Option<P<Pat>>),
|
||||
|
||||
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
|
||||
/// The `bool` is `true` in the presence of a `..`.
|
||||
|
@ -936,8 +937,8 @@ impl Stmt {
|
|||
/// a trailing semicolon.
|
||||
///
|
||||
/// This only modifies the parsed AST struct, not the attached
|
||||
/// `LazyTokenStream`. The parser is responsible for calling
|
||||
/// `CreateTokenStream::add_trailing_semi` when there is actually
|
||||
/// `LazyAttrTokenStream`. The parser is responsible for calling
|
||||
/// `ToAttrTokenStream::add_trailing_semi` when there is actually
|
||||
/// a semicolon in the tokenstream.
|
||||
pub fn add_trailing_semicolon(mut self) -> Self {
|
||||
self.kind = match self.kind {
|
||||
|
@ -983,7 +984,7 @@ pub struct MacCallStmt {
|
|||
pub mac: P<MacCall>,
|
||||
pub style: MacStmtStyle,
|
||||
pub attrs: AttrVec,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
|
||||
|
@ -1008,7 +1009,7 @@ pub struct Local {
|
|||
pub kind: LocalKind,
|
||||
pub span: Span,
|
||||
pub attrs: AttrVec,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
|
@ -1107,7 +1108,7 @@ pub struct Expr {
|
|||
pub kind: ExprKind,
|
||||
pub span: Span,
|
||||
pub attrs: AttrVec,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
|
@ -1966,7 +1967,7 @@ pub struct Ty {
|
|||
pub id: NodeId,
|
||||
pub kind: TyKind,
|
||||
pub span: Span,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
impl Clone for Ty {
|
||||
|
@ -2071,6 +2072,7 @@ impl TyKind {
|
|||
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub enum TraitObjectSyntax {
|
||||
Dyn,
|
||||
DynStar,
|
||||
None,
|
||||
}
|
||||
|
||||
|
@ -2086,15 +2088,15 @@ pub enum InlineAsmRegOrRegClass {
|
|||
bitflags::bitflags! {
|
||||
#[derive(Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct InlineAsmOptions: u16 {
|
||||
const PURE = 1 << 0;
|
||||
const NOMEM = 1 << 1;
|
||||
const READONLY = 1 << 2;
|
||||
const PURE = 1 << 0;
|
||||
const NOMEM = 1 << 1;
|
||||
const READONLY = 1 << 2;
|
||||
const PRESERVES_FLAGS = 1 << 3;
|
||||
const NORETURN = 1 << 4;
|
||||
const NOSTACK = 1 << 5;
|
||||
const ATT_SYNTAX = 1 << 6;
|
||||
const RAW = 1 << 7;
|
||||
const MAY_UNWIND = 1 << 8;
|
||||
const NORETURN = 1 << 4;
|
||||
const NOSTACK = 1 << 5;
|
||||
const ATT_SYNTAX = 1 << 6;
|
||||
const RAW = 1 << 7;
|
||||
const MAY_UNWIND = 1 << 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2230,7 +2232,7 @@ pub type ExplicitSelf = Spanned<SelfKind>;
|
|||
impl Param {
|
||||
/// Attempts to cast parameter to `ExplicitSelf`.
|
||||
pub fn to_self(&self) -> Option<ExplicitSelf> {
|
||||
if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.kind {
|
||||
if let PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), ident, _) = self.pat.kind {
|
||||
if ident.name == kw::SelfLower {
|
||||
return match self.ty.kind {
|
||||
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
||||
|
@ -2260,23 +2262,10 @@ impl Param {
|
|||
pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
|
||||
let span = eself.span.to(eself_ident.span);
|
||||
let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span, tokens: None });
|
||||
let param = |mutbl, ty| Param {
|
||||
attrs,
|
||||
pat: P(Pat {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
|
||||
span,
|
||||
tokens: None,
|
||||
}),
|
||||
span,
|
||||
ty,
|
||||
id: DUMMY_NODE_ID,
|
||||
is_placeholder: false,
|
||||
};
|
||||
match eself.node {
|
||||
SelfKind::Explicit(ty, mutbl) => param(mutbl, ty),
|
||||
SelfKind::Value(mutbl) => param(mutbl, infer_ty),
|
||||
SelfKind::Region(lt, mutbl) => param(
|
||||
let (mutbl, ty) = match eself.node {
|
||||
SelfKind::Explicit(ty, mutbl) => (mutbl, ty),
|
||||
SelfKind::Value(mutbl) => (mutbl, infer_ty),
|
||||
SelfKind::Region(lt, mutbl) => (
|
||||
Mutability::Not,
|
||||
P(Ty {
|
||||
id: DUMMY_NODE_ID,
|
||||
|
@ -2285,6 +2274,19 @@ impl Param {
|
|||
tokens: None,
|
||||
}),
|
||||
),
|
||||
};
|
||||
Param {
|
||||
attrs,
|
||||
pat: P(Pat {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), eself_ident, None),
|
||||
span,
|
||||
tokens: None,
|
||||
}),
|
||||
span,
|
||||
ty,
|
||||
id: DUMMY_NODE_ID,
|
||||
is_placeholder: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2336,9 +2338,9 @@ impl Async {
|
|||
}
|
||||
|
||||
/// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
|
||||
pub fn opt_return_id(self) -> Option<NodeId> {
|
||||
pub fn opt_return_id(self) -> Option<(NodeId, Span)> {
|
||||
match self {
|
||||
Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id),
|
||||
Async::Yes { return_impl_trait_id, span, .. } => Some((return_impl_trait_id, span)),
|
||||
Async::No => None,
|
||||
}
|
||||
}
|
||||
|
@ -2522,8 +2524,8 @@ impl<S: Encoder> Encodable<S> for AttrId {
|
|||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for AttrId {
|
||||
fn decode(_: &mut D) -> AttrId {
|
||||
crate::attr::mk_attr_id()
|
||||
default fn decode(_: &mut D) -> AttrId {
|
||||
panic!("cannot decode `AttrId` with `{}`", std::any::type_name::<D>());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2531,7 +2533,7 @@ impl<D: Decoder> Decodable<D> for AttrId {
|
|||
pub struct AttrItem {
|
||||
pub path: Path,
|
||||
pub args: MacArgs,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
/// A list of attributes.
|
||||
|
@ -2551,7 +2553,7 @@ pub struct Attribute {
|
|||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct NormalAttr {
|
||||
pub item: AttrItem,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
|
@ -2602,7 +2604,7 @@ impl PolyTraitRef {
|
|||
pub struct Visibility {
|
||||
pub kind: VisibilityKind,
|
||||
pub span: Span,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
|
@ -2688,7 +2690,7 @@ pub struct Item<K = ItemKind> {
|
|||
///
|
||||
/// Note that the tokens here do not include the outer attributes, but will
|
||||
/// include inner attributes.
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
|
@ -3044,9 +3046,10 @@ mod size_asserts {
|
|||
static_assert_size!(Block, 48);
|
||||
static_assert_size!(Expr, 104);
|
||||
static_assert_size!(ExprKind, 72);
|
||||
static_assert_size!(Fn, 192);
|
||||
static_assert_size!(Fn, 184);
|
||||
static_assert_size!(ForeignItem, 96);
|
||||
static_assert_size!(ForeignItemKind, 24);
|
||||
static_assert_size!(GenericArg, 24);
|
||||
static_assert_size!(GenericBound, 88);
|
||||
static_assert_size!(Generics, 72);
|
||||
static_assert_size!(Impl, 200);
|
||||
|
@ -3054,6 +3057,8 @@ mod size_asserts {
|
|||
static_assert_size!(ItemKind, 112);
|
||||
static_assert_size!(Lit, 48);
|
||||
static_assert_size!(LitKind, 24);
|
||||
static_assert_size!(Local, 72);
|
||||
static_assert_size!(Param, 40);
|
||||
static_assert_size!(Pat, 120);
|
||||
static_assert_size!(PatKind, 96);
|
||||
static_assert_size!(Path, 40);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use crate::ptr::P;
|
||||
use crate::token::Nonterminal;
|
||||
use crate::tokenstream::LazyTokenStream;
|
||||
use crate::tokenstream::LazyAttrTokenStream;
|
||||
use crate::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
|
||||
use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
|
||||
use crate::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
|
||||
|
@ -124,18 +124,18 @@ impl HasSpan for AttrItem {
|
|||
|
||||
/// A trait for AST nodes having (or not having) collected tokens.
|
||||
pub trait HasTokens {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream>;
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>>;
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream>;
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>>;
|
||||
}
|
||||
|
||||
macro_rules! impl_has_tokens {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasTokens for $T {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
self.tokens.as_ref()
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
Some(&mut self.tokens)
|
||||
}
|
||||
}
|
||||
|
@ -147,10 +147,10 @@ macro_rules! impl_has_tokens_none {
|
|||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasTokens for $T {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
None
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -162,25 +162,25 @@ impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path,
|
|||
impl_has_tokens_none!(Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant);
|
||||
|
||||
impl<T: AstDeref<Target: HasTokens>> HasTokens for T {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
self.ast_deref().tokens()
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
self.ast_deref_mut().tokens_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HasTokens> HasTokens for Option<T> {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
self.as_ref().and_then(|inner| inner.tokens())
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
self.as_mut().and_then(|inner| inner.tokens_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTokens for StmtKind {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
match self {
|
||||
StmtKind::Local(local) => local.tokens.as_ref(),
|
||||
StmtKind::Item(item) => item.tokens(),
|
||||
|
@ -189,7 +189,7 @@ impl HasTokens for StmtKind {
|
|||
StmtKind::MacCall(mac) => mac.tokens.as_ref(),
|
||||
}
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
match self {
|
||||
StmtKind::Local(local) => Some(&mut local.tokens),
|
||||
StmtKind::Item(item) => item.tokens_mut(),
|
||||
|
@ -201,16 +201,16 @@ impl HasTokens for StmtKind {
|
|||
}
|
||||
|
||||
impl HasTokens for Stmt {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
self.kind.tokens()
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
self.kind.tokens_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTokens for Attribute {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.tokens.as_ref(),
|
||||
kind @ AttrKind::DocComment(..) => {
|
||||
|
@ -218,7 +218,7 @@ impl HasTokens for Attribute {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
Some(match &mut self.kind {
|
||||
AttrKind::Normal(normal) => &mut normal.tokens,
|
||||
kind @ AttrKind::DocComment(..) => {
|
||||
|
@ -229,7 +229,7 @@ impl HasTokens for Attribute {
|
|||
}
|
||||
|
||||
impl HasTokens for Nonterminal {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
match self {
|
||||
Nonterminal::NtItem(item) => item.tokens(),
|
||||
Nonterminal::NtStmt(stmt) => stmt.tokens(),
|
||||
|
@ -243,7 +243,7 @@ impl HasTokens for Nonterminal {
|
|||
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
|
||||
}
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
match self {
|
||||
Nonterminal::NtItem(item) => item.tokens_mut(),
|
||||
Nonterminal::NtStmt(stmt) => stmt.tokens_mut(),
|
||||
|
@ -279,6 +279,7 @@ macro_rules! impl_has_attrs {
|
|||
impl HasAttrs for $T {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner;
|
||||
|
||||
#[inline]
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
&self.attrs
|
||||
}
|
||||
|
|
|
@ -7,17 +7,22 @@ use crate::ast::{MacArgs, MacArgsEq, MacDelimiter, MetaItem, MetaItemKind, Neste
|
|||
use crate::ast::{Path, PathSegment};
|
||||
use crate::ptr::P;
|
||||
use crate::token::{self, CommentKind, Delimiter, Token};
|
||||
use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
|
||||
use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
|
||||
use crate::tokenstream::{LazyTokenStream, TokenStream};
|
||||
use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
|
||||
use crate::util::comments;
|
||||
|
||||
use rustc_data_structures::sync::WorkerLocal;
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_span::source_map::BytePos;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::iter;
|
||||
#[cfg(debug_assertions)]
|
||||
use std::ops::BitXor;
|
||||
#[cfg(debug_assertions)]
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
pub struct MarkedAttrs(GrowableBitSet<AttrId>);
|
||||
|
||||
|
@ -232,6 +237,9 @@ impl AttrItem {
|
|||
}
|
||||
|
||||
impl Attribute {
|
||||
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
|
||||
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
|
||||
/// a doc comment) will return `false`.
|
||||
pub fn is_doc_comment(&self) -> bool {
|
||||
match self.kind {
|
||||
AttrKind::Normal(..) => false,
|
||||
|
@ -239,6 +247,11 @@ impl Attribute {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
|
||||
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
|
||||
match self.kind {
|
||||
AttrKind::DocComment(kind, data) => Some((data, kind)),
|
||||
|
@ -251,6 +264,10 @@ impl Attribute {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the documentation if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some("doc")`.
|
||||
/// * `#[doc = "doc"]` returns `Some("doc")`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
pub fn doc_str(&self) -> Option<Symbol> {
|
||||
match self.kind {
|
||||
AttrKind::DocComment(.., data) => Some(data),
|
||||
|
@ -294,20 +311,18 @@ impl Attribute {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn tokens(&self) -> AttrAnnotatedTokenStream {
|
||||
pub fn tokens(&self) -> TokenStream {
|
||||
match self.kind {
|
||||
AttrKind::Normal(ref normal) => normal
|
||||
.tokens
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self))
|
||||
.create_token_stream(),
|
||||
AttrKind::DocComment(comment_kind, data) => AttrAnnotatedTokenStream::from((
|
||||
AttrAnnotatedTokenTree::Token(Token::new(
|
||||
token::DocComment(comment_kind, self.style, data),
|
||||
self.span,
|
||||
)),
|
||||
.to_attr_token_stream()
|
||||
.to_tokenstream(),
|
||||
AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token(
|
||||
Token::new(token::DocComment(comment_kind, self.style, data), self.span),
|
||||
Spacing::Alone,
|
||||
)),
|
||||
)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,52 +352,86 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
|
|||
NestedMetaItem::MetaItem(mk_word_item(ident))
|
||||
}
|
||||
|
||||
pub(crate) fn mk_attr_id() -> AttrId {
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::atomic::Ordering;
|
||||
pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
|
||||
|
||||
static NEXT_ATTR_ID: AtomicU32 = AtomicU32::new(0);
|
||||
#[cfg(debug_assertions)]
|
||||
static MAX_ATTR_ID: AtomicU32 = AtomicU32::new(u32::MAX);
|
||||
|
||||
let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst);
|
||||
assert!(id != u32::MAX);
|
||||
AttrId::from_u32(id)
|
||||
impl AttrIdGenerator {
|
||||
pub fn new() -> Self {
|
||||
// We use `(index as u32).reverse_bits()` to initialize the
|
||||
// starting value of AttrId in each worker thread.
|
||||
// The `index` is the index of the worker thread.
|
||||
// This ensures that the AttrId generated in each thread is unique.
|
||||
AttrIdGenerator(WorkerLocal::new(|index| {
|
||||
let index: u32 = index.try_into().unwrap();
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let max_id = ((index + 1).next_power_of_two() - 1).bitxor(u32::MAX).reverse_bits();
|
||||
MAX_ATTR_ID.fetch_min(max_id, Ordering::Release);
|
||||
}
|
||||
|
||||
Cell::new(index.reverse_bits())
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn mk_attr_id(&self) -> AttrId {
|
||||
let id = self.0.get();
|
||||
|
||||
// Ensure the assigned attr_id does not overlap the bits
|
||||
// representing the number of threads.
|
||||
#[cfg(debug_assertions)]
|
||||
assert!(id <= MAX_ATTR_ID.load(Ordering::Acquire));
|
||||
|
||||
self.0.set(id + 1);
|
||||
AttrId::from_u32(id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
|
||||
mk_attr_from_item(AttrItem { path, args, tokens: None }, None, style, span)
|
||||
pub fn mk_attr(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
path: Path,
|
||||
args: MacArgs,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_from_item(
|
||||
g: &AttrIdGenerator,
|
||||
item: AttrItem,
|
||||
tokens: Option<LazyTokenStream>,
|
||||
tokens: Option<LazyAttrTokenStream>,
|
||||
style: AttrStyle,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
Attribute {
|
||||
kind: AttrKind::Normal(P(ast::NormalAttr { item, tokens })),
|
||||
id: mk_attr_id(),
|
||||
id: g.mk_attr_id(),
|
||||
style,
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an inner attribute with the given value and span.
|
||||
pub fn mk_attr_inner(item: MetaItem) -> Attribute {
|
||||
mk_attr(AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
|
||||
pub fn mk_attr_inner(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
|
||||
mk_attr(g, AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
|
||||
}
|
||||
|
||||
/// Returns an outer attribute with the given value and span.
|
||||
pub fn mk_attr_outer(item: MetaItem) -> Attribute {
|
||||
mk_attr(AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
|
||||
pub fn mk_attr_outer(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
|
||||
mk_attr(g, AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
|
||||
}
|
||||
|
||||
pub fn mk_doc_comment(
|
||||
g: &AttrIdGenerator,
|
||||
comment_kind: CommentKind,
|
||||
style: AttrStyle,
|
||||
data: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: mk_attr_id(), style, span }
|
||||
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
|
||||
}
|
||||
|
||||
pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#![feature(const_default_impls)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(if_let_guard)]
|
||||
#![cfg_attr(bootstrap, feature(label_break_value))]
|
||||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(negative_impls)]
|
||||
|
@ -26,6 +25,9 @@
|
|||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
pub mod util {
|
||||
pub mod classify;
|
||||
pub mod comments;
|
||||
|
|
|
@ -642,17 +642,17 @@ pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> Smal
|
|||
}
|
||||
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
pub fn visit_attr_annotated_tt<T: MutVisitor>(tt: &mut AttrAnnotatedTokenTree, vis: &mut T) {
|
||||
pub fn visit_attr_tt<T: MutVisitor>(tt: &mut AttrTokenTree, vis: &mut T) {
|
||||
match tt {
|
||||
AttrAnnotatedTokenTree::Token(token) => {
|
||||
AttrTokenTree::Token(token, _) => {
|
||||
visit_token(token, vis);
|
||||
}
|
||||
AttrAnnotatedTokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
|
||||
AttrTokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
|
||||
vis.visit_span(open);
|
||||
vis.visit_span(close);
|
||||
visit_attr_annotated_tts(tts, vis);
|
||||
visit_attr_tts(tts, vis);
|
||||
}
|
||||
AttrAnnotatedTokenTree::Attributes(data) => {
|
||||
AttrTokenTree::Attributes(data) => {
|
||||
for attr in &mut *data.attrs {
|
||||
match &mut attr.kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
|
@ -690,27 +690,27 @@ pub fn visit_tts<T: MutVisitor>(TokenStream(tts): &mut TokenStream, vis: &mut T)
|
|||
}
|
||||
}
|
||||
|
||||
pub fn visit_attr_annotated_tts<T: MutVisitor>(
|
||||
AttrAnnotatedTokenStream(tts): &mut AttrAnnotatedTokenStream,
|
||||
vis: &mut T,
|
||||
) {
|
||||
pub fn visit_attr_tts<T: MutVisitor>(AttrTokenStream(tts): &mut AttrTokenStream, vis: &mut T) {
|
||||
if T::VISIT_TOKENS && !tts.is_empty() {
|
||||
let tts = Lrc::make_mut(tts);
|
||||
visit_vec(tts, |(tree, _is_joint)| visit_attr_annotated_tt(tree, vis));
|
||||
visit_vec(tts, |tree| visit_attr_tt(tree, vis));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_lazy_tts_opt_mut<T: MutVisitor>(lazy_tts: Option<&mut LazyTokenStream>, vis: &mut T) {
|
||||
pub fn visit_lazy_tts_opt_mut<T: MutVisitor>(
|
||||
lazy_tts: Option<&mut LazyAttrTokenStream>,
|
||||
vis: &mut T,
|
||||
) {
|
||||
if T::VISIT_TOKENS {
|
||||
if let Some(lazy_tts) = lazy_tts {
|
||||
let mut tts = lazy_tts.create_token_stream();
|
||||
visit_attr_annotated_tts(&mut tts, vis);
|
||||
*lazy_tts = LazyTokenStream::new(tts);
|
||||
let mut tts = lazy_tts.to_attr_token_stream();
|
||||
visit_attr_tts(&mut tts, vis);
|
||||
*lazy_tts = LazyAttrTokenStream::new(tts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_lazy_tts<T: MutVisitor>(lazy_tts: &mut Option<LazyTokenStream>, vis: &mut T) {
|
||||
pub fn visit_lazy_tts<T: MutVisitor>(lazy_tts: &mut Option<LazyAttrTokenStream>, vis: &mut T) {
|
||||
visit_lazy_tts_opt_mut(lazy_tts.as_mut(), vis);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ rustc_index::newtype_index! {
|
|||
}
|
||||
}
|
||||
|
||||
rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId);
|
||||
rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId);
|
||||
|
||||
/// The [`NodeId`] used to represent the root of the crate.
|
||||
pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
|
||||
|
|
|
@ -398,6 +398,30 @@ impl Token {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the token can appear at the start of an pattern.
|
||||
///
|
||||
/// Shamelessly borrowed from `can_begin_expr`, only used for diagnostics right now.
|
||||
pub fn can_begin_pattern(&self) -> bool {
|
||||
match self.uninterpolate().kind {
|
||||
Ident(name, is_raw) =>
|
||||
ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
|
||||
| OpenDelim(Delimiter::Bracket | Delimiter::Parenthesis) // tuple or array
|
||||
| Literal(..) // literal
|
||||
| BinOp(Minus) // unary minus
|
||||
| BinOp(And) // reference
|
||||
| AndAnd // double reference
|
||||
// DotDotDot is no longer supported
|
||||
| DotDot | DotDotDot | DotDotEq // ranges
|
||||
| Lt | BinOp(Shl) // associated path
|
||||
| ModSep => true, // global path
|
||||
Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
|
||||
NtPat(..) |
|
||||
NtBlock(..) |
|
||||
NtPath(..)),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the token can appear at the start of a type.
|
||||
pub fn can_begin_type(&self) -> bool {
|
||||
match self.uninterpolate().kind {
|
||||
|
@ -449,6 +473,7 @@ impl Token {
|
|||
kw::Extern,
|
||||
kw::Impl,
|
||||
kw::Unsafe,
|
||||
kw::Const,
|
||||
kw::Static,
|
||||
kw::Union,
|
||||
kw::Macro,
|
||||
|
|
|
@ -121,12 +121,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub trait CreateTokenStream: sync::Send + sync::Sync {
|
||||
fn create_token_stream(&self) -> AttrAnnotatedTokenStream;
|
||||
pub trait ToAttrTokenStream: sync::Send + sync::Sync {
|
||||
fn to_attr_token_stream(&self) -> AttrTokenStream;
|
||||
}
|
||||
|
||||
impl CreateTokenStream for AttrAnnotatedTokenStream {
|
||||
fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
|
||||
impl ToAttrTokenStream for AttrTokenStream {
|
||||
fn to_attr_token_stream(&self) -> AttrTokenStream {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
@ -135,68 +135,68 @@ impl CreateTokenStream for AttrAnnotatedTokenStream {
|
|||
/// of an actual `TokenStream` until it is needed.
|
||||
/// `Box` is here only to reduce the structure size.
|
||||
#[derive(Clone)]
|
||||
pub struct LazyTokenStream(Lrc<Box<dyn CreateTokenStream>>);
|
||||
pub struct LazyAttrTokenStream(Lrc<Box<dyn ToAttrTokenStream>>);
|
||||
|
||||
impl LazyTokenStream {
|
||||
pub fn new(inner: impl CreateTokenStream + 'static) -> LazyTokenStream {
|
||||
LazyTokenStream(Lrc::new(Box::new(inner)))
|
||||
impl LazyAttrTokenStream {
|
||||
pub fn new(inner: impl ToAttrTokenStream + 'static) -> LazyAttrTokenStream {
|
||||
LazyAttrTokenStream(Lrc::new(Box::new(inner)))
|
||||
}
|
||||
|
||||
pub fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
|
||||
self.0.create_token_stream()
|
||||
pub fn to_attr_token_stream(&self) -> AttrTokenStream {
|
||||
self.0.to_attr_token_stream()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for LazyTokenStream {
|
||||
impl fmt::Debug for LazyAttrTokenStream {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "LazyTokenStream({:?})", self.create_token_stream())
|
||||
write!(f, "LazyAttrTokenStream({:?})", self.to_attr_token_stream())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for LazyTokenStream {
|
||||
impl<S: Encoder> Encodable<S> for LazyAttrTokenStream {
|
||||
fn encode(&self, s: &mut S) {
|
||||
// Used by AST json printing.
|
||||
Encodable::encode(&self.create_token_stream(), s);
|
||||
Encodable::encode(&self.to_attr_token_stream(), s);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for LazyTokenStream {
|
||||
impl<D: Decoder> Decodable<D> for LazyAttrTokenStream {
|
||||
fn decode(_d: &mut D) -> Self {
|
||||
panic!("Attempted to decode LazyTokenStream");
|
||||
panic!("Attempted to decode LazyAttrTokenStream");
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX> HashStable<CTX> for LazyTokenStream {
|
||||
impl<CTX> HashStable<CTX> for LazyAttrTokenStream {
|
||||
fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
|
||||
panic!("Attempted to compute stable hash for LazyTokenStream");
|
||||
panic!("Attempted to compute stable hash for LazyAttrTokenStream");
|
||||
}
|
||||
}
|
||||
|
||||
/// A `AttrAnnotatedTokenStream` is similar to a `TokenStream`, but with extra
|
||||
/// An `AttrTokenStream` is similar to a `TokenStream`, but with extra
|
||||
/// information about the tokens for attribute targets. This is used
|
||||
/// during expansion to perform early cfg-expansion, and to process attributes
|
||||
/// during proc-macro invocations.
|
||||
#[derive(Clone, Debug, Default, Encodable, Decodable)]
|
||||
pub struct AttrAnnotatedTokenStream(pub Lrc<Vec<(AttrAnnotatedTokenTree, Spacing)>>);
|
||||
pub struct AttrTokenStream(pub Lrc<Vec<AttrTokenTree>>);
|
||||
|
||||
/// Like `TokenTree`, but for `AttrAnnotatedTokenStream`
|
||||
/// Like `TokenTree`, but for `AttrTokenStream`.
|
||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||
pub enum AttrAnnotatedTokenTree {
|
||||
Token(Token),
|
||||
Delimited(DelimSpan, Delimiter, AttrAnnotatedTokenStream),
|
||||
pub enum AttrTokenTree {
|
||||
Token(Token, Spacing),
|
||||
Delimited(DelimSpan, Delimiter, AttrTokenStream),
|
||||
/// Stores the attributes for an attribute target,
|
||||
/// along with the tokens for that attribute target.
|
||||
/// See `AttributesData` for more information
|
||||
Attributes(AttributesData),
|
||||
}
|
||||
|
||||
impl AttrAnnotatedTokenStream {
|
||||
pub fn new(tokens: Vec<(AttrAnnotatedTokenTree, Spacing)>) -> AttrAnnotatedTokenStream {
|
||||
AttrAnnotatedTokenStream(Lrc::new(tokens))
|
||||
impl AttrTokenStream {
|
||||
pub fn new(tokens: Vec<AttrTokenTree>) -> AttrTokenStream {
|
||||
AttrTokenStream(Lrc::new(tokens))
|
||||
}
|
||||
|
||||
/// Converts this `AttrAnnotatedTokenStream` to a plain `TokenStream
|
||||
/// During conversion, `AttrAnnotatedTokenTree::Attributes` get 'flattened'
|
||||
/// Converts this `AttrTokenStream` to a plain `TokenStream`.
|
||||
/// During conversion, `AttrTokenTree::Attributes` get 'flattened'
|
||||
/// back to a `TokenStream` of the form `outer_attr attr_target`.
|
||||
/// If there are inner attributes, they are inserted into the proper
|
||||
/// place in the attribute target tokens.
|
||||
|
@ -204,31 +204,27 @@ impl AttrAnnotatedTokenStream {
|
|||
let trees: Vec<_> = self
|
||||
.0
|
||||
.iter()
|
||||
.flat_map(|tree| match &tree.0 {
|
||||
AttrAnnotatedTokenTree::Token(inner) => {
|
||||
smallvec![TokenTree::Token(inner.clone(), tree.1)].into_iter()
|
||||
.flat_map(|tree| match &tree {
|
||||
AttrTokenTree::Token(inner, spacing) => {
|
||||
smallvec![TokenTree::Token(inner.clone(), *spacing)].into_iter()
|
||||
}
|
||||
AttrAnnotatedTokenTree::Delimited(span, delim, stream) => {
|
||||
AttrTokenTree::Delimited(span, delim, stream) => {
|
||||
smallvec![TokenTree::Delimited(*span, *delim, stream.to_tokenstream()),]
|
||||
.into_iter()
|
||||
}
|
||||
AttrAnnotatedTokenTree::Attributes(data) => {
|
||||
AttrTokenTree::Attributes(data) => {
|
||||
let mut outer_attrs = Vec::new();
|
||||
let mut inner_attrs = Vec::new();
|
||||
for attr in &data.attrs {
|
||||
match attr.style {
|
||||
crate::AttrStyle::Outer => {
|
||||
outer_attrs.push(attr);
|
||||
}
|
||||
crate::AttrStyle::Inner => {
|
||||
inner_attrs.push(attr);
|
||||
}
|
||||
crate::AttrStyle::Outer => outer_attrs.push(attr),
|
||||
crate::AttrStyle::Inner => inner_attrs.push(attr),
|
||||
}
|
||||
}
|
||||
|
||||
let mut target_tokens: Vec<_> = data
|
||||
.tokens
|
||||
.create_token_stream()
|
||||
.to_attr_token_stream()
|
||||
.to_tokenstream()
|
||||
.0
|
||||
.iter()
|
||||
|
@ -239,9 +235,9 @@ impl AttrAnnotatedTokenStream {
|
|||
// Check the last two trees (to account for a trailing semi)
|
||||
for tree in target_tokens.iter_mut().rev().take(2) {
|
||||
if let TokenTree::Delimited(span, delim, delim_tokens) = tree {
|
||||
// Inner attributes are only supported on extern blocks, functions, impls,
|
||||
// and modules. All of these have their inner attributes placed at
|
||||
// the beginning of the rightmost outermost braced group:
|
||||
// Inner attributes are only supported on extern blocks, functions,
|
||||
// impls, and modules. All of these have their inner attributes
|
||||
// placed at the beginning of the rightmost outermost braced group:
|
||||
// e.g. fn foo() { #![my_attr} }
|
||||
//
|
||||
// Therefore, we can insert them back into the right location
|
||||
|
@ -255,7 +251,7 @@ impl AttrAnnotatedTokenStream {
|
|||
|
||||
let mut builder = TokenStreamBuilder::new();
|
||||
for inner_attr in inner_attrs {
|
||||
builder.push(inner_attr.tokens().to_tokenstream());
|
||||
builder.push(inner_attr.tokens());
|
||||
}
|
||||
builder.push(delim_tokens.clone());
|
||||
*tree = TokenTree::Delimited(*span, *delim, builder.build());
|
||||
|
@ -273,7 +269,7 @@ impl AttrAnnotatedTokenStream {
|
|||
let mut flat: SmallVec<[_; 1]> = SmallVec::new();
|
||||
for attr in outer_attrs {
|
||||
// FIXME: Make this more efficient
|
||||
flat.extend(attr.tokens().to_tokenstream().0.clone().iter().cloned());
|
||||
flat.extend(attr.tokens().0.clone().iter().cloned());
|
||||
}
|
||||
flat.extend(target_tokens);
|
||||
flat.into_iter()
|
||||
|
@ -300,7 +296,7 @@ pub struct AttributesData {
|
|||
pub attrs: AttrVec,
|
||||
/// The underlying tokens for the attribute target that `attrs`
|
||||
/// are applied to
|
||||
pub tokens: LazyTokenStream,
|
||||
pub tokens: LazyAttrTokenStream,
|
||||
}
|
||||
|
||||
/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
|
||||
|
@ -363,12 +359,6 @@ impl TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<(AttrAnnotatedTokenTree, Spacing)> for AttrAnnotatedTokenStream {
|
||||
fn from((tree, spacing): (AttrAnnotatedTokenTree, Spacing)) -> AttrAnnotatedTokenStream {
|
||||
AttrAnnotatedTokenStream::new(vec![(tree, spacing)])
|
||||
}
|
||||
}
|
||||
|
||||
impl iter::FromIterator<TokenTree> for TokenStream {
|
||||
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
|
||||
TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
|
||||
|
@ -420,21 +410,6 @@ impl TokenStream {
|
|||
TokenStream(Lrc::new(self.0.iter().enumerate().map(|(i, tree)| f(i, tree)).collect()))
|
||||
}
|
||||
|
||||
fn opt_from_ast(node: &(impl HasAttrs + HasTokens)) -> Option<TokenStream> {
|
||||
let tokens = node.tokens()?;
|
||||
let attrs = node.attrs();
|
||||
let attr_annotated = if attrs.is_empty() {
|
||||
tokens.create_token_stream()
|
||||
} else {
|
||||
let attr_data = AttributesData { attrs: attrs.to_vec().into(), tokens: tokens.clone() };
|
||||
AttrAnnotatedTokenStream::new(vec![(
|
||||
AttrAnnotatedTokenTree::Attributes(attr_data),
|
||||
Spacing::Alone,
|
||||
)])
|
||||
};
|
||||
Some(attr_annotated.to_tokenstream())
|
||||
}
|
||||
|
||||
// Create a token stream containing a single token with alone spacing.
|
||||
pub fn token_alone(kind: TokenKind, span: Span) -> TokenStream {
|
||||
TokenStream::new(vec![TokenTree::token_alone(kind, span)])
|
||||
|
@ -451,8 +426,18 @@ impl TokenStream {
|
|||
}
|
||||
|
||||
pub fn from_ast(node: &(impl HasAttrs + HasSpan + HasTokens + fmt::Debug)) -> TokenStream {
|
||||
TokenStream::opt_from_ast(node)
|
||||
.unwrap_or_else(|| panic!("missing tokens for node at {:?}: {:?}", node.span(), node))
|
||||
let Some(tokens) = node.tokens() else {
|
||||
panic!("missing tokens for node at {:?}: {:?}", node.span(), node);
|
||||
};
|
||||
let attrs = node.attrs();
|
||||
let attr_stream = if attrs.is_empty() {
|
||||
tokens.to_attr_token_stream()
|
||||
} else {
|
||||
let attr_data =
|
||||
AttributesData { attrs: attrs.iter().cloned().collect(), tokens: tokens.clone() };
|
||||
AttrTokenStream::new(vec![AttrTokenTree::Attributes(attr_data)])
|
||||
};
|
||||
attr_stream.to_tokenstream()
|
||||
}
|
||||
|
||||
pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
|
||||
|
@ -555,7 +540,7 @@ impl TokenStreamBuilder {
|
|||
|
||||
// Get the first stream, which will become the result stream.
|
||||
// If it's `None`, create an empty stream.
|
||||
let mut iter = streams.drain(..);
|
||||
let mut iter = streams.into_iter();
|
||||
let mut res_stream_lrc = iter.next().unwrap().0;
|
||||
|
||||
// Append the subsequent elements to the result stream, after
|
||||
|
|
|
@ -9,7 +9,6 @@ use rustc_span::symbol::{kw, sym, Symbol};
|
|||
use rustc_span::Span;
|
||||
|
||||
use std::ascii;
|
||||
use tracing::debug;
|
||||
|
||||
pub enum LitError {
|
||||
NotLiteral,
|
||||
|
@ -164,12 +163,7 @@ impl LitKind {
|
|||
}
|
||||
LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None),
|
||||
LitKind::ByteStr(ref bytes) => {
|
||||
let string = bytes
|
||||
.iter()
|
||||
.cloned()
|
||||
.flat_map(ascii::escape_default)
|
||||
.map(Into::<char>::into)
|
||||
.collect::<String>();
|
||||
let string = bytes.escape_ascii().to_string();
|
||||
(token::ByteStr, Symbol::intern(&string), None)
|
||||
}
|
||||
LitKind::Byte(byte) => {
|
||||
|
|
|
@ -297,11 +297,11 @@ impl ExprPrecedence {
|
|||
match self {
|
||||
ExprPrecedence::Closure => PREC_CLOSURE,
|
||||
|
||||
ExprPrecedence::Break |
|
||||
ExprPrecedence::Continue |
|
||||
ExprPrecedence::Ret |
|
||||
ExprPrecedence::Yield |
|
||||
ExprPrecedence::Yeet => PREC_JUMP,
|
||||
ExprPrecedence::Break
|
||||
| ExprPrecedence::Continue
|
||||
| ExprPrecedence::Ret
|
||||
| ExprPrecedence::Yield
|
||||
| ExprPrecedence::Yeet => PREC_JUMP,
|
||||
|
||||
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
|
||||
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
|
||||
|
@ -318,43 +318,43 @@ impl ExprPrecedence {
|
|||
ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
|
||||
|
||||
// Unary, prefix
|
||||
ExprPrecedence::Box |
|
||||
ExprPrecedence::AddrOf |
|
||||
ExprPrecedence::Box
|
||||
| ExprPrecedence::AddrOf
|
||||
// Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`.
|
||||
// However, this is not exactly right. When `let _ = a` is the LHS of a binop we
|
||||
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
|
||||
// but we need to print `(let _ = a) < b` as-is with parens.
|
||||
ExprPrecedence::Let |
|
||||
ExprPrecedence::Unary => PREC_PREFIX,
|
||||
| ExprPrecedence::Let
|
||||
| ExprPrecedence::Unary => PREC_PREFIX,
|
||||
|
||||
// Unary, postfix
|
||||
ExprPrecedence::Await |
|
||||
ExprPrecedence::Call |
|
||||
ExprPrecedence::MethodCall |
|
||||
ExprPrecedence::Field |
|
||||
ExprPrecedence::Index |
|
||||
ExprPrecedence::Try |
|
||||
ExprPrecedence::InlineAsm |
|
||||
ExprPrecedence::Mac => PREC_POSTFIX,
|
||||
ExprPrecedence::Await
|
||||
| ExprPrecedence::Call
|
||||
| ExprPrecedence::MethodCall
|
||||
| ExprPrecedence::Field
|
||||
| ExprPrecedence::Index
|
||||
| ExprPrecedence::Try
|
||||
| ExprPrecedence::InlineAsm
|
||||
| ExprPrecedence::Mac => PREC_POSTFIX,
|
||||
|
||||
// Never need parens
|
||||
ExprPrecedence::Array |
|
||||
ExprPrecedence::Repeat |
|
||||
ExprPrecedence::Tup |
|
||||
ExprPrecedence::Lit |
|
||||
ExprPrecedence::Path |
|
||||
ExprPrecedence::Paren |
|
||||
ExprPrecedence::If |
|
||||
ExprPrecedence::While |
|
||||
ExprPrecedence::ForLoop |
|
||||
ExprPrecedence::Loop |
|
||||
ExprPrecedence::Match |
|
||||
ExprPrecedence::ConstBlock |
|
||||
ExprPrecedence::Block |
|
||||
ExprPrecedence::TryBlock |
|
||||
ExprPrecedence::Async |
|
||||
ExprPrecedence::Struct |
|
||||
ExprPrecedence::Err => PREC_PAREN,
|
||||
ExprPrecedence::Array
|
||||
| ExprPrecedence::Repeat
|
||||
| ExprPrecedence::Tup
|
||||
| ExprPrecedence::Lit
|
||||
| ExprPrecedence::Path
|
||||
| ExprPrecedence::Paren
|
||||
| ExprPrecedence::If
|
||||
| ExprPrecedence::While
|
||||
| ExprPrecedence::ForLoop
|
||||
| ExprPrecedence::Loop
|
||||
| ExprPrecedence::Match
|
||||
| ExprPrecedence::ConstBlock
|
||||
| ExprPrecedence::Block
|
||||
| ExprPrecedence::TryBlock
|
||||
| ExprPrecedence::Async
|
||||
| ExprPrecedence::Struct
|
||||
| ExprPrecedence::Err => PREC_PAREN,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,8 +156,8 @@ pub trait Visitor<'ast>: Sized {
|
|||
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
|
||||
walk_where_predicate(self, p)
|
||||
}
|
||||
fn visit_fn(&mut self, fk: FnKind<'ast>, s: Span, _: NodeId) {
|
||||
walk_fn(self, fk, s)
|
||||
fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) {
|
||||
walk_fn(self, fk)
|
||||
}
|
||||
fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) {
|
||||
walk_assoc_item(self, i, ctxt)
|
||||
|
@ -201,11 +201,11 @@ pub trait Visitor<'ast>: Sized {
|
|||
fn visit_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId, _nested: bool) {
|
||||
walk_use_tree(self, use_tree, id)
|
||||
}
|
||||
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
|
||||
walk_path_segment(self, path_span, path_segment)
|
||||
fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
|
||||
walk_path_segment(self, path_segment)
|
||||
}
|
||||
fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) {
|
||||
walk_generic_args(self, path_span, generic_args)
|
||||
fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) {
|
||||
walk_generic_args(self, generic_args)
|
||||
}
|
||||
fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
|
||||
walk_generic_arg(self, generic_arg)
|
||||
|
@ -435,7 +435,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
|||
|
||||
pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) {
|
||||
for segment in &path.segments {
|
||||
visitor.visit_path_segment(path.span, segment);
|
||||
visitor.visit_path_segment(segment);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,18 +457,14 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(visitor: &mut V, use_tree: &'a UseTree,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn walk_path_segment<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
path_span: Span,
|
||||
segment: &'a PathSegment,
|
||||
) {
|
||||
pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, segment: &'a PathSegment) {
|
||||
visitor.visit_ident(segment.ident);
|
||||
if let Some(ref args) = segment.args {
|
||||
visitor.visit_generic_args(path_span, args);
|
||||
visitor.visit_generic_args(args);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_generic_args<'a, V>(visitor: &mut V, _path_span: Span, generic_args: &'a GenericArgs)
|
||||
pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs)
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
|
@ -502,7 +498,7 @@ where
|
|||
pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &'a AssocConstraint) {
|
||||
visitor.visit_ident(constraint.ident);
|
||||
if let Some(ref gen_args) = constraint.gen_args {
|
||||
visitor.visit_generic_args(gen_args.span(), gen_args);
|
||||
visitor.visit_generic_args(gen_args);
|
||||
}
|
||||
match constraint.kind {
|
||||
AssocConstraintKind::Equality { ref term } => match term {
|
||||
|
@ -659,7 +655,7 @@ pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &
|
|||
visitor.visit_fn_ret_ty(&function_declaration.output);
|
||||
}
|
||||
|
||||
pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) {
|
||||
pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) {
|
||||
match kind {
|
||||
FnKind::Fn(_, _, sig, _, generics, body) => {
|
||||
visitor.visit_generics(generics);
|
||||
|
@ -800,7 +796,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||
walk_list!(visitor, visit_expr, arguments);
|
||||
}
|
||||
ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _span) => {
|
||||
visitor.visit_path_segment(expression.span, segment);
|
||||
visitor.visit_path_segment(segment);
|
||||
visitor.visit_expr(receiver);
|
||||
walk_list!(visitor, visit_expr, arguments);
|
||||
}
|
||||
|
|
|
@ -8,17 +8,18 @@ doctest = false
|
|||
|
||||
[dependencies]
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
tracing = "0.1"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
thin-vec = "0.2.8"
|
||||
tracing = "0.1"
|
||||
|
|
|
@ -155,26 +155,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let op = match *op {
|
||||
InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
|
||||
reg: lower_reg(reg),
|
||||
expr: self.lower_expr_mut(expr),
|
||||
expr: self.lower_expr(expr),
|
||||
},
|
||||
InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
|
||||
reg: lower_reg(reg),
|
||||
late,
|
||||
expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
|
||||
expr: expr.as_ref().map(|expr| self.lower_expr(expr)),
|
||||
},
|
||||
InlineAsmOperand::InOut { reg, late, ref expr } => {
|
||||
hir::InlineAsmOperand::InOut {
|
||||
reg: lower_reg(reg),
|
||||
late,
|
||||
expr: self.lower_expr_mut(expr),
|
||||
expr: self.lower_expr(expr),
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
|
||||
hir::InlineAsmOperand::SplitInOut {
|
||||
reg: lower_reg(reg),
|
||||
late,
|
||||
in_expr: self.lower_expr_mut(in_expr),
|
||||
out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
|
||||
in_expr: self.lower_expr(in_expr),
|
||||
out_expr: out_expr.as_ref().map(|expr| self.lower_expr(expr)),
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::Const { ref anon_const } => {
|
||||
|
@ -220,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&sym.qself,
|
||||
&sym.path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
hir::InlineAsmOperand::SymStatic { path, def_id }
|
||||
} else {
|
||||
|
@ -237,7 +237,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// Wrap the expression in an AnonConst.
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let node_id = self.next_node_id();
|
||||
self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
|
||||
self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
|
||||
let anon_const = AnonConst { id: node_id, value: P(expr) };
|
||||
hir::InlineAsmOperand::SymFn {
|
||||
anon_const: self.lower_anon_const(&anon_const),
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
|
||||
use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};
|
||||
use rustc_hir as hir;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::sym;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -87,20 +85,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let ty = l
|
||||
.ty
|
||||
.as_ref()
|
||||
.map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable)));
|
||||
.map(|t| self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Variable)));
|
||||
let init = l.kind.init().map(|init| self.lower_expr(init));
|
||||
let hir_id = self.lower_node_id(l.id);
|
||||
let pat = self.lower_pat(&l.pat);
|
||||
let els = if let LocalKind::InitElse(_, els) = &l.kind {
|
||||
if !self.tcx.features().let_else {
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::let_else,
|
||||
l.span,
|
||||
"`let...else` statements are unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
Some(self.lower_block(els, false))
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay};
|
||||
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
|
||||
use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")]
|
||||
pub struct GenericTypeWithParentheses {
|
||||
#[primary_span]
|
||||
|
@ -18,7 +18,7 @@ pub struct UseAngleBrackets {
|
|||
pub close_param: Span,
|
||||
}
|
||||
|
||||
impl AddSubdiagnostic for UseAngleBrackets {
|
||||
impl AddToDiagnostic for UseAngleBrackets {
|
||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
||||
diag.multipart_suggestion(
|
||||
fluent::ast_lowering::use_angle_brackets,
|
||||
|
@ -28,18 +28,32 @@ impl AddSubdiagnostic for UseAngleBrackets {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[help]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering::invalid_abi, code = "E0703")]
|
||||
#[note]
|
||||
pub struct InvalidAbi {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub abi: Symbol,
|
||||
pub valid_abis: String,
|
||||
pub command: String,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: Option<InvalidAbiSuggestion>,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
ast_lowering::invalid_abi_suggestion,
|
||||
code = "{suggestion}",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
pub struct InvalidAbiSuggestion {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub suggestion: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::assoc_ty_parentheses)]
|
||||
pub struct AssocTyParentheses {
|
||||
#[primary_span]
|
||||
|
@ -54,7 +68,7 @@ pub enum AssocTyParenthesesSub {
|
|||
NotEmpty { open_param: Span, close_param: Span },
|
||||
}
|
||||
|
||||
impl AddSubdiagnostic for AssocTyParenthesesSub {
|
||||
impl AddToDiagnostic for AssocTyParenthesesSub {
|
||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
||||
match self {
|
||||
Self::Empty { parentheses_span } => diag.multipart_suggestion(
|
||||
|
@ -71,7 +85,7 @@ impl AddSubdiagnostic for AssocTyParenthesesSub {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering::misplaced_impl_trait, code = "E0562")]
|
||||
pub struct MisplacedImplTrait<'a> {
|
||||
#[primary_span]
|
||||
|
@ -79,14 +93,14 @@ pub struct MisplacedImplTrait<'a> {
|
|||
pub position: DiagnosticArgFromDisplay<'a>,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::rustc_box_attribute_error)]
|
||||
pub struct RustcBoxAttributeError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::underscore_expr_lhs_assign)]
|
||||
pub struct UnderscoreExprLhsAssign {
|
||||
#[primary_span]
|
||||
|
@ -94,7 +108,7 @@ pub struct UnderscoreExprLhsAssign {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::base_expression_double_dot)]
|
||||
pub struct BaseExpressionDoubleDot {
|
||||
#[primary_span]
|
||||
|
@ -102,7 +116,7 @@ pub struct BaseExpressionDoubleDot {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::await_only_in_async_fn_and_blocks, code = "E0728")]
|
||||
pub struct AwaitOnlyInAsyncFnAndBlocks {
|
||||
#[primary_span]
|
||||
|
@ -112,21 +126,21 @@ pub struct AwaitOnlyInAsyncFnAndBlocks {
|
|||
pub item_span: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")]
|
||||
pub struct GeneratorTooManyParameters {
|
||||
#[primary_span]
|
||||
pub fn_decl_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::closure_cannot_be_static, code = "E0697")]
|
||||
pub struct ClosureCannotBeStatic {
|
||||
#[primary_span]
|
||||
pub fn_decl_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[help]
|
||||
#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")]
|
||||
pub struct AsyncNonMoveClosureNotSupported {
|
||||
|
@ -134,7 +148,7 @@ pub struct AsyncNonMoveClosureNotSupported {
|
|||
pub fn_decl_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::functional_record_update_destructuring_assignment)]
|
||||
pub struct FunctionalRecordUpdateDestructuringAssignemnt {
|
||||
#[primary_span]
|
||||
|
@ -142,28 +156,28 @@ pub struct FunctionalRecordUpdateDestructuringAssignemnt {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::async_generators_not_supported, code = "E0727")]
|
||||
pub struct AsyncGeneratorsNotSupported {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::inline_asm_unsupported_target, code = "E0472")]
|
||||
pub struct InlineAsmUnsupportedTarget {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::att_syntax_only_x86)]
|
||||
pub struct AttSyntaxOnlyX86 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::abi_specified_multiple_times)]
|
||||
pub struct AbiSpecifiedMultipleTimes {
|
||||
#[primary_span]
|
||||
|
@ -175,14 +189,14 @@ pub struct AbiSpecifiedMultipleTimes {
|
|||
pub equivalent: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::clobber_abi_not_supported)]
|
||||
pub struct ClobberAbiNotSupported {
|
||||
#[primary_span]
|
||||
pub abi_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[note]
|
||||
#[diag(ast_lowering::invalid_abi_clobber_abi)]
|
||||
pub struct InvalidAbiClobberAbi {
|
||||
|
@ -191,7 +205,7 @@ pub struct InvalidAbiClobberAbi {
|
|||
pub supported_abis: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::invalid_register)]
|
||||
pub struct InvalidRegister<'a> {
|
||||
#[primary_span]
|
||||
|
@ -200,7 +214,7 @@ pub struct InvalidRegister<'a> {
|
|||
pub error: &'a str,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::invalid_register_class)]
|
||||
pub struct InvalidRegisterClass<'a> {
|
||||
#[primary_span]
|
||||
|
@ -209,7 +223,7 @@ pub struct InvalidRegisterClass<'a> {
|
|||
pub error: &'a str,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)]
|
||||
pub struct InvalidAsmTemplateModifierRegClass {
|
||||
#[primary_span]
|
||||
|
@ -221,7 +235,7 @@ pub struct InvalidAsmTemplateModifierRegClass {
|
|||
pub sub: InvalidAsmTemplateModifierRegClassSub,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum InvalidAsmTemplateModifierRegClassSub {
|
||||
#[note(ast_lowering::support_modifiers)]
|
||||
SupportModifier { class_name: Symbol, modifiers: String },
|
||||
|
@ -229,7 +243,7 @@ pub enum InvalidAsmTemplateModifierRegClassSub {
|
|||
DoesNotSupportModifier { class_name: Symbol },
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::invalid_asm_template_modifier_const)]
|
||||
pub struct InvalidAsmTemplateModifierConst {
|
||||
#[primary_span]
|
||||
|
@ -239,7 +253,7 @@ pub struct InvalidAsmTemplateModifierConst {
|
|||
pub op_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::invalid_asm_template_modifier_sym)]
|
||||
pub struct InvalidAsmTemplateModifierSym {
|
||||
#[primary_span]
|
||||
|
@ -249,7 +263,7 @@ pub struct InvalidAsmTemplateModifierSym {
|
|||
pub op_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::register_class_only_clobber)]
|
||||
pub struct RegisterClassOnlyClobber {
|
||||
#[primary_span]
|
||||
|
@ -257,7 +271,7 @@ pub struct RegisterClassOnlyClobber {
|
|||
pub reg_class_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::register_conflict)]
|
||||
pub struct RegisterConflict<'a> {
|
||||
#[primary_span]
|
||||
|
@ -271,7 +285,7 @@ pub struct RegisterConflict<'a> {
|
|||
pub in_out: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[help]
|
||||
#[diag(ast_lowering::sub_tuple_binding)]
|
||||
pub struct SubTupleBinding<'a> {
|
||||
|
@ -288,7 +302,7 @@ pub struct SubTupleBinding<'a> {
|
|||
pub ctx: &'a str,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::extra_double_dot)]
|
||||
pub struct ExtraDoubleDot<'a> {
|
||||
#[primary_span]
|
||||
|
@ -299,7 +313,7 @@ pub struct ExtraDoubleDot<'a> {
|
|||
pub ctx: &'a str,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[note]
|
||||
#[diag(ast_lowering::misplaced_double_dot)]
|
||||
pub struct MisplacedDoubleDot {
|
||||
|
@ -307,30 +321,41 @@ pub struct MisplacedDoubleDot {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::misplaced_relax_trait_bound)]
|
||||
pub struct MisplacedRelaxTraitBound {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::not_supported_for_lifetime_binder_async_closure)]
|
||||
pub struct NotSupportedForLifetimeBinderAsyncClosure {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::arbitrary_expression_in_pattern)]
|
||||
pub struct ArbitraryExpressionInPattern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic, Clone, Copy)]
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::inclusive_range_with_no_end)]
|
||||
pub struct InclusiveRangeWithNoEnd {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::trait_fn_async, code = "E0706")]
|
||||
#[note]
|
||||
#[note(ast_lowering::note2)]
|
||||
pub struct TraitFnAsync {
|
||||
#[primary_span]
|
||||
pub fn_span: Span,
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use super::errors::{
|
|||
use super::ResolverAstLoweringExt;
|
||||
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
|
||||
use crate::{FnDeclKind, ImplTraitPosition};
|
||||
|
||||
use rustc_ast::attr;
|
||||
use rustc_ast::ptr::P as AstP;
|
||||
use rustc_ast::*;
|
||||
|
@ -18,6 +17,7 @@ use rustc_hir::definitions::DefPathData;
|
|||
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
|
||||
|
@ -66,12 +66,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
seg,
|
||||
ParamMode::Optional,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
));
|
||||
let args = self.arena.alloc_from_iter(
|
||||
[&*receiver].into_iter().chain(args.iter()).map(|x| self.lower_expr_mut(x)),
|
||||
);
|
||||
hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span))
|
||||
let receiver = self.lower_expr(receiver);
|
||||
let args =
|
||||
self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));
|
||||
hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span))
|
||||
}
|
||||
ExprKind::Binary(binop, ref lhs, ref rhs) => {
|
||||
let binop = self.lower_binop(binop);
|
||||
|
@ -90,13 +90,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ExprKind::Cast(ref expr, ref ty) => {
|
||||
let expr = self.lower_expr(expr);
|
||||
let ty =
|
||||
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
hir::ExprKind::Cast(expr, ty)
|
||||
}
|
||||
ExprKind::Type(ref expr, ref ty) => {
|
||||
let expr = self.lower_expr(expr);
|
||||
let ty =
|
||||
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
hir::ExprKind::Type(expr, ty)
|
||||
}
|
||||
ExprKind::AddrOf(k, m, ref ohs) => {
|
||||
|
@ -146,13 +146,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
|
||||
),
|
||||
ExprKind::Await(ref expr) => {
|
||||
let span = if expr.span.hi() < e.span.hi() {
|
||||
expr.span.shrink_to_hi().with_hi(e.span.hi())
|
||||
let dot_await_span = if expr.span.hi() < e.span.hi() {
|
||||
let span_with_whitespace = self
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_extend_while(expr.span, char::is_whitespace)
|
||||
.unwrap_or(expr.span);
|
||||
span_with_whitespace.shrink_to_hi().with_hi(e.span.hi())
|
||||
} else {
|
||||
// this is a recovered `await expr`
|
||||
e.span
|
||||
};
|
||||
self.lower_expr_await(span, expr)
|
||||
self.lower_expr_await(dot_await_span, expr)
|
||||
}
|
||||
ExprKind::Closure(
|
||||
ref binder,
|
||||
|
@ -219,7 +225,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
qself,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
hir::ExprKind::Path(qpath)
|
||||
}
|
||||
|
@ -253,7 +259,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&se.qself,
|
||||
&se.path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
)),
|
||||
self.arena
|
||||
.alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
|
||||
|
@ -353,7 +359,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let node_id = self.next_node_id();
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
|
||||
self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
|
||||
|
||||
let anon_const = AnonConst { id: node_id, value: arg };
|
||||
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
|
||||
|
@ -552,7 +558,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
) -> hir::ExprKind<'hir> {
|
||||
let output = match ret_ty {
|
||||
Some(ty) => hir::FnRetTy::Return(
|
||||
self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)),
|
||||
self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)),
|
||||
),
|
||||
None => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
|
||||
};
|
||||
|
@ -577,7 +583,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (pat, task_context_hid) = self.pat_ident_binding_mode(
|
||||
span,
|
||||
Ident::with_dummy_span(sym::_task_context),
|
||||
hir::BindingAnnotation::Mutable,
|
||||
hir::BindingAnnotation::MUT,
|
||||
);
|
||||
let param = hir::Param {
|
||||
hir_id: self.next_id(),
|
||||
|
@ -671,7 +677,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// this name to identify what is being awaited by a suspended async functions.
|
||||
let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
|
||||
let (awaitee_pat, awaitee_pat_hid) =
|
||||
self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::Mutable);
|
||||
self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT);
|
||||
|
||||
let task_context_ident = Ident::with_dummy_span(sym::_task_context);
|
||||
|
||||
|
@ -849,7 +855,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
||||
// Lower outside new scope to preserve `is_in_loop_condition`.
|
||||
let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
|
||||
let fn_decl = self.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);
|
||||
|
||||
let c = self.arena.alloc(hir::Closure {
|
||||
binder: binder_clause,
|
||||
|
@ -949,11 +955,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
});
|
||||
|
||||
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
||||
|
||||
// We need to lower the declaration outside the new scope, because we
|
||||
// have to conserve the state of being inside a loop condition for the
|
||||
// closure argument types.
|
||||
let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
|
||||
let fn_decl =
|
||||
self.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);
|
||||
|
||||
let c = self.arena.alloc(hir::Closure {
|
||||
binder: binder_clause,
|
||||
|
@ -1123,11 +1129,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
qself,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
// Destructure like a tuple struct.
|
||||
let tuple_struct_pat =
|
||||
hir::PatKind::TupleStruct(qpath, pats, rest.map(|r| r.0));
|
||||
let tuple_struct_pat = hir::PatKind::TupleStruct(
|
||||
qpath,
|
||||
pats,
|
||||
hir::DotDotPos::new(rest.map(|r| r.0)),
|
||||
);
|
||||
return self.pat_without_dbm(lhs.span, tuple_struct_pat);
|
||||
}
|
||||
}
|
||||
|
@ -1139,7 +1148,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
qself,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
// Destructure like a unit struct.
|
||||
let unit_struct_pat = hir::PatKind::Path(qpath);
|
||||
|
@ -1163,7 +1172,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&se.qself,
|
||||
&se.path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
let fields_omitted = match &se.rest {
|
||||
StructRest::Base(e) => {
|
||||
|
@ -1182,13 +1191,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ExprKind::Tup(elements) => {
|
||||
let (pats, rest) =
|
||||
self.destructure_sequence(elements, "tuple", eq_sign_span, assignments);
|
||||
let tuple_pat = hir::PatKind::Tuple(pats, rest.map(|r| r.0));
|
||||
let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0)));
|
||||
return self.pat_without_dbm(lhs.span, tuple_pat);
|
||||
}
|
||||
ExprKind::Paren(e) => {
|
||||
// We special-case `(..)` for consistency with patterns.
|
||||
if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {
|
||||
let tuple_pat = hir::PatKind::Tuple(&[], Some(0));
|
||||
let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0)));
|
||||
return self.pat_without_dbm(lhs.span, tuple_pat);
|
||||
} else {
|
||||
return self.destructure_assign_mut(e, eq_sign_span, assignments);
|
||||
|
@ -1433,7 +1442,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// `mut iter`
|
||||
let iter = Ident::with_dummy_span(sym::iter);
|
||||
let (iter_pat, iter_pat_nid) =
|
||||
self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::Mutable);
|
||||
self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT);
|
||||
|
||||
// `match Iterator::next(&mut iter) { ... }`
|
||||
let match_expr = {
|
||||
|
@ -1539,9 +1548,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let uc_nested = attr::mk_nested_word_item(uc_ident);
|
||||
attr::mk_list_item(allow_ident, vec![uc_nested])
|
||||
};
|
||||
attr::mk_attr_outer(allow)
|
||||
attr::mk_attr_outer(&self.tcx.sess.parse_sess.attr_id_generator, allow)
|
||||
};
|
||||
let attrs: AttrVec = vec![attr].into();
|
||||
let attrs: AttrVec = thin_vec![attr];
|
||||
|
||||
// `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
|
||||
let continue_arm = {
|
||||
|
@ -1776,12 +1785,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
binding: hir::HirId,
|
||||
attrs: AttrVec,
|
||||
) -> hir::Expr<'hir> {
|
||||
let hir_id = self.next_id();
|
||||
let res = Res::Local(binding);
|
||||
let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
self.arena.alloc(hir::Path {
|
||||
span: self.lower_span(span),
|
||||
res: Res::Local(binding),
|
||||
segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
|
||||
res,
|
||||
segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)],
|
||||
}),
|
||||
));
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@ use rustc_session::Session;
|
|||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use tracing::debug;
|
||||
|
||||
/// A visitor that walks over the HIR and collects `Node`s into a HIR map.
|
||||
pub(super) struct NodeCollector<'a, 'hir> {
|
||||
/// Source map
|
||||
|
@ -26,12 +24,12 @@ pub(super) struct NodeCollector<'a, 'hir> {
|
|||
/// The parent of this node
|
||||
parent_node: hir::ItemLocalId,
|
||||
|
||||
owner: LocalDefId,
|
||||
owner: OwnerId,
|
||||
|
||||
definitions: &'a definitions::Definitions,
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(sess, definitions, bodies))]
|
||||
#[instrument(level = "debug", skip(sess, definitions, bodies))]
|
||||
pub(super) fn index_hir<'hir>(
|
||||
sess: &Session,
|
||||
definitions: &definitions::Definitions,
|
||||
|
@ -67,10 +65,11 @@ pub(super) fn index_hir<'hir>(
|
|||
}
|
||||
|
||||
impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
|
||||
debug_assert_eq!(self.owner, hir_id.owner);
|
||||
debug_assert_ne!(hir_id.local_id.as_u32(), 0);
|
||||
debug_assert_ne!(hir_id.local_id, self.parent_node);
|
||||
|
||||
// Make sure that the DepNode of some node coincides with the HirId
|
||||
// owner of that node.
|
||||
|
@ -82,9 +81,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
|||
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
|
||||
self.source_map.span_to_diagnostic_string(span),
|
||||
node,
|
||||
self.definitions.def_path(self.owner).to_string_no_crate_verbose(),
|
||||
self.definitions.def_path(self.owner.def_id).to_string_no_crate_verbose(),
|
||||
self.owner,
|
||||
self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(),
|
||||
self.definitions.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
|
||||
hir_id.owner,
|
||||
)
|
||||
}
|
||||
|
@ -113,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
|
||||
fn visit_nested_item(&mut self, item: ItemId) {
|
||||
debug!("visit_nested_item: {:?}", item);
|
||||
self.insert_nested(item.def_id);
|
||||
self.insert_nested(item.def_id.def_id);
|
||||
}
|
||||
|
||||
fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
|
||||
self.insert_nested(item_id.def_id);
|
||||
self.insert_nested(item_id.def_id.def_id);
|
||||
}
|
||||
|
||||
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
|
||||
self.insert_nested(item_id.def_id);
|
||||
self.insert_nested(item_id.def_id.def_id);
|
||||
}
|
||||
|
||||
fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
|
||||
self.insert_nested(foreign_id.def_id);
|
||||
self.insert_nested(foreign_id.def_id.def_id);
|
||||
}
|
||||
|
||||
fn visit_nested_body(&mut self, id: BodyId) {
|
||||
|
@ -142,7 +141,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn visit_item(&mut self, i: &'hir Item<'hir>) {
|
||||
debug_assert_eq!(i.def_id, self.owner);
|
||||
self.with_parent(i.hir_id(), |this| {
|
||||
|
@ -156,7 +155,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
|
||||
debug_assert_eq!(fi.def_id, self.owner);
|
||||
self.with_parent(fi.hir_id(), |this| {
|
||||
|
@ -175,7 +174,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
|
||||
debug_assert_eq!(ti.def_id, self.owner);
|
||||
self.with_parent(ti.hir_id(), |this| {
|
||||
|
@ -183,7 +182,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
|
||||
debug_assert_eq!(ii.def_id, self.owner);
|
||||
self.with_parent(ii.hir_id(), |this| {
|
||||
|
@ -247,11 +246,9 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment<'hir>) {
|
||||
if let Some(hir_id) = path_segment.hir_id {
|
||||
self.insert(path_span, hir_id, Node::PathSegment(path_segment));
|
||||
}
|
||||
intravisit::walk_path_segment(self, path_span, path_segment);
|
||||
fn visit_path_segment(&mut self, path_segment: &'hir PathSegment<'hir>) {
|
||||
self.insert(path_segment.ident.span, path_segment.hir_id, Node::PathSegment(path_segment));
|
||||
intravisit::walk_path_segment(self, path_segment);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'hir Ty<'hir>) {
|
||||
|
@ -283,12 +280,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
fk: intravisit::FnKind<'hir>,
|
||||
fd: &'hir FnDecl<'hir>,
|
||||
b: BodyId,
|
||||
s: Span,
|
||||
_: Span,
|
||||
id: HirId,
|
||||
) {
|
||||
assert_eq!(self.owner, id.owner);
|
||||
assert_eq!(self.parent_node, id.local_id);
|
||||
intravisit::walk_fn(self, fk, fd, b, s, id);
|
||||
intravisit::walk_fn(self, fk, fd, b, id);
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, block: &'hir Block<'hir>) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::errors::{InvalidAbi, MisplacedRelaxTraitBound};
|
||||
use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
|
||||
use super::ResolverAstLoweringExt;
|
||||
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
|
||||
use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition};
|
||||
use super::{FnDeclKind, LoweringContext, ParamMode};
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
|
@ -14,9 +14,10 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
|||
use rustc_hir::PredicateOrigin;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt};
|
||||
use rustc_span::lev_distance::find_best_match_for_name;
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::spec::abi;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
|
@ -25,6 +26,7 @@ use std::iter;
|
|||
pub(super) struct ItemLowerer<'a, 'hir> {
|
||||
pub(super) tcx: TyCtxt<'hir>,
|
||||
pub(super) resolver: &'a mut ResolverAstLowering,
|
||||
pub(super) ast_arena: &'a Arena<'static>,
|
||||
pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>,
|
||||
pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
|
||||
}
|
||||
|
@ -60,12 +62,13 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
tcx: self.tcx,
|
||||
resolver: self.resolver,
|
||||
arena: self.tcx.hir_arena,
|
||||
ast_arena: self.ast_arena,
|
||||
|
||||
// HirId handling.
|
||||
bodies: Vec::new(),
|
||||
attrs: SortedMap::default(),
|
||||
children: FxHashMap::default(),
|
||||
current_hir_id_owner: CRATE_DEF_ID,
|
||||
current_hir_id_owner: hir::CRATE_OWNER_ID,
|
||||
item_local_id_counter: hir::ItemLocalId::new(0),
|
||||
node_id_to_local_id: Default::default(),
|
||||
local_id_to_def_id: SortedMap::new(),
|
||||
|
@ -85,6 +88,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
|
||||
allow_gen_future: Some([sym::gen_future][..].into()),
|
||||
allow_into_future: Some([sym::into_future][..].into()),
|
||||
generics_def_id_map: Default::default(),
|
||||
};
|
||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||
|
||||
|
@ -120,7 +124,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
self.with_lctx(CRATE_NODE_ID, |lctx| {
|
||||
let module = lctx.lower_mod(&c.items, &c.spans);
|
||||
lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
|
||||
hir::OwnerNode::Crate(lctx.arena.alloc(module))
|
||||
hir::OwnerNode::Crate(module)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -158,18 +162,23 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
}
|
||||
|
||||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
pub(super) fn lower_mod(&mut self, items: &[P<Item>], spans: &ModSpans) -> hir::Mod<'hir> {
|
||||
hir::Mod {
|
||||
pub(super) fn lower_mod(
|
||||
&mut self,
|
||||
items: &[P<Item>],
|
||||
spans: &ModSpans,
|
||||
) -> &'hir hir::Mod<'hir> {
|
||||
self.arena.alloc(hir::Mod {
|
||||
spans: hir::ModSpans {
|
||||
inner_span: self.lower_span(spans.inner_span),
|
||||
inject_use_span: self.lower_span(spans.inject_use_span),
|
||||
},
|
||||
item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
|
||||
let mut node_ids = smallvec![hir::ItemId { def_id: self.local_def_id(i.id) }];
|
||||
let mut node_ids =
|
||||
smallvec![hir::ItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
|
||||
if let ItemKind::Use(ref use_tree) = &i.kind {
|
||||
self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
|
||||
}
|
||||
|
@ -185,7 +194,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
match tree.kind {
|
||||
UseTreeKind::Nested(ref nested_vec) => {
|
||||
for &(ref nested, id) in nested_vec {
|
||||
vec.push(hir::ItemId { def_id: self.local_def_id(id) });
|
||||
vec.push(hir::ItemId {
|
||||
def_id: hir::OwnerId { def_id: self.local_def_id(id) },
|
||||
});
|
||||
self.lower_item_id_use_tree(nested, id, vec);
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +205,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
for (_, &id) in
|
||||
iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
|
||||
{
|
||||
vec.push(hir::ItemId { def_id: self.local_def_id(id) });
|
||||
vec.push(hir::ItemId {
|
||||
def_id: hir::OwnerId { def_id: self.local_def_id(id) },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,10 +272,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let body_id =
|
||||
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
|
||||
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = this.lower_generics(generics, id, itctx, |this| {
|
||||
let mut itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
|
||||
let ret_id = asyncness.opt_return_id();
|
||||
this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id)
|
||||
this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id)
|
||||
});
|
||||
let sig = hir::FnSig {
|
||||
decl,
|
||||
|
@ -306,8 +319,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, ty) = self.lower_generics(
|
||||
&generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
|
||||
);
|
||||
hir::ItemKind::TyAlias(ty, generics)
|
||||
}
|
||||
|
@ -319,7 +332,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, ty) = self.lower_generics(
|
||||
&generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.arena.alloc(this.ty(span, hir::TyKind::Err)),
|
||||
);
|
||||
hir::ItemKind::TyAlias(ty, generics)
|
||||
|
@ -328,7 +341,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, variants) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
this.arena.alloc_from_iter(
|
||||
enum_definition.variants.iter().map(|x| this.lower_variant(x)),
|
||||
|
@ -341,7 +354,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, struct_def) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, struct_def),
|
||||
);
|
||||
hir::ItemKind::Struct(struct_def, generics)
|
||||
|
@ -350,7 +363,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, vdata) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, vdata),
|
||||
);
|
||||
hir::ItemKind::Union(vdata, generics)
|
||||
|
@ -378,18 +391,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// method, it will not be considered an in-band
|
||||
// lifetime to be added, but rather a reference to a
|
||||
// parent lifetime.
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let mut itctx = ImplTraitContext::Universal;
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
self.lower_generics(ast_generics, id, itctx, |this| {
|
||||
self.lower_generics(ast_generics, id, &mut itctx, |this| {
|
||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||
this.lower_trait_ref(
|
||||
trait_ref,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||
)
|
||||
});
|
||||
|
||||
let lowered_ty = this
|
||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
|
||||
(trait_ref, lowered_ty)
|
||||
});
|
||||
|
@ -428,11 +441,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, (unsafety, items, bounds)) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
let bounds = this.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
);
|
||||
let items = this.arena.alloc_from_iter(
|
||||
items.iter().map(|item| this.lower_trait_item_ref(item)),
|
||||
|
@ -447,11 +460,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, bounds) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
)
|
||||
},
|
||||
);
|
||||
|
@ -474,7 +487,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
span: Span,
|
||||
body: Option<&Expr>,
|
||||
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
(ty, self.lower_const_body(span, body))
|
||||
}
|
||||
|
||||
|
@ -545,7 +558,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
let item = hir::Item {
|
||||
def_id: new_id,
|
||||
def_id: hir::OwnerId { def_id: new_id },
|
||||
ident: this.lower_ident(ident),
|
||||
kind,
|
||||
vis_span,
|
||||
|
@ -619,7 +632,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
let item = hir::Item {
|
||||
def_id: new_hir_id,
|
||||
def_id: hir::OwnerId { def_id: new_hir_id },
|
||||
ident: this.lower_ident(ident),
|
||||
kind,
|
||||
vis_span,
|
||||
|
@ -647,12 +660,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
kind: match i.kind {
|
||||
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
|
||||
let fdec = &sig.decl;
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let mut itctx = ImplTraitContext::Universal;
|
||||
let (generics, (fn_dec, fn_args)) =
|
||||
self.lower_generics(generics, i.id, itctx, |this| {
|
||||
self.lower_generics(generics, i.id, &mut itctx, |this| {
|
||||
(
|
||||
// Disallow `impl Trait` in foreign items.
|
||||
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
|
||||
this.lower_fn_decl(
|
||||
fdec,
|
||||
None,
|
||||
sig.span,
|
||||
FnDeclKind::ExternFn,
|
||||
None,
|
||||
),
|
||||
this.lower_fn_params_to_names(fdec),
|
||||
)
|
||||
});
|
||||
|
@ -661,7 +680,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
ForeignItemKind::Static(ref t, m, _) => {
|
||||
let ty =
|
||||
self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
hir::ForeignItemKind::Static(ty, m)
|
||||
}
|
||||
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
|
||||
|
@ -675,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
|
||||
hir::ForeignItemRef {
|
||||
id: hir::ForeignItemId { def_id: self.local_def_id(i.id) },
|
||||
id: hir::ForeignItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
|
||||
ident: self.lower_ident(i.ident),
|
||||
span: self.lower_span(i.span),
|
||||
}
|
||||
|
@ -729,11 +748,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
qself,
|
||||
path,
|
||||
ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
self.arena.alloc(t)
|
||||
} else {
|
||||
self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
|
||||
self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
|
||||
};
|
||||
let hir_id = self.lower_node_id(f.id);
|
||||
self.lower_attrs(hir_id, &f.attrs);
|
||||
|
@ -756,14 +775,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let (generics, kind, has_default) = match i.kind {
|
||||
AssocItemKind::Const(_, ref ty, ref default) => {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
|
||||
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
|
||||
let asyncness = sig.header.asyncness;
|
||||
let names = self.lower_fn_params_to_names(&sig.decl);
|
||||
let (generics, sig) =
|
||||
self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None);
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
generics,
|
||||
sig,
|
||||
i.id,
|
||||
FnDeclKind::Trait,
|
||||
asyncness.opt_return_id(),
|
||||
);
|
||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
|
||||
|
@ -791,15 +816,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (generics, kind) = self.lower_generics(
|
||||
&generics,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
let ty = ty.as_ref().map(|x| {
|
||||
this.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
|
||||
this.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
|
||||
});
|
||||
hir::TraitItemKind::Type(
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
ty,
|
||||
)
|
||||
|
@ -831,7 +856,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
AssocItemKind::MacCall(..) => unimplemented!(),
|
||||
};
|
||||
let id = hir::TraitItemId { def_id: self.local_def_id(i.id) };
|
||||
let id = hir::TraitItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
|
||||
hir::TraitItemRef {
|
||||
id,
|
||||
ident: self.lower_ident(i.ident),
|
||||
|
@ -852,7 +877,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let (generics, kind) = match &i.kind {
|
||||
AssocItemKind::Const(_, ty, expr) => {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
(
|
||||
hir::Generics::empty(),
|
||||
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
|
||||
|
@ -879,14 +904,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.lower_generics(
|
||||
&generics,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
None => {
|
||||
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err));
|
||||
hir::ImplItemKind::TyAlias(ty)
|
||||
}
|
||||
Some(ty) => {
|
||||
let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy);
|
||||
let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy);
|
||||
hir::ImplItemKind::TyAlias(ty)
|
||||
}
|
||||
},
|
||||
|
@ -911,7 +936,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
|
||||
hir::ImplItemRef {
|
||||
id: hir::ImplItemId { def_id: self.local_def_id(i.id) },
|
||||
id: hir::ImplItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
|
||||
ident: self.lower_ident(i.ident),
|
||||
span: self.lower_span(i.span),
|
||||
kind: match &i.kind {
|
||||
|
@ -947,7 +972,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
params: &'hir [hir::Param<'hir>],
|
||||
value: hir::Expr<'hir>,
|
||||
) -> hir::BodyId {
|
||||
let body = hir::Body { generator_kind: self.generator_kind, params, value };
|
||||
let body = hir::Body {
|
||||
generator_kind: self.generator_kind,
|
||||
params,
|
||||
value: self.arena.alloc(value),
|
||||
};
|
||||
let id = body.id();
|
||||
debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
|
||||
self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
|
||||
|
@ -1026,9 +1055,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
asyncness: Async,
|
||||
body: Option<&Block>,
|
||||
) -> hir::BodyId {
|
||||
let closure_id = match asyncness {
|
||||
Async::Yes { closure_id, .. } => closure_id,
|
||||
Async::No => return self.lower_fn_body_block(span, decl, body),
|
||||
let (closure_id, body) = match (asyncness, body) {
|
||||
(Async::Yes { closure_id, .. }, Some(body)) => (closure_id, body),
|
||||
_ => return self.lower_fn_body_block(span, decl, body),
|
||||
};
|
||||
|
||||
self.lower_body(|this| {
|
||||
|
@ -1074,12 +1103,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// Check if this is a binding pattern, if so, we can optimize and avoid adding a
|
||||
// `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
|
||||
let (ident, is_simple_parameter) = match parameter.pat.kind {
|
||||
hir::PatKind::Binding(
|
||||
hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
|
||||
_,
|
||||
ident,
|
||||
_,
|
||||
) => (ident, true),
|
||||
hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
|
||||
(ident, true)
|
||||
}
|
||||
// For `ref mut` or wildcard arguments, we can't reuse the binding, but
|
||||
// we can keep the same name for the parameter.
|
||||
// This lets rustdoc render it correctly in documentation.
|
||||
|
@ -1144,7 +1170,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (move_pat, move_id) = this.pat_ident_binding_mode(
|
||||
desugared_span,
|
||||
ident,
|
||||
hir::BindingAnnotation::Mutable,
|
||||
hir::BindingAnnotation::MUT,
|
||||
);
|
||||
let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id);
|
||||
let move_stmt = this.stmt_let_pat(
|
||||
|
@ -1173,16 +1199,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
parameters.push(new_parameter);
|
||||
}
|
||||
|
||||
let body_span = body.map_or(span, |b| b.span);
|
||||
let async_expr = this.make_async_expr(
|
||||
CaptureBy::Value,
|
||||
closure_id,
|
||||
None,
|
||||
body_span,
|
||||
body.span,
|
||||
hir::AsyncGeneratorKind::Fn,
|
||||
|this| {
|
||||
// Create a block from the user's function body:
|
||||
let user_body = this.lower_block_expr_opt(body_span, body);
|
||||
let user_body = this.lower_block_expr(body);
|
||||
|
||||
// Transform into `drop-temps { <user-body> }`, an expression:
|
||||
let desugared_span =
|
||||
|
@ -1214,7 +1239,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
(
|
||||
this.arena.alloc_from_iter(parameters),
|
||||
this.expr(body_span, async_expr, AttrVec::new()),
|
||||
this.expr(body.span, async_expr, AttrVec::new()),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -1225,12 +1250,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
sig: &FnSig,
|
||||
id: NodeId,
|
||||
kind: FnDeclKind,
|
||||
is_async: Option<NodeId>,
|
||||
is_async: Option<(NodeId, Span)>,
|
||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||
let header = self.lower_fn_header(sig.header);
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, Some(id), kind, is_async)
|
||||
let mut itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async)
|
||||
});
|
||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||
}
|
||||
|
@ -1260,10 +1285,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
fn error_on_invalid_abi(&self, abi: StrLit) {
|
||||
let abi_names = abi::enabled_names(self.tcx.features(), abi.span)
|
||||
.iter()
|
||||
.map(|s| Symbol::intern(s))
|
||||
.collect::<Vec<_>>();
|
||||
let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
|
||||
self.tcx.sess.emit_err(InvalidAbi {
|
||||
abi: abi.symbol_unescaped,
|
||||
span: abi.span,
|
||||
abi: abi.symbol,
|
||||
valid_abis: abi::all_names().join(", "),
|
||||
suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
|
||||
span: abi.span,
|
||||
suggestion: format!("\"{suggested_name}\""),
|
||||
}),
|
||||
command: "rustc --print=calling-conventions".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1295,7 +1329,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&mut self,
|
||||
generics: &Generics,
|
||||
parent_node_id: NodeId,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
) -> (&'hir hir::Generics<'hir>, T) {
|
||||
debug_assert!(self.impl_trait_defs.is_empty());
|
||||
|
@ -1400,7 +1434,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
id: NodeId,
|
||||
kind: &GenericParamKind,
|
||||
bounds: &[GenericBound],
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
origin: PredicateOrigin,
|
||||
) -> Option<hir::WherePredicate<'hir>> {
|
||||
// Do not create a clause if we do not have anything inside it.
|
||||
|
@ -1431,10 +1465,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
GenericParamKind::Const { .. } => None,
|
||||
GenericParamKind::Type { .. } => {
|
||||
let def_id = self.local_def_id(id).to_def_id();
|
||||
let hir_id = self.next_id();
|
||||
let res = Res::Def(DefKind::TyParam, def_id);
|
||||
let ty_path = self.arena.alloc(hir::Path {
|
||||
span: param_span,
|
||||
res: Res::Def(DefKind::TyParam, def_id),
|
||||
segments: self.arena.alloc_from_iter([hir::PathSegment::from_ident(ident)]),
|
||||
res,
|
||||
segments: self
|
||||
.arena
|
||||
.alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]),
|
||||
});
|
||||
let ty_id = self.next_id();
|
||||
let bounded_ty =
|
||||
|
@ -1472,11 +1510,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bound_generic_params: self.lower_generic_params(bound_generic_params),
|
||||
bounded_ty: self
|
||||
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
|
||||
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
|
||||
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
|
||||
self.lower_param_bound(
|
||||
bound,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
)
|
||||
})),
|
||||
span: self.lower_span(span),
|
||||
|
@ -1491,16 +1529,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
lifetime: self.lower_lifetime(lifetime),
|
||||
bounds: self.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
in_where_clause: true,
|
||||
}),
|
||||
WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span }) => {
|
||||
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
|
||||
lhs_ty: self
|
||||
.lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
|
||||
.lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
|
||||
rhs_ty: self
|
||||
.lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
|
||||
.lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
|
||||
span: self.lower_span(span),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#![feature(box_patterns)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![feature(never_type)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
@ -42,8 +41,9 @@
|
|||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
|
||||
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync};
|
||||
|
||||
use rustc_arena::declare_arena;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit;
|
||||
use rustc_ast::{self as ast, *};
|
||||
|
@ -95,6 +95,13 @@ struct LoweringContext<'a, 'hir> {
|
|||
/// Used to allocate HIR nodes.
|
||||
arena: &'hir hir::Arena<'hir>,
|
||||
|
||||
/// Used to allocate temporary AST nodes for use during lowering.
|
||||
/// This allows us to create "fake" AST -- these nodes can sometimes
|
||||
/// be allocated on the stack, but other times we need them to live longer
|
||||
/// than the current stack frame, so they can be collected into vectors
|
||||
/// and things like that.
|
||||
ast_arena: &'a Arena<'static>,
|
||||
|
||||
/// Bodies inside the owner being lowered.
|
||||
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
|
||||
/// Attributes inside the owner being lowered.
|
||||
|
@ -118,7 +125,7 @@ struct LoweringContext<'a, 'hir> {
|
|||
is_in_trait_impl: bool,
|
||||
is_in_dyn_type: bool,
|
||||
|
||||
current_hir_id_owner: LocalDefId,
|
||||
current_hir_id_owner: hir::OwnerId,
|
||||
item_local_id_counter: hir::ItemLocalId,
|
||||
local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
|
||||
trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
|
||||
|
@ -132,8 +139,23 @@ struct LoweringContext<'a, 'hir> {
|
|||
allow_try_trait: Option<Lrc<[Symbol]>>,
|
||||
allow_gen_future: Option<Lrc<[Symbol]>>,
|
||||
allow_into_future: Option<Lrc<[Symbol]>>,
|
||||
|
||||
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
|
||||
/// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
|
||||
/// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
|
||||
/// field from the original parameter 'a to the new parameter 'a1.
|
||||
generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
|
||||
}
|
||||
|
||||
declare_arena!([
|
||||
[] tys: rustc_ast::Ty,
|
||||
[] aba: rustc_ast::AngleBracketedArgs,
|
||||
[] ptr: rustc_ast::PolyTraitRef,
|
||||
// This _marker field is needed because `declare_arena` creates `Arena<'tcx>` and we need to
|
||||
// use `'tcx`. If we don't have this we get a compile error.
|
||||
[] _marker: std::marker::PhantomData<&'tcx ()>,
|
||||
]);
|
||||
|
||||
trait ResolverAstLoweringExt {
|
||||
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
|
||||
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
|
||||
|
@ -142,12 +164,6 @@ trait ResolverAstLoweringExt {
|
|||
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
|
||||
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
|
||||
fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind;
|
||||
/// Record the map from `from` local def id to `to` local def id, on `generics_def_id_map`
|
||||
/// field.
|
||||
fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId);
|
||||
/// Get the previously recorded `to` local def id given the `from` local def id, obtained using
|
||||
/// `generics_def_id_map` field.
|
||||
fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId;
|
||||
}
|
||||
|
||||
impl ResolverAstLoweringExt for ResolverAstLowering {
|
||||
|
@ -215,41 +231,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
|
|||
fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind {
|
||||
self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang)
|
||||
}
|
||||
|
||||
/// Push a remapping into the top-most map.
|
||||
/// Panics if no map has been pushed.
|
||||
/// Remapping is used when creating lowering `-> impl Trait` return
|
||||
/// types to create the resulting opaque type.
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId) {
|
||||
self.generics_def_id_map.last_mut().expect("no map pushed").insert(from, to);
|
||||
}
|
||||
|
||||
fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId {
|
||||
// `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
|
||||
// push new mappings so we need to try first the latest mappings, hence `iter().rev()`.
|
||||
//
|
||||
// Consider:
|
||||
//
|
||||
// `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
|
||||
//
|
||||
// We would end with a generics_def_id_map like:
|
||||
//
|
||||
// `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
|
||||
//
|
||||
// for the opaque type generated on `impl Sized + 'b`, We want the result to be:
|
||||
// impl_sized#'b, so iterating forward is the wrong thing to do.
|
||||
for map in self.generics_def_id_map.iter().rev() {
|
||||
if let Some(r) = map.get(&local_def_id) {
|
||||
debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`");
|
||||
local_def_id = *r;
|
||||
} else {
|
||||
debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map");
|
||||
}
|
||||
}
|
||||
|
||||
local_def_id
|
||||
}
|
||||
}
|
||||
|
||||
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
|
||||
|
@ -270,6 +251,7 @@ enum ImplTraitContext {
|
|||
ReturnPositionOpaqueTy {
|
||||
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
|
||||
origin: hir::OpaqueTyOrigin,
|
||||
in_trait: bool,
|
||||
},
|
||||
/// Impl trait in type aliases.
|
||||
TypeAliasesOpaqueTy,
|
||||
|
@ -329,7 +311,7 @@ impl std::fmt::Display for ImplTraitPosition {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum FnDeclKind {
|
||||
Fn,
|
||||
Inherent,
|
||||
|
@ -341,9 +323,20 @@ enum FnDeclKind {
|
|||
}
|
||||
|
||||
impl FnDeclKind {
|
||||
fn impl_trait_return_allowed(&self) -> bool {
|
||||
fn impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
match self {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent => true,
|
||||
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
|
||||
FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn async_fn_allowed(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
match self {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent => true,
|
||||
FnDeclKind::Impl if tcx.features().async_fn_in_trait => true,
|
||||
FnDeclKind::Trait if tcx.features().async_fn_in_trait => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -436,10 +429,13 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> {
|
|||
tcx.definitions_untracked().def_index_count(),
|
||||
);
|
||||
|
||||
let ast_arena = Arena::default();
|
||||
|
||||
for def_id in ast_index.indices() {
|
||||
item::ItemLowerer {
|
||||
tcx,
|
||||
resolver: &mut resolver,
|
||||
ast_arena: &ast_arena,
|
||||
ast_index: &ast_index,
|
||||
owners: &mut owners,
|
||||
}
|
||||
|
@ -522,13 +518,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.resolver
|
||||
.node_id_to_def_id
|
||||
.get(&node)
|
||||
.map(|local_def_id| self.resolver.get_remapped_def_id(*local_def_id))
|
||||
.map(|local_def_id| self.get_remapped_def_id(*local_def_id))
|
||||
}
|
||||
|
||||
fn local_def_id(&self, node: NodeId) -> LocalDefId {
|
||||
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
|
||||
}
|
||||
|
||||
/// Get the previously recorded `to` local def id given the `from` local def id, obtained using
|
||||
/// `generics_def_id_map` field.
|
||||
fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId {
|
||||
// `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
|
||||
// push new mappings so we need to try first the latest mappings, hence `iter().rev()`.
|
||||
//
|
||||
// Consider:
|
||||
//
|
||||
// `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
|
||||
//
|
||||
// We would end with a generics_def_id_map like:
|
||||
//
|
||||
// `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
|
||||
//
|
||||
// for the opaque type generated on `impl Sized + 'b`, We want the result to be:
|
||||
// impl_sized#'b, so iterating forward is the wrong thing to do.
|
||||
for map in self.generics_def_id_map.iter().rev() {
|
||||
if let Some(r) = map.get(&local_def_id) {
|
||||
debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`");
|
||||
local_def_id = *r;
|
||||
} else {
|
||||
debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map");
|
||||
}
|
||||
}
|
||||
|
||||
local_def_id
|
||||
}
|
||||
|
||||
/// Freshen the `LoweringContext` and ready it to lower a nested item.
|
||||
/// The lowered item is registered into `self.children`.
|
||||
///
|
||||
|
@ -547,7 +571,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
|
||||
let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
|
||||
let current_trait_map = std::mem::take(&mut self.trait_map);
|
||||
let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id);
|
||||
let current_owner =
|
||||
std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
|
||||
let current_local_counter =
|
||||
std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
|
||||
let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
|
||||
|
@ -562,7 +587,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
debug_assert_eq!(_old, None);
|
||||
|
||||
let item = f(self);
|
||||
debug_assert_eq!(def_id, item.def_id());
|
||||
debug_assert_eq!(def_id, item.def_id().def_id);
|
||||
// `f` should have consumed all the elements in these vectors when constructing `item`.
|
||||
debug_assert!(self.impl_trait_defs.is_empty());
|
||||
debug_assert!(self.impl_trait_bounds.is_empty());
|
||||
|
@ -597,9 +622,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
remap: FxHashMap<LocalDefId, LocalDefId>,
|
||||
f: impl FnOnce(&mut Self) -> R,
|
||||
) -> R {
|
||||
self.resolver.generics_def_id_map.push(remap);
|
||||
self.generics_def_id_map.push(remap);
|
||||
let res = f(self);
|
||||
self.resolver.generics_def_id_map.pop();
|
||||
self.generics_def_id_map.pop();
|
||||
res
|
||||
}
|
||||
|
||||
|
@ -667,6 +692,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// actually used in the HIR, as that would trigger an assertion in the
|
||||
/// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
|
||||
/// properly. Calling the method twice with the same `NodeId` is fine though.
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
|
||||
assert_ne!(ast_node_id, DUMMY_NODE_ID);
|
||||
|
||||
|
@ -700,6 +726,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
/// Generate a new `HirId` without a backing `NodeId`.
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn next_id(&mut self) -> hir::HirId {
|
||||
let owner = self.current_hir_id_owner;
|
||||
let local_id = self.item_local_id_counter;
|
||||
|
@ -759,7 +786,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// Mark a span as relative to the current owning item.
|
||||
fn lower_span(&self, span: Span) -> Span {
|
||||
if self.tcx.sess.opts.unstable_opts.incremental_relative_spans {
|
||||
span.with_parent(Some(self.current_hir_id_owner))
|
||||
span.with_parent(Some(self.current_hir_id_owner.def_id))
|
||||
} else {
|
||||
// Do not make spans relative when not using incremental compilation.
|
||||
span
|
||||
|
@ -771,7 +798,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
/// Converts a lifetime into a new generic parameter.
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lifetime_res_to_generic_param(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
|
@ -785,7 +812,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
LifetimeRes::Fresh { param, .. } => {
|
||||
// Late resolution delegates to us the creation of the `LocalDefId`.
|
||||
let _def_id = self.create_def(
|
||||
self.current_hir_id_owner,
|
||||
self.current_hir_id_owner.def_id,
|
||||
param,
|
||||
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
||||
);
|
||||
|
@ -815,7 +842,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id
|
||||
/// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime
|
||||
/// parameters will be successful.
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
#[inline]
|
||||
fn lower_lifetime_binder(
|
||||
&mut self,
|
||||
|
@ -960,7 +987,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_assoc_ty_constraint(
|
||||
&mut self,
|
||||
constraint: &AssocConstraint,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::TypeBinding<'hir> {
|
||||
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
|
||||
// lower generic arguments of identifier in constraint
|
||||
|
@ -971,18 +998,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
GenericArgs::Parenthesized(ref data) => {
|
||||
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
|
||||
self.lower_angle_bracketed_parameter_data(
|
||||
&data.as_angle_bracketed_args(),
|
||||
ParamMode::Explicit,
|
||||
itctx,
|
||||
)
|
||||
.0
|
||||
let aba = self.ast_arena.aba.alloc(data.as_angle_bracketed_args());
|
||||
self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0
|
||||
}
|
||||
};
|
||||
gen_args_ctor.into_generic_args(self)
|
||||
} else {
|
||||
self.arena.alloc(hir::GenericArgs::none())
|
||||
};
|
||||
let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy;
|
||||
|
||||
let kind = match constraint.kind {
|
||||
AssocConstraintKind::Equality { ref term } => {
|
||||
|
@ -1020,9 +1044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// then to an opaque type).
|
||||
//
|
||||
// FIXME: this is only needed until `impl Trait` is allowed in type aliases.
|
||||
ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => {
|
||||
(true, ImplTraitContext::TypeAliasesOpaqueTy)
|
||||
}
|
||||
ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, itctx_tait),
|
||||
|
||||
// We are in the parameter position, but not within a dyn type:
|
||||
//
|
||||
|
@ -1040,19 +1062,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let impl_trait_node_id = self.next_node_id();
|
||||
self.create_def(parent_def_id, impl_trait_node_id, DefPathData::ImplTrait);
|
||||
self.create_def(
|
||||
parent_def_id.def_id,
|
||||
impl_trait_node_id,
|
||||
DefPathData::ImplTrait,
|
||||
);
|
||||
|
||||
self.with_dyn_type_scope(false, |this| {
|
||||
let node_id = this.next_node_id();
|
||||
let ty = this.lower_ty(
|
||||
&Ty {
|
||||
id: node_id,
|
||||
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
|
||||
span: this.lower_span(constraint.span),
|
||||
tokens: None,
|
||||
},
|
||||
itctx,
|
||||
);
|
||||
let ty = this.ast_arena.tys.alloc(Ty {
|
||||
id: node_id,
|
||||
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
|
||||
span: this.lower_span(constraint.span),
|
||||
tokens: None,
|
||||
});
|
||||
let ty = this.lower_ty(ty, itctx);
|
||||
|
||||
hir::TypeBindingKind::Equality { term: ty.into() }
|
||||
})
|
||||
|
@ -1103,7 +1127,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_generic_arg(
|
||||
&mut self,
|
||||
arg: &ast::GenericArg,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::GenericArg<'hir> {
|
||||
match arg {
|
||||
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
|
||||
|
@ -1134,7 +1158,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let node_id = self.next_node_id();
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
|
||||
self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
DefPathData::AnonConst,
|
||||
);
|
||||
|
||||
let span = self.lower_span(ty.span);
|
||||
let path_expr = Expr {
|
||||
|
@ -1155,7 +1183,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
GenericArg::Type(self.lower_ty_direct(&ty, itctx))
|
||||
GenericArg::Type(self.lower_ty(&ty, itctx))
|
||||
}
|
||||
ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
|
||||
value: self.lower_anon_const(&ct),
|
||||
|
@ -1165,7 +1193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> {
|
||||
fn lower_ty(&mut self, t: &Ty, itctx: &ImplTraitContext) -> &'hir hir::Ty<'hir> {
|
||||
self.arena.alloc(self.lower_ty_direct(t, itctx))
|
||||
}
|
||||
|
||||
|
@ -1175,11 +1203,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
qself: &Option<QSelf>,
|
||||
path: &Path,
|
||||
param_mode: ParamMode,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::Ty<'hir> {
|
||||
// Check whether we should interpret this as a bare trait object.
|
||||
// This check mirrors the one in late resolution. We only introduce this special case in
|
||||
// the rare occurence we need to lower `Fresh` anonymous lifetimes.
|
||||
// the rare occurrence we need to lower `Fresh` anonymous lifetimes.
|
||||
// The other cases when a qpath should be opportunistically made a trait object are handled
|
||||
// by `ty_path`.
|
||||
if qself.is_none()
|
||||
|
@ -1188,19 +1216,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&& let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
|
||||
{
|
||||
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
|
||||
let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef {
|
||||
bound_generic_params: vec![],
|
||||
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
|
||||
span: t.span
|
||||
});
|
||||
let bound = this.lower_poly_trait_ref(
|
||||
&PolyTraitRef {
|
||||
bound_generic_params: vec![],
|
||||
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
|
||||
span: t.span
|
||||
},
|
||||
poly_trait_ref,
|
||||
itctx,
|
||||
);
|
||||
let bounds = this.arena.alloc_from_iter([bound]);
|
||||
let lifetime_bound = this.elided_dyn_bound(t.span);
|
||||
(bounds, lifetime_bound)
|
||||
});
|
||||
let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None);
|
||||
let kind = hir::TyKind::TraitObject(bounds, &lifetime_bound, TraitObjectSyntax::None);
|
||||
return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };
|
||||
}
|
||||
|
||||
|
@ -1217,7 +1246,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.ty(span, hir::TyKind::Tup(tys))
|
||||
}
|
||||
|
||||
fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {
|
||||
fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> {
|
||||
let kind = match t.kind {
|
||||
TyKind::Infer => hir::TyKind::Infer,
|
||||
TyKind::Err => hir::TyKind::Err,
|
||||
|
@ -1245,7 +1274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
generic_params,
|
||||
unsafety: self.lower_unsafety(f.unsafety),
|
||||
abi: self.lower_extern(f.ext),
|
||||
decl: self.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
|
||||
decl: self.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None),
|
||||
param_names: self.lower_fn_params_to_names(&f.decl),
|
||||
}))
|
||||
}
|
||||
|
@ -1260,14 +1289,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
|
||||
}
|
||||
TyKind::ImplicitSelf => {
|
||||
let hir_id = self.next_id();
|
||||
let res = self.expect_full_res(t.id);
|
||||
let res = self.lower_res(res);
|
||||
hir::TyKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
self.arena.alloc(hir::Path {
|
||||
res,
|
||||
segments: arena_vec![self; hir::PathSegment::from_ident(
|
||||
Ident::with_dummy_span(kw::SelfUpper)
|
||||
segments: arena_vec![self; hir::PathSegment::new(
|
||||
Ident::with_dummy_span(kw::SelfUpper),
|
||||
hir_id,
|
||||
res
|
||||
)],
|
||||
span: self.lower_span(t.span),
|
||||
}),
|
||||
|
@ -1310,19 +1342,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
TyKind::ImplTrait(def_node_id, ref bounds) => {
|
||||
let span = t.span;
|
||||
match itctx {
|
||||
ImplTraitContext::ReturnPositionOpaqueTy { origin } => {
|
||||
self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx)
|
||||
}
|
||||
ImplTraitContext::TypeAliasesOpaqueTy => {
|
||||
let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy;
|
||||
self.lower_opaque_impl_trait(
|
||||
ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self
|
||||
.lower_opaque_impl_trait(
|
||||
span,
|
||||
hir::OpaqueTyOrigin::TyAlias,
|
||||
*origin,
|
||||
def_node_id,
|
||||
bounds,
|
||||
nested_itctx,
|
||||
)
|
||||
}
|
||||
*in_trait,
|
||||
itctx,
|
||||
),
|
||||
ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait(
|
||||
span,
|
||||
hir::OpaqueTyOrigin::TyAlias,
|
||||
def_node_id,
|
||||
bounds,
|
||||
false,
|
||||
&ImplTraitContext::TypeAliasesOpaqueTy,
|
||||
),
|
||||
ImplTraitContext::Universal => {
|
||||
let span = t.span;
|
||||
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
|
||||
|
@ -1334,6 +1370,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
path
|
||||
}
|
||||
ImplTraitContext::Disallowed(
|
||||
position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
|
||||
) => {
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
MisplacedImplTrait {
|
||||
span: t.span,
|
||||
position: DiagnosticArgFromDisplay(&position),
|
||||
},
|
||||
sym::return_position_impl_trait_in_trait,
|
||||
)
|
||||
.emit();
|
||||
hir::TyKind::Err
|
||||
}
|
||||
ImplTraitContext::Disallowed(position) => {
|
||||
self.tcx.sess.emit_err(MisplacedImplTrait {
|
||||
span: t.span,
|
||||
|
@ -1385,14 +1436,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// added explicitly in the HIR). But this includes all the lifetimes, and we only want to
|
||||
/// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters
|
||||
/// for the lifetimes that get captured (`'x`, in our example above) and reference those.
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn lower_opaque_impl_trait(
|
||||
&mut self,
|
||||
span: Span,
|
||||
origin: hir::OpaqueTyOrigin,
|
||||
opaque_ty_node_id: NodeId,
|
||||
bounds: &GenericBounds,
|
||||
itctx: ImplTraitContext,
|
||||
in_trait: bool,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::TyKind<'hir> {
|
||||
// Make sure we know that some funky desugaring has been going on here.
|
||||
// This is a first: there is code in other places like for loop
|
||||
|
@ -1480,6 +1532,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}),
|
||||
bounds: hir_bounds,
|
||||
origin,
|
||||
in_trait,
|
||||
};
|
||||
debug!(?opaque_ty_item);
|
||||
|
||||
|
@ -1506,7 +1559,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
debug!(?lifetimes);
|
||||
|
||||
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
|
||||
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
|
||||
hir::TyKind::OpaqueDef(
|
||||
hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } },
|
||||
lifetimes,
|
||||
in_trait,
|
||||
)
|
||||
}
|
||||
|
||||
/// Registers a new opaque type with the proper `NodeId`s and
|
||||
|
@ -1522,7 +1579,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// Generate an `type Foo = impl Trait;` declaration.
|
||||
trace!("registering opaque type with id {:#?}", opaque_ty_id);
|
||||
let opaque_ty_item = hir::Item {
|
||||
def_id: opaque_ty_id,
|
||||
def_id: hir::OwnerId { def_id: opaque_ty_id },
|
||||
ident: Ident::empty(),
|
||||
kind: opaque_ty_item_kind,
|
||||
vis_span: self.lower_span(span.shrink_to_lo()),
|
||||
|
@ -1565,8 +1622,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
LifetimeRes::Fresh { param, binder: _ } => {
|
||||
debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
|
||||
let old_def_id = self.local_def_id(param);
|
||||
if remapping.get(&old_def_id).is_none() {
|
||||
if let Some(old_def_id) = self.opt_local_def_id(param) && remapping.get(&old_def_id).is_none() {
|
||||
let node_id = self.next_node_id();
|
||||
|
||||
let new_def_id = self.create_def(
|
||||
|
@ -1615,19 +1671,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the
|
||||
// given DefId, otherwise impl Trait is disallowed. Must be `Some` if
|
||||
// `make_ret_async` is also `Some`.
|
||||
// `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position.
|
||||
// This guards against trait declarations and implementations where `impl Trait` is
|
||||
// disallowed.
|
||||
// `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
|
||||
// return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
|
||||
// return type `impl Trait` item.
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
// return type `impl Trait` item, and the `Span` points to the `async` keyword.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_fn_decl(
|
||||
&mut self,
|
||||
decl: &FnDecl,
|
||||
fn_node_id: Option<NodeId>,
|
||||
fn_span: Span,
|
||||
kind: FnDeclKind,
|
||||
make_ret_async: Option<NodeId>,
|
||||
make_ret_async: Option<(NodeId, Span)>,
|
||||
) -> &'hir hir::FnDecl<'hir> {
|
||||
let c_variadic = decl.c_variadic();
|
||||
|
||||
|
@ -1640,11 +1694,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
|
||||
if fn_node_id.is_some() {
|
||||
self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal)
|
||||
self.lower_ty_direct(¶m.ty, &ImplTraitContext::Universal)
|
||||
} else {
|
||||
self.lower_ty_direct(
|
||||
¶m.ty,
|
||||
ImplTraitContext::Disallowed(match kind {
|
||||
&ImplTraitContext::Disallowed(match kind {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
||||
unreachable!("fn should allow in-band lifetimes")
|
||||
}
|
||||
|
@ -1658,20 +1712,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}));
|
||||
|
||||
let output = if let Some(ret_id) = make_ret_async {
|
||||
let output = if let Some((ret_id, span)) = make_ret_async {
|
||||
if !kind.async_fn_allowed(self.tcx) {
|
||||
match kind {
|
||||
FnDeclKind::Trait | FnDeclKind::Impl => {
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
TraitFnAsync { fn_span, span },
|
||||
sym::async_fn_in_trait,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
_ => {
|
||||
self.tcx.sess.emit_err(TraitFnAsync { fn_span, span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.lower_async_fn_ret_ty(
|
||||
&decl.output,
|
||||
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
|
||||
ret_id,
|
||||
matches!(kind, FnDeclKind::Trait),
|
||||
)
|
||||
} else {
|
||||
match decl.output {
|
||||
FnRetTy::Ty(ref ty) => {
|
||||
let context = match fn_node_id {
|
||||
Some(fn_node_id) if kind.impl_trait_return_allowed() => {
|
||||
let mut context = match fn_node_id {
|
||||
Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => {
|
||||
let fn_def_id = self.local_def_id(fn_node_id);
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
in_trait: matches!(kind, FnDeclKind::Trait),
|
||||
}
|
||||
}
|
||||
_ => ImplTraitContext::Disallowed(match kind {
|
||||
|
@ -1685,7 +1758,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
|
||||
}),
|
||||
};
|
||||
hir::FnRetTy::Return(self.lower_ty(ty, context))
|
||||
hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
|
||||
}
|
||||
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
|
||||
}
|
||||
|
@ -1696,10 +1769,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
output,
|
||||
c_variadic,
|
||||
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
|
||||
use BindingMode::{ByRef, ByValue};
|
||||
let is_mutable_pat = matches!(
|
||||
arg.pat.kind,
|
||||
PatKind::Ident(ByValue(Mutability::Mut) | ByRef(Mutability::Mut), ..)
|
||||
PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..)
|
||||
);
|
||||
|
||||
match arg.ty.kind {
|
||||
|
@ -1730,12 +1802,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// `output`: unlowered output type (`T` in `-> T`)
|
||||
// `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition)
|
||||
// `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_async_fn_ret_ty(
|
||||
&mut self,
|
||||
output: &FnRetTy,
|
||||
fn_node_id: NodeId,
|
||||
opaque_ty_node_id: NodeId,
|
||||
in_trait: bool,
|
||||
) -> hir::FnRetTy<'hir> {
|
||||
let span = output.span();
|
||||
|
||||
|
@ -1862,8 +1935,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
//
|
||||
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
|
||||
// hence the elision takes place at the fn site.
|
||||
let future_bound =
|
||||
this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span);
|
||||
let future_bound = this.lower_async_fn_output_type_to_future_bound(
|
||||
output,
|
||||
span,
|
||||
if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
|
||||
} else {
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
in_trait,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map(
|
||||
|&(new_node_id, lifetime, _)| {
|
||||
|
@ -1901,6 +1984,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}),
|
||||
bounds: arena_vec![this; future_bound],
|
||||
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
||||
in_trait,
|
||||
};
|
||||
|
||||
trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
|
||||
|
@ -1937,8 +2021,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let res = res.unwrap_or(
|
||||
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
|
||||
);
|
||||
let l = self.new_named_lifetime_with_res(id, span, ident, res);
|
||||
hir::GenericArg::Lifetime(l)
|
||||
hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res))
|
||||
},
|
||||
));
|
||||
|
||||
|
@ -1946,8 +2029,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// Foo = impl Trait` is, internally, created as a child of the
|
||||
// async fn, so the *type parameters* are inherited. It's
|
||||
// only the lifetime parameters that we must supply.
|
||||
let opaque_ty_ref =
|
||||
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args);
|
||||
let opaque_ty_ref = hir::TyKind::OpaqueDef(
|
||||
hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } },
|
||||
generic_args,
|
||||
in_trait,
|
||||
);
|
||||
let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
|
||||
hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
|
||||
}
|
||||
|
@ -1956,8 +2042,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_async_fn_output_type_to_future_bound(
|
||||
&mut self,
|
||||
output: &FnRetTy,
|
||||
fn_def_id: LocalDefId,
|
||||
span: Span,
|
||||
mut nested_impl_trait_context: ImplTraitContext,
|
||||
) -> hir::GenericBound<'hir> {
|
||||
// Compute the `T` in `Future<Output = T>` from the return type.
|
||||
let output_ty = match output {
|
||||
|
@ -1965,10 +2051,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
|
||||
// `impl Future` opaque type that `async fn` implicitly
|
||||
// generates.
|
||||
let context = ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
};
|
||||
self.lower_ty(ty, context)
|
||||
self.lower_ty(ty, &mut nested_impl_trait_context)
|
||||
}
|
||||
FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
|
||||
};
|
||||
|
@ -1994,7 +2077,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_param_bound(
|
||||
&mut self,
|
||||
tpb: &GenericBound,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::GenericBound<'hir> {
|
||||
match tpb {
|
||||
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
|
||||
|
@ -2007,24 +2090,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
|
||||
fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
|
||||
let span = self.lower_span(l.ident.span);
|
||||
let ident = self.lower_ident(l.ident);
|
||||
self.new_named_lifetime(l.id, l.id, span, ident)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn new_named_lifetime_with_res(
|
||||
&mut self,
|
||||
id: NodeId,
|
||||
span: Span,
|
||||
ident: Ident,
|
||||
res: LifetimeRes,
|
||||
) -> hir::Lifetime {
|
||||
) -> &'hir hir::Lifetime {
|
||||
let name = match res {
|
||||
LifetimeRes::Param { param, .. } => {
|
||||
let p_name = ParamName::Plain(ident);
|
||||
let param = self.resolver.get_remapped_def_id(param);
|
||||
let param = self.get_remapped_def_id(param);
|
||||
|
||||
hir::LifetimeName::Param(param, p_name)
|
||||
}
|
||||
|
@ -2041,17 +2124,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
};
|
||||
|
||||
debug!(?name);
|
||||
hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name }
|
||||
self.arena.alloc(hir::Lifetime {
|
||||
hir_id: self.lower_node_id(id),
|
||||
span: self.lower_span(span),
|
||||
name,
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn new_named_lifetime(
|
||||
&mut self,
|
||||
id: NodeId,
|
||||
new_id: NodeId,
|
||||
span: Span,
|
||||
ident: Ident,
|
||||
) -> hir::Lifetime {
|
||||
) -> &'hir hir::Lifetime {
|
||||
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
|
||||
self.new_named_lifetime_with_res(new_id, span, ident, res)
|
||||
}
|
||||
|
@ -2106,7 +2193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
GenericParamKind::Type { ref default, .. } => {
|
||||
let kind = hir::GenericParamKind::Type {
|
||||
default: default.as_ref().map(|x| {
|
||||
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
|
||||
self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
|
||||
}),
|
||||
synthetic: false,
|
||||
};
|
||||
|
@ -2114,7 +2201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
|
||||
}
|
||||
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
|
||||
let ty = self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
|
||||
let default = default.as_ref().map(|def| self.lower_anon_const(def));
|
||||
(
|
||||
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
||||
|
@ -2124,7 +2211,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef<'hir> {
|
||||
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
|
||||
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
|
||||
hir::QPath::Resolved(None, path) => path,
|
||||
qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
|
||||
|
@ -2132,11 +2219,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) }
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_poly_trait_ref(
|
||||
&mut self,
|
||||
p: &PolyTraitRef,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::PolyTraitRef<'hir> {
|
||||
let bound_generic_params =
|
||||
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
|
||||
|
@ -2144,14 +2231,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
||||
}
|
||||
|
||||
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
|
||||
fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> {
|
||||
hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn lower_param_bounds(
|
||||
&mut self,
|
||||
bounds: &[GenericBound],
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::GenericBounds<'hir> {
|
||||
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
|
||||
}
|
||||
|
@ -2159,11 +2247,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_param_bounds_mut<'s>(
|
||||
&'s mut self,
|
||||
bounds: &'s [GenericBound],
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &'s ImplTraitContext,
|
||||
) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> {
|
||||
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn lower_generic_and_bounds(
|
||||
&mut self,
|
||||
node_id: NodeId,
|
||||
|
@ -2189,16 +2278,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
node_id,
|
||||
&GenericParamKind::Type { default: None },
|
||||
bounds,
|
||||
ImplTraitContext::Universal,
|
||||
&ImplTraitContext::Universal,
|
||||
hir::PredicateOrigin::ImplTrait,
|
||||
);
|
||||
|
||||
let hir_id = self.next_id();
|
||||
let res = Res::Def(DefKind::TyParam, def_id.to_def_id());
|
||||
let ty = hir::TyKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
self.arena.alloc(hir::Path {
|
||||
span: self.lower_span(span),
|
||||
res: Res::Def(DefKind::TyParam, def_id.to_def_id()),
|
||||
segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))],
|
||||
res,
|
||||
segments:
|
||||
arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],
|
||||
}),
|
||||
));
|
||||
|
||||
|
@ -2361,11 +2453,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
|
||||
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
|
||||
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE)
|
||||
}
|
||||
|
||||
fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) {
|
||||
self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::Unannotated)
|
||||
self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE)
|
||||
}
|
||||
|
||||
fn pat_ident_binding_mode(
|
||||
|
@ -2454,14 +2546,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// bound, like the bound in `Box<dyn Debug>`. This method is not invoked
|
||||
/// when the bound is written, even if it is written with `'_` like in
|
||||
/// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked.
|
||||
fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime {
|
||||
fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
|
||||
let r = hir::Lifetime {
|
||||
hir_id: self.next_id(),
|
||||
span: self.lower_span(span),
|
||||
name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
|
||||
};
|
||||
debug!("elided_dyn_bound: r={:?}", r);
|
||||
r
|
||||
self.arena.alloc(r)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
|
|||
self.record_lifetime_use(*lifetime);
|
||||
}
|
||||
|
||||
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
|
||||
self.record_elided_anchor(path_segment.id, path_span);
|
||||
visit::walk_path_segment(self, path_span, path_segment);
|
||||
fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
|
||||
self.record_elided_anchor(path_segment.id, path_segment.ident.span);
|
||||
visit::walk_path_segment(self, path_segment);
|
||||
}
|
||||
|
||||
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) {
|
||||
|
|
|
@ -24,7 +24,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let node = loop {
|
||||
match pattern.kind {
|
||||
PatKind::Wild => break hir::PatKind::Wild,
|
||||
PatKind::Ident(ref binding_mode, ident, ref sub) => {
|
||||
PatKind::Ident(binding_mode, ident, ref sub) => {
|
||||
let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
|
||||
break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
qself,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&mut ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
|
||||
break hir::PatKind::TupleStruct(qpath, pats, ddpos);
|
||||
|
@ -53,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
qself,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&mut ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
break hir::PatKind::Path(qpath);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
qself,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&mut ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
|
||||
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
|
||||
|
@ -116,7 +116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&mut self,
|
||||
pats: &[P<Pat>],
|
||||
ctx: &str,
|
||||
) -> (&'hir [hir::Pat<'hir>], Option<usize>) {
|
||||
) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) {
|
||||
let mut elems = Vec::with_capacity(pats.len());
|
||||
let mut rest = None;
|
||||
|
||||
|
@ -160,7 +160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
(self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
|
||||
(self.arena.alloc_from_iter(elems), hir::DotDotPos::new(rest.map(|(ddpos, _)| ddpos)))
|
||||
}
|
||||
|
||||
/// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
|
||||
|
@ -176,9 +176,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let mut prev_rest_span = None;
|
||||
|
||||
// Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
|
||||
let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| {
|
||||
let lower_rest_sub = |this: &mut Self, pat, ann, ident, sub| {
|
||||
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
|
||||
let node = this.lower_pat_ident(pat, bm, ident, lower_sub);
|
||||
let node = this.lower_pat_ident(pat, ann, ident, lower_sub);
|
||||
this.pat_with_node_id_of(pat, node)
|
||||
};
|
||||
|
||||
|
@ -194,9 +194,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
// Found a sub-slice pattern `$binding_mode $ident @ ..`.
|
||||
// Record, lower it to `$binding_mode $ident @ _`, and stop here.
|
||||
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
|
||||
PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => {
|
||||
prev_rest_span = Some(sub.span);
|
||||
slice = Some(self.arena.alloc(lower_rest_sub(self, pat, bm, ident, sub)));
|
||||
slice = Some(self.arena.alloc(lower_rest_sub(self, pat, ann, ident, sub)));
|
||||
break;
|
||||
}
|
||||
// It was not a subslice pattern so lower it normally.
|
||||
|
@ -209,9 +209,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// There was a previous subslice pattern; make sure we don't allow more.
|
||||
let rest_span = match pat.kind {
|
||||
PatKind::Rest => Some(pat.span),
|
||||
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
|
||||
PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => {
|
||||
// #69103: Lower into `binding @ _` as above to avoid ICEs.
|
||||
after.push(lower_rest_sub(self, pat, bm, ident, sub));
|
||||
after.push(lower_rest_sub(self, pat, ann, ident, sub));
|
||||
Some(sub.span)
|
||||
}
|
||||
_ => None,
|
||||
|
@ -235,7 +235,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_pat_ident(
|
||||
&mut self,
|
||||
p: &Pat,
|
||||
binding_mode: &BindingMode,
|
||||
annotation: BindingAnnotation,
|
||||
ident: Ident,
|
||||
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
|
||||
) -> hir::PatKind<'hir> {
|
||||
|
@ -248,29 +248,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
};
|
||||
|
||||
hir::PatKind::Binding(
|
||||
self.lower_binding_mode(binding_mode),
|
||||
annotation,
|
||||
self.lower_node_id(canonical_id),
|
||||
self.lower_ident(ident),
|
||||
lower_sub(self),
|
||||
)
|
||||
}
|
||||
Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
self.arena.alloc(hir::Path {
|
||||
span: self.lower_span(ident.span),
|
||||
res: self.lower_res(res),
|
||||
segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))],
|
||||
}),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
|
||||
match *b {
|
||||
BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
|
||||
BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
|
||||
BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
|
||||
BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
|
||||
Some(res) => {
|
||||
let hir_id = self.next_id();
|
||||
let res = self.lower_res(res);
|
||||
hir::PatKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
self.arena.alloc(hir::Path {
|
||||
span: self.lower_span(ident.span),
|
||||
res,
|
||||
segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],
|
||||
}),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ use rustc_span::symbol::{kw, Ident};
|
|||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
|
||||
use smallvec::smallvec;
|
||||
use tracing::debug;
|
||||
|
||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
|
@ -23,7 +22,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
qself: &Option<QSelf>,
|
||||
p: &Path,
|
||||
param_mode: ParamMode,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::QPath<'hir> {
|
||||
let qself_position = qself.as_ref().map(|q| q.position);
|
||||
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
|
||||
|
@ -157,7 +156,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
segment,
|
||||
param_mode,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
)
|
||||
})),
|
||||
span: self.lower_span(p.span),
|
||||
|
@ -181,7 +180,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
segment: &PathSegment,
|
||||
param_mode: ParamMode,
|
||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::PathSegment<'hir> {
|
||||
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
|
||||
let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
|
||||
|
@ -251,16 +250,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
let res = self.expect_full_res(segment.id);
|
||||
let id = self.lower_node_id(segment.id);
|
||||
let hir_id = self.lower_node_id(segment.id);
|
||||
debug!(
|
||||
"lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
|
||||
segment.ident, segment.id, id,
|
||||
segment.ident, segment.id, hir_id,
|
||||
);
|
||||
|
||||
hir::PathSegment {
|
||||
ident: self.lower_ident(segment.ident),
|
||||
hir_id: Some(id),
|
||||
res: Some(self.lower_res(res)),
|
||||
hir_id,
|
||||
res: self.lower_res(res),
|
||||
infer_args,
|
||||
args: if generic_args.is_empty() && generic_args.span.is_empty() {
|
||||
None
|
||||
|
@ -317,7 +316,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&mut self,
|
||||
data: &AngleBracketedArgs,
|
||||
param_mode: ParamMode,
|
||||
itctx: ImplTraitContext,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> (GenericArgsCtor<'hir>, bool) {
|
||||
let has_non_lt_args = data.args.iter().any(|arg| match arg {
|
||||
AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_))
|
||||
|
@ -351,15 +350,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// we generally don't permit such things (see #51008).
|
||||
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
||||
self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
|
||||
self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
|
||||
}));
|
||||
let output_ty = match output {
|
||||
FnRetTy::Ty(ty) => {
|
||||
self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
||||
self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
||||
}
|
||||
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
|
||||
};
|
||||
let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
|
||||
let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))];
|
||||
let binding = self.output_ty_binding(output_ty.span, output_ty);
|
||||
(
|
||||
GenericArgsCtor {
|
||||
|
|
|
@ -223,11 +223,9 @@ impl<'a> AstValidator<'a> {
|
|||
for (i, segment) in path.segments.iter().enumerate() {
|
||||
// Allow `impl Trait` iff we're on the final path segment
|
||||
if i == path.segments.len() - 1 {
|
||||
self.visit_path_segment(path.span, segment);
|
||||
self.visit_path_segment(segment);
|
||||
} else {
|
||||
self.with_banned_impl_trait(|this| {
|
||||
this.visit_path_segment(path.span, segment)
|
||||
});
|
||||
self.with_banned_impl_trait(|this| this.visit_path_segment(segment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,8 +279,8 @@ impl<'a> AstValidator<'a> {
|
|||
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
|
||||
for Param { pat, .. } in &decl.inputs {
|
||||
match pat.kind {
|
||||
PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
|
||||
PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ident, None) => {
|
||||
PatKind::Ident(BindingAnnotation::NONE, _, None) | PatKind::Wild => {}
|
||||
PatKind::Ident(BindingAnnotation::MUT, ident, None) => {
|
||||
report_err(pat.span, Some(ident), true)
|
||||
}
|
||||
_ => report_err(pat.span, None, false),
|
||||
|
@ -290,12 +288,6 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
|
||||
if let Async::Yes { span, .. } = asyncness {
|
||||
self.session.emit_err(TraitFnAsync { fn_span, span });
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_const(&self, constness: Const) {
|
||||
if let Const::Yes(span) = constness {
|
||||
self.session.emit_err(TraitFnConst { span });
|
||||
|
@ -845,10 +837,10 @@ fn validate_generic_param_order(
|
|||
let (kind, bounds, span) = (¶m.kind, ¶m.bounds, ident.span);
|
||||
let (ord_kind, ident) = match ¶m.kind {
|
||||
GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident.to_string()),
|
||||
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()),
|
||||
GenericParamKind::Type { default: _ } => (ParamKindOrd::TypeOrConst, ident.to_string()),
|
||||
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
|
||||
let ty = pprust::ty_to_string(ty);
|
||||
(ParamKindOrd::Const, format!("const {}: {}", ident, ty))
|
||||
(ParamKindOrd::TypeOrConst, format!("const {}: {}", ident, ty))
|
||||
}
|
||||
};
|
||||
param_idents.push((kind, ord_kind, bounds, idx, ident));
|
||||
|
@ -1299,7 +1291,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
|
||||
// Mirrors `visit::walk_generic_args`, but tracks relevant state.
|
||||
fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
|
||||
fn visit_generic_args(&mut self, generic_args: &'a GenericArgs) {
|
||||
match *generic_args {
|
||||
GenericArgs::AngleBracketed(ref data) => {
|
||||
self.check_generic_args_before_constraints(data);
|
||||
|
@ -1423,7 +1415,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
if !self.is_tilde_const_allowed {
|
||||
self.err_handler()
|
||||
.struct_span_err(bound.span(), "`~const` is not allowed here")
|
||||
.note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
|
||||
.note("only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -1531,11 +1523,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
let tilde_const_allowed =
|
||||
matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. }))
|
||||
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
|
||||
let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { .. }))
|
||||
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
|
||||
|
||||
self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk, span));
|
||||
self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk));
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
|
||||
|
@ -1596,7 +1587,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.invalid_visibility(&item.vis, None);
|
||||
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
self.check_trait_fn_not_async(item.span, sig.header.asyncness);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1800,7 +1790,7 @@ pub(crate) enum ForbiddenLetReason {
|
|||
NotSupportedOr(Span),
|
||||
/// A let chain with invalid parentheses
|
||||
///
|
||||
/// For exemple, `let 1 = 1 && (expr && expr)` is allowed
|
||||
/// For example, `let 1 = 1 && (expr && expr)` is allowed
|
||||
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
|
||||
NotSupportedParentheses(Span),
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//! Errors emitted by ast_passes.
|
||||
|
||||
use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic};
|
||||
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
|
||||
use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
use crate::ast_validation::ForbiddenLetReason;
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_let)]
|
||||
#[note]
|
||||
pub struct ForbiddenLet {
|
||||
|
@ -16,7 +16,7 @@ pub struct ForbiddenLet {
|
|||
pub(crate) reason: ForbiddenLetReason,
|
||||
}
|
||||
|
||||
impl AddSubdiagnostic for ForbiddenLetReason {
|
||||
impl AddToDiagnostic for ForbiddenLetReason {
|
||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
||||
match self {
|
||||
Self::GenericForbidden => {}
|
||||
|
@ -30,7 +30,7 @@ impl AddSubdiagnostic for ForbiddenLetReason {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_let_stable)]
|
||||
#[note]
|
||||
pub struct ForbiddenLetStable {
|
||||
|
@ -38,21 +38,21 @@ pub struct ForbiddenLetStable {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_assoc_constraint)]
|
||||
pub struct ForbiddenAssocConstraint {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::keyword_lifetime)]
|
||||
pub struct KeywordLifetime {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::invalid_label)]
|
||||
pub struct InvalidLabel {
|
||||
#[primary_span]
|
||||
|
@ -60,7 +60,7 @@ pub struct InvalidLabel {
|
|||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::invalid_visibility, code = "E0449")]
|
||||
pub struct InvalidVisibility {
|
||||
#[primary_span]
|
||||
|
@ -71,7 +71,7 @@ pub struct InvalidVisibility {
|
|||
pub note: Option<InvalidVisibilityNote>,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum InvalidVisibilityNote {
|
||||
#[note(ast_passes::individual_impl_items)]
|
||||
IndividualImplItems,
|
||||
|
@ -79,18 +79,7 @@ pub enum InvalidVisibilityNote {
|
|||
IndividualForeignItems,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(ast_passes::trait_fn_async, code = "E0706")]
|
||||
#[note]
|
||||
#[note(ast_passes::note2)]
|
||||
pub struct TraitFnAsync {
|
||||
#[primary_span]
|
||||
pub fn_span: Span,
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::trait_fn_const, code = "E0379")]
|
||||
pub struct TraitFnConst {
|
||||
#[primary_span]
|
||||
|
@ -98,21 +87,21 @@ pub struct TraitFnConst {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_lifetime_bound)]
|
||||
pub struct ForbiddenLifetimeBound {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_non_lifetime_param)]
|
||||
pub struct ForbiddenNonLifetimeParam {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_too_many)]
|
||||
pub struct FnParamTooMany {
|
||||
#[primary_span]
|
||||
|
@ -120,21 +109,21 @@ pub struct FnParamTooMany {
|
|||
pub max_num_args: usize,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_c_var_args_only)]
|
||||
pub struct FnParamCVarArgsOnly {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_c_var_args_not_last)]
|
||||
pub struct FnParamCVarArgsNotLast {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_doc_comment)]
|
||||
pub struct FnParamDocComment {
|
||||
#[primary_span]
|
||||
|
@ -142,14 +131,14 @@ pub struct FnParamDocComment {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_forbidden_attr)]
|
||||
pub struct FnParamForbiddenAttr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_forbidden_self)]
|
||||
#[note]
|
||||
pub struct FnParamForbiddenSelf {
|
||||
|
@ -158,7 +147,7 @@ pub struct FnParamForbiddenSelf {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_default)]
|
||||
pub struct ForbiddenDefault {
|
||||
#[primary_span]
|
||||
|
@ -167,7 +156,7 @@ pub struct ForbiddenDefault {
|
|||
pub def_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::assoc_const_without_body)]
|
||||
pub struct AssocConstWithoutBody {
|
||||
#[primary_span]
|
||||
|
@ -176,7 +165,7 @@ pub struct AssocConstWithoutBody {
|
|||
pub replace_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::assoc_fn_without_body)]
|
||||
pub struct AssocFnWithoutBody {
|
||||
#[primary_span]
|
||||
|
@ -185,7 +174,7 @@ pub struct AssocFnWithoutBody {
|
|||
pub replace_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::assoc_type_without_body)]
|
||||
pub struct AssocTypeWithoutBody {
|
||||
#[primary_span]
|
||||
|
@ -194,7 +183,7 @@ pub struct AssocTypeWithoutBody {
|
|||
pub replace_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::const_without_body)]
|
||||
pub struct ConstWithoutBody {
|
||||
#[primary_span]
|
||||
|
@ -203,7 +192,7 @@ pub struct ConstWithoutBody {
|
|||
pub replace_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::static_without_body)]
|
||||
pub struct StaticWithoutBody {
|
||||
#[primary_span]
|
||||
|
@ -212,7 +201,7 @@ pub struct StaticWithoutBody {
|
|||
pub replace_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::ty_alias_without_body)]
|
||||
pub struct TyAliasWithoutBody {
|
||||
#[primary_span]
|
||||
|
@ -221,7 +210,7 @@ pub struct TyAliasWithoutBody {
|
|||
pub replace_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_without_body)]
|
||||
pub struct FnWithoutBody {
|
||||
#[primary_span]
|
||||
|
@ -238,7 +227,7 @@ pub struct ExternBlockSuggestion {
|
|||
pub abi: Option<Symbol>,
|
||||
}
|
||||
|
||||
impl AddSubdiagnostic for ExternBlockSuggestion {
|
||||
impl AddToDiagnostic for ExternBlockSuggestion {
|
||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
||||
let start_suggestion = if let Some(abi) = self.abi {
|
||||
format!("extern \"{}\" {{", abi)
|
||||
|
|
|
@ -3,15 +3,13 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
|||
use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
|
||||
use rustc_ast::{PatKind, RangeEnd, VariantData};
|
||||
use rustc_errors::{struct_span_err, Applicability, StashKey};
|
||||
use rustc_feature::Features;
|
||||
use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_session::parse::{feature_err, feature_warn};
|
||||
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
use tracing::debug;
|
||||
use rustc_target::spec::abi;
|
||||
|
||||
macro_rules! gate_feature_fn {
|
||||
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
|
||||
|
@ -86,210 +84,26 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
match symbol_unescaped.as_str() {
|
||||
// Stable
|
||||
"Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
|
||||
| "system" => {}
|
||||
"rust-intrinsic" => {
|
||||
gate_feature_post!(&self, intrinsics, span, "intrinsics are subject to change");
|
||||
}
|
||||
"platform-intrinsic" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
platform_intrinsics,
|
||||
match abi::is_enabled(&self.features, span, symbol_unescaped.as_str()) {
|
||||
Ok(()) => (),
|
||||
Err(abi::AbiDisabled::Unstable { feature, explain }) => {
|
||||
feature_err_issue(
|
||||
&self.sess.parse_sess,
|
||||
feature,
|
||||
span,
|
||||
"platform intrinsics are experimental and possibly buggy"
|
||||
);
|
||||
GateIssue::Language,
|
||||
explain,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
"vectorcall" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_vectorcall,
|
||||
span,
|
||||
"vectorcall is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"thiscall" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_thiscall,
|
||||
span,
|
||||
"thiscall is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"rust-call" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
unboxed_closures,
|
||||
span,
|
||||
"rust-call ABI is subject to change"
|
||||
);
|
||||
}
|
||||
"rust-cold" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
rust_cold_cc,
|
||||
span,
|
||||
"rust-cold is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"ptx-kernel" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_ptx,
|
||||
span,
|
||||
"PTX ABIs are experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"unadjusted" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_unadjusted,
|
||||
span,
|
||||
"unadjusted ABI is an implementation detail and perma-unstable"
|
||||
);
|
||||
}
|
||||
"msp430-interrupt" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_msp430_interrupt,
|
||||
span,
|
||||
"msp430-interrupt ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"x86-interrupt" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_x86_interrupt,
|
||||
span,
|
||||
"x86-interrupt ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"amdgpu-kernel" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_amdgpu_kernel,
|
||||
span,
|
||||
"amdgpu-kernel ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"avr-interrupt" | "avr-non-blocking-interrupt" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_avr_interrupt,
|
||||
span,
|
||||
"avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"efiapi" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_efiapi,
|
||||
span,
|
||||
"efiapi ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"C-cmse-nonsecure-call" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
abi_c_cmse_nonsecure_call,
|
||||
span,
|
||||
"C-cmse-nonsecure-call ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"C-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"C-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"stdcall-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"stdcall-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"system-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"system-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"thiscall-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"thiscall-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"cdecl-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"cdecl-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"fastcall-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"fastcall-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"vectorcall-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"vectorcall-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"aapcs-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"aapcs-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"win64-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"win64-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"sysv64-unwind" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
c_unwind,
|
||||
span,
|
||||
"sysv64-unwind ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
"wasm" => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
wasm_abi,
|
||||
span,
|
||||
"wasm ABI is experimental and subject to change"
|
||||
);
|
||||
}
|
||||
abi => {
|
||||
Err(abi::AbiDisabled::Unrecognized) => {
|
||||
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
|
||||
self.sess.parse_sess.span_diagnostic.delay_span_bug(
|
||||
span,
|
||||
&format!("unrecognized ABI not caught in lowering: {}", abi),
|
||||
&format!(
|
||||
"unrecognized ABI not caught in lowering: {}",
|
||||
symbol_unescaped.as_str()
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -342,25 +156,6 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_gat(&self, generics: &ast::Generics, span: Span) {
|
||||
if !generics.params.is_empty() {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
generic_associated_types,
|
||||
span,
|
||||
"generic associated types are unstable"
|
||||
);
|
||||
}
|
||||
if !generics.where_clause.predicates.is_empty() {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
generic_associated_types,
|
||||
span,
|
||||
"where clauses on associated types are unstable"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
|
||||
fn check_impl_trait(&self, ty: &ast::Ty) {
|
||||
struct ImplTraitVisitor<'a> {
|
||||
|
@ -575,6 +370,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
ast::TyKind::Never => {
|
||||
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||
}
|
||||
ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::DynStar, ..) => {
|
||||
gate_feature_post!(&self, dyn_star, ty.span, "dyn* trait objects are unstable");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_ty(self, ty)
|
||||
|
@ -701,7 +499,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
|
||||
}
|
||||
|
||||
visit::walk_fn(self, fn_kind, span)
|
||||
visit::walk_fn(self, fn_kind)
|
||||
}
|
||||
|
||||
fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) {
|
||||
|
@ -719,7 +517,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||
let is_fn = match i.kind {
|
||||
ast::AssocItemKind::Fn(_) => true,
|
||||
ast::AssocItemKind::TyAlias(box ast::TyAlias { ref generics, ref ty, .. }) => {
|
||||
ast::AssocItemKind::TyAlias(box ast::TyAlias { ref ty, .. }) => {
|
||||
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
|
@ -731,7 +529,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
if let Some(ty) = ty {
|
||||
self.check_impl_trait(ty);
|
||||
}
|
||||
self.check_gat(generics, i.span);
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
#![feature(if_let_guard)]
|
||||
#![feature(iter_is_partitioned)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
pub mod ast_validation;
|
||||
mod errors;
|
||||
pub mod feature_gate;
|
||||
|
|
|
@ -63,9 +63,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
|
|||
self.count += 1;
|
||||
walk_generics(self, g)
|
||||
}
|
||||
fn visit_fn(&mut self, fk: visit::FnKind<'_>, s: Span, _: NodeId) {
|
||||
fn visit_fn(&mut self, fk: visit::FnKind<'_>, _: Span, _: NodeId) {
|
||||
self.count += 1;
|
||||
walk_fn(self, fk, s)
|
||||
walk_fn(self, fk)
|
||||
}
|
||||
fn visit_assoc_item(&mut self, ti: &AssocItem, ctxt: AssocCtxt) {
|
||||
self.count += 1;
|
||||
|
@ -115,9 +115,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
|
|||
self.count += 1;
|
||||
walk_use_tree(self, use_tree, id)
|
||||
}
|
||||
fn visit_generic_args(&mut self, path_span: Span, generic_args: &GenericArgs) {
|
||||
fn visit_generic_args(&mut self, generic_args: &GenericArgs) {
|
||||
self.count += 1;
|
||||
walk_generic_args(self, path_span, generic_args)
|
||||
walk_generic_args(self, generic_args)
|
||||
}
|
||||
fn visit_assoc_constraint(&mut self, constraint: &AssocConstraint) {
|
||||
self.count += 1;
|
||||
|
|
|
@ -11,8 +11,8 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
|||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
|
||||
use rustc_ast::util::parser;
|
||||
use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
||||
use rustc_ast::{attr, Term};
|
||||
use rustc_ast::{self as ast, BlockCheckMode, Mutability, PatKind, RangeEnd, RangeSyntax};
|
||||
use rustc_ast::{attr, BindingAnnotation, ByRef, Term};
|
||||
use rustc_ast::{GenericArg, MacArgs, MacArgsEq};
|
||||
use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
|
||||
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
||||
|
@ -22,6 +22,7 @@ use rustc_span::source_map::{SourceMap, Spanned};
|
|||
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
|
||||
use rustc_span::{BytePos, FileName, Span};
|
||||
|
||||
use rustc_ast::attr::AttrIdGenerator;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub use self::delimited::IterDelimited;
|
||||
|
@ -107,6 +108,7 @@ pub fn print_crate<'a>(
|
|||
ann: &'a dyn PpAnn,
|
||||
is_expanded: bool,
|
||||
edition: Edition,
|
||||
g: &AttrIdGenerator,
|
||||
) -> String {
|
||||
let mut s =
|
||||
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
|
||||
|
@ -120,7 +122,7 @@ pub fn print_crate<'a>(
|
|||
// `#![feature(prelude_import)]`
|
||||
let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import));
|
||||
let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]);
|
||||
let fake_attr = attr::mk_attr_inner(list);
|
||||
let fake_attr = attr::mk_attr_inner(g, list);
|
||||
s.print_attribute(&fake_attr);
|
||||
|
||||
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
|
||||
|
@ -128,7 +130,7 @@ pub fn print_crate<'a>(
|
|||
if edition == Edition::Edition2015 {
|
||||
// `#![no_std]`
|
||||
let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std));
|
||||
let fake_attr = attr::mk_attr_inner(no_std_meta);
|
||||
let fake_attr = attr::mk_attr_inner(g, no_std_meta);
|
||||
s.print_attribute(&fake_attr);
|
||||
}
|
||||
}
|
||||
|
@ -1399,16 +1401,12 @@ impl<'a> State<'a> {
|
|||
is that it doesn't matter */
|
||||
match pat.kind {
|
||||
PatKind::Wild => self.word("_"),
|
||||
PatKind::Ident(binding_mode, ident, ref sub) => {
|
||||
match binding_mode {
|
||||
ast::BindingMode::ByRef(mutbl) => {
|
||||
self.word_nbsp("ref");
|
||||
self.print_mutability(mutbl, false);
|
||||
}
|
||||
ast::BindingMode::ByValue(ast::Mutability::Not) => {}
|
||||
ast::BindingMode::ByValue(ast::Mutability::Mut) => {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, ref sub) => {
|
||||
if by_ref == ByRef::Yes {
|
||||
self.word_nbsp("ref");
|
||||
}
|
||||
if mutbl == Mutability::Mut {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
self.print_ident(ident);
|
||||
if let Some(ref p) = *sub {
|
||||
|
@ -1487,12 +1485,10 @@ impl<'a> State<'a> {
|
|||
}
|
||||
PatKind::Ref(ref inner, mutbl) => {
|
||||
self.word("&");
|
||||
if mutbl == ast::Mutability::Mut {
|
||||
if mutbl == Mutability::Mut {
|
||||
self.word("mut ");
|
||||
}
|
||||
if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) =
|
||||
inner.kind
|
||||
{
|
||||
if let PatKind::Ident(ast::BindingAnnotation::MUT, ..) = inner.kind {
|
||||
self.popen();
|
||||
self.print_pat(inner);
|
||||
self.pclose();
|
||||
|
|
|
@ -218,6 +218,8 @@ impl<'a> State<'a> {
|
|||
ast::ItemKind::GlobalAsm(ref asm) => {
|
||||
self.head(visibility_qualified(&item.vis, "global_asm!"));
|
||||
self.print_inline_asm(asm);
|
||||
self.word(";");
|
||||
self.end();
|
||||
self.end();
|
||||
}
|
||||
ast::ItemKind::TyAlias(box ast::TyAlias {
|
||||
|
|
|
@ -15,6 +15,18 @@ use std::num::NonZeroU32;
|
|||
|
||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||
|
||||
/// The version placeholder that recently stabilized features contain inside the
|
||||
/// `since` field of the `#[stable]` attribute.
|
||||
///
|
||||
/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
|
||||
pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
|
||||
|
||||
pub fn rust_version_symbol() -> Symbol {
|
||||
let version = option_env!("CFG_VERSION").unwrap_or("<current>");
|
||||
let version = version.split(' ').next().unwrap();
|
||||
Symbol::intern(&version)
|
||||
}
|
||||
|
||||
pub fn is_builtin_attr(attr: &Attribute) -> bool {
|
||||
attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
|
||||
}
|
||||
|
@ -57,7 +69,12 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
|
|||
sess.emit_err(session_diagnostics::MultipleStabilityLevels { span });
|
||||
}
|
||||
AttrError::UnsupportedLiteral(reason, is_bytestr) => {
|
||||
sess.emit_err(session_diagnostics::UnsupportedLiteral { span, reason, is_bytestr });
|
||||
sess.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span,
|
||||
reason,
|
||||
is_bytestr,
|
||||
start_point_span: sess.source_map().start_point(span),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -483,6 +500,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
|
||||
since = Some(rust_version_symbol());
|
||||
}
|
||||
|
||||
match (feature, since) {
|
||||
(Some(feature), Some(since)) => {
|
||||
let level = Stable { since, allowed_through_unstable_modules: false };
|
||||
|
@ -1028,18 +1049,16 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
&name,
|
||||
),
|
||||
});
|
||||
} else {
|
||||
if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::C | sym::simd | sym::transparent
|
||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
|
||||
span: meta_item.span,
|
||||
name: meta_item.name_or_empty().to_ident_string(),
|
||||
});
|
||||
}
|
||||
} else if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::C | sym::simd | sym::transparent
|
||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
|
||||
span: meta_item.span,
|
||||
name: meta_item.name_or_empty().to_ident_string(),
|
||||
});
|
||||
}
|
||||
} else if let MetaItemKind::List(_) = meta_item.kind {
|
||||
if meta_item.has_name(sym::align) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
//! to this crate.
|
||||
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
use std::num::IntErrorKind;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::{error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_macros::SessionDiagnostic;
|
||||
use rustc_session::{parse::ParseSess, SessionDiagnostic};
|
||||
use rustc_errors::{
|
||||
error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
|
||||
};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
use crate::UnsupportedLiteralReason;
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expected_one_cfg_pattern, code = "E0536")]
|
||||
pub(crate) struct ExpectedOneCfgPattern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_predicate, code = "E0537")]
|
||||
pub(crate) struct InvalidPredicate {
|
||||
#[primary_span]
|
||||
|
@ -24,7 +25,7 @@ pub(crate) struct InvalidPredicate {
|
|||
pub predicate: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::multiple_item, code = "E0538")]
|
||||
pub(crate) struct MultipleItem {
|
||||
#[primary_span]
|
||||
|
@ -33,7 +34,7 @@ pub(crate) struct MultipleItem {
|
|||
pub item: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_meta_item, code = "E0539")]
|
||||
pub(crate) struct IncorrectMetaItem {
|
||||
#[primary_span]
|
||||
|
@ -48,10 +49,10 @@ pub(crate) struct UnknownMetaItem<'a> {
|
|||
}
|
||||
|
||||
// Manual implementation to be able to format `expected` items correctly.
|
||||
impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> {
|
||||
fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
|
||||
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
|
||||
let mut diag = sess.span_diagnostic.struct_span_err_with_code(
|
||||
let mut diag = handler.struct_span_err_with_code(
|
||||
self.span,
|
||||
fluent::attr::unknown_meta_item,
|
||||
error_code!(E0541),
|
||||
|
@ -63,28 +64,28 @@ impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::missing_since, code = "E0542")]
|
||||
pub(crate) struct MissingSince {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::missing_note, code = "E0543")]
|
||||
pub(crate) struct MissingNote {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::multiple_stability_levels, code = "E0544")]
|
||||
pub(crate) struct MultipleStabilityLevels {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_issue_string, code = "E0545")]
|
||||
pub(crate) struct InvalidIssueString {
|
||||
#[primary_span]
|
||||
|
@ -96,7 +97,7 @@ pub(crate) struct InvalidIssueString {
|
|||
|
||||
// The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be
|
||||
// translatable.
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum InvalidIssueStringCause {
|
||||
#[label(attr::must_not_be_zero)]
|
||||
MustNotBeZero {
|
||||
|
@ -142,21 +143,21 @@ impl InvalidIssueStringCause {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::missing_feature, code = "E0546")]
|
||||
pub(crate) struct MissingFeature {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::non_ident_feature, code = "E0546")]
|
||||
pub(crate) struct NonIdentFeature {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::missing_issue, code = "E0547")]
|
||||
pub(crate) struct MissingIssue {
|
||||
#[primary_span]
|
||||
|
@ -165,7 +166,7 @@ pub(crate) struct MissingIssue {
|
|||
|
||||
// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider
|
||||
// changing this to `IncorrectMetaItem`. See #51489.
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_meta_item, code = "E0551")]
|
||||
pub(crate) struct IncorrectMetaItem2 {
|
||||
#[primary_span]
|
||||
|
@ -174,14 +175,14 @@ pub(crate) struct IncorrectMetaItem2 {
|
|||
|
||||
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
|
||||
// It is more similar to `IncorrectReprFormatGeneric`.
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
|
||||
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_repr_hint_no_paren, code = "E0552")]
|
||||
pub(crate) struct InvalidReprHintNoParen {
|
||||
#[primary_span]
|
||||
|
@ -190,7 +191,7 @@ pub(crate) struct InvalidReprHintNoParen {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_repr_hint_no_value, code = "E0552")]
|
||||
pub(crate) struct InvalidReprHintNoValue {
|
||||
#[primary_span]
|
||||
|
@ -204,11 +205,12 @@ pub(crate) struct UnsupportedLiteral {
|
|||
pub span: Span,
|
||||
pub reason: UnsupportedLiteralReason,
|
||||
pub is_bytestr: bool,
|
||||
pub start_point_span: Span,
|
||||
}
|
||||
|
||||
impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
|
||||
fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut diag = sess.span_diagnostic.struct_span_err_with_code(
|
||||
impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
||||
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut diag = handler.struct_span_err_with_code(
|
||||
self.span,
|
||||
match self.reason {
|
||||
UnsupportedLiteralReason::Generic => fluent::attr::unsupported_literal_generic,
|
||||
|
@ -224,7 +226,7 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
|
|||
);
|
||||
if self.is_bytestr {
|
||||
diag.span_suggestion(
|
||||
sess.source_map().start_point(self.span),
|
||||
self.start_point_span,
|
||||
fluent::attr::unsupported_literal_suggestion,
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -234,7 +236,7 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_repr_align_need_arg, code = "E0589")]
|
||||
pub(crate) struct InvalidReprAlignNeedArg {
|
||||
#[primary_span]
|
||||
|
@ -242,7 +244,7 @@ pub(crate) struct InvalidReprAlignNeedArg {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_repr_generic, code = "E0589")]
|
||||
pub(crate) struct InvalidReprGeneric<'a> {
|
||||
#[primary_span]
|
||||
|
@ -252,14 +254,14 @@ pub(crate) struct InvalidReprGeneric<'a> {
|
|||
pub error_part: &'a str,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_repr_format_align_one_arg, code = "E0693")]
|
||||
pub(crate) struct IncorrectReprFormatAlignOneArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_repr_format_generic, code = "E0693")]
|
||||
pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
||||
#[primary_span]
|
||||
|
@ -271,7 +273,7 @@ pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
|||
pub cause: Option<IncorrectReprFormatGenericCause<'a>>,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
||||
#[suggestion(attr::suggestion, code = "{name}({int})", applicability = "machine-applicable")]
|
||||
Int {
|
||||
|
@ -314,28 +316,28 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::rustc_promotable_pairing, code = "E0717")]
|
||||
pub(crate) struct RustcPromotablePairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::rustc_allowed_unstable_pairing, code = "E0789")]
|
||||
pub(crate) struct RustcAllowedUnstablePairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::cfg_predicate_identifier)]
|
||||
pub(crate) struct CfgPredicateIdentifier {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::deprecated_item_suggestion)]
|
||||
pub(crate) struct DeprecatedItemSuggestion {
|
||||
#[primary_span]
|
||||
|
@ -348,21 +350,21 @@ pub(crate) struct DeprecatedItemSuggestion {
|
|||
pub details: (),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expected_single_version_literal)]
|
||||
pub(crate) struct ExpectedSingleVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expected_version_literal)]
|
||||
pub(crate) struct ExpectedVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expects_feature_list)]
|
||||
pub(crate) struct ExpectsFeatureList {
|
||||
#[primary_span]
|
||||
|
@ -371,7 +373,7 @@ pub(crate) struct ExpectsFeatureList {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expects_features)]
|
||||
pub(crate) struct ExpectsFeatures {
|
||||
#[primary_span]
|
||||
|
@ -380,14 +382,14 @@ pub(crate) struct ExpectsFeatures {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::soft_no_args)]
|
||||
pub(crate) struct SoftNoArgs {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::unknown_version_literal)]
|
||||
pub(crate) struct UnknownVersionLiteral {
|
||||
#[primary_span]
|
||||
|
|
|
@ -21,10 +21,7 @@ pub(crate) struct OutlivesConstraintSet<'tcx> {
|
|||
|
||||
impl<'tcx> OutlivesConstraintSet<'tcx> {
|
||||
pub(crate) fn push(&mut self, constraint: OutlivesConstraint<'tcx>) {
|
||||
debug!(
|
||||
"OutlivesConstraintSet::push({:?}: {:?} @ {:?}",
|
||||
constraint.sup, constraint.sub, constraint.locations
|
||||
);
|
||||
debug!("OutlivesConstraintSet::push({:?})", constraint);
|
||||
if constraint.sup == constraint.sub {
|
||||
// 'a: 'a is pretty uninteresting
|
||||
return;
|
||||
|
@ -73,7 +70,7 @@ impl<'tcx> Index<OutlivesConstraintIndex> for OutlivesConstraintSet<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct OutlivesConstraint<'tcx> {
|
||||
// NB. The ordering here is not significant for correctness, but
|
||||
// it is for convenience. Before we dump the constraints in the
|
||||
|
|
|
@ -391,7 +391,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
|||
| mir::StatementKind::Retag { .. }
|
||||
| mir::StatementKind::AscribeUserType(..)
|
||||
| mir::StatementKind::Coverage(..)
|
||||
| mir::StatementKind::CopyNonOverlapping(..)
|
||||
| mir::StatementKind::Intrinsic(..)
|
||||
| mir::StatementKind::Nop => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use rustc_middle::mir::{
|
|||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
|
||||
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
||||
};
|
||||
use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty};
|
||||
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
|
||||
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
|
@ -198,7 +198,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
move_span,
|
||||
move_spans,
|
||||
*moved_place,
|
||||
Some(used_place),
|
||||
partially_str,
|
||||
loop_message,
|
||||
move_msg,
|
||||
|
@ -258,7 +257,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let ty = place.ty(self.body, self.infcx.tcx).ty;
|
||||
|
||||
// If we're in pattern, we do nothing in favor of the previous suggestion (#80913).
|
||||
if is_loop_move & !in_pattern {
|
||||
// Same for if we're in a loop, see #101119.
|
||||
if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) {
|
||||
if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
|
||||
// We have a `&mut` ref, we need to reborrow on each iteration (#62112).
|
||||
err.span_suggestion_verbose(
|
||||
|
@ -368,6 +368,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
|
||||
visitor.visit_body(&body);
|
||||
|
||||
let mut show_assign_sugg = false;
|
||||
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
|
||||
| InitializationRequiringAction::Assignment = desired_action
|
||||
{
|
||||
|
@ -395,6 +396,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
.count()
|
||||
== 0
|
||||
{
|
||||
show_assign_sugg = true;
|
||||
"isn't initialized"
|
||||
} else {
|
||||
"is possibly-uninitialized"
|
||||
|
@ -445,10 +447,78 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
err.span_label(decl_span, "binding declared here but left uninitialized");
|
||||
if show_assign_sugg {
|
||||
struct LetVisitor {
|
||||
decl_span: Span,
|
||||
sugg_span: Option<Span>,
|
||||
}
|
||||
|
||||
impl<'v> Visitor<'v> for LetVisitor {
|
||||
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
|
||||
if self.sugg_span.is_some() {
|
||||
return;
|
||||
}
|
||||
if let hir::StmtKind::Local(hir::Local {
|
||||
span, ty, init: None, ..
|
||||
}) = &ex.kind && span.contains(self.decl_span) {
|
||||
self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span));
|
||||
}
|
||||
hir::intravisit::walk_stmt(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = LetVisitor { decl_span, sugg_span: None };
|
||||
visitor.visit_body(&body);
|
||||
if let Some(span) = visitor.sugg_span {
|
||||
self.suggest_assign_value(&mut err, moved_place, span);
|
||||
}
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
fn suggest_assign_value(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
moved_place: PlaceRef<'tcx>,
|
||||
sugg_span: Span,
|
||||
) {
|
||||
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
|
||||
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
let implements_default = |ty, param_env| {
|
||||
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
|
||||
return false;
|
||||
};
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
infcx
|
||||
.type_implements_trait(default_trait, ty, ty::List::empty(), param_env)
|
||||
.may_apply()
|
||||
})
|
||||
};
|
||||
|
||||
let assign_value = match ty.kind() {
|
||||
ty::Bool => "false",
|
||||
ty::Float(_) => "0.0",
|
||||
ty::Int(_) | ty::Uint(_) => "0",
|
||||
ty::Never | ty::Error(_) => "",
|
||||
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]",
|
||||
ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()",
|
||||
_ => "todo!()",
|
||||
};
|
||||
|
||||
if !assign_value.is_empty() {
|
||||
err.span_suggestion_verbose(
|
||||
sugg_span.shrink_to_hi(),
|
||||
format!("consider assigning a value"),
|
||||
format!(" = {}", assign_value),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_borrow_fn_like(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
|
@ -2145,7 +2215,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
StorageDeadOrDrop::Destructor(_) => kind,
|
||||
},
|
||||
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
|
||||
ProjectionElem::OpaqueCast { .. }
|
||||
| ProjectionElem::Field(..)
|
||||
| ProjectionElem::Downcast(..) => {
|
||||
match place_ty.ty.kind() {
|
||||
ty::Adt(def, _) if def.has_dtor(tcx) => {
|
||||
// Report the outermost adt with a destructor
|
||||
|
|
|
@ -15,7 +15,7 @@ use rustc_middle::ty::{self, RegionVid, TyCtxt};
|
|||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{sym, DesugaringKind, Span};
|
||||
|
||||
use crate::region_infer::BlameConstraint;
|
||||
use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
|
||||
use crate::{
|
||||
borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt,
|
||||
WriteKind,
|
||||
|
@ -38,6 +38,7 @@ pub(crate) enum BorrowExplanation<'tcx> {
|
|||
span: Span,
|
||||
region_name: RegionName,
|
||||
opt_place_desc: Option<String>,
|
||||
extra_info: Vec<ExtraConstraintInfo>,
|
||||
},
|
||||
Unexplained,
|
||||
}
|
||||
|
@ -243,6 +244,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
ref region_name,
|
||||
ref opt_place_desc,
|
||||
from_closure: _,
|
||||
ref extra_info,
|
||||
} => {
|
||||
region_name.highlight_region_name(err);
|
||||
|
||||
|
@ -268,6 +270,14 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
);
|
||||
};
|
||||
|
||||
for extra in extra_info {
|
||||
match extra {
|
||||
ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
|
||||
err.span_note(*span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -309,18 +319,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
&self,
|
||||
borrow_region: RegionVid,
|
||||
outlived_region: RegionVid,
|
||||
) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>) {
|
||||
let BlameConstraint { category, from_closure, cause, variance_info: _ } =
|
||||
self.regioncx.best_blame_constraint(
|
||||
&self.body,
|
||||
borrow_region,
|
||||
NllRegionVariableOrigin::FreeRegion,
|
||||
|r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
|
||||
);
|
||||
) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) {
|
||||
let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint(
|
||||
borrow_region,
|
||||
NllRegionVariableOrigin::FreeRegion,
|
||||
|r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
|
||||
);
|
||||
let BlameConstraint { category, from_closure, cause, .. } = blame_constraint;
|
||||
|
||||
let outlived_fr_name = self.give_region_a_name(outlived_region);
|
||||
|
||||
(category, from_closure, cause.span, outlived_fr_name)
|
||||
(category, from_closure, cause.span, outlived_fr_name, extra_info)
|
||||
}
|
||||
|
||||
/// Returns structured explanation for *why* the borrow contains the
|
||||
|
@ -392,7 +401,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
None => {
|
||||
if let Some(region) = self.to_error_region_vid(borrow_region_vid) {
|
||||
let (category, from_closure, span, region_name) =
|
||||
let (category, from_closure, span, region_name, extra_info) =
|
||||
self.free_region_constraint_info(borrow_region_vid, region);
|
||||
if let Some(region_name) = region_name {
|
||||
let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
|
||||
|
@ -402,6 +411,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
span,
|
||||
region_name,
|
||||
opt_place_desc,
|
||||
extra_info,
|
||||
}
|
||||
} else {
|
||||
debug!("Could not generate a region name");
|
||||
|
|
|
@ -237,6 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
ProjectionElem::Downcast(..) if opt.including_downcast => return None,
|
||||
ProjectionElem::Downcast(..) => (),
|
||||
ProjectionElem::OpaqueCast(..) => (),
|
||||
ProjectionElem::Field(field, _ty) => {
|
||||
// FIXME(project-rfc_2229#36): print capture precisely here.
|
||||
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
|
||||
|
@ -317,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
|
||||
}
|
||||
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
|
||||
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
|
||||
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
|
||||
},
|
||||
};
|
||||
|
@ -970,7 +972,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
move_span: Span,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
moved_place: Place<'tcx>,
|
||||
used_place: Option<PlaceRef<'tcx>>,
|
||||
partially_str: &str,
|
||||
loop_message: &str,
|
||||
move_msg: &str,
|
||||
|
@ -1058,9 +1059,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
place_name, partially_str, loop_message
|
||||
),
|
||||
);
|
||||
// If we have a `&mut` ref, we need to reborrow.
|
||||
if let Some(ty::Ref(_, _, hir::Mutability::Mut)) = used_place
|
||||
.map(|used_place| used_place.ty(self.body, self.infcx.tcx).ty.kind())
|
||||
// If the moved place was a `&mut` ref, then we can
|
||||
// suggest to reborrow it where it was moved, so it
|
||||
// will still be valid by the time we get to the usage.
|
||||
if let ty::Ref(_, _, hir::Mutability::Mut) =
|
||||
moved_place.ty(self.body, self.infcx.tcx).ty.kind()
|
||||
{
|
||||
// If we are in a loop this will be suggested later.
|
||||
if !is_loop_move {
|
||||
|
|
|
@ -360,7 +360,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
diag.span_label(upvar_span, "captured outer variable");
|
||||
diag.span_label(
|
||||
self.body.span,
|
||||
self.infcx.tcx.def_span(def_id),
|
||||
format!("captured by this `{closure_kind}` closure"),
|
||||
);
|
||||
|
||||
|
@ -401,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
};
|
||||
if let Some(use_spans) = use_spans {
|
||||
self.explain_captures(
|
||||
&mut err, span, span, use_spans, move_place, None, "", "", "", false, true,
|
||||
&mut err, span, span, use_spans, move_place, "", "", "", false, true,
|
||||
);
|
||||
}
|
||||
err
|
||||
|
|
|
@ -9,10 +9,7 @@ use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{
|
||||
hir::place::PlaceBase,
|
||||
mir::{
|
||||
self, BindingForm, ClearCrossCrate, ImplicitSelfKind, Local, LocalDecl, LocalInfo,
|
||||
LocalKind, Location,
|
||||
},
|
||||
mir::{self, BindingForm, ClearCrossCrate, Local, LocalDecl, LocalInfo, LocalKind, Location},
|
||||
};
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
|
@ -172,6 +169,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
..,
|
||||
ProjectionElem::Index(_)
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::OpaqueCast { .. }
|
||||
| ProjectionElem::Subslice { .. }
|
||||
| ProjectionElem::Downcast(..),
|
||||
],
|
||||
|
@ -312,7 +310,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
&& !matches!(
|
||||
decl.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
ImplicitSelfKind::MutRef
|
||||
hir::ImplicitSelfKind::MutRef
|
||||
))))
|
||||
)
|
||||
{
|
||||
|
@ -367,7 +365,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
if let Some(Node::Pat(pat)) = self.infcx.tcx.hir().find(upvar_hir_id)
|
||||
&& let hir::PatKind::Binding(
|
||||
hir::BindingAnnotation::Unannotated,
|
||||
hir::BindingAnnotation::NONE,
|
||||
_,
|
||||
upvar_ident,
|
||||
_,
|
||||
|
@ -711,8 +709,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
self.suggested = true;
|
||||
} else if let hir::ExprKind::MethodCall(_path, args @ [_, ..], sp) = expr.kind
|
||||
&& let hir::ExprKind::Index(val, index) = args[0].kind
|
||||
} else if let hir::ExprKind::MethodCall(_path, receiver, _, sp) = expr.kind
|
||||
&& let hir::ExprKind::Index(val, index) = receiver.kind
|
||||
&& expr.span == self.assign_span
|
||||
{
|
||||
// val[index].path(args..);
|
||||
|
@ -724,7 +722,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
".get_mut(".to_string(),
|
||||
),
|
||||
(
|
||||
index.span.shrink_to_hi().with_hi(args[0].span.hi()),
|
||||
index.span.shrink_to_hi().with_hi(receiver.span.hi()),
|
||||
").map(|val| val".to_string(),
|
||||
),
|
||||
(sp.shrink_to_hi(), ")".to_string()),
|
||||
|
@ -911,11 +909,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
[
|
||||
Expr {
|
||||
kind:
|
||||
MethodCall(
|
||||
path_segment,
|
||||
_args,
|
||||
span,
|
||||
),
|
||||
MethodCall(path_segment, _, _, span),
|
||||
hir_id,
|
||||
..
|
||||
},
|
||||
|
@ -935,10 +929,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
_,
|
||||
) = hir_map.body(fn_body_id).value.kind
|
||||
{
|
||||
let opt_suggestions = path_segment
|
||||
.hir_id
|
||||
.map(|path_hir_id| self.infcx.tcx.typeck(path_hir_id.owner))
|
||||
.and_then(|typeck| typeck.type_dependent_def_id(*hir_id))
|
||||
let opt_suggestions = self
|
||||
.infcx
|
||||
.tcx
|
||||
.typeck(path_segment.hir_id.owner.def_id)
|
||||
.type_dependent_def_id(*hir_id)
|
||||
.and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
|
||||
.map(|def_id| self.infcx.tcx.associated_items(def_id))
|
||||
.map(|assoc_items| {
|
||||
|
@ -976,6 +971,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
let hir = self.infcx.tcx.hir();
|
||||
let closure_id = self.mir_hir_id();
|
||||
let closure_span = self.infcx.tcx.def_span(self.mir_def_id());
|
||||
let fn_call_id = hir.get_parent_node(closure_id);
|
||||
let node = hir.get(fn_call_id);
|
||||
let def_id = hir.enclosing_body_owner(fn_call_id);
|
||||
|
@ -1027,7 +1023,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if let Some(span) = arg {
|
||||
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
|
||||
err.span_label(func.span, "expects `Fn` instead of `FnMut`");
|
||||
err.span_label(self.body.span, "in this closure");
|
||||
err.span_label(closure_span, "in this closure");
|
||||
look_at_return = false;
|
||||
}
|
||||
}
|
||||
|
@ -1036,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if look_at_return && hir.get_return_block(closure_id).is_some() {
|
||||
// ...otherwise we are probably in the tail expression of the function, point at the
|
||||
// return type.
|
||||
match hir.get_by_def_id(hir.get_parent_item(fn_call_id)) {
|
||||
match hir.get_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
|
||||
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
|
||||
| hir::Node::TraitItem(hir::TraitItem {
|
||||
ident,
|
||||
|
@ -1053,7 +1049,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
sig.decl.output.span(),
|
||||
"change this to return `FnMut` instead of `Fn`",
|
||||
);
|
||||
err.span_label(self.body.span, "in this closure");
|
||||
err.span_label(closure_span, "in this closure");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -1077,7 +1073,7 @@ fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symb
|
|||
//
|
||||
// Deliberately fall into this case for all implicit self types,
|
||||
// so that we don't fall in to the next case with them.
|
||||
*kind == mir::ImplicitSelfKind::MutRef
|
||||
*kind == hir::ImplicitSelfKind::MutRef
|
||||
}
|
||||
_ if Some(kw::SelfLower) == local_name => {
|
||||
// Otherwise, check if the name is the `self` keyword - in which case
|
||||
|
|
|
@ -6,7 +6,6 @@ use rustc_errors::Diagnostic;
|
|||
use rustc_middle::ty::RegionVid;
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::BTreeMap;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::MirBorrowckCtxt;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ use crate::session_diagnostics::{
|
|||
};
|
||||
|
||||
use super::{OutlivesSuggestionBuilder, RegionName};
|
||||
use crate::region_infer::BlameConstraint;
|
||||
use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
|
||||
use crate::{
|
||||
nll::ConstraintDescription,
|
||||
region_infer::{values::RegionElement, TypeTest},
|
||||
|
@ -234,7 +234,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
|
||||
let (_, cause) = self.regioncx.find_outlives_blame_span(
|
||||
&self.body,
|
||||
longer_fr,
|
||||
NllRegionVariableOrigin::Placeholder(placeholder),
|
||||
error_vid,
|
||||
|
@ -282,7 +281,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let tcx = self.infcx.tcx;
|
||||
match tcx.hir().get_if_local(def_id) {
|
||||
Some(Node::ImplItem(impl_item)) => {
|
||||
match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) {
|
||||
match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
|
||||
{
|
||||
Some(Node::Item(Item {
|
||||
kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
|
||||
..
|
||||
|
@ -292,7 +292,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
Some(Node::TraitItem(trait_item)) => {
|
||||
let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
|
||||
match tcx.hir().find_by_def_id(trait_did) {
|
||||
match tcx.hir().find_by_def_id(trait_did.def_id) {
|
||||
Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
|
||||
// The method being called is defined in the `trait`, but the `'static`
|
||||
// obligation comes from the `impl`. Find that `impl` so that we can point
|
||||
|
@ -355,10 +355,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
) {
|
||||
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
|
||||
|
||||
let BlameConstraint { category, cause, variance_info, from_closure: _ } =
|
||||
self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| {
|
||||
let (blame_constraint, extra_info) =
|
||||
self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
|
||||
self.regioncx.provides_universal_region(r, fr, outlived_fr)
|
||||
});
|
||||
let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
|
||||
|
||||
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
|
||||
|
||||
|
@ -467,6 +468,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
for extra in extra_info {
|
||||
match extra {
|
||||
ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
|
||||
diag.span_note(span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.buffer_error(diag);
|
||||
}
|
||||
|
||||
|
@ -558,6 +567,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
/// LL | ref_obj(x)
|
||||
/// | ^^^^^^^^^^ `x` escapes the function body here
|
||||
/// ```
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn report_escaping_data_error(
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo<'tcx>,
|
||||
|
@ -900,10 +910,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let mut closure_span = None::<rustc_span::Span>;
|
||||
match expr.kind {
|
||||
hir::ExprKind::MethodCall(.., args, _) => {
|
||||
// only the first closre parameter of the method. args[0] is MethodCall PathSegment
|
||||
for i in 1..args.len() {
|
||||
if let hir::ExprKind::Closure(..) = args[i].kind {
|
||||
closure_span = Some(args[i].span.shrink_to_lo());
|
||||
for arg in args {
|
||||
if let hir::ExprKind::Closure(hir::Closure {
|
||||
capture_clause: hir::CaptureBy::Ref,
|
||||
..
|
||||
}) = arg.kind
|
||||
{
|
||||
closure_span = Some(arg.span.shrink_to_lo());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -911,7 +924,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
hir::ExprKind::Block(blk, _) => {
|
||||
if let Some(ref expr) = blk.expr {
|
||||
// only when the block is a closure
|
||||
if let hir::ExprKind::Closure(..) = expr.kind {
|
||||
if let hir::ExprKind::Closure(hir::Closure {
|
||||
capture_clause: hir::CaptureBy::Ref,
|
||||
..
|
||||
}) = expr.kind
|
||||
{
|
||||
closure_span = Some(expr.span.shrink_to_lo());
|
||||
}
|
||||
}
|
||||
|
@ -921,7 +938,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if let Some(closure_span) = closure_span {
|
||||
diag.span_suggestion_verbose(
|
||||
closure_span,
|
||||
format!("consider adding 'move' keyword before the nested closure"),
|
||||
"consider adding 'move' keyword before the nested closure",
|
||||
"move ",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
|
@ -265,7 +265,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
/// *user* has a name for. In that case, we'll be able to map
|
||||
/// `fr` to a `Region<'tcx>`, and that region will be one of
|
||||
/// named variants.
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
|
||||
let error_region = self.to_error_region(fr)?;
|
||||
|
||||
|
@ -357,11 +357,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
ty::BoundRegionKind::BrAnon(_) => None,
|
||||
},
|
||||
|
||||
ty::ReLateBound(..)
|
||||
| ty::ReVar(..)
|
||||
| ty::RePlaceholder(..)
|
||||
| ty::ReEmpty(_)
|
||||
| ty::ReErased => None,
|
||||
ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,7 +369,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
/// | fn foo(x: &u32) { .. }
|
||||
/// ------- fully elaborated type of `x` is `&'1 u32`
|
||||
/// ```
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn give_name_if_anonymous_region_appears_in_arguments(
|
||||
&self,
|
||||
fr: RegionVid,
|
||||
|
@ -662,7 +658,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
/// | let x = Some(&22);
|
||||
/// - fully elaborated type of `x` is `Option<&'1 u32>`
|
||||
/// ```
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
|
||||
let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
|
||||
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
|
||||
|
@ -682,7 +678,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
/// must be a closure since, in a free fn, such an argument would
|
||||
/// have to either also appear in an argument (if using elision)
|
||||
/// or be early bound (named, not in argument).
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let hir = tcx.hir();
|
||||
|
@ -711,7 +707,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
hir::AsyncGeneratorKind::Block => " of async block",
|
||||
hir::AsyncGeneratorKind::Closure => " of async closure",
|
||||
hir::AsyncGeneratorKind::Fn => {
|
||||
let parent_item = hir.get_by_def_id(hir.get_parent_item(mir_hir_id));
|
||||
let parent_item =
|
||||
hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("generator lowered from async fn should be in fn")
|
||||
|
@ -772,7 +769,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
|
||||
let hir = self.infcx.tcx.hir();
|
||||
|
||||
let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind else {
|
||||
let hir::TyKind::OpaqueDef(id, _, _) = hir_ty.kind else {
|
||||
span_bug!(
|
||||
hir_ty.span,
|
||||
"lowered return type of async fn is not OpaqueDef: {:?}",
|
||||
|
@ -814,7 +811,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn give_name_if_anonymous_region_appears_in_yield_ty(
|
||||
&self,
|
||||
fr: RegionVid,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{BasicBlock, Body, Location, Place, Rvalue};
|
||||
use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue};
|
||||
use rustc_middle::mir::{BorrowKind, Mutability, Operand};
|
||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||
use rustc_middle::mir::{Statement, StatementKind};
|
||||
|
@ -63,23 +63,24 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
StatementKind::FakeRead(box (_, _)) => {
|
||||
// Only relevant for initialized/liveness/safety checks.
|
||||
}
|
||||
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
|
||||
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
|
||||
self.consume_operand(location, op);
|
||||
}
|
||||
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
|
||||
ref src,
|
||||
ref dst,
|
||||
ref count,
|
||||
}) => {
|
||||
})) => {
|
||||
self.consume_operand(location, src);
|
||||
self.consume_operand(location, dst);
|
||||
self.consume_operand(location, count);
|
||||
}
|
||||
StatementKind::Nop
|
||||
// Only relevant for mir typeck
|
||||
StatementKind::AscribeUserType(..)
|
||||
// Doesn't have any language semantics
|
||||
| StatementKind::Coverage(..)
|
||||
| StatementKind::AscribeUserType(..)
|
||||
| StatementKind::Retag { .. }
|
||||
| StatementKind::StorageLive(..) => {
|
||||
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
|
||||
// to borrow check.
|
||||
}
|
||||
// Does not actually affect borrowck
|
||||
| StatementKind::StorageLive(..) => {}
|
||||
StatementKind::StorageDead(local) => {
|
||||
self.access_place(
|
||||
location,
|
||||
|
@ -88,7 +89,10 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
LocalMutationIsAllowed::Yes,
|
||||
);
|
||||
}
|
||||
StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
|
||||
StatementKind::Nop
|
||||
| StatementKind::Retag { .. }
|
||||
| StatementKind::Deinit(..)
|
||||
| StatementKind::SetDiscriminant { .. } => {
|
||||
bug!("Statement not allowed in this MIR phase")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#![allow(rustc::potential_query_instability)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
@ -26,8 +25,8 @@ use rustc_index::bit_set::ChunkedBitSet;
|
|||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_middle::mir::{
|
||||
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
|
||||
PlaceRef, VarDebugInfoContents,
|
||||
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
|
||||
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
|
||||
};
|
||||
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||
use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
||||
|
@ -134,7 +133,7 @@ fn mir_borrowck<'tcx>(
|
|||
|
||||
let opt_closure_req = tcx
|
||||
.infer_ctxt()
|
||||
.with_opaque_type_inference(DefiningAnchor::Bind(hir_owner))
|
||||
.with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id))
|
||||
.enter(|infcx| {
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||
|
@ -591,22 +590,19 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
|||
flow_state,
|
||||
);
|
||||
}
|
||||
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
|
||||
..
|
||||
}) => {
|
||||
span_bug!(
|
||||
StatementKind::Intrinsic(box ref kind) => match kind {
|
||||
NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state),
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
|
||||
span,
|
||||
"Unexpected CopyNonOverlapping, should only appear after lower_intrinsics",
|
||||
)
|
||||
}
|
||||
StatementKind::Nop
|
||||
// Only relevant for mir typeck
|
||||
StatementKind::AscribeUserType(..)
|
||||
// Doesn't have any language semantics
|
||||
| StatementKind::Coverage(..)
|
||||
| StatementKind::AscribeUserType(..)
|
||||
| StatementKind::Retag { .. }
|
||||
| StatementKind::StorageLive(..) => {
|
||||
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
|
||||
// to borrow check.
|
||||
}
|
||||
// Does not actually affect borrowck
|
||||
| StatementKind::StorageLive(..) => {}
|
||||
StatementKind::StorageDead(local) => {
|
||||
self.access_place(
|
||||
location,
|
||||
|
@ -616,7 +612,10 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
|||
flow_state,
|
||||
);
|
||||
}
|
||||
StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
|
||||
StatementKind::Nop
|
||||
| StatementKind::Retag { .. }
|
||||
| StatementKind::Deinit(..)
|
||||
| StatementKind::SetDiscriminant { .. } => {
|
||||
bug!("Statement not allowed in this MIR phase")
|
||||
}
|
||||
}
|
||||
|
@ -1781,6 +1780,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
for (place_base, elem) in place.iter_projections().rev() {
|
||||
match elem {
|
||||
ProjectionElem::Index(_/*operand*/) |
|
||||
ProjectionElem::OpaqueCast(_) |
|
||||
ProjectionElem::ConstantIndex { .. } |
|
||||
// assigning to P[i] requires P to be valid.
|
||||
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
|
||||
|
@ -2172,6 +2172,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
| ProjectionElem::Index(..)
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::Subslice { .. }
|
||||
| ProjectionElem::OpaqueCast { .. }
|
||||
| ProjectionElem::Downcast(..) => {
|
||||
let upvar_field_projection = self.is_upvar_field_projection(place);
|
||||
if let Some(field) = upvar_field_projection {
|
||||
|
|
|
@ -86,8 +86,7 @@ impl LocationTable {
|
|||
let (block, &first_index) = self
|
||||
.statements_before_block
|
||||
.iter_enumerated()
|
||||
.filter(|(_, first_index)| **first_index <= point_index)
|
||||
.last()
|
||||
.rfind(|&(_, &first_index)| first_index <= point_index)
|
||||
.unwrap();
|
||||
|
||||
let statement_index = (point_index - first_index) / 2;
|
||||
|
|
|
@ -389,8 +389,9 @@ pub(super) fn dump_annotation<'a, 'tcx>(
|
|||
// viewing the intraprocedural state, the -Zdump-mir output is
|
||||
// better.
|
||||
|
||||
let def_span = tcx.def_span(body.source.def_id());
|
||||
let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
|
||||
let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "external requirements");
|
||||
let mut err = tcx.sess.diagnostic().span_note_diag(def_span, "external requirements");
|
||||
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
|
@ -409,7 +410,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
|
|||
|
||||
err
|
||||
} else {
|
||||
let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "no external requirements");
|
||||
let mut err = tcx.sess.diagnostic().span_note_diag(def_span, "no external requirements");
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
err
|
||||
|
|
|
@ -250,6 +250,7 @@ fn place_components_conflict<'tcx>(
|
|||
| (ProjectionElem::Index { .. }, _, _)
|
||||
| (ProjectionElem::ConstantIndex { .. }, _, _)
|
||||
| (ProjectionElem::Subslice { .. }, _, _)
|
||||
| (ProjectionElem::OpaqueCast { .. }, _, _)
|
||||
| (ProjectionElem::Downcast { .. }, _, _) => {
|
||||
// Recursive case. This can still be disjoint on a
|
||||
// further iteration if this a shallow access and
|
||||
|
@ -317,6 +318,17 @@ fn place_projection_conflict<'tcx>(
|
|||
debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
|
||||
Overlap::EqualOrDisjoint
|
||||
}
|
||||
(ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
|
||||
if v1 == v2 {
|
||||
// same type - recur.
|
||||
debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
|
||||
Overlap::EqualOrDisjoint
|
||||
} else {
|
||||
// Different types. Disjoint!
|
||||
debug!("place_element_conflict: DISJOINT-OPAQUE");
|
||||
Overlap::Disjoint
|
||||
}
|
||||
}
|
||||
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
|
||||
if f1 == f2 {
|
||||
// same field (e.g., `a.y` vs. `a.y`) - recur.
|
||||
|
@ -520,6 +532,7 @@ fn place_projection_conflict<'tcx>(
|
|||
| ProjectionElem::Field(..)
|
||||
| ProjectionElem::Index(..)
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::OpaqueCast { .. }
|
||||
| ProjectionElem::Subslice { .. }
|
||||
| ProjectionElem::Downcast(..),
|
||||
_,
|
||||
|
|
|
@ -81,6 +81,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
|
|||
}
|
||||
ProjectionElem::Downcast(..)
|
||||
| ProjectionElem::Subslice { .. }
|
||||
| ProjectionElem::OpaqueCast { .. }
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::Index(_) => {
|
||||
cursor = cursor_base;
|
||||
|
|
|
@ -135,7 +135,6 @@ pub struct RegionInferenceContext<'tcx> {
|
|||
/// adds a new lower bound to the SCC it is analyzing: so you wind up
|
||||
/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
|
||||
/// minimal viable option.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub(crate) struct AppliedMemberConstraint {
|
||||
/// The SCC that was affected. (The "member region".)
|
||||
///
|
||||
|
@ -246,6 +245,11 @@ enum Trace<'tcx> {
|
|||
NotVisited,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum ExtraConstraintInfo {
|
||||
PlaceholderFromPredicate(Span),
|
||||
}
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// Creates a new region inference context with a total of
|
||||
/// `num_region_variables` valid inference variables; the first N
|
||||
|
@ -591,13 +595,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// constraints were too strong, and if so, emit or propagate those errors.
|
||||
if infcx.tcx.sess.opts.unstable_opts.polonius {
|
||||
self.check_polonius_subset_errors(
|
||||
body,
|
||||
outlives_requirements.as_mut(),
|
||||
&mut errors_buffer,
|
||||
polonius_output.expect("Polonius output is unavailable despite `-Z polonius`"),
|
||||
);
|
||||
} else {
|
||||
self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer);
|
||||
self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer);
|
||||
}
|
||||
|
||||
if errors_buffer.is_empty() {
|
||||
|
@ -1139,7 +1142,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// include the CFG anyhow.
|
||||
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
|
||||
/// a result `'y`.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
#[instrument(skip(self), level = "debug", ret)]
|
||||
pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
|
||||
debug!(r = %self.region_value_str(r));
|
||||
|
||||
|
@ -1151,8 +1154,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
|
||||
}
|
||||
|
||||
debug!(?lub);
|
||||
|
||||
lub
|
||||
}
|
||||
|
||||
|
@ -1333,15 +1334,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
}
|
||||
|
||||
// Evaluate whether `sup_region: sub_region`.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
#[instrument(skip(self), level = "debug", ret)]
|
||||
fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
|
||||
debug!(
|
||||
"eval_outlives: sup_region's value = {:?} universal={:?}",
|
||||
"sup_region's value = {:?} universal={:?}",
|
||||
self.region_value_str(sup_region),
|
||||
self.universal_regions.is_universal_region(sup_region),
|
||||
);
|
||||
debug!(
|
||||
"eval_outlives: sub_region's value = {:?} universal={:?}",
|
||||
"sub_region's value = {:?} universal={:?}",
|
||||
self.region_value_str(sub_region),
|
||||
self.universal_regions.is_universal_region(sub_region),
|
||||
);
|
||||
|
@ -1354,7 +1355,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// true if `'sup` outlives static.
|
||||
if !self.universe_compatible(sub_region_scc, sup_region_scc) {
|
||||
debug!(
|
||||
"eval_outlives: sub universe `{sub_region_scc:?}` is not nameable \
|
||||
"sub universe `{sub_region_scc:?}` is not nameable \
|
||||
by super `{sup_region_scc:?}`, promoting to static",
|
||||
);
|
||||
|
||||
|
@ -1375,9 +1376,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
});
|
||||
|
||||
if !universal_outlives {
|
||||
debug!(
|
||||
"eval_outlives: returning false because sub region contains a universal region not present in super"
|
||||
);
|
||||
debug!("sub region contains a universal region not present in super");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1386,15 +1385,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
if self.universal_regions.is_universal_region(sup_region) {
|
||||
// Micro-opt: universal regions contain all points.
|
||||
debug!(
|
||||
"eval_outlives: returning true because super is universal and hence contains all points"
|
||||
);
|
||||
debug!("super is universal and hence contains all points");
|
||||
return true;
|
||||
}
|
||||
|
||||
let result = self.scc_values.contains_points(sup_region_scc, sub_region_scc);
|
||||
debug!("returning {} because of comparison between points in sup/sub", result);
|
||||
result
|
||||
debug!("comparison between points in sup/sub");
|
||||
|
||||
self.scc_values.contains_points(sup_region_scc, sub_region_scc)
|
||||
}
|
||||
|
||||
/// Once regions have been propagated, this method is used to see
|
||||
|
@ -1416,7 +1413,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// report them as errors.
|
||||
fn check_universal_regions(
|
||||
&self,
|
||||
body: &Body<'tcx>,
|
||||
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
|
||||
errors_buffer: &mut RegionErrors<'tcx>,
|
||||
) {
|
||||
|
@ -1427,7 +1423,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// they did not grow too large, accumulating any requirements
|
||||
// for our caller into the `outlives_requirements` vector.
|
||||
self.check_universal_region(
|
||||
body,
|
||||
fr,
|
||||
&mut propagated_outlives_requirements,
|
||||
errors_buffer,
|
||||
|
@ -1468,7 +1463,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// report them as errors.
|
||||
fn check_polonius_subset_errors(
|
||||
&self,
|
||||
body: &Body<'tcx>,
|
||||
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
|
||||
errors_buffer: &mut RegionErrors<'tcx>,
|
||||
polonius_output: Rc<PoloniusOutput>,
|
||||
|
@ -1515,7 +1509,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let propagated = self.try_propagate_universal_region_error(
|
||||
*longer_fr,
|
||||
*shorter_fr,
|
||||
body,
|
||||
&mut propagated_outlives_requirements,
|
||||
);
|
||||
if propagated == RegionRelationCheckResult::Error {
|
||||
|
@ -1555,13 +1548,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
///
|
||||
/// Things that are to be propagated are accumulated into the
|
||||
/// `outlives_requirements` vector.
|
||||
#[instrument(
|
||||
skip(self, body, propagated_outlives_requirements, errors_buffer),
|
||||
level = "debug"
|
||||
)]
|
||||
#[instrument(skip(self, propagated_outlives_requirements, errors_buffer), level = "debug")]
|
||||
fn check_universal_region(
|
||||
&self,
|
||||
body: &Body<'tcx>,
|
||||
longer_fr: RegionVid,
|
||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
|
||||
errors_buffer: &mut RegionErrors<'tcx>,
|
||||
|
@ -1584,7 +1573,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
if let RegionRelationCheckResult::Error = self.check_universal_region_relation(
|
||||
longer_fr,
|
||||
representative,
|
||||
body,
|
||||
propagated_outlives_requirements,
|
||||
) {
|
||||
errors_buffer.push(RegionErrorKind::RegionError {
|
||||
|
@ -1604,7 +1592,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
if let RegionRelationCheckResult::Error = self.check_universal_region_relation(
|
||||
longer_fr,
|
||||
shorter_fr,
|
||||
body,
|
||||
propagated_outlives_requirements,
|
||||
) {
|
||||
// We only report the first region error. Subsequent errors are hidden so as
|
||||
|
@ -1629,7 +1616,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
&self,
|
||||
longer_fr: RegionVid,
|
||||
shorter_fr: RegionVid,
|
||||
body: &Body<'tcx>,
|
||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
|
||||
) -> RegionRelationCheckResult {
|
||||
// If it is known that `fr: o`, carry on.
|
||||
|
@ -1645,7 +1631,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
self.try_propagate_universal_region_error(
|
||||
longer_fr,
|
||||
shorter_fr,
|
||||
body,
|
||||
propagated_outlives_requirements,
|
||||
)
|
||||
}
|
||||
|
@ -1657,7 +1642,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
&self,
|
||||
longer_fr: RegionVid,
|
||||
shorter_fr: RegionVid,
|
||||
body: &Body<'tcx>,
|
||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
|
||||
) -> RegionRelationCheckResult {
|
||||
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
|
||||
|
@ -1669,7 +1653,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
|
||||
|
||||
let blame_span_category = self.find_outlives_blame_span(
|
||||
body,
|
||||
longer_fr,
|
||||
NllRegionVariableOrigin::FreeRegion,
|
||||
shorter_fr,
|
||||
|
@ -1823,50 +1806,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
pub(crate) fn retrieve_closure_constraint_info(
|
||||
&self,
|
||||
_body: &Body<'tcx>,
|
||||
constraint: &OutlivesConstraint<'tcx>,
|
||||
) -> BlameConstraint<'tcx> {
|
||||
let loc = match constraint.locations {
|
||||
Locations::All(span) => {
|
||||
return BlameConstraint {
|
||||
category: constraint.category,
|
||||
from_closure: false,
|
||||
cause: ObligationCause::dummy_with_span(span),
|
||||
variance_info: constraint.variance_info,
|
||||
};
|
||||
constraint: OutlivesConstraint<'tcx>,
|
||||
) -> Option<(ConstraintCategory<'tcx>, Span)> {
|
||||
match constraint.locations {
|
||||
Locations::All(_) => None,
|
||||
Locations::Single(loc) => {
|
||||
self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
|
||||
}
|
||||
Locations::Single(loc) => loc,
|
||||
};
|
||||
|
||||
let opt_span_category =
|
||||
self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
|
||||
opt_span_category
|
||||
.map(|&(category, span)| BlameConstraint {
|
||||
category,
|
||||
from_closure: true,
|
||||
cause: ObligationCause::dummy_with_span(span),
|
||||
variance_info: constraint.variance_info,
|
||||
})
|
||||
.unwrap_or(BlameConstraint {
|
||||
category: constraint.category,
|
||||
from_closure: false,
|
||||
cause: ObligationCause::dummy_with_span(constraint.span),
|
||||
variance_info: constraint.variance_info,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
|
||||
pub(crate) fn find_outlives_blame_span(
|
||||
&self,
|
||||
body: &Body<'tcx>,
|
||||
fr1: RegionVid,
|
||||
fr1_origin: NllRegionVariableOrigin,
|
||||
fr2: RegionVid,
|
||||
) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) {
|
||||
let BlameConstraint { category, cause, .. } =
|
||||
self.best_blame_constraint(body, fr1, fr1_origin, |r| {
|
||||
self.provides_universal_region(r, fr1, fr2)
|
||||
});
|
||||
let BlameConstraint { category, cause, .. } = self
|
||||
.best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2))
|
||||
.0;
|
||||
(category, cause)
|
||||
}
|
||||
|
||||
|
@ -1971,7 +1930,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
}
|
||||
|
||||
/// Finds some region R such that `fr1: R` and `R` is live at `elem`.
|
||||
#[instrument(skip(self), level = "trace")]
|
||||
#[instrument(skip(self), level = "trace", ret)]
|
||||
pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
|
||||
trace!(scc = ?self.constraint_sccs.scc(fr1));
|
||||
trace!(universe = ?self.scc_universes[self.constraint_sccs.scc(fr1)]);
|
||||
|
@ -2052,11 +2011,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
#[instrument(level = "debug", skip(self, target_test))]
|
||||
pub(crate) fn best_blame_constraint(
|
||||
&self,
|
||||
body: &Body<'tcx>,
|
||||
from_region: RegionVid,
|
||||
from_region_origin: NllRegionVariableOrigin,
|
||||
target_test: impl Fn(RegionVid) -> bool,
|
||||
) -> BlameConstraint<'tcx> {
|
||||
) -> (BlameConstraint<'tcx>, Vec<ExtraConstraintInfo>) {
|
||||
// Find all paths
|
||||
let (path, target_region) =
|
||||
self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
|
||||
|
@ -2072,6 +2030,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let mut extra_info = vec![];
|
||||
for constraint in path.iter() {
|
||||
let outlived = constraint.sub;
|
||||
let Some(origin) = self.var_infos.get(outlived) else { continue; };
|
||||
let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin else { continue; };
|
||||
debug!(?constraint, ?p);
|
||||
let ConstraintCategory::Predicate(span) = constraint.category else { continue; };
|
||||
extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span));
|
||||
// We only want to point to one
|
||||
break;
|
||||
}
|
||||
|
||||
// We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
|
||||
// Instead, we use it to produce an improved `ObligationCauseCode`.
|
||||
// FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate`
|
||||
|
@ -2097,19 +2067,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
|
||||
.iter()
|
||||
.map(|constraint| {
|
||||
if constraint.category == ConstraintCategory::ClosureBounds {
|
||||
self.retrieve_closure_constraint_info(body, &constraint)
|
||||
} else {
|
||||
BlameConstraint {
|
||||
category: constraint.category,
|
||||
from_closure: false,
|
||||
cause: ObligationCause::new(
|
||||
constraint.span,
|
||||
CRATE_HIR_ID,
|
||||
cause_code.clone(),
|
||||
),
|
||||
variance_info: constraint.variance_info,
|
||||
}
|
||||
let (category, span, from_closure, cause_code) =
|
||||
if constraint.category == ConstraintCategory::ClosureBounds {
|
||||
if let Some((category, span)) =
|
||||
self.retrieve_closure_constraint_info(*constraint)
|
||||
{
|
||||
(category, span, true, ObligationCauseCode::MiscObligation)
|
||||
} else {
|
||||
(
|
||||
constraint.category,
|
||||
constraint.span,
|
||||
false,
|
||||
ObligationCauseCode::MiscObligation,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
(constraint.category, constraint.span, false, cause_code.clone())
|
||||
};
|
||||
BlameConstraint {
|
||||
category,
|
||||
from_closure,
|
||||
cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
|
||||
variance_info: constraint.variance_info,
|
||||
outlives_constraint: *constraint,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
@ -2211,7 +2191,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let best_choice =
|
||||
if blame_source { range.rev().find(find_region) } else { range.find(find_region) };
|
||||
|
||||
debug!(?best_choice, ?blame_source);
|
||||
debug!(?best_choice, ?blame_source, ?extra_info);
|
||||
|
||||
if let Some(i) = best_choice {
|
||||
if let Some(next) = categorized_path.get(i + 1) {
|
||||
|
@ -2220,7 +2200,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
{
|
||||
// The return expression is being influenced by the return type being
|
||||
// impl Trait, point at the return type and not the return expr.
|
||||
return next.clone();
|
||||
return (next.clone(), extra_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2240,7 +2220,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
return categorized_path[i].clone();
|
||||
return (categorized_path[i].clone(), extra_info);
|
||||
}
|
||||
|
||||
// If that search fails, that is.. unusual. Maybe everything
|
||||
|
@ -2250,7 +2230,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
|
||||
debug!("sorted_path={:#?}", categorized_path);
|
||||
|
||||
categorized_path.remove(0)
|
||||
(categorized_path.remove(0), extra_info)
|
||||
}
|
||||
|
||||
pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
|
||||
|
@ -2332,7 +2312,13 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
|
|||
outlives_requirement={:?}",
|
||||
region, outlived_region, outlives_requirement,
|
||||
);
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(region.into(), outlived_region))
|
||||
(
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(
|
||||
region.into(),
|
||||
outlived_region,
|
||||
)),
|
||||
ConstraintCategory::BoringNoLocation,
|
||||
)
|
||||
}
|
||||
|
||||
ClosureOutlivesSubject::Ty(ty) => {
|
||||
|
@ -2342,7 +2328,10 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
|
|||
outlives_requirement={:?}",
|
||||
ty, outlived_region, outlives_requirement,
|
||||
);
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region))
|
||||
(
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
|
||||
ConstraintCategory::BoringNoLocation,
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -2356,4 +2345,5 @@ pub struct BlameConstraint<'tcx> {
|
|||
pub from_closure: bool,
|
||||
pub cause: ObligationCause<'tcx>,
|
||||
pub variance_info: ty::VarianceDiagInfo<'tcx>,
|
||||
pub outlives_constraint: OutlivesConstraint<'tcx>,
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
|
||||
/// which has no `external_name` in which case we use `'empty` as the
|
||||
/// region to pass to `infer_opaque_definition_from_instantiation`.
|
||||
#[instrument(level = "debug", skip(self, infcx))]
|
||||
#[instrument(level = "debug", skip(self, infcx), ret)]
|
||||
pub(crate) fn infer_opaque_types(
|
||||
&self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
|
@ -109,7 +109,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
.iter()
|
||||
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
|
||||
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
|
||||
.unwrap_or(infcx.tcx.lifetimes.re_root_empty),
|
||||
.unwrap_or(infcx.tcx.lifetimes.re_erased),
|
||||
_ => region,
|
||||
});
|
||||
|
||||
|
@ -433,7 +433,7 @@ struct ReverseMapper<'tcx> {
|
|||
|
||||
key: ty::OpaqueTypeKey<'tcx>,
|
||||
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
|
||||
map_missing_regions_to_empty: bool,
|
||||
do_not_error: bool,
|
||||
|
||||
/// initially `Some`, set to `None` once error has been reported
|
||||
hidden_ty: Option<Ty<'tcx>>,
|
||||
|
@ -450,29 +450,19 @@ impl<'tcx> ReverseMapper<'tcx> {
|
|||
hidden_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> Self {
|
||||
Self {
|
||||
tcx,
|
||||
key,
|
||||
map,
|
||||
map_missing_regions_to_empty: false,
|
||||
hidden_ty: Some(hidden_ty),
|
||||
span,
|
||||
}
|
||||
Self { tcx, key, map, do_not_error: false, hidden_ty: Some(hidden_ty), span }
|
||||
}
|
||||
|
||||
fn fold_kind_mapping_missing_regions_to_empty(
|
||||
&mut self,
|
||||
kind: GenericArg<'tcx>,
|
||||
) -> GenericArg<'tcx> {
|
||||
assert!(!self.map_missing_regions_to_empty);
|
||||
self.map_missing_regions_to_empty = true;
|
||||
fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
|
||||
assert!(!self.do_not_error);
|
||||
self.do_not_error = true;
|
||||
let kind = kind.fold_with(self);
|
||||
self.map_missing_regions_to_empty = false;
|
||||
self.do_not_error = false;
|
||||
kind
|
||||
}
|
||||
|
||||
fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
|
||||
assert!(!self.map_missing_regions_to_empty);
|
||||
assert!(!self.do_not_error);
|
||||
kind.fold_with(self)
|
||||
}
|
||||
}
|
||||
|
@ -496,9 +486,9 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
ty::ReErased => return r,
|
||||
|
||||
// The regions that we expect from borrow checking.
|
||||
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
|
||||
ty::ReEarlyBound(_) | ty::ReFree(_) => {}
|
||||
|
||||
ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => {
|
||||
ty::RePlaceholder(_) | ty::ReVar(_) => {
|
||||
// All of the regions in the type should either have been
|
||||
// erased by writeback, or mapped back to named regions by
|
||||
// borrow checking.
|
||||
|
@ -510,7 +500,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
match self.map.get(&r.into()).map(|k| k.unpack()) {
|
||||
Some(GenericArgKind::Lifetime(r1)) => r1,
|
||||
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
|
||||
None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty,
|
||||
None if self.do_not_error => self.tcx.lifetimes.re_static,
|
||||
None if generics.parent.is_some() => {
|
||||
if let Some(hidden_ty) = self.hidden_ty.take() {
|
||||
unexpected_hidden_region_diagnostic(
|
||||
|
@ -522,7 +512,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
)
|
||||
.emit();
|
||||
}
|
||||
self.tcx.lifetimes.re_root_empty
|
||||
self.tcx.lifetimes.re_static
|
||||
}
|
||||
None => {
|
||||
self.tcx
|
||||
|
@ -574,7 +564,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
|
||||
if index < generics.parent_count {
|
||||
// Accommodate missing regions in the parent kinds...
|
||||
self.fold_kind_mapping_missing_regions_to_empty(kind)
|
||||
self.fold_kind_no_missing_regions_error(kind)
|
||||
} else {
|
||||
// ...but not elsewhere.
|
||||
self.fold_kind_normally(kind)
|
||||
|
@ -589,7 +579,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
|
||||
if index < generics.parent_count {
|
||||
// Accommodate missing regions in the parent kinds...
|
||||
self.fold_kind_mapping_missing_regions_to_empty(kind)
|
||||
self.fold_kind_no_missing_regions_error(kind)
|
||||
} else {
|
||||
// ...but not elsewhere.
|
||||
self.fold_kind_normally(kind)
|
||||
|
|
|
@ -2,6 +2,7 @@ use rustc_index::vec::IndexVec;
|
|||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
|
||||
use rustc_middle::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc_middle::mir::{Body, Location, Promoted};
|
||||
use rustc_middle::mir::{Constant, ConstantKind};
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
|
||||
|
@ -37,6 +38,21 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
// FIXME(valtrees): This function is necessary because `fold_regions`
|
||||
// panics for mir constants in the visitor.
|
||||
//
|
||||
// Once `visit_mir_constant` is removed we can also remove this function
|
||||
// and just use `renumber_regions`.
|
||||
fn renumber_regions_in_mir_constant<'tcx>(
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
value: ConstantKind<'tcx>,
|
||||
) -> ConstantKind<'tcx> {
|
||||
infcx.tcx.super_fold_regions(value, |_region, _depth| {
|
||||
let origin = NllRegionVariableOrigin::Existential { from_forall: false };
|
||||
infcx.next_nll_region_var(origin)
|
||||
})
|
||||
}
|
||||
|
||||
struct NllVisitor<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
@ -48,6 +64,13 @@ impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
|
|||
{
|
||||
renumber_regions(self.infcx, value)
|
||||
}
|
||||
|
||||
fn renumber_regions_in_mir_constant(
|
||||
&mut self,
|
||||
value: ConstantKind<'tcx>,
|
||||
) -> ConstantKind<'tcx> {
|
||||
renumber_regions_in_mir_constant(self.infcx, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
|
||||
|
@ -77,7 +100,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
|
|||
debug!(?region);
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, constant: &mut ty::Const<'tcx>, _location: Location) {
|
||||
*constant = self.renumber_regions(*constant);
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _location: Location) {
|
||||
let literal = constant.literal;
|
||||
constant.literal = self.renumber_regions_in_mir_constant(literal);
|
||||
debug!("constant: {:#?}", constant);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use rustc_errors::{IntoDiagnosticArg, MultiSpan};
|
||||
use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::diagnostics::RegionName;
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::move_unsized, code = "E0161")]
|
||||
pub(crate) struct MoveUnsized<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
|
@ -14,7 +14,7 @@ pub(crate) struct MoveUnsized<'tcx> {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::higher_ranked_lifetime_error)]
|
||||
pub(crate) struct HigherRankedLifetimeError {
|
||||
#[subdiagnostic]
|
||||
|
@ -23,7 +23,7 @@ pub(crate) struct HigherRankedLifetimeError {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum HigherRankedErrorCause {
|
||||
#[note(borrowck::could_not_prove)]
|
||||
CouldNotProve { predicate: String },
|
||||
|
@ -31,14 +31,14 @@ pub(crate) enum HigherRankedErrorCause {
|
|||
CouldNotNormalize { value: String },
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::higher_ranked_subtype_error)]
|
||||
pub(crate) struct HigherRankedSubtypeError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::generic_does_not_live_long_enough)]
|
||||
pub(crate) struct GenericDoesNotLiveLongEnough {
|
||||
pub kind: String,
|
||||
|
@ -53,7 +53,7 @@ pub(crate) struct VarNeedNotMut {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::const_not_used_in_type_alias)]
|
||||
pub(crate) struct ConstNotUsedTraitAlias {
|
||||
pub ct: String,
|
||||
|
@ -61,7 +61,7 @@ pub(crate) struct ConstNotUsedTraitAlias {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::var_cannot_escape_closure)]
|
||||
#[note]
|
||||
#[note(borrowck::cannot_escape)]
|
||||
|
@ -72,7 +72,7 @@ pub(crate) struct FnMutError {
|
|||
pub ty_err: FnMutReturnTypeErr,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum VarHereDenote {
|
||||
#[label(borrowck::var_here_captured)]
|
||||
Captured {
|
||||
|
@ -91,7 +91,7 @@ pub(crate) enum VarHereDenote {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum FnMutReturnTypeErr {
|
||||
#[label(borrowck::returned_closure_escaped)]
|
||||
ReturnClosure {
|
||||
|
@ -110,14 +110,14 @@ pub(crate) enum FnMutReturnTypeErr {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::lifetime_constraints_error)]
|
||||
pub(crate) struct LifetimeOutliveErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum LifetimeReturnCategoryErr<'a> {
|
||||
#[label(borrowck::returned_lifetime_wrong)]
|
||||
WrongReturn {
|
||||
|
@ -149,7 +149,7 @@ impl IntoDiagnosticArg for RegionName {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum RequireStaticErr {
|
||||
#[note(borrowck::used_impl_require_static)]
|
||||
UsedImpl {
|
||||
|
|
|
@ -25,7 +25,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
/// constraints should occur within this method so that those
|
||||
/// constraints can be properly localized!**
|
||||
#[instrument(skip(self, op), level = "trace")]
|
||||
pub(super) fn fully_perform_op<R, Op>(
|
||||
pub(super) fn fully_perform_op<R: fmt::Debug, Op>(
|
||||
&mut self,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
|
@ -39,6 +39,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
|
||||
let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
|
||||
|
||||
debug!(?output, ?constraints);
|
||||
|
||||
if let Some(data) = constraints {
|
||||
self.push_region_constraints(locations, category, data);
|
||||
}
|
||||
|
@ -102,6 +104,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(super) fn normalize_and_prove_instantiated_predicates(
|
||||
&mut self,
|
||||
// Keep this parameter for now, in case we start using
|
||||
|
@ -116,8 +119,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
.zip(instantiated_predicates.spans.into_iter())
|
||||
{
|
||||
debug!(?predicate);
|
||||
let predicate = self.normalize(predicate, locations);
|
||||
self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
|
||||
let category = ConstraintCategory::Predicate(span);
|
||||
let predicate = self.normalize_with_category(predicate, locations, category);
|
||||
self.prove_predicate(predicate, locations, category);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,15 +157,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
|
||||
where
|
||||
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
|
||||
{
|
||||
self.normalize_with_category(value, location, ConstraintCategory::Boring)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn normalize_with_category<T>(
|
||||
&mut self,
|
||||
value: T,
|
||||
location: impl NormalizeLocation,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
) -> T
|
||||
where
|
||||
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
|
||||
{
|
||||
let param_env = self.param_env;
|
||||
self.fully_perform_op(
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
category,
|
||||
param_env.and(type_op::normalize::Normalize::new(value)),
|
||||
)
|
||||
.unwrap_or_else(|NoSolution| {
|
||||
|
|
|
@ -86,7 +86,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
|
||||
fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
|
||||
debug!("generate: constraints at: {:#?}", self.locations);
|
||||
|
||||
// Extract out various useful fields we'll need below.
|
||||
|
@ -98,15 +98,18 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
// region constraints like `for<'a> 'a: 'b`. At some point
|
||||
// when we move to universes, we will, and this assertion
|
||||
// will start to fail.
|
||||
let ty::OutlivesPredicate(k1, r2) = query_constraint.no_bound_vars().unwrap_or_else(|| {
|
||||
bug!("query_constraint {:?} contained bound vars", query_constraint,);
|
||||
});
|
||||
let ty::OutlivesPredicate(k1, r2) =
|
||||
query_constraint.0.no_bound_vars().unwrap_or_else(|| {
|
||||
bug!("query_constraint {:?} contained bound vars", query_constraint,);
|
||||
});
|
||||
|
||||
let constraint_category = query_constraint.1;
|
||||
|
||||
match k1.unpack() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
let r2_vid = self.to_region_vid(r2);
|
||||
self.add_outlives(r1_vid, r2_vid);
|
||||
self.add_outlives(r1_vid, r2_vid, constraint_category);
|
||||
}
|
||||
|
||||
GenericArgKind::Type(t1) => {
|
||||
|
@ -121,7 +124,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
Some(implicit_region_bound),
|
||||
param_env,
|
||||
)
|
||||
.type_must_outlive(origin, t1, r2);
|
||||
.type_must_outlive(origin, t1, r2, constraint_category);
|
||||
}
|
||||
|
||||
GenericArgKind::Const(_) => {
|
||||
|
@ -168,10 +171,19 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
|
||||
fn add_outlives(
|
||||
&mut self,
|
||||
sup: ty::RegionVid,
|
||||
sub: ty::RegionVid,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
) {
|
||||
let category = match self.category {
|
||||
ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category,
|
||||
_ => self.category,
|
||||
};
|
||||
self.constraints.outlives_constraints.push(OutlivesConstraint {
|
||||
locations: self.locations,
|
||||
category: self.category,
|
||||
category,
|
||||
span: self.span,
|
||||
sub,
|
||||
sup,
|
||||
|
@ -191,10 +203,11 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
|
|||
_origin: SubregionOrigin<'tcx>,
|
||||
a: ty::Region<'tcx>,
|
||||
b: ty::Region<'tcx>,
|
||||
constraint_category: ConstraintCategory<'tcx>,
|
||||
) {
|
||||
let b = self.to_region_vid(b);
|
||||
let a = self.to_region_vid(a);
|
||||
self.add_outlives(b, a);
|
||||
self.add_outlives(b, a, constraint_category);
|
||||
}
|
||||
|
||||
fn push_verify(
|
||||
|
|
|
@ -347,13 +347,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
|
||||
match outlives_bound {
|
||||
OutlivesBound::RegionSubRegion(r1, r2) => {
|
||||
// `where Type:` is lowered to `where Type: 'empty` so that
|
||||
// we check `Type` is well formed, but there's no use for
|
||||
// this bound here.
|
||||
if r1.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// The bound says that `r1 <= r2`; we store `r2: r1`.
|
||||
let r1 = self.universal_regions.to_region_vid(r1);
|
||||
let r2 = self.universal_regions.to_region_vid(r2);
|
||||
|
@ -369,6 +362,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
self.region_bound_pairs
|
||||
.insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a));
|
||||
}
|
||||
|
||||
OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => {
|
||||
self.region_bound_pairs
|
||||
.insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,9 @@ use rustc_middle::ty::cast::CastTy;
|
|||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{
|
||||
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueHiddenType,
|
||||
OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
|
||||
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
|
||||
OpaqueHiddenType, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType,
|
||||
UserTypeAnnotationIndex,
|
||||
};
|
||||
use rustc_span::def_id::CRATE_DEF_ID;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
@ -311,6 +312,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
||||
debug!(?constant, ?location, "visit_constant");
|
||||
|
||||
self.super_constant(constant, location);
|
||||
let ty = self.sanitize_type(constant, constant.literal.ty());
|
||||
|
||||
|
@ -354,11 +357,15 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
let maybe_uneval = match constant.literal {
|
||||
ConstantKind::Ty(ct) => match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => Some(uv),
|
||||
ty::ConstKind::Unevaluated(_) => {
|
||||
bug!("should not encounter unevaluated ConstantKind::Ty here, got {:?}", ct)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
ConstantKind::Unevaluated(uv, _) => Some(uv),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(uv) = maybe_uneval {
|
||||
if let Some(promoted) = uv.promoted {
|
||||
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
|
||||
|
@ -421,12 +428,18 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
|
||||
// const_trait_impl: use a non-const param env when checking that a FnDef type is well formed.
|
||||
// this is because the well-formedness of the function does not need to be proved to have `const`
|
||||
// impls for trait bounds.
|
||||
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
|
||||
let prev = self.cx.param_env;
|
||||
self.cx.param_env = prev.without_const();
|
||||
self.cx.normalize_and_prove_instantiated_predicates(
|
||||
def_id,
|
||||
instantiated_predicates,
|
||||
locations,
|
||||
);
|
||||
self.cx.param_env = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -757,6 +770,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
}
|
||||
PlaceTy::from_ty(fty)
|
||||
}
|
||||
ProjectionElem::OpaqueCast(ty) => {
|
||||
let ty = self.sanitize_type(place, ty);
|
||||
let ty = self.cx.normalize(ty, location);
|
||||
self.cx
|
||||
.eq_types(
|
||||
base.ty,
|
||||
ty,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::TypeAnnotation,
|
||||
)
|
||||
.unwrap();
|
||||
PlaceTy::from_ty(ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1163,10 +1189,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
tcx,
|
||||
self.param_env,
|
||||
proj,
|
||||
|this, field, ()| {
|
||||
|this, field, _| {
|
||||
let ty = this.field_ty(tcx, field);
|
||||
self.normalize(ty, locations)
|
||||
},
|
||||
|_, _| unreachable!(),
|
||||
);
|
||||
curr_projected_ty = projected_ty;
|
||||
}
|
||||
|
@ -1302,12 +1329,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
|
||||
..
|
||||
}) => span_bug!(
|
||||
stmt.source_info.span,
|
||||
"Unexpected StatementKind::CopyNonOverlapping, should only appear after lowering_intrinsics",
|
||||
),
|
||||
StatementKind::Intrinsic(box ref kind) => match kind {
|
||||
NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
|
||||
stmt.source_info.span,
|
||||
"Unexpected NonDivergingIntrinsic::CopyNonOverlapping, should only appear after lowering_intrinsics",
|
||||
),
|
||||
},
|
||||
StatementKind::FakeRead(..)
|
||||
| StatementKind::StorageLive(..)
|
||||
| StatementKind::StorageDead(..)
|
||||
|
@ -1809,14 +1837,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
|
||||
debug!(?op, ?location, "check_operand");
|
||||
|
||||
if let Operand::Constant(constant) = op {
|
||||
let maybe_uneval = match constant.literal {
|
||||
ConstantKind::Ty(ct) => match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => Some(uv),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
|
||||
ConstantKind::Unevaluated(uv, _) => Some(uv),
|
||||
};
|
||||
|
||||
if let Some(uv) = maybe_uneval {
|
||||
if uv.promoted.is_none() {
|
||||
let tcx = self.tcx();
|
||||
|
@ -2008,6 +2036,36 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
CastKind::DynStar => {
|
||||
// get the constraints from the target type (`dyn* Clone`)
|
||||
//
|
||||
// apply them to prove that the source type `Foo` implements `Clone` etc
|
||||
let (existential_predicates, region) = match ty.kind() {
|
||||
Dynamic(predicates, region, ty::DynStar) => (predicates, region),
|
||||
_ => panic!("Invalid dyn* cast_ty"),
|
||||
};
|
||||
|
||||
let self_ty = op.ty(body, tcx);
|
||||
|
||||
self.prove_predicates(
|
||||
existential_predicates
|
||||
.iter()
|
||||
.map(|predicate| predicate.with_self_ty(tcx, self_ty)),
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast,
|
||||
);
|
||||
|
||||
let outlives_predicate =
|
||||
tcx.mk_predicate(Binder::dummy(ty::PredicateKind::TypeOutlives(
|
||||
ty::OutlivesPredicate(self_ty, *region),
|
||||
)));
|
||||
self.prove_predicate(
|
||||
outlives_predicate,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast,
|
||||
);
|
||||
}
|
||||
|
||||
CastKind::Pointer(PointerCast::MutToConstPointer) => {
|
||||
let ty::RawPtr(ty::TypeAndMut {
|
||||
ty: ty_from,
|
||||
|
@ -2465,6 +2523,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
ProjectionElem::Field(..)
|
||||
| ProjectionElem::Downcast(..)
|
||||
| ProjectionElem::OpaqueCast(..)
|
||||
| ProjectionElem::Index(..)
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::Subslice { .. } => {
|
||||
|
@ -2559,7 +2618,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
.enumerate()
|
||||
.filter_map(|(idx, constraint)| {
|
||||
let ty::OutlivesPredicate(k1, r2) =
|
||||
constraint.no_bound_vars().unwrap_or_else(|| {
|
||||
constraint.0.no_bound_vars().unwrap_or_else(|| {
|
||||
bug!("query_constraint {:?} contained bound vars", constraint,);
|
||||
});
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ use rustc_hir::{BodyOwnerKind, HirId};
|
|||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
||||
use std::iter;
|
||||
|
||||
use crate::nll::ToRegionVid;
|
||||
|
@ -54,13 +54,6 @@ pub struct UniversalRegions<'tcx> {
|
|||
/// The total number of universal region variables instantiated.
|
||||
num_universals: usize,
|
||||
|
||||
/// A special region variable created for the `'empty(U0)` region.
|
||||
/// Note that this is **not** a "universal" region, as it doesn't
|
||||
/// represent a universally bound placeholder or any such thing.
|
||||
/// But we do create it here in this type because it's a useful region
|
||||
/// to have around in a few limited cases.
|
||||
pub root_empty: RegionVid,
|
||||
|
||||
/// The "defining" type for this function, with all universal
|
||||
/// regions instantiated. For a closure or generator, this is the
|
||||
/// closure type, but for a top-level function it's the `FnDef`.
|
||||
|
@ -323,11 +316,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
|||
|
||||
/// See `UniversalRegionIndices::to_region_vid`.
|
||||
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
|
||||
if let ty::ReEmpty(ty::UniverseIndex::ROOT) = *r {
|
||||
self.root_empty
|
||||
} else {
|
||||
self.indices.to_region_vid(r)
|
||||
}
|
||||
self.indices.to_region_vid(r)
|
||||
}
|
||||
|
||||
/// As part of the NLL unit tests, you can annotate a function with
|
||||
|
@ -501,16 +490,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
_ => None,
|
||||
};
|
||||
|
||||
let root_empty = self
|
||||
.infcx
|
||||
.next_nll_region_var(NllRegionVariableOrigin::Existential { from_forall: true })
|
||||
.to_region_vid();
|
||||
|
||||
UniversalRegions {
|
||||
indices,
|
||||
fr_static,
|
||||
fr_fn_body,
|
||||
root_empty,
|
||||
first_extern_index,
|
||||
first_local_index,
|
||||
num_universals,
|
||||
|
@ -768,10 +751,9 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
|
|||
mir_def_id: LocalDefId,
|
||||
indices: &mut UniversalRegionIndices<'tcx>,
|
||||
) {
|
||||
debug!("replace_late_bound_regions_with_nll_infer_vars(mir_def_id={:?})", mir_def_id);
|
||||
let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id());
|
||||
for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| {
|
||||
debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r);
|
||||
debug!(?r);
|
||||
if !indices.indices.contains_key(&r) {
|
||||
let region_vid = self.next_nll_region_var(FR);
|
||||
debug!(?region_vid);
|
||||
|
|
|
@ -7,20 +7,21 @@ edition = "2021"
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||
tracing = "0.1"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_expand = { path = "../rustc_expand" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_expand = { path = "../rustc_expand" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
thin-vec = "0.2.8"
|
||||
tracing = "0.1"
|
||||
|
|
|
@ -13,6 +13,7 @@ use rustc_span::{
|
|||
symbol::{sym, Ident, Symbol},
|
||||
Span,
|
||||
};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub(super) struct Context<'cx, 'a> {
|
||||
// An optimization.
|
||||
|
@ -116,11 +117,10 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
self.cx.item(
|
||||
self.span,
|
||||
Ident::empty(),
|
||||
vec![self.cx.attribute(attr::mk_list_item(
|
||||
thin_vec![self.cx.attribute(attr::mk_list_item(
|
||||
Ident::new(sym::allow, self.span),
|
||||
vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))],
|
||||
))]
|
||||
.into(),
|
||||
))],
|
||||
ItemKind::Use(UseTree {
|
||||
prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
|
||||
kind: UseTreeKind::Nested(vec![
|
||||
|
|
|
@ -8,7 +8,7 @@ use rustc_ast::tokenstream::TokenStream;
|
|||
use rustc_attr as attr;
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{self, *};
|
||||
use rustc_macros::SessionDiagnostic;
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub fn expand_cfg(
|
||||
|
@ -35,7 +35,7 @@ pub fn expand_cfg(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros::requires_cfg_pattern)]
|
||||
struct RequiresCfgPattern {
|
||||
#[primary_span]
|
||||
|
@ -43,7 +43,7 @@ struct RequiresCfgPattern {
|
|||
span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros::expected_one_cfg_pattern)]
|
||||
struct OneCfgPattern {
|
||||
#[primary_span]
|
||||
|
|
|
@ -7,6 +7,7 @@ use rustc_ast::visit::Visitor;
|
|||
use rustc_ast::NodeId;
|
||||
use rustc_ast::{mut_visit, visit};
|
||||
use rustc_ast::{Attribute, HasAttrs, HasTokens};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_expand::config::StripUnconfigured;
|
||||
use rustc_expand::configure;
|
||||
|
@ -144,33 +145,34 @@ impl CfgEval<'_, '_> {
|
|||
// the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization
|
||||
// process is lossless, so this process is invisible to proc-macros.
|
||||
|
||||
let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable {
|
||||
Annotatable::Item(_) => {
|
||||
|parser| Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap())
|
||||
}
|
||||
Annotatable::TraitItem(_) => |parser| {
|
||||
Annotatable::TraitItem(
|
||||
parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
|
||||
)
|
||||
},
|
||||
Annotatable::ImplItem(_) => |parser| {
|
||||
Annotatable::ImplItem(
|
||||
parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
|
||||
)
|
||||
},
|
||||
Annotatable::ForeignItem(_) => |parser| {
|
||||
Annotatable::ForeignItem(
|
||||
parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
|
||||
)
|
||||
},
|
||||
Annotatable::Stmt(_) => |parser| {
|
||||
Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap()))
|
||||
},
|
||||
Annotatable::Expr(_) => {
|
||||
|parser| Annotatable::Expr(parser.parse_expr_force_collect().unwrap())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let parse_annotatable_with: for<'a> fn(&mut Parser<'a>) -> PResult<'a, _> =
|
||||
match annotatable {
|
||||
Annotatable::Item(_) => {
|
||||
|parser| Ok(Annotatable::Item(parser.parse_item(ForceCollect::Yes)?.unwrap()))
|
||||
}
|
||||
Annotatable::TraitItem(_) => |parser| {
|
||||
Ok(Annotatable::TraitItem(
|
||||
parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(),
|
||||
))
|
||||
},
|
||||
Annotatable::ImplItem(_) => |parser| {
|
||||
Ok(Annotatable::ImplItem(
|
||||
parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(),
|
||||
))
|
||||
},
|
||||
Annotatable::ForeignItem(_) => |parser| {
|
||||
Ok(Annotatable::ForeignItem(
|
||||
parser.parse_foreign_item(ForceCollect::Yes)?.unwrap().unwrap(),
|
||||
))
|
||||
},
|
||||
Annotatable::Stmt(_) => |parser| {
|
||||
Ok(Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes)?.unwrap())))
|
||||
},
|
||||
Annotatable::Expr(_) => {
|
||||
|parser| Ok(Annotatable::Expr(parser.parse_expr_force_collect()?))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`)
|
||||
// to `None`-delimited groups containing the corresponding tokens. This
|
||||
|
@ -188,14 +190,20 @@ impl CfgEval<'_, '_> {
|
|||
let orig_tokens = annotatable.to_tokens().flattened();
|
||||
|
||||
// Re-parse the tokens, setting the `capture_cfg` flag to save extra information
|
||||
// to the captured `AttrAnnotatedTokenStream` (specifically, we capture
|
||||
// `AttrAnnotatedTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
|
||||
// to the captured `AttrTokenStream` (specifically, we capture
|
||||
// `AttrTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
|
||||
let mut parser =
|
||||
rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
|
||||
parser.capture_cfg = true;
|
||||
annotatable = parse_annotatable_with(&mut parser);
|
||||
match parse_annotatable_with(&mut parser) {
|
||||
Ok(a) => annotatable = a,
|
||||
Err(mut err) => {
|
||||
err.emit();
|
||||
return Some(annotatable);
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring
|
||||
// Now that we have our re-parsed `AttrTokenStream`, recursively configuring
|
||||
// our attribute target will correctly the tokens as well.
|
||||
flat_map_annotatable(self, annotatable)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,13 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
|
|||
continue;
|
||||
}
|
||||
|
||||
krate.attrs.push(mk_attr(AttrStyle::Inner, path, args, start_span.to(end_span)));
|
||||
krate.attrs.push(mk_attr(
|
||||
&parse_sess.attr_id_generator,
|
||||
AttrStyle::Inner,
|
||||
path,
|
||||
args,
|
||||
start_span.to(end_span),
|
||||
));
|
||||
}
|
||||
|
||||
krate
|
||||
|
|
|
@ -32,7 +32,8 @@ impl MultiItemModifier for Expander {
|
|||
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
|
||||
let template =
|
||||
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
||||
let attr = attr::mk_attr_outer(meta_item.clone());
|
||||
let attr =
|
||||
attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone());
|
||||
validate_attr::check_builtin_attribute(
|
||||
&sess.parse_sess,
|
||||
&attr,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::deriving::generic::ty::*;
|
||||
use crate::deriving::generic::*;
|
||||
use crate::deriving::path_std;
|
||||
|
||||
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_clone(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
|
@ -68,7 +68,7 @@ pub fn expand_deriving_clone(
|
|||
}
|
||||
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
let attrs = vec![cx.attribute(inline)].into();
|
||||
let attrs = thin_vec![cx.attribute(inline)];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(clone::Clone),
|
||||
|
|
|
@ -7,6 +7,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_eq(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
|
@ -20,7 +21,7 @@ pub fn expand_deriving_eq(
|
|||
let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span));
|
||||
let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]);
|
||||
let no_coverage = cx.meta_word(span, sym::no_coverage);
|
||||
let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)].into();
|
||||
let attrs = thin_vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(cmp::Eq),
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::deriving::generic::ty::*;
|
||||
use crate::deriving::generic::*;
|
||||
use crate::deriving::path_std;
|
||||
|
||||
use rustc_ast::MetaItem;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_ord(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
|
@ -15,7 +15,7 @@ pub fn expand_deriving_ord(
|
|||
push: &mut dyn FnMut(Annotatable),
|
||||
) {
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
let attrs = vec![cx.attribute(inline)].into();
|
||||
let attrs = thin_vec![cx.attribute(inline)];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(cmp::Ord),
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::deriving::generic::ty::*;
|
||||
use crate::deriving::generic::*;
|
||||
use crate::deriving::{path_local, path_std};
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_partial_eq(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
|
@ -68,7 +68,7 @@ pub fn expand_deriving_partial_eq(
|
|||
// No need to generate `ne`, the default suffices, and not generating it is
|
||||
// faster.
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
let attrs = vec![cx.attribute(inline)].into();
|
||||
let attrs = thin_vec![cx.attribute(inline)];
|
||||
let methods = vec![MethodDef {
|
||||
name: sym::eq,
|
||||
generics: Bounds::empty(),
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::deriving::generic::ty::*;
|
||||
use crate::deriving::generic::*;
|
||||
use crate::deriving::{path_std, pathvec_std};
|
||||
|
||||
use rustc_ast::MetaItem;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_partial_ord(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
|
@ -19,7 +19,7 @@ pub fn expand_deriving_partial_ord(
|
|||
Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
|
||||
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
let attrs = vec![cx.attribute(inline)].into();
|
||||
let attrs = thin_vec![cx.attribute(inline)];
|
||||
|
||||
let partial_cmp_def = MethodDef {
|
||||
name: sym::partial_cmp,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::deriving::generic::ty::*;
|
||||
use crate::deriving::generic::*;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::{walk_list, EnumDef, VariantData};
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -9,6 +8,7 @@ use rustc_span::symbol::Ident;
|
|||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::Span;
|
||||
use smallvec::SmallVec;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_default(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
|
@ -20,7 +20,7 @@ pub fn expand_deriving_default(
|
|||
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
|
||||
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
let attrs = vec![cx.attribute(inline)].into();
|
||||
let attrs = thin_vec![cx.attribute(inline)];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: Path::new(vec![kw::Default, sym::Default]),
|
||||
|
|
|
@ -162,22 +162,22 @@
|
|||
pub use StaticFields::*;
|
||||
pub use SubstructureFields::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::iter;
|
||||
use std::vec;
|
||||
|
||||
use crate::deriving;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, EnumDef, Expr, Generics, PatKind};
|
||||
use rustc_ast::{
|
||||
self as ast, BindingAnnotation, ByRef, EnumDef, Expr, Generics, Mutability, PatKind,
|
||||
};
|
||||
use rustc_ast::{GenericArg, GenericParamKind, VariantData};
|
||||
use rustc_attr as attr;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::iter;
|
||||
use std::vec;
|
||||
use thin_vec::thin_vec;
|
||||
use ty::{Bounds, Path, Ref, Self_, Ty};
|
||||
|
||||
use crate::deriving;
|
||||
|
||||
pub mod ty;
|
||||
|
||||
pub struct TraitDef<'a> {
|
||||
|
@ -715,7 +715,7 @@ impl<'a> TraitDef<'a> {
|
|||
let self_type = cx.ty_path(path);
|
||||
|
||||
let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
|
||||
let attrs = vec![attr].into();
|
||||
let attrs = thin_vec![attr];
|
||||
let opt_trait_ref = Some(trait_ref);
|
||||
|
||||
cx.item(
|
||||
|
@ -1065,9 +1065,9 @@ impl<'a> MethodDef<'a> {
|
|||
let mut body = mk_body(cx, selflike_fields);
|
||||
|
||||
let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]);
|
||||
let use_ref_pat = is_packed && !always_copy;
|
||||
let by_ref = ByRef::from(is_packed && !always_copy);
|
||||
let patterns =
|
||||
trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, use_ref_pat);
|
||||
trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, by_ref);
|
||||
|
||||
// Do the let-destructuring.
|
||||
let mut stmts: Vec<_> = iter::zip(selflike_args, patterns)
|
||||
|
@ -1249,13 +1249,13 @@ impl<'a> MethodDef<'a> {
|
|||
|
||||
let sp = variant.span.with_ctxt(trait_.span.ctxt());
|
||||
let variant_path = cx.path(sp, vec![type_ident, variant.ident]);
|
||||
let use_ref_pat = false; // because enums can't be repr(packed)
|
||||
let by_ref = ByRef::No; // because enums can't be repr(packed)
|
||||
let mut subpats: Vec<_> = trait_.create_struct_patterns(
|
||||
cx,
|
||||
variant_path,
|
||||
&variant.data,
|
||||
&prefixes,
|
||||
use_ref_pat,
|
||||
by_ref,
|
||||
);
|
||||
|
||||
// `(VariantK, VariantK, ...)` or just `VariantK`.
|
||||
|
@ -1416,7 +1416,7 @@ impl<'a> TraitDef<'a> {
|
|||
struct_path: ast::Path,
|
||||
struct_def: &'a VariantData,
|
||||
prefixes: &[String],
|
||||
use_ref_pat: bool,
|
||||
by_ref: ByRef,
|
||||
) -> Vec<P<ast::Pat>> {
|
||||
prefixes
|
||||
.iter()
|
||||
|
@ -1424,17 +1424,19 @@ impl<'a> TraitDef<'a> {
|
|||
let pieces_iter =
|
||||
struct_def.fields().iter().enumerate().map(|(i, struct_field)| {
|
||||
let sp = struct_field.span.with_ctxt(self.span.ctxt());
|
||||
let binding_mode = if use_ref_pat {
|
||||
ast::BindingMode::ByRef(ast::Mutability::Not)
|
||||
} else {
|
||||
ast::BindingMode::ByValue(ast::Mutability::Not)
|
||||
};
|
||||
let ident = self.mk_pattern_ident(prefix, i);
|
||||
let path = ident.with_span_pos(sp);
|
||||
(
|
||||
sp,
|
||||
struct_field.ident,
|
||||
cx.pat(path.span, PatKind::Ident(binding_mode, path, None)),
|
||||
cx.pat(
|
||||
path.span,
|
||||
PatKind::Ident(
|
||||
BindingAnnotation(by_ref, Mutability::Not),
|
||||
path,
|
||||
None,
|
||||
),
|
||||
),
|
||||
)
|
||||
});
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
|
|||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand(
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
|
@ -116,7 +117,7 @@ impl AllocFnFactory<'_, '_> {
|
|||
fn attrs(&self) -> AttrVec {
|
||||
let special = sym::rustc_std_internal_symbol;
|
||||
let special = self.cx.meta_word(self.span, special);
|
||||
vec![self.cx.attribute(special)].into()
|
||||
thin_vec![self.cx.attribute(special)]
|
||||
}
|
||||
|
||||
fn arg_ty(
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
#![feature(if_let_guard)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_quote)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
use crate::deriving::*;
|
||||
|
||||
use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
|
||||
|
|
|
@ -6,6 +6,7 @@ use rustc_span::edition::Edition::*;
|
|||
use rustc_span::hygiene::AstPass;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn inject(
|
||||
mut krate: ast::Crate,
|
||||
|
@ -51,7 +52,7 @@ pub fn inject(
|
|||
cx.item(
|
||||
span,
|
||||
ident,
|
||||
vec![cx.attribute(cx.meta_word(span, sym::macro_use))].into(),
|
||||
thin_vec![cx.attribute(cx.meta_word(span, sym::macro_use))],
|
||||
ast::ItemKind::ExternCrate(None),
|
||||
),
|
||||
);
|
||||
|
@ -78,7 +79,7 @@ pub fn inject(
|
|||
let use_item = cx.item(
|
||||
span,
|
||||
Ident::empty(),
|
||||
vec![cx.attribute(cx.meta_word(span, sym::prelude_import))].into(),
|
||||
thin_vec![cx.attribute(cx.meta_word(span, sym::prelude_import))],
|
||||
ast::ItemKind::Use(ast::UseTree {
|
||||
prefix: cx.path(span, import_path),
|
||||
kind: ast::UseTreeKind::Glob,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/// The expansion from a test function to the appropriate test struct for libtest
|
||||
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
||||
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::attr;
|
||||
use rustc_ast::ptr::P;
|
||||
|
@ -11,8 +10,8 @@ use rustc_expand::base::*;
|
|||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::iter;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
// #[test_case] is used by custom test authors to mark tests
|
||||
// When building for test, it needs to make the item public and gensym the name
|
||||
|
@ -219,7 +218,7 @@ pub fn expand_test_or_bench(
|
|||
let mut test_const = cx.item(
|
||||
sp,
|
||||
Ident::new(item.ident.name, sp),
|
||||
vec![
|
||||
thin_vec![
|
||||
// #[cfg(test)]
|
||||
cx.attribute(attr::mk_list_item(
|
||||
Ident::new(sym::cfg, attr_sp),
|
||||
|
@ -227,8 +226,7 @@ pub fn expand_test_or_bench(
|
|||
)),
|
||||
// #[rustc_test_marker]
|
||||
cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)),
|
||||
]
|
||||
.into(),
|
||||
],
|
||||
// const $ident: test::TestDescAndFn =
|
||||
ast::ItemKind::Const(
|
||||
ast::Defaultness::Final,
|
||||
|
@ -337,7 +335,7 @@ pub fn expand_test_or_bench(
|
|||
// extern crate test
|
||||
let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
|
||||
|
||||
tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
|
||||
debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
|
||||
|
||||
if is_stmt {
|
||||
vec![
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc_span::symbol::{sym, Ident, Symbol};
|
|||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use tracing::debug;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use std::{iter, mem};
|
||||
|
||||
|
@ -187,7 +187,10 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
|||
let dc_nested =
|
||||
attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site));
|
||||
let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
|
||||
let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item);
|
||||
let allow_dead_code = attr::mk_attr_outer(
|
||||
&self.sess.parse_sess.attr_id_generator,
|
||||
allow_dead_code_item,
|
||||
);
|
||||
let attrs = attrs
|
||||
.into_iter()
|
||||
.filter(|attr| {
|
||||
|
@ -335,7 +338,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
|
|||
|
||||
let main = P(ast::Item {
|
||||
ident: main_id,
|
||||
attrs: vec![main_attr].into(),
|
||||
attrs: thin_vec![main_attr],
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: main,
|
||||
vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None },
|
||||
|
|
|
@ -342,7 +342,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
|
||||
let ret_place = codegen_place(fx, destination);
|
||||
|
||||
// Handle special calls like instrinsics and empty drop glue.
|
||||
// Handle special calls like intrinsics and empty drop glue.
|
||||
let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() {
|
||||
let instance = ty::Instance::resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
|
||||
.unwrap()
|
||||
|
|
|
@ -701,6 +701,10 @@ fn codegen_stmt<'tcx>(
|
|||
let operand = codegen_operand(fx, operand);
|
||||
operand.unsize_value(fx, lval);
|
||||
}
|
||||
Rvalue::Cast(CastKind::DynStar, _, _) => {
|
||||
// FIXME(dyn-star)
|
||||
unimplemented!()
|
||||
}
|
||||
Rvalue::Discriminant(place) => {
|
||||
let place = codegen_place(fx, place);
|
||||
let value = place.to_cvalue(fx);
|
||||
|
@ -794,20 +798,31 @@ fn codegen_stmt<'tcx>(
|
|||
| StatementKind::AscribeUserType(..) => {}
|
||||
|
||||
StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"),
|
||||
StatementKind::CopyNonOverlapping(inner) => {
|
||||
let dst = codegen_operand(fx, &inner.dst);
|
||||
let pointee = dst
|
||||
.layout()
|
||||
.pointee_info_at(fx, rustc_target::abi::Size::ZERO)
|
||||
.expect("Expected pointer");
|
||||
let dst = dst.load_scalar(fx);
|
||||
let src = codegen_operand(fx, &inner.src).load_scalar(fx);
|
||||
let count = codegen_operand(fx, &inner.count).load_scalar(fx);
|
||||
let elem_size: u64 = pointee.size.bytes();
|
||||
let bytes =
|
||||
if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count };
|
||||
fx.bcx.call_memcpy(fx.target_config, dst, src, bytes);
|
||||
}
|
||||
StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic {
|
||||
// We ignore `assume` intrinsics, they are only useful for optimizations
|
||||
NonDivergingIntrinsic::Assume(_) => {}
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
|
||||
src,
|
||||
dst,
|
||||
count,
|
||||
}) => {
|
||||
let dst = codegen_operand(fx, dst);
|
||||
let pointee = dst
|
||||
.layout()
|
||||
.pointee_info_at(fx, rustc_target::abi::Size::ZERO)
|
||||
.expect("Expected pointer");
|
||||
let dst = dst.load_scalar(fx);
|
||||
let src = codegen_operand(fx, src).load_scalar(fx);
|
||||
let count = codegen_operand(fx, count).load_scalar(fx);
|
||||
let elem_size: u64 = pointee.size.bytes();
|
||||
let bytes = if elem_size != 1 {
|
||||
fx.bcx.ins().imul_imm(count, elem_size as i64)
|
||||
} else {
|
||||
count
|
||||
};
|
||||
fx.bcx.call_memcpy(fx.target_config, dst, src, bytes);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,6 +850,7 @@ pub(crate) fn codegen_place<'tcx>(
|
|||
PlaceElem::Deref => {
|
||||
cplace = cplace.place_deref(fx);
|
||||
}
|
||||
PlaceElem::OpaqueCast(ty) => cplace = cplace.place_opaque_cast(fx, ty),
|
||||
PlaceElem::Field(field, _ty) => {
|
||||
cplace = cplace.place_field(fx, field);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
|||
use rustc_middle::mir::interpret::{
|
||||
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
|
||||
};
|
||||
use rustc_middle::ty::ConstKind;
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use cranelift_codegen::ir::GlobalValueData;
|
||||
|
@ -41,36 +40,22 @@ impl ConstantCx {
|
|||
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
|
||||
let mut all_constants_ok = true;
|
||||
for constant in &fx.mir.required_consts {
|
||||
let const_ = match fx.monomorphize(constant.literal) {
|
||||
ConstantKind::Ty(ct) => ct,
|
||||
let unevaluated = match fx.monomorphize(constant.literal) {
|
||||
ConstantKind::Ty(_) => unreachable!(),
|
||||
ConstantKind::Unevaluated(uv, _) => uv,
|
||||
ConstantKind::Val(..) => continue,
|
||||
};
|
||||
match const_.kind() {
|
||||
ConstKind::Value(_) => {}
|
||||
ConstKind::Unevaluated(unevaluated) => {
|
||||
if let Err(err) =
|
||||
fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None)
|
||||
{
|
||||
all_constants_ok = false;
|
||||
match err {
|
||||
ErrorHandled::Reported(_) | ErrorHandled::Linted => {
|
||||
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
|
||||
}
|
||||
ErrorHandled::TooGeneric => {
|
||||
span_bug!(
|
||||
constant.span,
|
||||
"codgen encountered polymorphic constant: {:?}",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(err) = fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
|
||||
all_constants_ok = false;
|
||||
match err {
|
||||
ErrorHandled::Reported(_) | ErrorHandled::Linted => {
|
||||
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
|
||||
}
|
||||
ErrorHandled::TooGeneric => {
|
||||
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
|
||||
}
|
||||
}
|
||||
ConstKind::Param(_)
|
||||
| ConstKind::Infer(_)
|
||||
| ConstKind::Bound(_, _)
|
||||
| ConstKind::Placeholder(_)
|
||||
| ConstKind::Error(_) => unreachable!("{:?}", const_),
|
||||
}
|
||||
}
|
||||
all_constants_ok
|
||||
|
@ -122,36 +107,28 @@ pub(crate) fn codegen_constant<'tcx>(
|
|||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
constant: &Constant<'tcx>,
|
||||
) -> CValue<'tcx> {
|
||||
let const_ = match fx.monomorphize(constant.literal) {
|
||||
ConstantKind::Ty(ct) => ct,
|
||||
ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
|
||||
};
|
||||
let const_val = match const_.kind() {
|
||||
ConstKind::Value(valtree) => fx.tcx.valtree_to_const_val((const_.ty(), valtree)),
|
||||
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
|
||||
let (const_val, ty) = match fx.monomorphize(constant.literal) {
|
||||
ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
|
||||
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs, promoted }, ty)
|
||||
if fx.tcx.is_static(def.did) =>
|
||||
{
|
||||
assert!(substs.is_empty());
|
||||
assert!(promoted.is_none());
|
||||
|
||||
return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty())).to_cvalue(fx);
|
||||
return codegen_static_ref(fx, def.did, fx.layout_of(ty)).to_cvalue(fx);
|
||||
}
|
||||
ConstKind::Unevaluated(unevaluated) => {
|
||||
ConstantKind::Unevaluated(unevaluated, ty) => {
|
||||
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
|
||||
Ok(const_val) => const_val,
|
||||
Ok(const_val) => (const_val, ty),
|
||||
Err(_) => {
|
||||
span_bug!(constant.span, "erroneous constant not captured by required_consts");
|
||||
}
|
||||
}
|
||||
}
|
||||
ConstKind::Param(_)
|
||||
| ConstKind::Infer(_)
|
||||
| ConstKind::Bound(_, _)
|
||||
| ConstKind::Placeholder(_)
|
||||
| ConstKind::Error(_) => unreachable!("{:?}", const_),
|
||||
ConstantKind::Val(val, ty) => (val, ty),
|
||||
};
|
||||
|
||||
codegen_const_value(fx, const_val, const_.ty())
|
||||
codegen_const_value(fx, const_val, ty)
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_const_value<'tcx>(
|
||||
|
@ -496,6 +473,9 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
|
|||
.eval_for_mir(fx.tcx, ParamEnv::reveal_all())
|
||||
.try_to_value(fx.tcx),
|
||||
ConstantKind::Val(val, _) => Some(val),
|
||||
ConstantKind::Unevaluated(uv, _) => {
|
||||
fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).ok()
|
||||
}
|
||||
},
|
||||
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
|
||||
// inside a temporary before being passed to the intrinsic requiring the const argument.
|
||||
|
@ -536,9 +516,11 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
|
|||
{
|
||||
return None;
|
||||
}
|
||||
StatementKind::CopyNonOverlapping(_) => {
|
||||
return None;
|
||||
} // conservative handling
|
||||
StatementKind::Intrinsic(ref intrinsic) => match **intrinsic {
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(..) => return None,
|
||||
NonDivergingIntrinsic::Assume(..) => {}
|
||||
},
|
||||
// conservative handling
|
||||
StatementKind::Assign(_)
|
||||
| StatementKind::FakeRead(_)
|
||||
| StatementKind::SetDiscriminant { .. }
|
||||
|
|
|
@ -68,9 +68,9 @@ impl DebugContext {
|
|||
) -> (Lrc<SourceFile>, u64, u64) {
|
||||
// Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
|
||||
// In order to have a good line stepping behavior in debugger, we overwrite debug
|
||||
// locations of macro expansions with that of the outermost expansion site
|
||||
// (unless the crate is being compiled with `-Z debug-macros`).
|
||||
let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros {
|
||||
// locations of macro expansions with that of the outermost expansion site (when the macro is
|
||||
// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
|
||||
let span = if tcx.should_collapse_debuginfo(span) {
|
||||
span
|
||||
} else {
|
||||
// Walk up the macro expansion chain until we reach a non-expanded span.
|
||||
|
|
|
@ -42,10 +42,10 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
|
|||
Variants::Multiple {
|
||||
tag: _,
|
||||
tag_field,
|
||||
tag_encoding: TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
tag_encoding: TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
|
||||
variants: _,
|
||||
} => {
|
||||
if variant_index != dataful_variant {
|
||||
if variant_index != untagged_variant {
|
||||
let niche = place.place_field(fx, mir::Field::new(tag_field));
|
||||
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
|
||||
let niche_value = ty::ScalarInt::try_from_uint(
|
||||
|
@ -113,7 +113,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
|
|||
let res = CValue::by_val(val, dest_layout);
|
||||
dest.write_cvalue(fx, res);
|
||||
}
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
|
||||
// Rebase from niche values to discriminants, and check
|
||||
// whether the result is in range for the niche variants.
|
||||
|
||||
|
@ -169,8 +169,9 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
|
|||
fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32()))
|
||||
};
|
||||
|
||||
let dataful_variant = fx.bcx.ins().iconst(cast_to, i64::from(dataful_variant.as_u32()));
|
||||
let discr = fx.bcx.ins().select(is_niche, niche_discr, dataful_variant);
|
||||
let untagged_variant =
|
||||
fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()));
|
||||
let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant);
|
||||
let res = CValue::by_val(discr, dest_layout);
|
||||
dest.write_cvalue(fx, res);
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||
sym::transmute => {
|
||||
crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info);
|
||||
}
|
||||
_ => unimplemented!("unsupported instrinsic {}", intrinsic),
|
||||
_ => unimplemented!("unsupported intrinsic {}", intrinsic),
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
@ -357,9 +357,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
let usize_layout = fx.layout_of(fx.tcx.types.usize);
|
||||
|
||||
match intrinsic {
|
||||
sym::assume => {
|
||||
intrinsic_args!(fx, args => (_a); intrinsic);
|
||||
}
|
||||
sym::likely | sym::unlikely => {
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
|
||||
|
@ -819,20 +816,13 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
sym::ptr_guaranteed_eq => {
|
||||
sym::ptr_guaranteed_cmp => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
|
||||
let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b);
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
sym::ptr_guaranteed_ne => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
|
||||
let val = crate::num::codegen_ptr_binop(fx, BinOp::Ne, a, b);
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
sym::caller_location => {
|
||||
intrinsic_args!(fx, args => (); intrinsic);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_hir::LangItem;
|
||||
use rustc_middle::ty::subst::GenericArg;
|
||||
use rustc_middle::ty::AssocKind;
|
||||
use rustc_session::config::EntryFnType;
|
||||
use rustc_session::config::{sigpipe, EntryFnType};
|
||||
use rustc_span::symbol::Ident;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
@ -15,12 +15,12 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
is_jit: bool,
|
||||
is_primary_cgu: bool,
|
||||
) {
|
||||
let (main_def_id, is_main_fn) = match tcx.entry_fn(()) {
|
||||
let (main_def_id, (is_main_fn, sigpipe)) = match tcx.entry_fn(()) {
|
||||
Some((def_id, entry_ty)) => (
|
||||
def_id,
|
||||
match entry_ty {
|
||||
EntryFnType::Main => true,
|
||||
EntryFnType::Start => false,
|
||||
EntryFnType::Main { sigpipe } => (true, sigpipe),
|
||||
EntryFnType::Start => (false, sigpipe::DEFAULT),
|
||||
},
|
||||
),
|
||||
None => return,
|
||||
|
@ -35,7 +35,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
return;
|
||||
}
|
||||
|
||||
create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn);
|
||||
create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn, sigpipe);
|
||||
|
||||
fn create_entry_fn(
|
||||
tcx: TyCtxt<'_>,
|
||||
|
@ -44,6 +44,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
rust_main_def_id: DefId,
|
||||
ignore_lang_start_wrapper: bool,
|
||||
is_main_fn: bool,
|
||||
sigpipe: u8,
|
||||
) {
|
||||
let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
|
||||
// Given that `main()` has no arguments,
|
||||
|
@ -83,6 +84,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
bcx.switch_to_block(block);
|
||||
let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type());
|
||||
let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());
|
||||
let arg_sigpipe = bcx.ins().iconst(types::I8, sigpipe as i64);
|
||||
|
||||
let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);
|
||||
|
||||
|
@ -143,7 +145,8 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);
|
||||
|
||||
let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
|
||||
let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]);
|
||||
let call_inst =
|
||||
bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv, arg_sigpipe]);
|
||||
bcx.inst_results(call_inst)[0]
|
||||
} else {
|
||||
// using user-defined start fn
|
||||
|
|
|
@ -621,6 +621,14 @@ impl<'tcx> CPlace<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn place_opaque_cast(
|
||||
self,
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> CPlace<'tcx> {
|
||||
CPlace { inner: self.inner, layout: fx.layout_of(ty) }
|
||||
}
|
||||
|
||||
pub(crate) fn place_field(
|
||||
self,
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
|
@ -815,7 +823,8 @@ pub(crate) fn assert_assignable<'tcx>(
|
|||
);
|
||||
// fn(&T) -> for<'l> fn(&'l T) is allowed
|
||||
}
|
||||
(&ty::Dynamic(from_traits, _), &ty::Dynamic(to_traits, _)) => {
|
||||
(&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => {
|
||||
// FIXME(dyn-star): Do the right thing with DynKinds
|
||||
for (from, to) in from_traits.iter().zip(to_traits) {
|
||||
let from =
|
||||
fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from);
|
||||
|
|
|
@ -158,10 +158,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
None
|
||||
}
|
||||
|
||||
fn zst_to_backend(&self, _ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
self.const_undef(self.type_ix(0))
|
||||
}
|
||||
|
||||
fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
|
||||
match cv {
|
||||
|
|
|
@ -11,7 +11,6 @@ doctest = false
|
|||
bitflags = "1.0"
|
||||
cstr = "0.2"
|
||||
libc = "0.2"
|
||||
libloading = "0.7.1"
|
||||
measureme = "10.0.0"
|
||||
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "archive", "coff", "elf", "macho", "pe"] }
|
||||
tracing = "0.1"
|
||||
|
|
|
@ -19,6 +19,7 @@ use rustc_target::abi::call::ArgAbi;
|
|||
pub use rustc_target::abi::call::*;
|
||||
use rustc_target::abi::{self, HasDataLayout, Int};
|
||||
pub use rustc_target::spec::abi::Abi;
|
||||
use rustc_target::spec::SanitizerSet;
|
||||
|
||||
use libc::c_uint;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -90,6 +91,13 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
|
|||
if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) {
|
||||
attrs.push(llvm::AttributeKind::NoAlias.create_attr(cx.llcx));
|
||||
}
|
||||
} else if cx.tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
|
||||
// If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects
|
||||
// memory sanitizer's behavior.
|
||||
|
||||
if regular.contains(ArgAttribute::NoUndef) {
|
||||
attrs.push(llvm::AttributeKind::NoUndef.create_attr(cx.llcx));
|
||||
}
|
||||
}
|
||||
|
||||
attrs
|
||||
|
|
|
@ -19,7 +19,6 @@ use rustc_target::asm::*;
|
|||
|
||||
use libc::{c_char, c_uint};
|
||||
use smallvec::SmallVec;
|
||||
use tracing::debug;
|
||||
|
||||
impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
||||
fn codegen_inline_asm(
|
||||
|
|
|
@ -35,6 +35,10 @@ pub fn apply_to_callsite(callsite: &Value, idx: AttributePlace, attrs: &[&Attrib
|
|||
/// Get LLVM attribute for the provided inline heuristic.
|
||||
#[inline]
|
||||
fn inline_attr<'ll>(cx: &CodegenCx<'ll, '_>, inline: InlineAttr) -> Option<&'ll Attribute> {
|
||||
if !cx.tcx.sess.opts.unstable_opts.inline_llvm {
|
||||
// disable LLVM inlining
|
||||
return Some(AttributeKind::NoInline.create_attr(cx.llcx));
|
||||
}
|
||||
match inline {
|
||||
InlineAttr::Hint => Some(AttributeKind::InlineHint.create_attr(cx.llcx)),
|
||||
InlineAttr::Always => Some(AttributeKind::AlwaysInline.create_attr(cx.llcx)),
|
||||
|
@ -386,7 +390,8 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
|||
) {
|
||||
let span = cx
|
||||
.tcx
|
||||
.get_attr(instance.def_id(), sym::target_feature)
|
||||
.get_attrs(instance.def_id(), sym::target_feature)
|
||||
.next()
|
||||
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
|
||||
let msg = format!(
|
||||
"the target features {} must all be either enabled or disabled together",
|
||||
|
|
|
@ -190,10 +190,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
|
||||
let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
|
||||
|
||||
tracing::trace!("invoking LLVMRustWriteImportLibrary");
|
||||
tracing::trace!(" dll_name {:#?}", dll_name_z);
|
||||
tracing::trace!(" output_path {}", output_path.display());
|
||||
tracing::trace!(
|
||||
trace!("invoking LLVMRustWriteImportLibrary");
|
||||
trace!(" dll_name {:#?}", dll_name_z);
|
||||
trace!(" output_path {}", output_path.display());
|
||||
trace!(
|
||||
" import names: {}",
|
||||
dll_imports
|
||||
.iter()
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use crate::back::write::{
|
||||
self, save_temp_bitcode, to_llvm_opt_settings, with_llvm_pmb, DiagnosticHandlers,
|
||||
};
|
||||
use crate::llvm::{self, build_string, False, True};
|
||||
use crate::{llvm_util, LlvmCodegenBackend, ModuleLlvm};
|
||||
use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
|
||||
use crate::llvm::{self, build_string};
|
||||
use crate::{LlvmCodegenBackend, ModuleLlvm};
|
||||
use object::read::archive::ArchiveFile;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
|
||||
use rustc_codegen_ssa::back::symbol_export;
|
||||
|
@ -18,7 +16,6 @@ use rustc_middle::dep_graph::WorkProduct;
|
|||
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
|
||||
use rustc_session::cgu_reuse_tracker::CguReuse;
|
||||
use rustc_session::config::{self, CrateType, Lto};
|
||||
use tracing::{debug, info};
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fs::File;
|
||||
|
@ -598,61 +595,9 @@ pub(crate) fn run_pass_manager(
|
|||
1,
|
||||
);
|
||||
}
|
||||
if llvm_util::should_use_new_llvm_pass_manager(
|
||||
&config.new_llvm_pass_manager,
|
||||
&cgcx.target_arch,
|
||||
) {
|
||||
let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
|
||||
let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
|
||||
write::optimize_with_new_llvm_pass_manager(
|
||||
cgcx,
|
||||
diag_handler,
|
||||
module,
|
||||
config,
|
||||
opt_level,
|
||||
opt_stage,
|
||||
)?;
|
||||
debug!("lto done");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let pm = llvm::LLVMCreatePassManager();
|
||||
llvm::LLVMAddAnalysisPasses(module.module_llvm.tm, pm);
|
||||
|
||||
if config.verify_llvm_ir {
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
|
||||
llvm::LLVMRustAddPass(pm, pass.unwrap());
|
||||
}
|
||||
|
||||
let opt_level = config
|
||||
.opt_level
|
||||
.map(|x| to_llvm_opt_settings(x).0)
|
||||
.unwrap_or(llvm::CodeGenOptLevel::None);
|
||||
with_llvm_pmb(module.module_llvm.llmod(), config, opt_level, false, &mut |b| {
|
||||
if thin {
|
||||
llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm);
|
||||
} else {
|
||||
llvm::LLVMRustPassManagerBuilderPopulateLTOPassManager(
|
||||
b, pm, /* Internalize = */ False, /* RunInliner = */ True,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// We always generate bitcode through ThinLTOBuffers,
|
||||
// which do not support anonymous globals
|
||||
if config.bitcode_needed() {
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast());
|
||||
llvm::LLVMRustAddPass(pm, pass.unwrap());
|
||||
}
|
||||
|
||||
if config.verify_llvm_ir {
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
|
||||
llvm::LLVMRustAddPass(pm, pass.unwrap());
|
||||
}
|
||||
|
||||
llvm::LLVMRunPassManager(pm, module.module_llvm.llmod());
|
||||
|
||||
llvm::LLVMDisposePassManager(pm);
|
||||
let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
|
||||
let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
|
||||
write::llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage)?;
|
||||
}
|
||||
debug!("lto done");
|
||||
Ok(())
|
||||
|
|
|
@ -21,14 +21,12 @@ use rustc_data_structures::profiling::SelfProfilerRef;
|
|||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_errors::{FatalError, Handler, Level};
|
||||
use rustc_fs_util::{link_or_copy, path_to_c_string};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::InnerSpan;
|
||||
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo};
|
||||
use tracing::debug;
|
||||
|
||||
use libc::{c_char, c_int, c_uint, c_void, size_t};
|
||||
use std::ffi::CString;
|
||||
|
@ -418,7 +416,7 @@ fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn optimize_with_new_llvm_pass_manager(
|
||||
pub(crate) unsafe fn llvm_optimize(
|
||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
diag_handler: &Handler,
|
||||
module: &ModuleCodegen<ModuleLlvm>,
|
||||
|
@ -466,7 +464,7 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager(
|
|||
// FIXME: NewPM doesn't provide a facility to pass custom InlineParams.
|
||||
// We would have to add upstream support for this first, before we can support
|
||||
// config.inline_threshold and our more aggressive default thresholds.
|
||||
let result = llvm::LLVMRustOptimizeWithNewPassManager(
|
||||
let result = llvm::LLVMRustOptimize(
|
||||
module.module_llvm.llmod(),
|
||||
&*module.module_llvm.tm,
|
||||
to_pass_builder_opt_level(opt_level),
|
||||
|
@ -510,18 +508,11 @@ pub(crate) unsafe fn optimize(
|
|||
|
||||
let llmod = module.module_llvm.llmod();
|
||||
let llcx = &*module.module_llvm.llcx;
|
||||
let tm = &*module.module_llvm.tm;
|
||||
let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
|
||||
|
||||
let module_name = module.name.clone();
|
||||
let module_name = Some(&module_name[..]);
|
||||
|
||||
if let Some(false) = config.new_llvm_pass_manager && llvm_util::get_version() >= (15, 0, 0) {
|
||||
diag_handler.warn(
|
||||
"ignoring `-Z new-llvm-pass-manager=no`, which is no longer supported with LLVM 15",
|
||||
);
|
||||
}
|
||||
|
||||
if config.emit_no_opt_bc {
|
||||
let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
|
||||
let out = path_to_c_string(&out);
|
||||
|
@ -529,184 +520,17 @@ pub(crate) unsafe fn optimize(
|
|||
}
|
||||
|
||||
if let Some(opt_level) = config.opt_level {
|
||||
if llvm_util::should_use_new_llvm_pass_manager(
|
||||
&config.new_llvm_pass_manager,
|
||||
&cgcx.target_arch,
|
||||
) {
|
||||
let opt_stage = match cgcx.lto {
|
||||
Lto::Fat => llvm::OptStage::PreLinkFatLTO,
|
||||
Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO,
|
||||
_ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO,
|
||||
_ => llvm::OptStage::PreLinkNoLTO,
|
||||
};
|
||||
return optimize_with_new_llvm_pass_manager(
|
||||
cgcx,
|
||||
diag_handler,
|
||||
module,
|
||||
config,
|
||||
opt_level,
|
||||
opt_stage,
|
||||
);
|
||||
}
|
||||
|
||||
if cgcx.prof.llvm_recording_enabled() {
|
||||
diag_handler
|
||||
.warn("`-Z self-profile-events = llvm` requires `-Z new-llvm-pass-manager`");
|
||||
}
|
||||
|
||||
// Create the two optimizing pass managers. These mirror what clang
|
||||
// does, and are by populated by LLVM's default PassManagerBuilder.
|
||||
// Each manager has a different set of passes, but they also share
|
||||
// some common passes.
|
||||
let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
|
||||
let mpm = llvm::LLVMCreatePassManager();
|
||||
|
||||
{
|
||||
let find_pass = |pass_name: &str| {
|
||||
let pass_name = SmallCStr::new(pass_name);
|
||||
llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr())
|
||||
};
|
||||
|
||||
if config.verify_llvm_ir {
|
||||
// Verification should run as the very first pass.
|
||||
llvm::LLVMRustAddPass(fpm, find_pass("verify").unwrap());
|
||||
}
|
||||
|
||||
let mut extra_passes = Vec::new();
|
||||
let mut have_name_anon_globals_pass = false;
|
||||
|
||||
for pass_name in &config.passes {
|
||||
if pass_name == "lint" {
|
||||
// Linting should also be performed early, directly on the generated IR.
|
||||
llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap());
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(pass) = find_pass(pass_name) {
|
||||
extra_passes.push(pass);
|
||||
} else {
|
||||
diag_handler.warn(&format!("unknown pass `{}`, ignoring", pass_name));
|
||||
}
|
||||
|
||||
if pass_name == "name-anon-globals" {
|
||||
have_name_anon_globals_pass = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Instrumentation must be inserted before optimization,
|
||||
// otherwise LLVM may optimize some functions away which
|
||||
// breaks llvm-cov.
|
||||
//
|
||||
// This mirrors what Clang does in lib/CodeGen/BackendUtil.cpp.
|
||||
if config.instrument_gcov {
|
||||
llvm::LLVMRustAddPass(mpm, find_pass("insert-gcov-profiling").unwrap());
|
||||
}
|
||||
if config.instrument_coverage {
|
||||
llvm::LLVMRustAddPass(mpm, find_pass("instrprof").unwrap());
|
||||
}
|
||||
if config.debug_info_for_profiling {
|
||||
llvm::LLVMRustAddPass(mpm, find_pass("add-discriminators").unwrap());
|
||||
}
|
||||
|
||||
add_sanitizer_passes(config, &mut extra_passes);
|
||||
|
||||
// Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need
|
||||
// to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise
|
||||
// we'll get errors in LLVM.
|
||||
let using_thin_buffers = config.bitcode_needed();
|
||||
if !config.no_prepopulate_passes {
|
||||
llvm::LLVMAddAnalysisPasses(tm, fpm);
|
||||
llvm::LLVMAddAnalysisPasses(tm, mpm);
|
||||
let opt_level = to_llvm_opt_settings(opt_level).0;
|
||||
let prepare_for_thin_lto = cgcx.lto == Lto::Thin
|
||||
|| cgcx.lto == Lto::ThinLocal
|
||||
|| (cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled());
|
||||
with_llvm_pmb(llmod, config, opt_level, prepare_for_thin_lto, &mut |b| {
|
||||
llvm::LLVMRustAddLastExtensionPasses(
|
||||
b,
|
||||
extra_passes.as_ptr(),
|
||||
extra_passes.len() as size_t,
|
||||
);
|
||||
llvm::LLVMRustPassManagerBuilderPopulateFunctionPassManager(b, fpm);
|
||||
llvm::LLVMRustPassManagerBuilderPopulateModulePassManager(b, mpm);
|
||||
});
|
||||
|
||||
have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
|
||||
if using_thin_buffers && !prepare_for_thin_lto {
|
||||
llvm::LLVMRustAddPass(mpm, find_pass("name-anon-globals").unwrap());
|
||||
have_name_anon_globals_pass = true;
|
||||
}
|
||||
} else {
|
||||
// If we don't use the standard pipeline, directly populate the MPM
|
||||
// with the extra passes.
|
||||
for pass in extra_passes {
|
||||
llvm::LLVMRustAddPass(mpm, pass);
|
||||
}
|
||||
}
|
||||
|
||||
if using_thin_buffers && !have_name_anon_globals_pass {
|
||||
// As described above, this will probably cause an error in LLVM
|
||||
if config.no_prepopulate_passes {
|
||||
diag_handler.err(
|
||||
"The current compilation is going to use thin LTO buffers \
|
||||
without running LLVM's NameAnonGlobals pass. \
|
||||
This will likely cause errors in LLVM. Consider adding \
|
||||
-C passes=name-anon-globals to the compiler command line.",
|
||||
);
|
||||
} else {
|
||||
bug!(
|
||||
"We are using thin LTO buffers without running the NameAnonGlobals pass. \
|
||||
This will likely cause errors in LLVM and should never happen."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diag_handler.abort_if_errors();
|
||||
|
||||
// Finally, run the actual optimization passes
|
||||
{
|
||||
let _timer = cgcx.prof.extra_verbose_generic_activity(
|
||||
"LLVM_module_optimize_function_passes",
|
||||
&*module.name,
|
||||
);
|
||||
llvm::LLVMRustRunFunctionPassManager(fpm, llmod);
|
||||
}
|
||||
{
|
||||
let _timer = cgcx.prof.extra_verbose_generic_activity(
|
||||
"LLVM_module_optimize_module_passes",
|
||||
&*module.name,
|
||||
);
|
||||
llvm::LLVMRunPassManager(mpm, llmod);
|
||||
}
|
||||
|
||||
// Deallocate managers that we're now done with
|
||||
llvm::LLVMDisposePassManager(fpm);
|
||||
llvm::LLVMDisposePassManager(mpm);
|
||||
let opt_stage = match cgcx.lto {
|
||||
Lto::Fat => llvm::OptStage::PreLinkFatLTO,
|
||||
Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO,
|
||||
_ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO,
|
||||
_ => llvm::OptStage::PreLinkNoLTO,
|
||||
};
|
||||
return llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn add_sanitizer_passes(config: &ModuleConfig, passes: &mut Vec<&'static mut llvm::Pass>) {
|
||||
if config.sanitizer.contains(SanitizerSet::ADDRESS) {
|
||||
let recover = config.sanitizer_recover.contains(SanitizerSet::ADDRESS);
|
||||
passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(recover));
|
||||
passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(recover));
|
||||
}
|
||||
if config.sanitizer.contains(SanitizerSet::MEMORY) {
|
||||
let track_origins = config.sanitizer_memory_track_origins as c_int;
|
||||
let recover = config.sanitizer_recover.contains(SanitizerSet::MEMORY);
|
||||
passes.push(llvm::LLVMRustCreateMemorySanitizerPass(track_origins, recover));
|
||||
}
|
||||
if config.sanitizer.contains(SanitizerSet::THREAD) {
|
||||
passes.push(llvm::LLVMRustCreateThreadSanitizerPass());
|
||||
}
|
||||
if config.sanitizer.contains(SanitizerSet::HWADDRESS) {
|
||||
let recover = config.sanitizer_recover.contains(SanitizerSet::HWADDRESS);
|
||||
passes.push(llvm::LLVMRustCreateHWAddressSanitizerPass(recover));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn link(
|
||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
diag_handler: &Handler,
|
||||
|
@ -1073,72 +897,6 @@ unsafe fn embed_bitcode(
|
|||
}
|
||||
}
|
||||
|
||||
pub unsafe fn with_llvm_pmb(
|
||||
llmod: &llvm::Module,
|
||||
config: &ModuleConfig,
|
||||
opt_level: llvm::CodeGenOptLevel,
|
||||
prepare_for_thin_lto: bool,
|
||||
f: &mut dyn FnMut(&llvm::PassManagerBuilder),
|
||||
) {
|
||||
use std::ptr;
|
||||
|
||||
// Create the PassManagerBuilder for LLVM. We configure it with
|
||||
// reasonable defaults and prepare it to actually populate the pass
|
||||
// manager.
|
||||
let builder = llvm::LLVMRustPassManagerBuilderCreate();
|
||||
let opt_size = config.opt_size.map_or(llvm::CodeGenOptSizeNone, |x| to_llvm_opt_settings(x).1);
|
||||
let inline_threshold = config.inline_threshold;
|
||||
let pgo_gen_path = get_pgo_gen_path(config);
|
||||
let pgo_use_path = get_pgo_use_path(config);
|
||||
let pgo_sample_use_path = get_pgo_sample_use_path(config);
|
||||
|
||||
llvm::LLVMRustConfigurePassManagerBuilder(
|
||||
builder,
|
||||
opt_level,
|
||||
config.merge_functions,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop,
|
||||
prepare_for_thin_lto,
|
||||
pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
|
||||
pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
|
||||
pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
|
||||
opt_size as c_int,
|
||||
);
|
||||
|
||||
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
|
||||
|
||||
// Here we match what clang does (kinda). For O0 we only inline
|
||||
// always-inline functions (but don't add lifetime intrinsics), at O1 we
|
||||
// inline with lifetime intrinsics, and O2+ we add an inliner with a
|
||||
// thresholds copied from clang.
|
||||
match (opt_level, opt_size, inline_threshold) {
|
||||
(.., Some(t)) => {
|
||||
llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, t);
|
||||
}
|
||||
(llvm::CodeGenOptLevel::Aggressive, ..) => {
|
||||
llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 275);
|
||||
}
|
||||
(_, llvm::CodeGenOptSizeDefault, _) => {
|
||||
llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 75);
|
||||
}
|
||||
(_, llvm::CodeGenOptSizeAggressive, _) => {
|
||||
llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 25);
|
||||
}
|
||||
(llvm::CodeGenOptLevel::None, ..) => {
|
||||
llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers);
|
||||
}
|
||||
(llvm::CodeGenOptLevel::Less, ..) => {
|
||||
llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers);
|
||||
}
|
||||
(llvm::CodeGenOptLevel::Default, ..) => {
|
||||
llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 225);
|
||||
}
|
||||
}
|
||||
|
||||
f(builder);
|
||||
llvm::LLVMRustPassManagerBuilderDispose(builder);
|
||||
}
|
||||
|
||||
// Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
|
||||
// This is required to satisfy `dllimport` references to static data in .rlibs
|
||||
// when using MSVC linker. We do this only for data, as linker can fix up
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
use crate::attributes;
|
||||
use crate::common::Funclet;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::llvm::{self, BasicBlock, False};
|
||||
use crate::llvm::{AtomicOrdering, AtomicRmwBinOp, SynchronizationScope};
|
||||
use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock};
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use crate::value::Value;
|
||||
use cstr::cstr;
|
||||
use libc::{c_char, c_uint};
|
||||
use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, TypeKind};
|
||||
use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind};
|
||||
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
@ -27,7 +26,6 @@ use std::ffi::CStr;
|
|||
use std::iter;
|
||||
use std::ops::Deref;
|
||||
use std::ptr;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
// All Builders must have an llfn associated with them
|
||||
#[must_use]
|
||||
|
@ -1043,15 +1041,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
) -> &'ll Value {
|
||||
let weak = if weak { llvm::True } else { llvm::False };
|
||||
unsafe {
|
||||
llvm::LLVMRustBuildAtomicCmpXchg(
|
||||
let value = llvm::LLVMBuildAtomicCmpXchg(
|
||||
self.llbuilder,
|
||||
dst,
|
||||
cmp,
|
||||
src,
|
||||
AtomicOrdering::from_generic(order),
|
||||
AtomicOrdering::from_generic(failure_order),
|
||||
weak,
|
||||
)
|
||||
llvm::False, // SingleThreaded
|
||||
);
|
||||
llvm::LLVMSetWeak(value, weak);
|
||||
value
|
||||
}
|
||||
}
|
||||
fn atomic_rmw(
|
||||
|
@ -1068,7 +1068,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
dst,
|
||||
src,
|
||||
AtomicOrdering::from_generic(order),
|
||||
False,
|
||||
llvm::False, // SingleThreaded
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1076,13 +1076,18 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
fn atomic_fence(
|
||||
&mut self,
|
||||
order: rustc_codegen_ssa::common::AtomicOrdering,
|
||||
scope: rustc_codegen_ssa::common::SynchronizationScope,
|
||||
scope: SynchronizationScope,
|
||||
) {
|
||||
let single_threaded = match scope {
|
||||
SynchronizationScope::SingleThread => llvm::True,
|
||||
SynchronizationScope::CrossThread => llvm::False,
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMRustBuildAtomicFence(
|
||||
llvm::LLVMBuildFence(
|
||||
self.llbuilder,
|
||||
AtomicOrdering::from_generic(order),
|
||||
SynchronizationScope::from_generic(scope),
|
||||
single_threaded,
|
||||
UNNAMED,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue