Merge remote-tracking branch 'origin/master' into mpk/add-long-error-message-for-E0311

This commit is contained in:
Matthew Kelly 2022-09-26 19:59:52 -04:00
commit 24aab524cb
5269 changed files with 128288 additions and 36333 deletions

View file

@ -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
View file

@ -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
View file

@ -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

View file

@ -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"

View file

@ -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",

View file

@ -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:

View file

@ -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]

View file

@ -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"

View file

@ -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);

View file

@ -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
}

View file

@ -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 {

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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) => {

View file

@ -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,
}
}
}

View file

@ -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);
}

View file

@ -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"

View file

@ -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),

View file

@ -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

View file

@ -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,
}

View file

@ -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)],
}),
));

View file

@ -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>) {

View file

@ -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),
})
}

View file

@ -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(&lt)),
@ -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(&param.ty, ImplTraitContext::Universal)
self.lower_ty_direct(&param.ty, &ImplTraitContext::Universal)
} else {
self.lower_ty_direct(
&param.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)
}
}

View file

@ -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) {

View file

@ -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)],
}),
))
}
}
}

View file

@ -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 {

View file

@ -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) = (&param.kind, &param.bounds, ident.span);
let (ord_kind, ident) = match &param.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),
}

View file

@ -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)

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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 {

View file

@ -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) {

View file

@ -5,7 +5,6 @@
//! to this crate.
#![feature(let_chains)]
#![feature(let_else)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]

View file

@ -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]

View file

@ -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

View file

@ -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 => {}
}
}

View file

@ -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

View file

@ -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");

View file

@ -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 {

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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,
);

View file

@ -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,

View file

@ -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")
}
}

View file

@ -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 {

View file

@ -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;

View file

@ -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

View file

@ -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(..),
_,

View file

@ -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;

View file

@ -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>,
}

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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| {

View file

@ -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(

View file

@ -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));
}
}
}
}

View file

@ -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,);
});

View file

@ -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);

View file

@ -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"

View file

@ -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![

View file

@ -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]

View file

@ -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)
}

View file

@ -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

View file

@ -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,

View file

@ -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),

View file

@ -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),

View file

@ -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),

View file

@ -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(),

View file

@ -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,

View file

@ -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]),

View file

@ -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,
),
),
)
});

View file

@ -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(

View file

@ -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};

View file

@ -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,

View file

@ -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![

View file

@ -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 },

View file

@ -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()

View file

@ -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);
}

View file

@ -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 { .. }

View file

@ -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.

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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 {

View file

@ -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"

View file

@ -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

View file

@ -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(

View file

@ -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",

View file

@ -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()

View file

@ -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(())

View file

@ -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

View file

@ -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