commit
949a38509e
.github/workflows
.gitmodules.mailmapCONTRIBUTING.mdCargo.lockRELEASES.mdcompiler
rustc_abi/src
rustc_ast/src
rustc_ast_lowering
rustc_ast_passes/src
rustc_ast_pretty/src/pprust
rustc_attr/src
rustc_borrowck/src
constraints
consumers.rsdiagnostics
lib.rsmember_constraints.rsnll.rspath_utils.rsregion_infer
renumber.rstype_check
rustc_codegen_cranelift
rustc_codegen_gcc
rustc_codegen_llvm
messages.ftl
src
rustc_codegen_ssa/src
rustc_const_eval
rustc_data_structures
rustc_driver_impl/src
rustc_error_codes/src/error_codes
rustc_error_messages/src
rustc_errors/src
rustc_expand/src
rustc_feature/src
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -34,7 +34,7 @@ jobs:
|
||||
pr:
|
||||
permissions:
|
||||
actions: write
|
||||
name: PR
|
||||
name: "PR - ${{ matrix.name }}"
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
|
||||
@ -159,7 +159,7 @@ jobs:
|
||||
auto:
|
||||
permissions:
|
||||
actions: write
|
||||
name: auto
|
||||
name: "auto - ${{ matrix.name }}"
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
|
||||
@ -578,7 +578,7 @@ jobs:
|
||||
try:
|
||||
permissions:
|
||||
actions: write
|
||||
name: try
|
||||
name: "try - ${{ matrix.name }}"
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
|
||||
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -25,7 +25,7 @@
|
||||
[submodule "src/llvm-project"]
|
||||
path = src/llvm-project
|
||||
url = https://github.com/rust-lang/llvm-project.git
|
||||
branch = rustc/15.0-2022-12-07
|
||||
branch = rustc/16.0-2023-03-06
|
||||
[submodule "src/doc/embedded-book"]
|
||||
path = src/doc/embedded-book
|
||||
url = https://github.com/rust-embedded/book.git
|
||||
|
2
.mailmap
2
.mailmap
@ -102,6 +102,7 @@ Carol Willing <carolcode@willingconsulting.com>
|
||||
Chandler Deng <chandde@microsoft.com>
|
||||
Charles Lew <crlf0710@gmail.com> CrLF0710 <crlf0710@gmail.com>
|
||||
Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
|
||||
Chris Denton <chris@chrisdenton.dev> Chris Denton <ChrisDenton@users.noreply.github.com>
|
||||
Chris Gregory <czipperz@gmail.com>
|
||||
Chris Pardy <chrispardy36@gmail.com>
|
||||
Chris Pressey <cpressey@gmail.com>
|
||||
@ -415,6 +416,7 @@ Nick Platt <platt.nicholas@gmail.com>
|
||||
Niclas Schwarzlose <15schnic@gmail.com>
|
||||
Nicolas Abram <abramlujan@gmail.com>
|
||||
Nicole Mazzuca <npmazzuca@gmail.com>
|
||||
Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> nils <48135649+Nilstrieb@users.noreply.github.com>
|
||||
Nif Ward <nif.ward@gmail.com>
|
||||
Nika Layzell <nika@thelayzells.com> <michael@thelayzells.com>
|
||||
NODA Kai <nodakai@gmail.com>
|
||||
|
@ -33,7 +33,6 @@ find a mentor! You can learn more about asking questions and getting help in the
|
||||
Did a compiler error message tell you to come here? If you want to create an ICE report,
|
||||
refer to [this section][contributing-bug-reports] and [open an issue][issue template].
|
||||
|
||||
[Contributing to Rust]: https://rustc-dev-guide.rust-lang.org/contributing.html#contributing-to-rust
|
||||
[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/
|
||||
[std-dev-guide]: https://std-dev-guide.rust-lang.org/
|
||||
[contributing-bug-reports]: https://rustc-dev-guide.rust-lang.org/contributing.html#bug-reports
|
||||
|
229
Cargo.lock
229
Cargo.lock
@ -98,6 +98,46 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-wincon",
|
||||
"concolor-override",
|
||||
"concolor-query 0.3.3",
|
||||
"is-terminal",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.65"
|
||||
@ -106,11 +146,11 @@ checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
|
||||
|
||||
[[package]]
|
||||
name = "ar_archive_writer"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "276881980556fdadeb88aa1ffc667e4d2e8fe72531dfabcb7a82bb3c9ea9ba31"
|
||||
checksum = "b0639441fd17a3197d1cbca8dc8768cc172a63b64b4bb6c372e8f41ed0acc9bb"
|
||||
dependencies = [
|
||||
"object 0.29.0",
|
||||
"object 0.30.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -149,9 +189,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "askama_derive"
|
||||
version = "0.12.0"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e80b5ad1afe82872b7aa3e9de9b206ecb85584aa324f0f60fa4c903ce935936b"
|
||||
checksum = "c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94"
|
||||
dependencies = [
|
||||
"basic-toml",
|
||||
"mime",
|
||||
@ -160,7 +200,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn",
|
||||
"syn 2.0.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -362,7 +402,7 @@ dependencies = [
|
||||
"cargo-test-macro",
|
||||
"cargo-test-support",
|
||||
"cargo-util",
|
||||
"clap 4.1.4",
|
||||
"clap 4.2.1",
|
||||
"crates-io",
|
||||
"curl",
|
||||
"curl-sys",
|
||||
@ -398,6 +438,7 @@ dependencies = [
|
||||
"pasetors",
|
||||
"pathdiff",
|
||||
"pretty_env_logger",
|
||||
"rand",
|
||||
"rustc-workspace-hack",
|
||||
"rustfix",
|
||||
"same-file",
|
||||
@ -590,7 +631,7 @@ checksum = "d552b2fa341f5fc35c6b917b1d289d3c3a34d0b74e579390ea6192d6152a8cdb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -669,17 +710,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.4"
|
||||
version = "4.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76"
|
||||
checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive 4.2.0",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"bitflags",
|
||||
"clap_derive 4.1.0",
|
||||
"clap_lex 0.3.0",
|
||||
"is-terminal",
|
||||
"clap_lex 0.4.1",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"terminal_size",
|
||||
]
|
||||
|
||||
@ -689,7 +740,7 @@ version = "4.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
|
||||
dependencies = [
|
||||
"clap 4.1.4",
|
||||
"clap 4.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -702,20 +753,19 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.1.0"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
|
||||
checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -729,18 +779,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
|
||||
|
||||
[[package]]
|
||||
name = "clippy"
|
||||
version = "0.1.70"
|
||||
dependencies = [
|
||||
"clap 4.1.4",
|
||||
"clap 4.2.1",
|
||||
"clippy_lints",
|
||||
"clippy_utils",
|
||||
"compiletest_rs",
|
||||
@ -757,7 +804,7 @@ dependencies = [
|
||||
"rustc_tools_util",
|
||||
"semver",
|
||||
"serde",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"tempfile",
|
||||
"termize",
|
||||
"tester",
|
||||
@ -771,7 +818,7 @@ name = "clippy_dev"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"clap 4.1.4",
|
||||
"clap 4.2.1",
|
||||
"indoc",
|
||||
"itertools",
|
||||
"opener",
|
||||
@ -868,9 +915,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.87"
|
||||
version = "0.1.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f867ce54c09855ccd135ad4a50c777182a0c7af5ff20a8f537617bd648b10d50"
|
||||
checksum = "571298a3cce7e2afbd3d61abb91a18667d5ab25993ec577a88ee8ac45f00cc3a"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc-std-workspace-core",
|
||||
@ -932,15 +979,30 @@ checksum = "b90f9dcd9490a97db91a85ccd79e38a87e14323f0bb824659ee3274e9143ba37"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"concolor-query",
|
||||
"concolor-query 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concolor-override"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f"
|
||||
|
||||
[[package]]
|
||||
name = "concolor-query"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317"
|
||||
|
||||
[[package]]
|
||||
name = "concolor-query"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf"
|
||||
dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.1"
|
||||
@ -1108,7 +1170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1154,7 +1216,7 @@ version = "0.1.70"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1176,7 +1238,7 @@ checksum = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1189,7 +1251,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1267,7 +1329,7 @@ checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1683,7 +1745,7 @@ checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2530,7 +2592,7 @@ dependencies = [
|
||||
"markup5ever",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2619,7 +2681,7 @@ checksum = "9ddb07844c2ffc4c28840e799e9e54ff054393cf090740decf25624e9d94b93a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2689,9 +2751,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
@ -2844,7 +2906,7 @@ name = "jsondoclint"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.4",
|
||||
"clap 4.2.1",
|
||||
"fs-err",
|
||||
"rustc-hash",
|
||||
"rustdoc-json-types",
|
||||
@ -2879,18 +2941,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.139"
|
||||
version = "0.2.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libffi"
|
||||
version = "3.0.1"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
|
||||
checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libffi-sys",
|
||||
@ -2898,9 +2960,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libffi-sys"
|
||||
version = "2.0.0"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
|
||||
checksum = "dc65067b78c0fc069771e8b9a9e02df71e08858bec92c1f101377c67b9dca7c7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
@ -3089,7 +3151,7 @@ checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3110,7 +3172,7 @@ dependencies = [
|
||||
"ammonia",
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"clap 4.1.4",
|
||||
"clap 4.2.1",
|
||||
"clap_complete",
|
||||
"elasticlunr-rs",
|
||||
"env_logger 0.10.0",
|
||||
@ -3679,7 +3741,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3823,7 +3885,7 @@ dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
@ -3846,9 +3908,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.46"
|
||||
version = "1.0.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
|
||||
checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -3925,9 +3987,9 @@ checksum = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -4115,7 +4177,7 @@ dependencies = [
|
||||
name = "rustbook"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 4.1.4",
|
||||
"clap 4.2.1",
|
||||
"env_logger 0.7.1",
|
||||
"mdbook",
|
||||
]
|
||||
@ -4160,21 +4222,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-rayon"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a79f0b0b2609e2eacf9758013f50e7176cb4b29fd6436a747b14a5362c8727a"
|
||||
checksum = "eb81aadc8837ca6ecebe0fe1353f15df83b3b3cc2cf7a8afd571bc22aa121710"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rustc-rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-rayon-core"
|
||||
version = "0.4.1"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02269144a0db9bb55cf5d4a41a5a0e95b334b0b78b08269018ca9b0250718c30"
|
||||
checksum = "67668daaf00e359c126f6dcb40d652d89b458a008c8afa727a42a2d20fca0b7f"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
@ -4224,7 +4284,7 @@ dependencies = [
|
||||
"regex",
|
||||
"serde_json",
|
||||
"smallvec",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"url",
|
||||
"winapi",
|
||||
]
|
||||
@ -4934,7 +4994,7 @@ dependencies = [
|
||||
"fluent-syntax",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"synstructure",
|
||||
"unic-langid",
|
||||
]
|
||||
@ -5514,7 +5574,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5684,7 +5744,7 @@ checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6028,7 +6088,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6048,6 +6108,17 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
@ -6056,7 +6127,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
@ -6190,7 +6261,7 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6387,7 +6458,7 @@ checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6586,7 +6657,7 @@ checksum = "1f5cdec05b907f4e2f6843f4354f4ce6a5bebe1a56df320a49134944477ce4d8"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"unic-langid-impl",
|
||||
]
|
||||
|
||||
@ -6739,9 +6810,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
@ -6834,7 +6905,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -6856,7 +6927,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -7082,7 +7153,7 @@ checksum = "ca800d73d6b7a7ee54f2608205c98b549fca71c9500c1abcb3abdc7708b4a8cb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -7103,7 +7174,7 @@ checksum = "2e8aa86add9ddbd2409c1ed01e033cd457d79b1b1229b64922c25095c595e829"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -7132,6 +7203,6 @@ checksum = "2154cb6e2a748163354165e22c6a555effb09ca2d16334767bf66bb404f2206e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.102",
|
||||
"synstructure",
|
||||
]
|
||||
|
24
RELEASES.md
24
RELEASES.md
@ -1,3 +1,26 @@
|
||||
Version 1.68.2 (2023-03-28)
|
||||
===========================
|
||||
|
||||
- [Update the GitHub RSA host key bundled within Cargo](https://github.com/rust-lang/cargo/pull/11883).
|
||||
The key was [rotated by GitHub](https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/)
|
||||
on 2023-03-24 after the old one leaked.
|
||||
- [Mark the old GitHub RSA host key as revoked](https://github.com/rust-lang/cargo/pull/11889).
|
||||
This will prevent Cargo from accepting the leaked key even when trusted by
|
||||
the system.
|
||||
- [Add support for `@revoked` and a better error message for `@cert-authority` in Cargo's SSH host key verification](https://github.com/rust-lang/cargo/pull/11635)
|
||||
|
||||
Version 1.68.1 (2023-03-23)
|
||||
===========================
|
||||
|
||||
- [Fix miscompilation in produced Windows MSVC artifacts](https://github.com/rust-lang/rust/pull/109094)
|
||||
This was introduced by enabling ThinLTO for the distributed rustc which led
|
||||
to miscompilations in the resulting binary. Currently this is believed to be
|
||||
limited to the -Zdylib-lto flag used for rustc compilation, rather than a
|
||||
general bug in ThinLTO, so only rustc artifacts should be affected.
|
||||
- [Fix --enable-local-rust builds](https://github.com/rust-lang/rust/pull/109111/)
|
||||
- [Treat `$prefix-clang` as `clang` in linker detection code](https://github.com/rust-lang/rust/pull/109156)
|
||||
- [Fix panic in compiler code](https://github.com/rust-lang/rust/pull/108162)
|
||||
|
||||
Version 1.68.0 (2023-03-09)
|
||||
==========================
|
||||
|
||||
@ -71,6 +94,7 @@ Misc
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
|
||||
- [Only support Android NDK 25 or newer](https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html)
|
||||
- [Add `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` to future-incompat report](https://github.com/rust-lang/rust/pull/103418/)
|
||||
- [Only specify `--target` by default for `-Zgcc-ld=lld` on wasm](https://github.com/rust-lang/rust/pull/101792/)
|
||||
- [Bump `IMPLIED_BOUNDS_ENTAILMENT` to Deny + ReportNow](https://github.com/rust-lang/rust/pull/106465/)
|
||||
|
@ -43,7 +43,7 @@ pub trait LayoutCalculator {
|
||||
.max_by_key(|niche| niche.available(dl));
|
||||
|
||||
LayoutS {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
variants: Variants::Single { index: FIRST_VARIANT },
|
||||
fields: FieldsShape::Arbitrary {
|
||||
offsets: vec![Size::ZERO, b_offset],
|
||||
memory_index: vec![0, 1],
|
||||
@ -264,7 +264,7 @@ pub trait LayoutCalculator {
|
||||
abi = Abi::Uninhabited;
|
||||
}
|
||||
Some(LayoutS {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
variants: Variants::Single { index: FIRST_VARIANT },
|
||||
fields: FieldsShape::Arbitrary { offsets, memory_index },
|
||||
abi,
|
||||
largest_niche,
|
||||
@ -277,7 +277,7 @@ pub trait LayoutCalculator {
|
||||
let dl = self.current_data_layout();
|
||||
let dl = dl.borrow();
|
||||
LayoutS {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
variants: Variants::Single { index: FIRST_VARIANT },
|
||||
fields: FieldsShape::Primitive,
|
||||
abi: Abi::Uninhabited,
|
||||
largest_niche: None,
|
||||
@ -289,7 +289,7 @@ pub trait LayoutCalculator {
|
||||
fn layout_of_struct_or_enum(
|
||||
&self,
|
||||
repr: &ReprOptions,
|
||||
variants: &IndexVec<VariantIdx, Vec<Layout<'_>>>,
|
||||
variants: &IndexSlice<VariantIdx, Vec<Layout<'_>>>,
|
||||
is_enum: bool,
|
||||
is_unsafe_cell: bool,
|
||||
scalar_valid_range: (Bound<u128>, Bound<u128>),
|
||||
@ -331,7 +331,7 @@ pub trait LayoutCalculator {
|
||||
}
|
||||
// If it's a struct, still compute a layout so that we can still compute the
|
||||
// field offsets.
|
||||
None => VariantIdx::new(0),
|
||||
None => FIRST_VARIANT,
|
||||
};
|
||||
|
||||
let is_struct = !is_enum ||
|
||||
@ -467,7 +467,7 @@ pub trait LayoutCalculator {
|
||||
.max_by_key(|(_i, layout)| layout.size.bytes())
|
||||
.map(|(i, _layout)| i)?;
|
||||
|
||||
let all_indices = (0..=variants.len() - 1).map(VariantIdx::new);
|
||||
let all_indices = variants.indices();
|
||||
let needs_disc =
|
||||
|index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
|
||||
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
|
||||
@ -883,7 +883,7 @@ pub trait LayoutCalculator {
|
||||
fn layout_of_union(
|
||||
&self,
|
||||
repr: &ReprOptions,
|
||||
variants: &IndexVec<VariantIdx, Vec<Layout<'_>>>,
|
||||
variants: &IndexSlice<VariantIdx, Vec<Layout<'_>>>,
|
||||
) -> Option<LayoutS> {
|
||||
let dl = self.current_data_layout();
|
||||
let dl = dl.borrow();
|
||||
@ -896,8 +896,8 @@ pub trait LayoutCalculator {
|
||||
let optimize = !repr.inhibit_union_abi_opt();
|
||||
let mut size = Size::ZERO;
|
||||
let mut abi = Abi::Aggregate { sized: true };
|
||||
let index = VariantIdx::new(0);
|
||||
for field in &variants[index] {
|
||||
let only_variant = &variants[FIRST_VARIANT];
|
||||
for field in only_variant {
|
||||
assert!(field.0.is_sized());
|
||||
align = align.max(field.align());
|
||||
|
||||
@ -930,8 +930,8 @@ pub trait LayoutCalculator {
|
||||
}
|
||||
|
||||
Some(LayoutS {
|
||||
variants: Variants::Single { index },
|
||||
fields: FieldsShape::Union(NonZeroUsize::new(variants[index].len())?),
|
||||
variants: Variants::Single { index: FIRST_VARIANT },
|
||||
fields: FieldsShape::Union(NonZeroUsize::new(only_variant.len())?),
|
||||
abi,
|
||||
largest_niche: None,
|
||||
align,
|
||||
|
@ -11,7 +11,7 @@ use bitflags::bitflags;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::StableOrd;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::HashStable_Generic;
|
||||
#[cfg(feature = "nightly")]
|
||||
@ -1057,6 +1057,32 @@ impl Scalar {
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// The *source-order* index of a field in a variant.
|
||||
///
|
||||
/// This is how most code after type checking refers to fields, rather than
|
||||
/// using names (as names have hygiene complications and more complex lookup).
|
||||
///
|
||||
/// Particularly for `repr(Rust)` types, this may not be the same as *layout* order.
|
||||
/// (It is for `repr(C)` `struct`s, however.)
|
||||
///
|
||||
/// For example, in the following types,
|
||||
/// ```rust
|
||||
/// # enum Never {}
|
||||
/// # #[repr(u16)]
|
||||
/// enum Demo1 {
|
||||
/// Variant0 { a: Never, b: i32 } = 100,
|
||||
/// Variant1 { c: u8, d: u64 } = 10,
|
||||
/// }
|
||||
/// struct Demo2 { e: u8, f: u16, g: u8 }
|
||||
/// ```
|
||||
/// `b` is `FieldIdx(1)` in `VariantIdx(0)`,
|
||||
/// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and
|
||||
/// `f` is `FieldIdx(1)` in `VariantIdx(0)`.
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct FieldIdx {}
|
||||
}
|
||||
|
||||
/// Describes how the fields of a type are located in memory.
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||
@ -1380,8 +1406,21 @@ impl Niche {
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// The *source-order* index of a variant in a type.
|
||||
///
|
||||
/// For enums, these are always `0..variant_count`, regardless of any
|
||||
/// custom discriminants that may have been defined, and including any
|
||||
/// variants that may end up uninhabited due to field types. (Some of the
|
||||
/// variants may not be present in a monomorphized ABI [`Variants`], but
|
||||
/// those skipped variants are always counted when determining the *index*.)
|
||||
///
|
||||
/// `struct`s, `tuples`, and `unions`s are considered to have a single variant
|
||||
/// with variant index zero, aka [`FIRST_VARIANT`].
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct VariantIdx {}
|
||||
pub struct VariantIdx {
|
||||
/// Equivalent to `VariantIdx(0)`.
|
||||
const FIRST_VARIANT = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
@ -1422,7 +1461,7 @@ impl LayoutS {
|
||||
let size = scalar.size(cx);
|
||||
let align = scalar.align(cx);
|
||||
LayoutS {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
variants: Variants::Single { index: FIRST_VARIANT },
|
||||
fields: FieldsShape::Primitive,
|
||||
abi: Abi::Scalar(scalar),
|
||||
largest_niche,
|
||||
|
@ -167,6 +167,9 @@ pub enum GenericArgs {
|
||||
AngleBracketed(AngleBracketedArgs),
|
||||
/// The `(A, B)` and `C` in `Foo(A, B) -> C`.
|
||||
Parenthesized(ParenthesizedArgs),
|
||||
/// Associated return type bounds, like `T: Trait<method(..): Send>`
|
||||
/// which applies the `Send` bound to the return-type of `method`.
|
||||
ReturnTypeNotation(Span),
|
||||
}
|
||||
|
||||
impl GenericArgs {
|
||||
@ -178,6 +181,7 @@ impl GenericArgs {
|
||||
match self {
|
||||
AngleBracketed(data) => data.span,
|
||||
Parenthesized(data) => data.span,
|
||||
ReturnTypeNotation(span) => *span,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,15 +235,15 @@ impl AngleBracketedArg {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Option<P<GenericArgs>>> for AngleBracketedArgs {
|
||||
fn into(self) -> Option<P<GenericArgs>> {
|
||||
Some(P(GenericArgs::AngleBracketed(self)))
|
||||
impl Into<P<GenericArgs>> for AngleBracketedArgs {
|
||||
fn into(self) -> P<GenericArgs> {
|
||||
P(GenericArgs::AngleBracketed(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Option<P<GenericArgs>>> for ParenthesizedArgs {
|
||||
fn into(self) -> Option<P<GenericArgs>> {
|
||||
Some(P(GenericArgs::Parenthesized(self)))
|
||||
impl Into<P<GenericArgs>> for ParenthesizedArgs {
|
||||
fn into(self) -> P<GenericArgs> {
|
||||
P(GenericArgs::Parenthesized(self))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2570,7 +2574,7 @@ pub enum AttrStyle {
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[custom_encodable]
|
||||
#[debug_format = "AttrId({})]"]
|
||||
#[debug_format = "AttrId({})"]
|
||||
pub struct AttrId {}
|
||||
}
|
||||
|
||||
|
@ -561,6 +561,7 @@ pub fn noop_visit_generic_args<T: MutVisitor>(generic_args: &mut GenericArgs, vi
|
||||
match generic_args {
|
||||
GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
|
||||
GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
|
||||
GenericArgs::ReturnTypeNotation(_span) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,6 +481,7 @@ where
|
||||
walk_list!(visitor, visit_ty, &data.inputs);
|
||||
walk_fn_ret_ty(visitor, &data.output);
|
||||
}
|
||||
GenericArgs::ReturnTypeNotation(_span) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,3 +139,15 @@ ast_lowering_trait_fn_async =
|
||||
.label = `async` because of this
|
||||
.note = `async` trait functions are not currently supported
|
||||
.note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
|
||||
|
||||
ast_lowering_bad_return_type_notation_inputs =
|
||||
argument types not allowed with return type notation
|
||||
.suggestion = remove the input types
|
||||
|
||||
ast_lowering_bad_return_type_notation_needs_dots =
|
||||
return type notation arguments must be elided with `..`
|
||||
.suggestion = add `..`
|
||||
|
||||
ast_lowering_bad_return_type_notation_output =
|
||||
return type not allowed with return type notation
|
||||
.suggestion = remove the return type
|
||||
|
@ -347,3 +347,25 @@ pub struct TraitFnAsync {
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub enum BadReturnTypeNotation {
|
||||
#[diag(ast_lowering_bad_return_type_notation_inputs)]
|
||||
Inputs {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "(..)", applicability = "maybe-incorrect")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag(ast_lowering_bad_return_type_notation_needs_dots)]
|
||||
NeedsDots {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "(..)", applicability = "maybe-incorrect")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag(ast_lowering_bad_return_type_notation_output)]
|
||||
Output {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "", applicability = "maybe-incorrect")]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use super::LoweringContext;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, Visitor};
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_span::{
|
||||
sym,
|
||||
@ -238,7 +238,7 @@ fn make_count<'hir>(
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
sp: Span,
|
||||
count: &Option<FormatCount>,
|
||||
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
|
||||
argmap: &mut FxIndexMap<(usize, ArgumentType), Option<Span>>,
|
||||
) -> hir::Expr<'hir> {
|
||||
match count {
|
||||
Some(FormatCount::Literal(n)) => {
|
||||
@ -252,7 +252,7 @@ fn make_count<'hir>(
|
||||
}
|
||||
Some(FormatCount::Argument(arg)) => {
|
||||
if let Ok(arg_index) = arg.index {
|
||||
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
|
||||
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize), arg.span);
|
||||
let count_param = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
|
||||
sp,
|
||||
hir::LangItem::FormatCount,
|
||||
@ -291,12 +291,14 @@ fn make_format_spec<'hir>(
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
sp: Span,
|
||||
placeholder: &FormatPlaceholder,
|
||||
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
|
||||
argmap: &mut FxIndexMap<(usize, ArgumentType), Option<Span>>,
|
||||
) -> hir::Expr<'hir> {
|
||||
let position = match placeholder.argument.index {
|
||||
Ok(arg_index) => {
|
||||
let (i, _) =
|
||||
argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
|
||||
let (i, _) = argmap.insert_full(
|
||||
(arg_index, ArgumentType::Format(placeholder.format_trait)),
|
||||
placeholder.span,
|
||||
);
|
||||
ctx.expr_usize(sp, i)
|
||||
}
|
||||
Err(_) => ctx.expr(
|
||||
@ -386,7 +388,7 @@ fn expand_format_args<'hir>(
|
||||
|
||||
// Create a list of all _unique_ (argument, format trait) combinations.
|
||||
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
|
||||
let mut argmap = FxIndexSet::default();
|
||||
let mut argmap = FxIndexMap::default();
|
||||
for piece in &fmt.template {
|
||||
let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
|
||||
if placeholder.format_options != Default::default() {
|
||||
@ -394,7 +396,10 @@ fn expand_format_args<'hir>(
|
||||
use_format_options = true;
|
||||
}
|
||||
if let Ok(index) = placeholder.argument.index {
|
||||
if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) {
|
||||
if argmap
|
||||
.insert((index, ArgumentType::Format(placeholder.format_trait)), placeholder.span)
|
||||
.is_some()
|
||||
{
|
||||
// Duplicate (argument, format trait) combination,
|
||||
// which we'll only put once in the args array.
|
||||
use_format_options = true;
|
||||
@ -438,7 +443,7 @@ fn expand_format_args<'hir>(
|
||||
// This is an optimization, speeding up compilation about 1-2% in some cases.
|
||||
// See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
|
||||
let use_simple_array = argmap.len() == arguments.len()
|
||||
&& argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
|
||||
&& argmap.iter().enumerate().all(|(i, (&(j, _), _))| i == j)
|
||||
&& arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));
|
||||
|
||||
let args = if use_simple_array {
|
||||
@ -452,14 +457,19 @@ fn expand_format_args<'hir>(
|
||||
let elements: Vec<_> = arguments
|
||||
.iter()
|
||||
.zip(argmap)
|
||||
.map(|(arg, (_, ty))| {
|
||||
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
|
||||
.map(|(arg, ((_, ty), placeholder_span))| {
|
||||
let placeholder_span =
|
||||
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
|
||||
let arg_span = match arg.kind {
|
||||
FormatArgumentKind::Captured(_) => placeholder_span,
|
||||
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
|
||||
};
|
||||
let arg = ctx.lower_expr(&arg.expr);
|
||||
let ref_arg = ctx.arena.alloc(ctx.expr(
|
||||
sp,
|
||||
arg_span,
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg),
|
||||
));
|
||||
make_argument(ctx, sp, ref_arg, ty)
|
||||
make_argument(ctx, placeholder_span, ref_arg, ty)
|
||||
})
|
||||
.collect();
|
||||
ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
|
||||
@ -475,16 +485,26 @@ fn expand_format_args<'hir>(
|
||||
// }
|
||||
let args_ident = Ident::new(sym::args, macsp);
|
||||
let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident);
|
||||
let args = ctx.arena.alloc_from_iter(argmap.iter().map(|&(arg_index, ty)| {
|
||||
let arg = &arguments[arg_index];
|
||||
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
|
||||
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
|
||||
let arg = ctx.arena.alloc(ctx.expr(
|
||||
sp,
|
||||
hir::ExprKind::Field(args_ident_expr, Ident::new(sym::integer(arg_index), macsp)),
|
||||
));
|
||||
make_argument(ctx, sp, arg, ty)
|
||||
}));
|
||||
let args = ctx.arena.alloc_from_iter(argmap.iter().map(
|
||||
|(&(arg_index, ty), &placeholder_span)| {
|
||||
let arg = &arguments[arg_index];
|
||||
let placeholder_span =
|
||||
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
|
||||
let arg_span = match arg.kind {
|
||||
FormatArgumentKind::Captured(_) => placeholder_span,
|
||||
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
|
||||
};
|
||||
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
|
||||
let arg = ctx.arena.alloc(ctx.expr(
|
||||
arg_span,
|
||||
hir::ExprKind::Field(
|
||||
args_ident_expr,
|
||||
Ident::new(sym::integer(arg_index), macsp),
|
||||
),
|
||||
));
|
||||
make_argument(ctx, placeholder_span, arg, ty)
|
||||
},
|
||||
));
|
||||
let elements: Vec<_> = arguments
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
|
@ -12,7 +12,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::PredicateOrigin;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
@ -25,7 +25,7 @@ use thin_vec::ThinVec;
|
||||
pub(super) struct ItemLowerer<'a, 'hir> {
|
||||
pub(super) tcx: TyCtxt<'hir>,
|
||||
pub(super) resolver: &'a mut ResolverAstLowering,
|
||||
pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>,
|
||||
pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||
pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
|
||||
}
|
||||
|
||||
|
@ -60,13 +60,13 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_middle::{
|
||||
span_bug,
|
||||
ty::{ResolverAstLowering, TyCtxt},
|
||||
};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::parse::{add_feature_diagnostics, feature_err};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
@ -414,7 +414,7 @@ fn index_crate<'a>(
|
||||
/// This hash will then be part of the crate_hash which is stored in the metadata.
|
||||
fn compute_hir_hash(
|
||||
tcx: TyCtxt<'_>,
|
||||
owners: &IndexVec<LocalDefId, hir::MaybeOwner<&hir::OwnerInfo<'_>>>,
|
||||
owners: &IndexSlice<LocalDefId, hir::MaybeOwner<&hir::OwnerInfo<'_>>>,
|
||||
) -> Fingerprint {
|
||||
let mut hir_body_nodes: Vec<_> = owners
|
||||
.iter_enumerated()
|
||||
@ -482,7 +482,7 @@ enum ParamMode {
|
||||
}
|
||||
|
||||
enum ParenthesizedGenericArgs {
|
||||
Ok,
|
||||
ParenSugar,
|
||||
Err,
|
||||
}
|
||||
|
||||
@ -987,14 +987,56 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
GenericArgs::AngleBracketed(data) => {
|
||||
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
|
||||
}
|
||||
&GenericArgs::ReturnTypeNotation(span) => GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
bindings: &[],
|
||||
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
|
||||
span,
|
||||
},
|
||||
GenericArgs::Parenthesized(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
|
||||
if let Some(start_char) = constraint.ident.as_str().chars().next()
|
||||
&& start_char.is_ascii_lowercase()
|
||||
{
|
||||
let mut err = if !data.inputs.is_empty() {
|
||||
self.tcx.sess.create_err(errors::BadReturnTypeNotation::Inputs {
|
||||
span: data.inputs_span,
|
||||
})
|
||||
} else if let FnRetTy::Ty(ty) = &data.output {
|
||||
self.tcx.sess.create_err(errors::BadReturnTypeNotation::Output {
|
||||
span: data.inputs_span.shrink_to_hi().to(ty.span),
|
||||
})
|
||||
} else {
|
||||
self.tcx.sess.create_err(errors::BadReturnTypeNotation::NeedsDots {
|
||||
span: data.inputs_span,
|
||||
})
|
||||
};
|
||||
if !self.tcx.features().return_type_notation
|
||||
&& self.tcx.sess.is_nightly_build()
|
||||
{
|
||||
add_feature_diagnostics(
|
||||
&mut err,
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::return_type_notation,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
bindings: &[],
|
||||
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
|
||||
span: data.span,
|
||||
}
|
||||
} else {
|
||||
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
|
||||
// FIXME(return_type_notation): we could issue a feature error
|
||||
// if the parens are empty and there's no return type.
|
||||
self.lower_angle_bracketed_parameter_data(
|
||||
&data.as_angle_bracketed_args(),
|
||||
ParamMode::Explicit,
|
||||
itctx,
|
||||
)
|
||||
.0
|
||||
}
|
||||
}
|
||||
};
|
||||
gen_args_ctor.into_generic_args(self)
|
||||
@ -2075,7 +2117,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let future_args = self.arena.alloc(hir::GenericArgs {
|
||||
args: &[],
|
||||
bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
|
||||
parenthesized: false,
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span_ext: DUMMY_SP,
|
||||
});
|
||||
|
||||
@ -2595,13 +2637,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
struct GenericArgsCtor<'hir> {
|
||||
args: SmallVec<[hir::GenericArg<'hir>; 4]>,
|
||||
bindings: &'hir [hir::TypeBinding<'hir>],
|
||||
parenthesized: bool,
|
||||
parenthesized: hir::GenericArgsParentheses,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
impl<'hir> GenericArgsCtor<'hir> {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
|
||||
self.args.is_empty()
|
||||
&& self.bindings.is_empty()
|
||||
&& self.parenthesized == hir::GenericArgsParentheses::No
|
||||
}
|
||||
|
||||
fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> {
|
||||
|
@ -13,6 +13,7 @@ use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
@ -51,7 +52,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let parenthesized_generic_args = match base_res {
|
||||
// `a::b::Trait(Args)`
|
||||
Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
|
||||
ParenthesizedGenericArgs::Ok
|
||||
ParenthesizedGenericArgs::ParenSugar
|
||||
}
|
||||
// `a::b::Trait(Args)::TraitItem`
|
||||
Res::Def(DefKind::AssocFn, _)
|
||||
@ -59,10 +60,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
| Res::Def(DefKind::AssocTy, _)
|
||||
if i + 2 == proj_start =>
|
||||
{
|
||||
ParenthesizedGenericArgs::Ok
|
||||
ParenthesizedGenericArgs::ParenSugar
|
||||
}
|
||||
// Avoid duplicated errors.
|
||||
Res::Err => ParenthesizedGenericArgs::Ok,
|
||||
Res::Err => ParenthesizedGenericArgs::ParenSugar,
|
||||
// An error
|
||||
_ => ParenthesizedGenericArgs::Err,
|
||||
};
|
||||
@ -180,7 +181,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
|
||||
}
|
||||
GenericArgs::Parenthesized(data) => match parenthesized_generic_args {
|
||||
ParenthesizedGenericArgs::Ok => {
|
||||
ParenthesizedGenericArgs::ParenSugar => {
|
||||
self.lower_parenthesized_parameter_data(data, itctx)
|
||||
}
|
||||
ParenthesizedGenericArgs::Err => {
|
||||
@ -218,13 +219,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
)
|
||||
}
|
||||
},
|
||||
&GenericArgs::ReturnTypeNotation(span) => {
|
||||
self.tcx.sess.emit_err(GenericTypeWithParentheses { span, sub: None });
|
||||
(
|
||||
self.lower_angle_bracketed_parameter_data(
|
||||
&AngleBracketedArgs { span, args: ThinVec::default() },
|
||||
param_mode,
|
||||
itctx,
|
||||
)
|
||||
.0,
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(
|
||||
GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
bindings: &[],
|
||||
parenthesized: false,
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span: path_span.shrink_to_hi(),
|
||||
},
|
||||
param_mode == ParamMode::Optional,
|
||||
@ -233,7 +246,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
let has_lifetimes =
|
||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||
if !generic_args.parenthesized && !has_lifetimes {
|
||||
|
||||
// FIXME(return_type_notation): Is this correct? I think so.
|
||||
if generic_args.parenthesized != hir::GenericArgsParentheses::ParenSugar && !has_lifetimes {
|
||||
self.maybe_insert_elided_lifetimes_in_path(
|
||||
path_span,
|
||||
segment.id,
|
||||
@ -328,7 +343,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)),
|
||||
AngleBracketedArg::Arg(_) => None,
|
||||
}));
|
||||
let ctor = GenericArgsCtor { args, bindings, parenthesized: false, span: data.span };
|
||||
let ctor = GenericArgsCtor {
|
||||
args,
|
||||
bindings,
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span: data.span,
|
||||
};
|
||||
(ctor, !has_non_lt_args && param_mode == ParamMode::Optional)
|
||||
}
|
||||
|
||||
@ -376,7 +396,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
GenericArgsCtor {
|
||||
args,
|
||||
bindings: arena_vec![self; binding],
|
||||
parenthesized: true,
|
||||
parenthesized: hir::GenericArgsParentheses::ParenSugar,
|
||||
span: data.inputs_span,
|
||||
},
|
||||
false,
|
||||
@ -396,7 +416,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let gen_args = self.arena.alloc(hir::GenericArgs {
|
||||
args,
|
||||
bindings,
|
||||
parenthesized: false,
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span_ext: DUMMY_SP,
|
||||
});
|
||||
hir::TypeBinding {
|
||||
|
@ -1075,6 +1075,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
self.with_impl_trait(None, |this| this.visit_ty(ty));
|
||||
}
|
||||
}
|
||||
GenericArgs::ReturnTypeNotation(_span) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1387,16 +1388,19 @@ fn deny_equality_constraints(
|
||||
match &mut assoc_path.segments[len].args {
|
||||
Some(args) => match args.deref_mut() {
|
||||
GenericArgs::Parenthesized(_) => continue,
|
||||
GenericArgs::ReturnTypeNotation(_span) => continue,
|
||||
GenericArgs::AngleBracketed(args) => {
|
||||
args.args.push(arg);
|
||||
}
|
||||
},
|
||||
empty_args => {
|
||||
*empty_args = AngleBracketedArgs {
|
||||
span: ident.span,
|
||||
args: thin_vec![arg],
|
||||
}
|
||||
.into();
|
||||
*empty_args = Some(
|
||||
AngleBracketedArgs {
|
||||
span: ident.span,
|
||||
args: thin_vec![arg],
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
err.assoc = Some(errors::AssociatedSuggestion {
|
||||
|
@ -482,12 +482,28 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
|
||||
fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) {
|
||||
if let AssocConstraintKind::Bound { .. } = constraint.kind {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
associated_type_bounds,
|
||||
constraint.span,
|
||||
"associated type bounds are unstable"
|
||||
)
|
||||
if let Some(args) = constraint.gen_args.as_ref()
|
||||
&& matches!(
|
||||
args,
|
||||
ast::GenericArgs::ReturnTypeNotation(..) | ast::GenericArgs::Parenthesized(..)
|
||||
)
|
||||
{
|
||||
// RTN is gated elsewhere, and parenthesized args will turn into
|
||||
// another error.
|
||||
if matches!(args, ast::GenericArgs::Parenthesized(..)) {
|
||||
self.sess.delay_span_bug(
|
||||
constraint.span,
|
||||
"should have emitted a parenthesized generics error",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
associated_type_bounds,
|
||||
constraint.span,
|
||||
"associated type bounds are unstable"
|
||||
)
|
||||
}
|
||||
}
|
||||
visit::walk_assoc_constraint(self, constraint)
|
||||
}
|
||||
@ -577,6 +593,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||
gate_all!(yeet_expr, "`do yeet` expression is experimental");
|
||||
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
|
||||
gate_all!(const_closures, "const closures are experimental");
|
||||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
|
||||
// All uses of `gate_all!` below this point were added in #65742,
|
||||
// and subsequently disabled (with the non-early gating readded).
|
||||
|
@ -936,6 +936,10 @@ impl<'a> PrintState<'a> for State<'a> {
|
||||
self.word(")");
|
||||
self.print_fn_ret_ty(&data.output);
|
||||
}
|
||||
|
||||
ast::GenericArgs::ReturnTypeNotation(_span) => {
|
||||
self.word("(..)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,315 +226,39 @@ impl UnstableReason {
|
||||
}
|
||||
}
|
||||
|
||||
/// Collects stability info from all stability attributes in `attrs`.
|
||||
/// Returns `None` if no stability attributes are found.
|
||||
/// Collects stability info from `stable`/`unstable`/`rustc_allowed_through_unstable_modules`
|
||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||
pub fn find_stability(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
item_sp: Span,
|
||||
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>)
|
||||
{
|
||||
find_stability_generic(sess, attrs.iter(), item_sp)
|
||||
}
|
||||
|
||||
fn find_stability_generic<'a, I>(
|
||||
sess: &Session,
|
||||
attrs_iter: I,
|
||||
item_sp: Span,
|
||||
) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>)
|
||||
where
|
||||
I: Iterator<Item = &'a Attribute>,
|
||||
{
|
||||
use StabilityLevel::*;
|
||||
|
||||
) -> Option<(Stability, Span)> {
|
||||
let mut stab: Option<(Stability, Span)> = None;
|
||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
|
||||
let mut promotable = false;
|
||||
let mut allowed_through_unstable_modules = false;
|
||||
|
||||
'outer: for attr in attrs_iter {
|
||||
if ![
|
||||
sym::rustc_const_unstable,
|
||||
sym::rustc_const_stable,
|
||||
sym::unstable,
|
||||
sym::stable,
|
||||
sym::rustc_promotable,
|
||||
sym::rustc_allowed_through_unstable_modules,
|
||||
sym::rustc_default_body_unstable,
|
||||
]
|
||||
.iter()
|
||||
.any(|&s| attr.has_name(s))
|
||||
{
|
||||
continue; // not a stability level
|
||||
}
|
||||
|
||||
let meta = attr.meta();
|
||||
|
||||
if attr.has_name(sym::rustc_promotable) {
|
||||
promotable = true;
|
||||
} else if attr.has_name(sym::rustc_allowed_through_unstable_modules) {
|
||||
allowed_through_unstable_modules = true;
|
||||
}
|
||||
// attributes with data
|
||||
else if let Some(meta @ MetaItem { kind: MetaItemKind::List(metas), .. }) = &meta {
|
||||
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span,
|
||||
AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
|
||||
);
|
||||
return false;
|
||||
for attr in attrs {
|
||||
match attr.name_or_empty() {
|
||||
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
|
||||
sym::unstable => {
|
||||
if stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
if let Some(v) = meta.value_str() {
|
||||
*item = Some(v);
|
||||
true
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||
false
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
stab = Some((Stability { level, feature }, attr.span));
|
||||
}
|
||||
};
|
||||
|
||||
let meta_name = meta.name_or_empty();
|
||||
match meta_name {
|
||||
sym::rustc_const_unstable | sym::rustc_default_body_unstable | sym::unstable => {
|
||||
if meta_name == sym::unstable && stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
} else if meta_name == sym::rustc_const_unstable && const_stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
} else if meta_name == sym::rustc_default_body_unstable && body_stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
let mut feature = None;
|
||||
let mut reason = None;
|
||||
let mut issue = None;
|
||||
let mut issue_num = None;
|
||||
let mut is_soft = false;
|
||||
let mut implied_by = None;
|
||||
for meta in metas {
|
||||
let Some(mi) = meta.meta_item() else {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
|
||||
);
|
||||
continue 'outer;
|
||||
};
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => {
|
||||
if !get(mi, &mut feature) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::reason => {
|
||||
if !get(mi, &mut reason) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::issue => {
|
||||
if !get(mi, &mut issue) {
|
||||
continue 'outer;
|
||||
}
|
||||
|
||||
// These unwraps are safe because `get` ensures the meta item
|
||||
// is a name/value pair string literal.
|
||||
issue_num = match issue.unwrap().as_str() {
|
||||
"none" => None,
|
||||
issue => match issue.parse::<NonZeroU32>() {
|
||||
Ok(num) => Some(num),
|
||||
Err(err) => {
|
||||
sess.emit_err(
|
||||
session_diagnostics::InvalidIssueString {
|
||||
span: mi.span,
|
||||
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
||||
mi.name_value_literal_span().unwrap(),
|
||||
err.kind(),
|
||||
),
|
||||
},
|
||||
);
|
||||
continue 'outer;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
sym::soft => {
|
||||
if !mi.is_word() {
|
||||
sess.emit_err(session_diagnostics::SoftNoArgs {
|
||||
span: mi.span,
|
||||
});
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
sym::implied_by => {
|
||||
if !get(mi, &mut implied_by) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "reason", "issue", "soft"],
|
||||
),
|
||||
);
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match (feature, reason, issue) {
|
||||
(Some(feature), reason, Some(_)) => {
|
||||
if !rustc_lexer::is_ident(feature.as_str()) {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::NonIdentFeature,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
let level = Unstable {
|
||||
reason: UnstableReason::from_opt_reason(reason),
|
||||
issue: issue_num,
|
||||
is_soft,
|
||||
implied_by,
|
||||
};
|
||||
if sym::unstable == meta_name {
|
||||
stab = Some((Stability { level, feature }, attr.span));
|
||||
} else if sym::rustc_const_unstable == meta_name {
|
||||
const_stab = Some((
|
||||
ConstStability { level, feature, promotable: false },
|
||||
attr.span,
|
||||
));
|
||||
} else if sym::rustc_default_body_unstable == meta_name {
|
||||
body_stab =
|
||||
Some((DefaultBodyStability { level, feature }, attr.span));
|
||||
} else {
|
||||
unreachable!("Unknown stability attribute {meta_name}");
|
||||
}
|
||||
}
|
||||
(None, _, _) => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
sess.emit_err(session_diagnostics::MissingIssue { span: attr.span });
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
sym::rustc_const_stable | sym::stable => {
|
||||
if meta_name == sym::stable && stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
} else if meta_name == sym::rustc_const_stable && const_stab.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
attr.span,
|
||||
AttrError::MultipleStabilityLevels,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
let mut feature = None;
|
||||
let mut since = None;
|
||||
for meta in metas {
|
||||
match meta {
|
||||
NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() {
|
||||
sym::feature => {
|
||||
if !get(mi, &mut feature) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::since => {
|
||||
if !get(mi, &mut since) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "since"],
|
||||
),
|
||||
);
|
||||
continue 'outer;
|
||||
}
|
||||
},
|
||||
NestedMetaItem::Lit(lit) => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
lit.span,
|
||||
AttrError::UnsupportedLiteral(
|
||||
UnsupportedLiteralReason::Generic,
|
||||
false,
|
||||
),
|
||||
);
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 };
|
||||
if sym::stable == meta_name {
|
||||
stab = Some((Stability { level, feature }, attr.span));
|
||||
} else {
|
||||
const_stab = Some((
|
||||
ConstStability { level, feature, promotable: false },
|
||||
attr.span,
|
||||
));
|
||||
}
|
||||
}
|
||||
(None, _) => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the const-unstable info into the stability info
|
||||
if promotable {
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => stab.promotable = promotable,
|
||||
_ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
|
||||
sym::stable => {
|
||||
if stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||
stab = Some((Stability { level, feature }, attr.span));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,7 +277,286 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
(stab, const_stab, body_stab)
|
||||
stab
|
||||
}
|
||||
|
||||
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
|
||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||
pub fn find_const_stability(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
item_sp: Span,
|
||||
) -> Option<(ConstStability, Span)> {
|
||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||
let mut promotable = false;
|
||||
|
||||
for attr in attrs {
|
||||
match attr.name_or_empty() {
|
||||
sym::rustc_promotable => promotable = true,
|
||||
sym::rustc_const_unstable => {
|
||||
if const_stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
const_stab =
|
||||
Some((ConstStability { level, feature, promotable: false }, attr.span));
|
||||
}
|
||||
}
|
||||
sym::rustc_const_stable => {
|
||||
if const_stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||
const_stab =
|
||||
Some((ConstStability { level, feature, promotable: false }, attr.span));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the const-unstable info into the stability info
|
||||
if promotable {
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => stab.promotable = promotable,
|
||||
_ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
|
||||
}
|
||||
}
|
||||
|
||||
const_stab
|
||||
}
|
||||
|
||||
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
|
||||
/// Returns `None` if no stability attributes are found.
|
||||
pub fn find_body_stability(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
) -> Option<(DefaultBodyStability, Span)> {
|
||||
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
|
||||
|
||||
for attr in attrs {
|
||||
if attr.has_name(sym::rustc_default_body_unstable) {
|
||||
if body_stab.is_some() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels);
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
body_stab = Some((DefaultBodyStability { level, feature }, attr.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body_stab
|
||||
}
|
||||
|
||||
/// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and
|
||||
/// its stability information.
|
||||
fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
|
||||
let meta = attr.meta()?;
|
||||
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
|
||||
let insert_or_error = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span,
|
||||
AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if let Some(v) = meta.value_str() {
|
||||
*item = Some(v);
|
||||
true
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let mut feature = None;
|
||||
let mut since = None;
|
||||
for meta in metas {
|
||||
let Some(mi) = meta.meta_item() else {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => {
|
||||
if !insert_or_error(mi, &mut feature) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
sym::since => {
|
||||
if !insert_or_error(mi, &mut since) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "since"],
|
||||
),
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
|
||||
since = Some(rust_version_symbol());
|
||||
}
|
||||
|
||||
match (feature, since) {
|
||||
(Some(feature), Some(since)) => {
|
||||
let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false };
|
||||
Some((feature, level))
|
||||
}
|
||||
(None, _) => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
|
||||
/// attribute, and return the feature name and its stability information.
|
||||
fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
|
||||
let meta = attr.meta()?;
|
||||
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
|
||||
let insert_or_error = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span,
|
||||
AttrError::MultipleItem(pprust::path_to_string(&meta.path)),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if let Some(v) = meta.value_str() {
|
||||
*item = Some(v);
|
||||
true
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let mut feature = None;
|
||||
let mut reason = None;
|
||||
let mut issue = None;
|
||||
let mut issue_num = None;
|
||||
let mut is_soft = false;
|
||||
let mut implied_by = None;
|
||||
for meta in metas {
|
||||
let Some(mi) = meta.meta_item() else {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnsupportedLiteral(UnsupportedLiteralReason::Generic, false),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => {
|
||||
if !insert_or_error(mi, &mut feature) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
sym::reason => {
|
||||
if !insert_or_error(mi, &mut reason) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
sym::issue => {
|
||||
if !insert_or_error(mi, &mut issue) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// These unwraps are safe because `insert_or_error` ensures the meta item
|
||||
// is a name/value pair string literal.
|
||||
issue_num = match issue.unwrap().as_str() {
|
||||
"none" => None,
|
||||
issue => match issue.parse::<NonZeroU32>() {
|
||||
Ok(num) => Some(num),
|
||||
Err(err) => {
|
||||
sess.emit_err(
|
||||
session_diagnostics::InvalidIssueString {
|
||||
span: mi.span,
|
||||
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
||||
mi.name_value_literal_span().unwrap(),
|
||||
err.kind(),
|
||||
),
|
||||
},
|
||||
);
|
||||
return None;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
sym::soft => {
|
||||
if !mi.is_word() {
|
||||
sess.emit_err(session_diagnostics::SoftNoArgs { span: mi.span });
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
sym::implied_by => {
|
||||
if !insert_or_error(mi, &mut implied_by) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
&["feature", "reason", "issue", "soft", "implied_by"],
|
||||
),
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match (feature, reason, issue) {
|
||||
(Some(feature), reason, Some(_)) => {
|
||||
if !rustc_lexer::is_ident(feature.as_str()) {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::NonIdentFeature);
|
||||
return None;
|
||||
}
|
||||
let level = StabilityLevel::Unstable {
|
||||
reason: UnstableReason::from_opt_reason(reason),
|
||||
issue: issue_num,
|
||||
is_soft,
|
||||
implied_by,
|
||||
};
|
||||
Some((feature, level))
|
||||
}
|
||||
(None, _, _) => {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
|
||||
return None;
|
||||
}
|
||||
_ => {
|
||||
sess.emit_err(session_diagnostics::MissingIssue { span: attr.span });
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
|
||||
use rustc_span::Span;
|
||||
@ -60,7 +60,9 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
|
||||
Sccs::new(region_graph)
|
||||
}
|
||||
|
||||
pub(crate) fn outlives(&self) -> &IndexVec<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> {
|
||||
pub(crate) fn outlives(
|
||||
&self,
|
||||
) -> &IndexSlice<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> {
|
||||
&self.outlives
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! This file provides API for compiler consumers.
|
||||
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||
use rustc_middle::mir::Body;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
@ -35,6 +35,6 @@ pub fn get_body_with_borrowck_facts(
|
||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build();
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||
let promoted: &IndexSlice<_, _> = &promoted.borrow();
|
||||
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::mir::{
|
||||
Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
|
||||
@ -60,7 +60,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
local_names: &IndexVec<Local, Option<Symbol>>,
|
||||
local_names: &IndexSlice<Local, Option<Symbol>>,
|
||||
err: &mut Diagnostic,
|
||||
borrow_desc: &str,
|
||||
borrow_span: Option<Span>,
|
||||
|
@ -6,18 +6,19 @@ use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::GeneratorKind;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt};
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::{
|
||||
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
|
||||
Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place,
|
||||
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::print::Print;
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{
|
||||
type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause,
|
||||
@ -302,7 +303,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn describe_field(
|
||||
&self,
|
||||
place: PlaceRef<'tcx>,
|
||||
field: Field,
|
||||
field: FieldIdx,
|
||||
including_tuple_field: IncludingTupleField,
|
||||
) -> Option<String> {
|
||||
let place_ty = match place {
|
||||
@ -331,7 +332,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn describe_field_from_ty(
|
||||
&self,
|
||||
ty: Ty<'_>,
|
||||
field: Field,
|
||||
field: FieldIdx,
|
||||
variant_index: Option<VariantIdx>,
|
||||
including_tuple_field: IncludingTupleField,
|
||||
) -> Option<String> {
|
||||
@ -350,7 +351,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if !including_tuple_field.0 && variant.ctor_kind() == Some(CtorKind::Fn) {
|
||||
return None;
|
||||
}
|
||||
Some(variant.fields[field.index()].name.to_string())
|
||||
Some(variant.fields[field].name.to_string())
|
||||
}
|
||||
ty::Tuple(_) => Some(field.index().to_string()),
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
|
||||
@ -825,7 +826,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
|
||||
let places = &[Operand::Move(place)];
|
||||
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
|
||||
self.closure_span(closure_def_id, moved_place, places)
|
||||
self.closure_span(closure_def_id, moved_place, IndexSlice::from_raw(places))
|
||||
{
|
||||
return ClosureUse {
|
||||
generator_kind,
|
||||
@ -975,7 +976,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
def_id: LocalDefId,
|
||||
target_place: PlaceRef<'tcx>,
|
||||
places: &[Operand<'tcx>],
|
||||
places: &IndexSlice<FieldIdx, Operand<'tcx>>,
|
||||
) -> Option<(Span, Option<GeneratorKind>, Span, Span)> {
|
||||
debug!(
|
||||
"closure_span: def_id={:?} target_place={:?} places={:?}",
|
||||
|
@ -12,6 +12,7 @@ use rustc_middle::{
|
||||
use rustc_span::source_map::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
|
||||
use crate::diagnostics::BorrowedContentSource;
|
||||
use crate::MirBorrowckCtxt;
|
||||
@ -1275,7 +1276,7 @@ fn is_closure_or_generator(ty: Ty<'_>) -> bool {
|
||||
fn get_mut_span_in_struct_field<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
field: mir::Field,
|
||||
field: FieldIdx,
|
||||
) -> Option<Span> {
|
||||
// Expect our local to be a reference to a struct of some kind.
|
||||
if let ty::Ref(_, ty, _) = ty.kind()
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
use crate::Upvar;
|
||||
use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::{Idx, IndexSlice};
|
||||
use rustc_middle::mir::{Body, Local};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
@ -14,7 +14,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
local_names: &IndexVec<Local, Option<Symbol>>,
|
||||
local_names: &IndexSlice<Local, Option<Symbol>>,
|
||||
upvars: &[Upvar<'tcx>],
|
||||
fr: RegionVid,
|
||||
) -> Option<(Option<Symbol>, Span)> {
|
||||
@ -113,7 +113,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
pub(crate) fn get_argument_name_and_span_for_region(
|
||||
&self,
|
||||
body: &Body<'tcx>,
|
||||
local_names: &IndexVec<Local, Option<Symbol>>,
|
||||
local_names: &IndexSlice<Local, Option<Symbol>>,
|
||||
argument_index: usize,
|
||||
) -> (Option<Symbol>, Span) {
|
||||
let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
|
||||
|
@ -5,7 +5,7 @@
|
||||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(trusted_step)]
|
||||
@ -23,7 +23,7 @@ use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, Subdiagnost
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::bit_set::ChunkedBitSet;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::{
|
||||
DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
|
||||
};
|
||||
@ -33,12 +33,13 @@ use rustc_middle::mir::{
|
||||
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
|
||||
};
|
||||
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||
use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||
use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
|
||||
use rustc_session::lint::builtin::UNUSED_MUT;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
|
||||
use either::Either;
|
||||
use smallvec::SmallVec;
|
||||
@ -153,7 +154,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
|
||||
let infcx =
|
||||
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||
let promoted: &IndexSlice<_, _> = &promoted.borrow();
|
||||
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0;
|
||||
debug!("mir_borrowck done");
|
||||
|
||||
@ -169,7 +170,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
|
||||
fn do_mir_borrowck<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
input_body: &Body<'tcx>,
|
||||
input_promoted: &IndexVec<Promoted, Body<'tcx>>,
|
||||
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
|
||||
return_body_with_facts: bool,
|
||||
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
|
||||
let def = input_body.source.with_opt_param().as_local().unwrap();
|
||||
@ -222,7 +223,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
// be modified (in place) to contain non-lexical lifetimes. It
|
||||
// will have a lifetime tied to the inference context.
|
||||
let mut body_owned = input_body.clone();
|
||||
let mut promoted = input_promoted.clone();
|
||||
let mut promoted = input_promoted.to_owned();
|
||||
let free_regions =
|
||||
nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
|
||||
let body = &body_owned; // no further changes
|
||||
@ -597,7 +598,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
|
||||
used_mut: FxIndexSet<Local>,
|
||||
/// If the function we're checking is a closure, then we'll need to report back the list of
|
||||
/// mutable upvars that have been used. This field keeps track of them.
|
||||
used_mut_upvars: SmallVec<[Field; 8]>,
|
||||
used_mut_upvars: SmallVec<[FieldIdx; 8]>,
|
||||
/// Region inference context. This contains the results from region inference and lets us e.g.
|
||||
/// find out which CFG points are contained in each borrow region.
|
||||
regioncx: Rc<RegionInferenceContext<'tcx>>,
|
||||
@ -1342,7 +1343,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
self.infcx.tcx.mir_borrowck(def_id);
|
||||
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
|
||||
for field in used_mut_upvars {
|
||||
self.propagate_closure_used_mut_upvar(&operands[field.index()]);
|
||||
self.propagate_closure_used_mut_upvar(&operands[*field]);
|
||||
}
|
||||
}
|
||||
AggregateKind::Adt(..)
|
||||
@ -2277,7 +2278,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// then returns the index of the field being projected. Note that this closure will always
|
||||
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
||||
/// of a closure type.
|
||||
fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
|
||||
fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<FieldIdx> {
|
||||
path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body())
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_middle::infer::MemberConstraint;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
@ -215,7 +215,7 @@ where
|
||||
/// target_list: A -> B -> C -> D -> E -> F -> (None)
|
||||
/// ```
|
||||
fn append_list(
|
||||
constraints: &mut IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'_>>,
|
||||
constraints: &mut IndexSlice<NllMemberConstraintIndex, NllMemberConstraint<'_>>,
|
||||
target_list: NllMemberConstraintIndex,
|
||||
source_list: NllMemberConstraintIndex,
|
||||
) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
|
||||
use rustc_middle::mir::{
|
||||
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
|
||||
@ -59,7 +59,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'_, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
|
||||
promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
|
||||
) -> UniversalRegions<'tcx> {
|
||||
let def = body.source.with_opt_param().as_local().unwrap();
|
||||
|
||||
@ -158,7 +158,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'_, 'tcx>,
|
||||
universal_regions: UniversalRegions<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
promoted: &IndexVec<Promoted, Body<'tcx>>,
|
||||
promoted: &IndexSlice<Promoted, Body<'tcx>>,
|
||||
location_table: &LocationTable,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
|
||||
|
@ -7,8 +7,9 @@ use crate::BorrowIndex;
|
||||
use crate::Upvar;
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_middle::mir::BorrowKind;
|
||||
use rustc_middle::mir::{BasicBlock, Body, Field, Location, Place, PlaceRef, ProjectionElem};
|
||||
use rustc_middle::mir::{BasicBlock, Body, Location, Place, PlaceRef, ProjectionElem};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_target::abi::FieldIdx;
|
||||
|
||||
/// Returns `true` if the borrow represented by `kind` is
|
||||
/// allowed to be split into separate Reservation and
|
||||
@ -148,7 +149,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>(
|
||||
upvars: &[Upvar<'tcx>],
|
||||
place_ref: PlaceRef<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
) -> Option<Field> {
|
||||
) -> Option<FieldIdx> {
|
||||
let mut place_ref = place_ref;
|
||||
let mut by_ref = false;
|
||||
|
||||
|
@ -7,7 +7,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::outlives::test_type_match;
|
||||
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
|
||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
|
||||
@ -399,7 +399,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// the minimum, or narrowest, universe.
|
||||
fn compute_scc_universes(
|
||||
constraint_sccs: &Sccs<RegionVid, ConstraintSccIndex>,
|
||||
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
|
||||
definitions: &IndexSlice<RegionVid, RegionDefinition<'tcx>>,
|
||||
) -> IndexVec<ConstraintSccIndex, ty::UniverseIndex> {
|
||||
let num_sccs = constraint_sccs.num_sccs();
|
||||
let mut scc_universes = IndexVec::from_elem_n(ty::UniverseIndex::MAX, num_sccs);
|
||||
@ -486,7 +486,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// more details.
|
||||
fn compute_scc_representatives(
|
||||
constraints_scc: &Sccs<RegionVid, ConstraintSccIndex>,
|
||||
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
|
||||
definitions: &IndexSlice<RegionVid, RegionDefinition<'tcx>>,
|
||||
) -> IndexVec<ConstraintSccIndex, ty::RegionVid> {
|
||||
let num_sccs = constraints_scc.num_sccs();
|
||||
let next_region_vid = definitions.next_index();
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use crate::BorrowckInferCtxt;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc_middle::mir::Constant;
|
||||
@ -16,7 +16,7 @@ use rustc_span::{Span, Symbol};
|
||||
pub fn renumber_mir<'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'_, 'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
|
||||
promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
|
||||
) {
|
||||
debug!(?body.arg_count);
|
||||
|
||||
|
@ -14,7 +14,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc_infer::infer::region_constraints::RegionConstraintData;
|
||||
@ -36,7 +36,7 @@ use rustc_middle::ty::{
|
||||
};
|
||||
use rustc_span::def_id::CRATE_DEF_ID;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
|
||||
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
@ -125,7 +125,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'_, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
promoted: &IndexVec<Promoted, Body<'tcx>>,
|
||||
promoted: &IndexSlice<Promoted, Body<'tcx>>,
|
||||
universal_regions: &Rc<UniversalRegions<'tcx>>,
|
||||
location_table: &LocationTable,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
@ -292,7 +292,7 @@ enum FieldAccessError {
|
||||
/// is a problem.
|
||||
struct TypeVerifier<'a, 'b, 'tcx> {
|
||||
cx: &'a mut TypeChecker<'b, 'tcx>,
|
||||
promoted: &'b IndexVec<Promoted, Body<'tcx>>,
|
||||
promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
|
||||
last_span: Span,
|
||||
errors_reported: bool,
|
||||
}
|
||||
@ -493,7 +493,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
fn new(
|
||||
cx: &'a mut TypeChecker<'b, 'tcx>,
|
||||
promoted: &'b IndexVec<Promoted, Body<'tcx>>,
|
||||
promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
|
||||
) -> Self {
|
||||
TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false }
|
||||
}
|
||||
@ -786,7 +786,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
&mut self,
|
||||
parent: &dyn fmt::Debug,
|
||||
base_ty: PlaceTy<'tcx>,
|
||||
field: Field,
|
||||
field: FieldIdx,
|
||||
location: Location,
|
||||
) -> Result<Ty<'tcx>, FieldAccessError> {
|
||||
let tcx = self.tcx();
|
||||
@ -812,7 +812,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
},
|
||||
PlaceTy { ty, variant_index: None } => match *ty.kind() {
|
||||
ty::Adt(adt_def, substs) if !adt_def.is_enum() => {
|
||||
(adt_def.variant(VariantIdx::new(0)), substs)
|
||||
(adt_def.variant(FIRST_VARIANT), substs)
|
||||
}
|
||||
ty::Closure(_, substs) => {
|
||||
return match substs
|
||||
@ -854,7 +854,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(field) = variant.fields.get(field.index()) {
|
||||
if let Some(field) = variant.fields.get(field) {
|
||||
Ok(self.cx.normalize(field.ty(tcx, substs), location))
|
||||
} else {
|
||||
Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
|
||||
@ -1716,7 +1716,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
fn aggregate_field_ty(
|
||||
&mut self,
|
||||
ak: &AggregateKind<'tcx>,
|
||||
field_index: usize,
|
||||
field_index: FieldIdx,
|
||||
location: Location,
|
||||
) -> Result<Ty<'tcx>, FieldAccessError> {
|
||||
let tcx = self.tcx();
|
||||
@ -1733,7 +1733,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
AggregateKind::Closure(_, substs) => {
|
||||
match substs.as_closure().upvar_tys().nth(field_index) {
|
||||
match substs.as_closure().upvar_tys().nth(field_index.as_usize()) {
|
||||
Some(ty) => Ok(ty),
|
||||
None => Err(FieldAccessError::OutOfRange {
|
||||
field_count: substs.as_closure().upvar_tys().count(),
|
||||
@ -1744,7 +1744,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// It doesn't make sense to look at a field beyond the prefix;
|
||||
// these require a variant index, and are not initialized in
|
||||
// aggregate rvalues.
|
||||
match substs.as_generator().prefix_tys().nth(field_index) {
|
||||
match substs.as_generator().prefix_tys().nth(field_index.as_usize()) {
|
||||
Some(ty) => Ok(ty),
|
||||
None => Err(FieldAccessError::OutOfRange {
|
||||
field_count: substs.as_generator().prefix_tys().count(),
|
||||
@ -2349,7 +2349,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
body: &Body<'tcx>,
|
||||
rvalue: &Rvalue<'tcx>,
|
||||
aggregate_kind: &AggregateKind<'tcx>,
|
||||
operands: &[Operand<'tcx>],
|
||||
operands: &IndexSlice<FieldIdx, Operand<'tcx>>,
|
||||
location: Location,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
@ -2361,7 +2361,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i, operand) in operands.iter().enumerate() {
|
||||
for (i, operand) in operands.iter_enumerated() {
|
||||
let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
|
||||
Ok(field_ty) => field_ty,
|
||||
Err(FieldAccessError::OutOfRange { field_count }) => {
|
||||
@ -2369,8 +2369,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
self,
|
||||
rvalue,
|
||||
"accessed field #{} but variant only has {}",
|
||||
i,
|
||||
field_count
|
||||
i.as_u32(),
|
||||
field_count,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
@ -235,9 +235,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
|
@ -25,7 +25,7 @@ target-lexicon = "0.12.0"
|
||||
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
|
||||
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
||||
indexmap = "1.9.1"
|
||||
indexmap = "1.9.3"
|
||||
libloading = { version = "0.7.3", optional = true }
|
||||
once_cell = "1.10.0"
|
||||
smallvec = "1.8.1"
|
||||
|
@ -327,7 +327,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
|
||||
ArgKind::Spread(params) => {
|
||||
for (i, param) in params.into_iter().enumerate() {
|
||||
if let Some(param) = param {
|
||||
place.place_field(fx, mir::Field::new(i)).write_cvalue(fx, param);
|
||||
place.place_field(fx, FieldIdx::new(i)).write_cvalue(fx, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -460,7 +460,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||
args.push(self_arg);
|
||||
for i in 0..tupled_arguments.len() {
|
||||
args.push(CallArgument {
|
||||
value: pack_arg.value.value_field(fx, mir::Field::new(i)),
|
||||
value: pack_arg.value.value_field(fx, FieldIdx::new(i)),
|
||||
is_owned: pack_arg.is_owned,
|
||||
});
|
||||
}
|
||||
|
@ -379,6 +379,18 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
|
||||
source_info.span,
|
||||
);
|
||||
}
|
||||
AssertKind::MisalignedPointerDereference { ref required, ref found } => {
|
||||
let required = codegen_operand(fx, required).load_scalar(fx);
|
||||
let found = codegen_operand(fx, found).load_scalar(fx);
|
||||
let location = fx.get_caller_location(source_info).load_scalar(fx);
|
||||
|
||||
codegen_panic_inner(
|
||||
fx,
|
||||
rustc_hir::LangItem::PanicBoundsCheck,
|
||||
&[required, found, location],
|
||||
source_info.span,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
let msg_str = msg.description();
|
||||
codegen_panic(fx, msg_str, source_info);
|
||||
@ -785,19 +797,20 @@ fn codegen_stmt<'tcx>(
|
||||
let variant_dest = lval.downcast_variant(fx, variant_index);
|
||||
(variant_index, variant_dest, active_field_index)
|
||||
}
|
||||
_ => (VariantIdx::from_u32(0), lval, None),
|
||||
_ => (FIRST_VARIANT, lval, None),
|
||||
};
|
||||
if active_field_index.is_some() {
|
||||
assert_eq!(operands.len(), 1);
|
||||
}
|
||||
for (i, operand) in operands.iter().enumerate() {
|
||||
for (i, operand) in operands.iter_enumerated() {
|
||||
let operand = codegen_operand(fx, operand);
|
||||
let field_index = active_field_index.unwrap_or(i);
|
||||
let to = if let mir::AggregateKind::Array(_) = **kind {
|
||||
let index = fx.bcx.ins().iconst(fx.pointer_type, field_index as i64);
|
||||
let array_index = i64::from(field_index.as_u32());
|
||||
let index = fx.bcx.ins().iconst(fx.pointer_type, array_index);
|
||||
variant_dest.place_index(fx, index)
|
||||
} else {
|
||||
variant_dest.place_field(fx, mir::Field::new(field_index))
|
||||
variant_dest.place_field(fx, field_index)
|
||||
};
|
||||
to.write_cvalue(fx, operand);
|
||||
}
|
||||
|
@ -54,12 +54,22 @@ pub(crate) fn codegen_tls_ref<'tcx>(
|
||||
def_id: DefId,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> CValue<'tcx> {
|
||||
let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("tls {:?}", def_id));
|
||||
}
|
||||
let tls_ptr = fx.bcx.ins().tls_value(fx.pointer_type, local_data_id);
|
||||
let tls_ptr = if !def_id.is_local() && fx.tcx.needs_thread_local_shim(def_id) {
|
||||
let instance = ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
substs: ty::InternalSubsts::empty(),
|
||||
};
|
||||
let func_ref = fx.get_function_ref(instance);
|
||||
let call = fx.bcx.ins().call(func_ref, &[]);
|
||||
fx.bcx.func.dfg.first_result(call)
|
||||
} else {
|
||||
let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("tls {:?}", def_id));
|
||||
}
|
||||
fx.bcx.ins().tls_value(fx.pointer_type, local_data_id)
|
||||
};
|
||||
CValue::by_val(tls_ptr, layout)
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
variants: _,
|
||||
} => {
|
||||
let ptr = place.place_field(fx, mir::Field::new(tag_field));
|
||||
let ptr = place.place_field(fx, FieldIdx::new(tag_field));
|
||||
let to = layout.ty.discriminant_for_variant(fx.tcx, variant_index).unwrap().val;
|
||||
let to = if ptr.layout().abi.is_signed() {
|
||||
ty::ScalarInt::try_from_int(
|
||||
@ -47,7 +47,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
|
||||
variants: _,
|
||||
} => {
|
||||
if variant_index != untagged_variant {
|
||||
let niche = place.place_field(fx, mir::Field::new(tag_field));
|
||||
let niche = place.place_field(fx, FieldIdx::new(tag_field));
|
||||
let niche_type = fx.clif_type(niche.layout().ty).unwrap();
|
||||
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
|
||||
let niche_value = (niche_value as u128).wrapping_add(niche_start);
|
||||
@ -107,7 +107,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
|
||||
let cast_to = fx.clif_type(dest_layout.ty).unwrap();
|
||||
|
||||
// Read the tag/niche-encoded discriminant from memory.
|
||||
let tag = value.value_field(fx, mir::Field::new(tag_field));
|
||||
let tag = value.value_field(fx, FieldIdx::new(tag_field));
|
||||
let tag = tag.load_scalar(fx);
|
||||
|
||||
// Decode the discriminant (specifically if it's niche-encoded).
|
||||
|
@ -179,8 +179,8 @@ fn llvm_add_sub<'tcx>(
|
||||
|
||||
// c + carry -> c + first intermediate carry or borrow respectively
|
||||
let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
|
||||
let c = int0.value_field(fx, mir::Field::new(0));
|
||||
let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
|
||||
let c = int0.value_field(fx, FieldIdx::new(0));
|
||||
let cb0 = int0.value_field(fx, FieldIdx::new(1)).load_scalar(fx);
|
||||
|
||||
// c + carry -> c + second intermediate carry or borrow respectively
|
||||
let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
|
||||
|
@ -253,7 +253,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||
}
|
||||
|
||||
ret.write_cvalue(fx, base);
|
||||
let ret_lane = ret.place_field(fx, mir::Field::new(idx.try_into().unwrap()));
|
||||
let ret_lane = ret.place_field(fx, FieldIdx::new(idx.try_into().unwrap()));
|
||||
ret_lane.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ mod prelude {
|
||||
self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
|
||||
TypeFoldable, TypeVisitableExt, UintTy,
|
||||
};
|
||||
pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx};
|
||||
pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT};
|
||||
|
||||
pub(crate) use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
|
@ -146,9 +146,9 @@ pub(crate) fn coerce_unsized_into<'tcx>(
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
|
||||
assert_eq!(def_a, def_b);
|
||||
|
||||
for i in 0..def_a.variant(VariantIdx::new(0)).fields.len() {
|
||||
let src_f = src.value_field(fx, mir::Field::new(i));
|
||||
let dst_f = dst.place_field(fx, mir::Field::new(i));
|
||||
for i in 0..def_a.variant(FIRST_VARIANT).fields.len() {
|
||||
let src_f = src.value_field(fx, FieldIdx::new(i));
|
||||
let dst_f = dst.place_field(fx, FieldIdx::new(i));
|
||||
|
||||
if dst_f.layout().is_zst() {
|
||||
continue;
|
||||
|
@ -10,7 +10,7 @@ fn codegen_field<'tcx>(
|
||||
base: Pointer,
|
||||
extra: Option<Value>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
field: mir::Field,
|
||||
field: FieldIdx,
|
||||
) -> (Pointer, TyAndLayout<'tcx>) {
|
||||
let field_offset = layout.fields.offset(field.index());
|
||||
let field_layout = layout.field(&*fx, field.index());
|
||||
@ -210,7 +210,7 @@ impl<'tcx> CValue<'tcx> {
|
||||
pub(crate) fn value_field(
|
||||
self,
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
field: mir::Field,
|
||||
field: FieldIdx,
|
||||
) -> CValue<'tcx> {
|
||||
let layout = self.1;
|
||||
match self.0 {
|
||||
@ -687,7 +687,7 @@ impl<'tcx> CPlace<'tcx> {
|
||||
pub(crate) fn place_field(
|
||||
self,
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
field: mir::Field,
|
||||
field: FieldIdx,
|
||||
) -> CPlace<'tcx> {
|
||||
let layout = self.layout();
|
||||
|
||||
@ -701,7 +701,8 @@ impl<'tcx> CPlace<'tcx> {
|
||||
};
|
||||
}
|
||||
ty::Adt(adt_def, substs) if layout.ty.is_simd() => {
|
||||
let f0_ty = adt_def.non_enum_variant().fields[0].ty(fx.tcx, substs);
|
||||
let f0 = &adt_def.non_enum_variant().fields[FieldIdx::from_u32(0)];
|
||||
let f0_ty = f0.ty(fx.tcx, substs);
|
||||
|
||||
match f0_ty.kind() {
|
||||
ty::Array(_, _) => {
|
||||
|
@ -50,7 +50,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
||||
if let Abi::Scalar(_) = arg.layout().abi {
|
||||
'descend_newtypes: while !arg.layout().ty.is_unsafe_ptr() && !arg.layout().ty.is_ref() {
|
||||
for i in 0..arg.layout().fields.count() {
|
||||
let field = arg.value_field(fx, mir::Field::new(i));
|
||||
let field = arg.value_field(fx, FieldIdx::new(i));
|
||||
if !field.layout().is_zst() {
|
||||
// we found the one non-zero-sized field that is allowed
|
||||
// now find *its* non-zero-sized field, or stop if it's a
|
||||
@ -68,9 +68,9 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
||||
if ty.is_dyn_star() {
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
|
||||
let ptr = dyn_star.place_field(fx, mir::Field::new(0)).to_ptr();
|
||||
let ptr = dyn_star.place_field(fx, FieldIdx::new(0)).to_ptr();
|
||||
let vtable =
|
||||
dyn_star.place_field(fx, mir::Field::new(1)).to_cvalue(fx).load_scalar(fx);
|
||||
dyn_star.place_field(fx, FieldIdx::new(1)).to_cvalue(fx).load_scalar(fx);
|
||||
break 'block (ptr, vtable);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "1.0.0"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#eefb8c662d61477f34b7c32d26bcda5f1ef08432"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
@ -43,9 +43,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#eefb8c662d61477f34b7c32d26bcda5f1ef08432"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3"
|
||||
dependencies = [
|
||||
"libc 0.1.12",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -64,7 +64,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc 0.2.112",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
@ -74,7 +74,7 @@ version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc 0.2.112",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -85,7 +85,7 @@ checksum = "96bd995a092cac79868250589869b5a5d656b02a02bd74c8ebdc566dc7203090"
|
||||
dependencies = [
|
||||
"fm",
|
||||
"getopts",
|
||||
"libc 0.2.112",
|
||||
"libc",
|
||||
"num_cpus",
|
||||
"termcolor",
|
||||
"threadpool",
|
||||
@ -93,12 +93,6 @@ dependencies = [
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.112"
|
||||
@ -118,7 +112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc 0.2.112",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -133,7 +127,7 @@ version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||
dependencies = [
|
||||
"libc 0.2.112",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
@ -234,7 +228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc 0.2.112",
|
||||
"libc",
|
||||
"rand",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
@ -271,7 +265,7 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
dependencies = [
|
||||
"libc 0.2.112",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -73,6 +73,11 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn const_poison(&self, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
// No distinction between undef and poison.
|
||||
self.const_undef(typ)
|
||||
}
|
||||
|
||||
fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
|
||||
self.gcc_int(typ, int)
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ codegen_llvm_error_calling_dlltool =
|
||||
Error calling dlltool: {$error}
|
||||
|
||||
codegen_llvm_dlltool_fail_import_library =
|
||||
Dlltool could not create import library: {$stdout}\n{$stderr}
|
||||
Dlltool could not create import library: {$stdout}
|
||||
{$stderr}
|
||||
|
||||
codegen_llvm_target_feature_disable_or_enable =
|
||||
the target features {$features} must all be either enabled or disabled together
|
||||
|
@ -110,7 +110,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
|
||||
// FIXME use ArArchiveBuilder on most targets again once reading thin archives is
|
||||
// implemented
|
||||
if true || sess.target.arch == "wasm32" || sess.target.arch == "wasm64" {
|
||||
if true {
|
||||
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
|
||||
} else {
|
||||
Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols))
|
||||
|
@ -214,6 +214,8 @@ pub fn target_machine_factory(
|
||||
|
||||
let path_mapping = sess.source_map().path_mapping().clone();
|
||||
|
||||
let force_emulated_tls = sess.target.force_emulated_tls;
|
||||
|
||||
Arc::new(move |config: TargetMachineFactoryConfig| {
|
||||
let split_dwarf_file =
|
||||
path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0;
|
||||
@ -239,6 +241,7 @@ pub fn target_machine_factory(
|
||||
relax_elf_relocations,
|
||||
use_init_array,
|
||||
split_dwarf_file.as_ptr(),
|
||||
force_emulated_tls,
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -990,7 +990,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
|
||||
fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
|
||||
let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
|
||||
let mut exn = self.const_undef(ty);
|
||||
let mut exn = self.const_poison(ty);
|
||||
exn = self.insert_value(exn, exn0, 0);
|
||||
exn = self.insert_value(exn, exn1, 1);
|
||||
unsafe {
|
||||
@ -1190,8 +1190,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
// Set KCFI operand bundle
|
||||
let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
|
||||
let kcfi_bundle =
|
||||
if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
|
||||
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
|
||||
if let Some(fn_abi) = fn_abi && self.tcx.sess.is_sanitizer_kcfi_enabled() && is_indirect_call {
|
||||
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi);
|
||||
Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
|
||||
} else {
|
||||
None
|
||||
|
@ -130,6 +130,10 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
unsafe { llvm::LLVMGetUndef(t) }
|
||||
}
|
||||
|
||||
fn const_poison(&self, t: &'ll Type) -> &'ll Value {
|
||||
unsafe { llvm::LLVMGetPoison(t) }
|
||||
}
|
||||
|
||||
fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
|
||||
unsafe { llvm::LLVMConstInt(t, i as u64, True) }
|
||||
}
|
||||
@ -374,8 +378,7 @@ pub(crate) fn get_dllimport<'tcx>(
|
||||
name: &str,
|
||||
) -> Option<&'tcx DllImport> {
|
||||
tcx.native_library(id)
|
||||
.map(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
|
||||
.flatten()
|
||||
.and_then(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
|
||||
}
|
||||
|
||||
pub(crate) fn is_mingw_gnu_toolchain(target: &Target) -> bool {
|
||||
|
@ -3,10 +3,10 @@ use rustc_codegen_ssa::debuginfo::{
|
||||
wants_c_like_enum_debuginfo,
|
||||
};
|
||||
use rustc_hir::def::CtorKind;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_middle::{
|
||||
bug,
|
||||
mir::{Field, GeneratorLayout, GeneratorSavedLocal},
|
||||
mir::{GeneratorLayout, GeneratorSavedLocal},
|
||||
ty::{
|
||||
self,
|
||||
layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
|
||||
@ -14,7 +14,9 @@ use rustc_middle::{
|
||||
},
|
||||
};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::abi::{HasDataLayout, Integer, Primitive, TagEncoding, VariantIdx, Variants};
|
||||
use rustc_target::abi::{
|
||||
FieldIdx, HasDataLayout, Integer, Primitive, TagEncoding, VariantIdx, Variants,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::{
|
||||
@ -272,7 +274,8 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
|
||||
.map(|field_index| {
|
||||
let field_name = if variant_def.ctor_kind() != Some(CtorKind::Fn) {
|
||||
// Fields have names
|
||||
Cow::from(variant_def.fields[field_index].name.as_str())
|
||||
let field = &variant_def.fields[FieldIdx::from_usize(field_index)];
|
||||
Cow::from(field.name.as_str())
|
||||
} else {
|
||||
// Tuple-like
|
||||
super::tuple_field_name(field_index)
|
||||
@ -320,7 +323,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
|
||||
generator_type_and_layout: TyAndLayout<'tcx>,
|
||||
generator_type_di_node: &'ll DIType,
|
||||
generator_layout: &GeneratorLayout<'tcx>,
|
||||
state_specific_upvar_names: &IndexVec<GeneratorSavedLocal, Option<Symbol>>,
|
||||
state_specific_upvar_names: &IndexSlice<GeneratorSavedLocal, Option<Symbol>>,
|
||||
common_upvar_names: &[String],
|
||||
) -> &'ll DIType {
|
||||
let variant_name = GeneratorSubsts::variant_name(variant_index);
|
||||
@ -353,7 +356,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
|
||||
let state_specific_fields: SmallVec<_> = (0..variant_layout.fields.count())
|
||||
.map(|field_index| {
|
||||
let generator_saved_local = generator_layout.variant_fields[variant_index]
|
||||
[Field::from_usize(field_index)];
|
||||
[FieldIdx::from_usize(field_index)];
|
||||
let field_name_maybe = state_specific_upvar_names[generator_saved_local];
|
||||
let field_name = field_name_maybe
|
||||
.as_ref()
|
||||
|
@ -10,7 +10,6 @@
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(once_cell)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
|
@ -1069,6 +1069,7 @@ extern "C" {
|
||||
// Operations on constants of any type
|
||||
pub fn LLVMConstNull(Ty: &Type) -> &Value;
|
||||
pub fn LLVMGetUndef(Ty: &Type) -> &Value;
|
||||
pub fn LLVMGetPoison(Ty: &Type) -> &Value;
|
||||
|
||||
// Operations on metadata
|
||||
pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value;
|
||||
@ -2256,6 +2257,7 @@ extern "C" {
|
||||
RelaxELFRelocations: bool,
|
||||
UseInitArray: bool,
|
||||
SplitDwarfFile: *const c_char,
|
||||
ForceEmulatedTls: bool,
|
||||
) -> Option<&'static mut TargetMachine>;
|
||||
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
|
||||
pub fn LLVMRustAddLibraryInfo<'a>(
|
||||
|
@ -1621,7 +1621,7 @@ impl<'a> Linker for AixLinker<'a> {
|
||||
let path = tmpdir.join("list.exp");
|
||||
let res: io::Result<()> = try {
|
||||
let mut f = BufWriter::new(File::create(&path)?);
|
||||
// TODO: use llvm-nm to generate export list.
|
||||
// FIXME: use llvm-nm to generate export list.
|
||||
for symbol in symbols {
|
||||
debug!(" _{}", symbol);
|
||||
writeln!(f, " {}", symbol)?;
|
||||
|
@ -177,14 +177,29 @@ fn exported_symbols_provider_local(
|
||||
|
||||
// FIXME: Sorting this is unnecessary since we are sorting later anyway.
|
||||
// Can we skip the later sorting?
|
||||
let mut symbols: Vec<_> = tcx.with_stable_hashing_context(|hcx| {
|
||||
tcx.reachable_non_generics(LOCAL_CRATE)
|
||||
.to_sorted(&hcx, true)
|
||||
.into_iter()
|
||||
.map(|(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info))
|
||||
.collect()
|
||||
let sorted = tcx.with_stable_hashing_context(|hcx| {
|
||||
tcx.reachable_non_generics(LOCAL_CRATE).to_sorted(&hcx, true)
|
||||
});
|
||||
|
||||
let mut symbols: Vec<_> =
|
||||
sorted.iter().map(|(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info)).collect();
|
||||
|
||||
// Export TLS shims
|
||||
if !tcx.sess.target.dll_tls_export {
|
||||
symbols.extend(sorted.iter().filter_map(|(&def_id, &info)| {
|
||||
tcx.needs_thread_local_shim(def_id).then(|| {
|
||||
(
|
||||
ExportedSymbol::ThreadLocalShim(def_id),
|
||||
SymbolExportInfo {
|
||||
level: info.level,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: info.used,
|
||||
},
|
||||
)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
if tcx.entry_fn(()).is_some() {
|
||||
let exported_symbol =
|
||||
ExportedSymbol::NoDefId(SymbolName::new(tcx, tcx.sess.target.entry_name.as_ref()));
|
||||
@ -380,7 +395,9 @@ fn upstream_monomorphizations_provider(
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ExportedSymbol::NonGeneric(..) | ExportedSymbol::NoDefId(..) => {
|
||||
ExportedSymbol::NonGeneric(..)
|
||||
| ExportedSymbol::ThreadLocalShim(..)
|
||||
| ExportedSymbol::NoDefId(..) => {
|
||||
// These are no monomorphizations
|
||||
continue;
|
||||
}
|
||||
@ -500,6 +517,16 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
|
||||
instantiating_crate,
|
||||
)
|
||||
}
|
||||
ExportedSymbol::ThreadLocalShim(def_id) => {
|
||||
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
|
||||
tcx,
|
||||
ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
substs: ty::InternalSubsts::empty(),
|
||||
},
|
||||
instantiating_crate,
|
||||
)
|
||||
}
|
||||
ExportedSymbol::DropGlue(ty) => rustc_symbol_mangling::symbol_name_for_instance_in_crate(
|
||||
tcx,
|
||||
Instance::resolve_drop_in_place(tcx, ty),
|
||||
@ -548,6 +575,8 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
|
||||
ExportedSymbol::DropGlue(..) => None,
|
||||
// NoDefId always follow the target's default symbol decoration scheme.
|
||||
ExportedSymbol::NoDefId(..) => None,
|
||||
// ThreadLocalShim always follow the target's default symbol decoration scheme.
|
||||
ExportedSymbol::ThreadLocalShim(..) => None,
|
||||
};
|
||||
|
||||
let (conv, args) = instance
|
||||
|
@ -1452,8 +1452,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
Err(e) => {
|
||||
let msg = &format!("failed to acquire jobserver token: {}", e);
|
||||
shared_emitter.fatal(msg);
|
||||
// Exit the coordinator thread
|
||||
panic!("{}", msg)
|
||||
codegen_done = true;
|
||||
codegen_aborted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ use rustc_data_structures::sync::ParallelIterator;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::middle::exported_symbols;
|
||||
@ -40,7 +39,7 @@ use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
|
||||
use rustc_target::abi::{Align, VariantIdx};
|
||||
use rustc_target::abi::{Align, FIRST_VARIANT};
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::time::{Duration, Instant};
|
||||
@ -307,9 +306,9 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
|
||||
assert_eq!(def_a, def_b);
|
||||
|
||||
for i in 0..def_a.variant(VariantIdx::new(0)).fields.len() {
|
||||
let src_f = src.project_field(bx, i);
|
||||
let dst_f = dst.project_field(bx, i);
|
||||
for i in def_a.variant(FIRST_VARIANT).fields.indices() {
|
||||
let src_f = src.project_field(bx, i.as_usize());
|
||||
let dst_f = dst.project_field(bx, i.as_usize());
|
||||
|
||||
if dst_f.layout.is_zst() {
|
||||
continue;
|
||||
|
@ -10,6 +10,7 @@ use rustc_middle::mir::mono::Linkage;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self as ty, TyCtxt};
|
||||
use rustc_session::{lint, parse::feature_err};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_target::spec::{abi, SanitizerSet};
|
||||
|
||||
@ -83,336 +84,345 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||
}
|
||||
};
|
||||
|
||||
if attr.has_name(sym::cold) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
|
||||
} else if attr.has_name(sym::rustc_allocator) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
|
||||
} else if attr.has_name(sym::ffi_returns_twice) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
|
||||
} else if attr.has_name(sym::ffi_pure) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
|
||||
} else if attr.has_name(sym::ffi_const) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
|
||||
} else if attr.has_name(sym::rustc_nounwind) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
||||
} else if attr.has_name(sym::rustc_reallocator) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
|
||||
} else if attr.has_name(sym::rustc_deallocator) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
|
||||
} else if attr.has_name(sym::rustc_allocator_zeroed) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
|
||||
} else if attr.has_name(sym::naked) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
|
||||
} else if attr.has_name(sym::no_mangle) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
||||
} else if attr.has_name(sym::no_coverage) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
|
||||
} else if attr.has_name(sym::rustc_std_internal_symbol) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||
} else if attr.has_name(sym::used) {
|
||||
let inner = attr.meta_item_list();
|
||||
match inner.as_deref() {
|
||||
Some([item]) if item.has_name(sym::linker) => {
|
||||
if !tcx.features().used_with_arg {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::used_with_arg,
|
||||
let Some(Ident { name, .. }) = attr.ident() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
match name {
|
||||
sym::cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD,
|
||||
sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR,
|
||||
sym::ffi_returns_twice => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE
|
||||
}
|
||||
sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE,
|
||||
sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST,
|
||||
sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND,
|
||||
sym::rustc_reallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR,
|
||||
sym::rustc_deallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR,
|
||||
sym::rustc_allocator_zeroed => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
|
||||
}
|
||||
sym::naked => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
|
||||
sym::no_mangle => {
|
||||
if tcx.opt_item_name(did.to_def_id()).is_some() {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE
|
||||
} else {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
attr.span,
|
||||
"`#[used(linker)]` is currently unstable",
|
||||
format!(
|
||||
"`#[no_mangle]` cannot be used on {} {} as it has no name",
|
||||
tcx.def_descr_article(did.to_def_id()),
|
||||
tcx.def_descr(did.to_def_id()),
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
sym::no_coverage => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE,
|
||||
sym::rustc_std_internal_symbol => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
|
||||
}
|
||||
sym::used => {
|
||||
let inner = attr.meta_item_list();
|
||||
match inner.as_deref() {
|
||||
Some([item]) if item.has_name(sym::linker) => {
|
||||
if !tcx.features().used_with_arg {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::used_with_arg,
|
||||
attr.span,
|
||||
"`#[used(linker)]` is currently unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
|
||||
}
|
||||
Some([item]) if item.has_name(sym::compiler) => {
|
||||
if !tcx.features().used_with_arg {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::used_with_arg,
|
||||
attr.span,
|
||||
"`#[used(compiler)]` is currently unstable",
|
||||
)
|
||||
.emit();
|
||||
Some([item]) if item.has_name(sym::compiler) => {
|
||||
if !tcx.features().used_with_arg {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::used_with_arg,
|
||||
attr.span,
|
||||
"`#[used(compiler)]` is currently unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.sess.emit_err(ExpectedUsedSymbol { span: attr.span });
|
||||
}
|
||||
None => {
|
||||
// Unfortunately, unconditionally using `llvm.used` causes
|
||||
// issues in handling `.init_array` with the gold linker,
|
||||
// but using `llvm.compiler.used` caused a nontrival amount
|
||||
// of unintentional ecosystem breakage -- particularly on
|
||||
// Mach-O targets.
|
||||
//
|
||||
// As a result, we emit `llvm.compiler.used` only on ELF
|
||||
// targets. This is somewhat ad-hoc, but actually follows
|
||||
// our pre-LLVM 13 behavior (prior to the ecosystem
|
||||
// breakage), and seems to match `clang`'s behavior as well
|
||||
// (both before and after LLVM 13), possibly because they
|
||||
// have similar compatibility concerns to us. See
|
||||
// https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
|
||||
// and following comments for some discussion of this, as
|
||||
// well as the comments in `rustc_codegen_llvm` where these
|
||||
// flags are handled.
|
||||
//
|
||||
// Anyway, to be clear: this is still up in the air
|
||||
// somewhat, and is subject to change in the future (which
|
||||
// is a good thing, because this would ideally be a bit
|
||||
// more firmed up).
|
||||
let is_like_elf = !(tcx.sess.target.is_like_osx
|
||||
|| tcx.sess.target.is_like_windows
|
||||
|| tcx.sess.target.is_like_wasm);
|
||||
codegen_fn_attrs.flags |= if is_like_elf {
|
||||
CodegenFnAttrFlags::USED
|
||||
} else {
|
||||
CodegenFnAttrFlags::USED_LINKER
|
||||
};
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.sess.emit_err(ExpectedUsedSymbol { span: attr.span });
|
||||
}
|
||||
None => {
|
||||
// Unfortunately, unconditionally using `llvm.used` causes
|
||||
// issues in handling `.init_array` with the gold linker,
|
||||
// but using `llvm.compiler.used` caused a nontrival amount
|
||||
// of unintentional ecosystem breakage -- particularly on
|
||||
// Mach-O targets.
|
||||
//
|
||||
// As a result, we emit `llvm.compiler.used` only on ELF
|
||||
// targets. This is somewhat ad-hoc, but actually follows
|
||||
// our pre-LLVM 13 behavior (prior to the ecosystem
|
||||
// breakage), and seems to match `clang`'s behavior as well
|
||||
// (both before and after LLVM 13), possibly because they
|
||||
// have similar compatibility concerns to us. See
|
||||
// https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
|
||||
// and following comments for some discussion of this, as
|
||||
// well as the comments in `rustc_codegen_llvm` where these
|
||||
// flags are handled.
|
||||
//
|
||||
// Anyway, to be clear: this is still up in the air
|
||||
// somewhat, and is subject to change in the future (which
|
||||
// is a good thing, because this would ideally be a bit
|
||||
// more firmed up).
|
||||
let is_like_elf = !(tcx.sess.target.is_like_osx
|
||||
|| tcx.sess.target.is_like_windows
|
||||
|| tcx.sess.target.is_like_wasm);
|
||||
codegen_fn_attrs.flags |= if is_like_elf {
|
||||
CodegenFnAttrFlags::USED
|
||||
} else {
|
||||
CodegenFnAttrFlags::USED_LINKER
|
||||
};
|
||||
}
|
||||
}
|
||||
} else if attr.has_name(sym::cmse_nonsecure_entry) {
|
||||
if let Some(fn_sig) = fn_sig()
|
||||
&& !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. })
|
||||
{
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0776,
|
||||
"`#[cmse_nonsecure_entry]` requires C ABI"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
if !tcx.sess.target.llvm_target.contains("thumbv8m") {
|
||||
struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
|
||||
} else if attr.has_name(sym::thread_local) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
|
||||
} else if attr.has_name(sym::track_caller) {
|
||||
if !tcx.is_closure(did.to_def_id())
|
||||
&& let Some(fn_sig) = fn_sig()
|
||||
&& fn_sig.skip_binder().abi() != abi::Abi::Rust
|
||||
{
|
||||
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
|
||||
.emit();
|
||||
}
|
||||
if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::closure_track_caller,
|
||||
attr.span,
|
||||
"`#[track_caller]` on closures is currently unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
||||
} else if attr.has_name(sym::export_name) {
|
||||
if let Some(s) = attr.value_str() {
|
||||
if s.as_str().contains('\0') {
|
||||
// `#[export_name = ...]` will be converted to a null-terminated string,
|
||||
// so it may not contain any null characters.
|
||||
sym::cmse_nonsecure_entry => {
|
||||
if let Some(fn_sig) = fn_sig()
|
||||
&& !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. })
|
||||
{
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0648,
|
||||
"`export_name` may not contain null characters"
|
||||
E0776,
|
||||
"`#[cmse_nonsecure_entry]` requires C ABI"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.export_name = Some(s);
|
||||
if !tcx.sess.target.llvm_target.contains("thumbv8m") {
|
||||
struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY
|
||||
}
|
||||
} else if attr.has_name(sym::target_feature) {
|
||||
if !tcx.is_closure(did.to_def_id())
|
||||
&& let Some(fn_sig) = fn_sig()
|
||||
&& fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal
|
||||
{
|
||||
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
|
||||
// The `#[target_feature]` attribute is allowed on
|
||||
// WebAssembly targets on all functions, including safe
|
||||
// ones. Other targets require that `#[target_feature]` is
|
||||
// only applied to unsafe functions (pending the
|
||||
// `target_feature_11` feature) because on most targets
|
||||
// execution of instructions that are not supported is
|
||||
// considered undefined behavior. For WebAssembly which is a
|
||||
// 100% safe target at execution time it's not possible to
|
||||
// execute undefined instructions, and even if a future
|
||||
// feature was added in some form for this it would be a
|
||||
// deterministic trap. There is no undefined behavior when
|
||||
// executing WebAssembly so `#[target_feature]` is allowed
|
||||
// on safe functions (but again, only for WebAssembly)
|
||||
//
|
||||
// Note that this is also allowed if `actually_rustdoc` so
|
||||
// if a target is documenting some wasm-specific code then
|
||||
// it's not spuriously denied.
|
||||
//
|
||||
// This exception needs to be kept in sync with allowing
|
||||
// `#[target_feature]` on `main` and `start`.
|
||||
} else if !tcx.features().target_feature_11 {
|
||||
let mut err = feature_err(
|
||||
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
|
||||
sym::track_caller => {
|
||||
if !tcx.is_closure(did.to_def_id())
|
||||
&& let Some(fn_sig) = fn_sig()
|
||||
&& fn_sig.skip_binder().abi() != abi::Abi::Rust
|
||||
{
|
||||
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
|
||||
.emit();
|
||||
}
|
||||
if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::target_feature_11,
|
||||
sym::closure_track_caller,
|
||||
attr.span,
|
||||
"`#[target_feature(..)]` can only be applied to `unsafe` functions",
|
||||
);
|
||||
err.span_label(tcx.def_span(did), "not an `unsafe` function");
|
||||
err.emit();
|
||||
} else {
|
||||
check_target_feature_trait_unsafe(tcx, did, attr.span);
|
||||
"`#[track_caller]` on closures is currently unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER
|
||||
}
|
||||
sym::export_name => {
|
||||
if let Some(s) = attr.value_str() {
|
||||
if s.as_str().contains('\0') {
|
||||
// `#[export_name = ...]` will be converted to a null-terminated string,
|
||||
// so it may not contain any null characters.
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0648,
|
||||
"`export_name` may not contain null characters"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.export_name = Some(s);
|
||||
}
|
||||
}
|
||||
from_target_feature(
|
||||
tcx,
|
||||
attr,
|
||||
supported_target_features,
|
||||
&mut codegen_fn_attrs.target_features,
|
||||
);
|
||||
} else if attr.has_name(sym::linkage) {
|
||||
if let Some(val) = attr.value_str() {
|
||||
let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
|
||||
if tcx.is_foreign_item(did) {
|
||||
codegen_fn_attrs.import_linkage = linkage;
|
||||
} else {
|
||||
codegen_fn_attrs.linkage = linkage;
|
||||
}
|
||||
}
|
||||
} else if attr.has_name(sym::link_section) {
|
||||
if let Some(val) = attr.value_str() {
|
||||
if val.as_str().bytes().any(|b| b == 0) {
|
||||
let msg = format!(
|
||||
"illegal null byte in link_section \
|
||||
value: `{}`",
|
||||
&val
|
||||
);
|
||||
tcx.sess.span_err(attr.span, &msg);
|
||||
} else {
|
||||
codegen_fn_attrs.link_section = Some(val);
|
||||
}
|
||||
}
|
||||
} else if attr.has_name(sym::link_name) {
|
||||
codegen_fn_attrs.link_name = attr.value_str();
|
||||
} else if attr.has_name(sym::link_ordinal) {
|
||||
link_ordinal_span = Some(attr.span);
|
||||
if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
|
||||
codegen_fn_attrs.link_ordinal = ordinal;
|
||||
}
|
||||
} else if attr.has_name(sym::no_sanitize) {
|
||||
no_sanitize_span = Some(attr.span);
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list.iter() {
|
||||
if item.has_name(sym::address) {
|
||||
codegen_fn_attrs.no_sanitize |=
|
||||
SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS;
|
||||
} else if item.has_name(sym::cfi) {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
|
||||
} else if item.has_name(sym::kcfi) {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
|
||||
} else if item.has_name(sym::memory) {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
|
||||
} else if item.has_name(sym::memtag) {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
|
||||
} else if item.has_name(sym::shadow_call_stack) {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
|
||||
} else if item.has_name(sym::thread) {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
|
||||
} else if item.has_name(sym::hwaddress) {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
|
||||
sym::target_feature => {
|
||||
if !tcx.is_closure(did.to_def_id())
|
||||
&& let Some(fn_sig) = fn_sig()
|
||||
&& fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal
|
||||
{
|
||||
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
|
||||
// The `#[target_feature]` attribute is allowed on
|
||||
// WebAssembly targets on all functions, including safe
|
||||
// ones. Other targets require that `#[target_feature]` is
|
||||
// only applied to unsafe functions (pending the
|
||||
// `target_feature_11` feature) because on most targets
|
||||
// execution of instructions that are not supported is
|
||||
// considered undefined behavior. For WebAssembly which is a
|
||||
// 100% safe target at execution time it's not possible to
|
||||
// execute undefined instructions, and even if a future
|
||||
// feature was added in some form for this it would be a
|
||||
// deterministic trap. There is no undefined behavior when
|
||||
// executing WebAssembly so `#[target_feature]` is allowed
|
||||
// on safe functions (but again, only for WebAssembly)
|
||||
//
|
||||
// Note that this is also allowed if `actually_rustdoc` so
|
||||
// if a target is documenting some wasm-specific code then
|
||||
// it's not spuriously denied.
|
||||
//
|
||||
// This exception needs to be kept in sync with allowing
|
||||
// `#[target_feature]` on `main` and `start`.
|
||||
} else if !tcx.features().target_feature_11 {
|
||||
let mut err = feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::target_feature_11,
|
||||
attr.span,
|
||||
"`#[target_feature(..)]` can only be applied to `unsafe` functions",
|
||||
);
|
||||
err.span_label(tcx.def_span(did), "not an `unsafe` function");
|
||||
err.emit();
|
||||
} else {
|
||||
tcx.sess
|
||||
.struct_span_err(item.span(), "invalid argument for `no_sanitize`")
|
||||
.note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
|
||||
.emit();
|
||||
check_target_feature_trait_unsafe(tcx, did, attr.span);
|
||||
}
|
||||
}
|
||||
from_target_feature(
|
||||
tcx,
|
||||
attr,
|
||||
supported_target_features,
|
||||
&mut codegen_fn_attrs.target_features,
|
||||
);
|
||||
}
|
||||
sym::linkage => {
|
||||
if let Some(val) = attr.value_str() {
|
||||
let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
|
||||
if tcx.is_foreign_item(did) {
|
||||
codegen_fn_attrs.import_linkage = linkage;
|
||||
} else {
|
||||
codegen_fn_attrs.linkage = linkage;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if attr.has_name(sym::instruction_set) {
|
||||
codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] {
|
||||
[NestedMetaItem::MetaItem(set)] => {
|
||||
let segments =
|
||||
set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
|
||||
match segments.as_slice() {
|
||||
[sym::arm, sym::a32] | [sym::arm, sym::t32] => {
|
||||
if !tcx.sess.target.has_thumb_interworking {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0779,
|
||||
"target does not support `#[instruction_set]`"
|
||||
)
|
||||
.emit();
|
||||
None
|
||||
} else if segments[1] == sym::a32 {
|
||||
Some(InstructionSetAttr::ArmA32)
|
||||
} else if segments[1] == sym::t32 {
|
||||
Some(InstructionSetAttr::ArmT32)
|
||||
} else {
|
||||
unreachable!()
|
||||
sym::link_section => {
|
||||
if let Some(val) = attr.value_str() {
|
||||
if val.as_str().bytes().any(|b| b == 0) {
|
||||
let msg = format!("illegal null byte in link_section value: `{}`", &val);
|
||||
tcx.sess.span_err(attr.span, &msg);
|
||||
} else {
|
||||
codegen_fn_attrs.link_section = Some(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
sym::link_name => codegen_fn_attrs.link_name = attr.value_str(),
|
||||
sym::link_ordinal => {
|
||||
link_ordinal_span = Some(attr.span);
|
||||
if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
|
||||
codegen_fn_attrs.link_ordinal = ordinal;
|
||||
}
|
||||
}
|
||||
sym::no_sanitize => {
|
||||
no_sanitize_span = Some(attr.span);
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list.iter() {
|
||||
match item.name_or_empty() {
|
||||
sym::address => {
|
||||
codegen_fn_attrs.no_sanitize |=
|
||||
SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
|
||||
}
|
||||
sym::cfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
|
||||
sym::kcfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
|
||||
sym::memory => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY,
|
||||
sym::memtag => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG,
|
||||
sym::shadow_call_stack => {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK
|
||||
}
|
||||
sym::thread => codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD,
|
||||
sym::hwaddress => {
|
||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS
|
||||
}
|
||||
_ => {
|
||||
tcx.sess
|
||||
.struct_span_err(item.span(), "invalid argument for `no_sanitize`")
|
||||
.note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sym::instruction_set => {
|
||||
codegen_fn_attrs.instruction_set =
|
||||
attr.meta_item_list().and_then(|l| match &l[..] {
|
||||
[NestedMetaItem::MetaItem(set)] => {
|
||||
let segments =
|
||||
set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
|
||||
match segments.as_slice() {
|
||||
[sym::arm, sym::a32] | [sym::arm, sym::t32] => {
|
||||
if !tcx.sess.target.has_thumb_interworking {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0779,
|
||||
"target does not support `#[instruction_set]`"
|
||||
)
|
||||
.emit();
|
||||
None
|
||||
} else if segments[1] == sym::a32 {
|
||||
Some(InstructionSetAttr::ArmA32)
|
||||
} else if segments[1] == sym::t32 {
|
||||
Some(InstructionSetAttr::ArmT32)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0779,
|
||||
"invalid instruction set specified",
|
||||
)
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
[] => {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0778,
|
||||
"`#[instruction_set]` requires an argument"
|
||||
)
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0779,
|
||||
"invalid instruction set specified",
|
||||
"cannot specify more than one instruction set"
|
||||
)
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
[] => {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0778,
|
||||
"`#[instruction_set]` requires an argument"
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
}
|
||||
sym::repr => {
|
||||
codegen_fn_attrs.alignment = if let Some(items) = attr.meta_item_list()
|
||||
&& let [item] = items.as_slice()
|
||||
&& let Some((sym::align, literal)) = item.name_value_literal()
|
||||
{
|
||||
rustc_attr::parse_alignment(&literal.kind).map_err(|msg| {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0589,
|
||||
"invalid `repr(align)` attribute: {}",
|
||||
msg
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
.ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0779,
|
||||
"cannot specify more than one instruction set"
|
||||
)
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
})
|
||||
} else if attr.has_name(sym::repr) {
|
||||
codegen_fn_attrs.alignment = match attr.meta_item_list() {
|
||||
Some(items) => match items.as_slice() {
|
||||
[item] => match item.name_value_literal() {
|
||||
Some((sym::align, literal)) => {
|
||||
let alignment = rustc_attr::parse_alignment(&literal.kind);
|
||||
|
||||
match alignment {
|
||||
Ok(align) => Some(align),
|
||||
Err(msg) => {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
attr.span,
|
||||
E0589,
|
||||
"invalid `repr(align)` attribute: {}",
|
||||
msg
|
||||
)
|
||||
.emit();
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
[] => None,
|
||||
_ => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub use super::ffi::*;
|
||||
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::coverage::{
|
||||
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId,
|
||||
InjectedExpressionIndex, MappedExpressionIndex, Op,
|
||||
@ -205,7 +205,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||
// `expression_index`s lower than the referencing `Expression`. Therefore, it is
|
||||
// reasonable to look up the new index of an expression operand while the `new_indexes`
|
||||
// vector is only complete up to the current `ExpressionIndex`.
|
||||
let id_to_counter = |new_indexes: &IndexVec<
|
||||
let id_to_counter = |new_indexes: &IndexSlice<
|
||||
InjectedExpressionIndex,
|
||||
Option<MappedExpressionIndex>,
|
||||
>,
|
||||
|
@ -5,7 +5,6 @@
|
||||
#![feature(int_roundings)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
|
@ -5,7 +5,7 @@ use super::FunctionCx;
|
||||
use crate::traits::*;
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::traversal;
|
||||
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::{self, Location, TerminatorKind};
|
||||
@ -277,7 +277,7 @@ impl CleanupKind {
|
||||
/// Recover that structure in an analyze pass.
|
||||
pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKind> {
|
||||
fn discover_masters<'tcx>(
|
||||
result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
|
||||
result: &mut IndexSlice<mir::BasicBlock, CleanupKind>,
|
||||
mir: &mir::Body<'tcx>,
|
||||
) {
|
||||
for (bb, data) in mir.basic_blocks.iter_enumerated() {
|
||||
@ -308,7 +308,10 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
|
||||
}
|
||||
}
|
||||
|
||||
fn propagate<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>, mir: &mir::Body<'tcx>) {
|
||||
fn propagate<'tcx>(
|
||||
result: &mut IndexSlice<mir::BasicBlock, CleanupKind>,
|
||||
mir: &mir::Body<'tcx>,
|
||||
) {
|
||||
let mut funclet_succs = IndexVec::from_elem(None, &mir.basic_blocks);
|
||||
|
||||
let mut set_successor = |funclet: mir::BasicBlock, succ| match funclet_succs[funclet] {
|
||||
|
@ -397,8 +397,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
PassMode::Cast(cast_ty, _) => {
|
||||
let op = match self.locals[mir::RETURN_PLACE] {
|
||||
LocalRef::Operand(Some(op)) => op,
|
||||
LocalRef::Operand(None) => bug!("use of return before def"),
|
||||
LocalRef::Operand(op) => op,
|
||||
LocalRef::PendingOperand => bug!("use of return before def"),
|
||||
LocalRef::Place(cg_place) => OperandRef {
|
||||
val: Ref(cg_place.llval, None, cg_place.align),
|
||||
layout: cg_place.layout,
|
||||
@ -600,6 +600,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
// and `#[track_caller]` adds an implicit third argument.
|
||||
(LangItem::PanicBoundsCheck, vec![index, len, location])
|
||||
}
|
||||
AssertKind::MisalignedPointerDereference { ref required, ref found } => {
|
||||
let required = self.codegen_operand(bx, required).immediate();
|
||||
let found = self.codegen_operand(bx, found).immediate();
|
||||
// It's `fn panic_bounds_check(index: usize, len: usize)`,
|
||||
// and `#[track_caller]` adds an implicit third argument.
|
||||
(LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
|
||||
}
|
||||
_ => {
|
||||
let msg = bx.const_str(msg.description());
|
||||
// It's `pub fn panic(expr: &str)`, with the wide reference being passed
|
||||
@ -1673,7 +1680,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
match self.locals[index] {
|
||||
LocalRef::Place(dest) => dest,
|
||||
LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
|
||||
LocalRef::Operand(None) => {
|
||||
LocalRef::PendingOperand => {
|
||||
// Handle temporary places, specifically `Operand` ones, as
|
||||
// they don't have `alloca`s.
|
||||
return if fn_ret.is_indirect() {
|
||||
@ -1694,7 +1701,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
ReturnDest::DirectOperand(index)
|
||||
};
|
||||
}
|
||||
LocalRef::Operand(Some(_)) => {
|
||||
LocalRef::Operand(_) => {
|
||||
bug!("place local already assigned to");
|
||||
}
|
||||
}
|
||||
@ -1737,7 +1744,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
IndirectOperand(tmp, index) => {
|
||||
let op = bx.load_operand(tmp);
|
||||
tmp.storage_dead(bx);
|
||||
self.locals[index] = LocalRef::Operand(Some(op));
|
||||
self.locals[index] = LocalRef::Operand(op);
|
||||
self.debug_introduce_local(bx, index);
|
||||
}
|
||||
DirectOperand(index) => {
|
||||
@ -1752,7 +1759,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
} else {
|
||||
OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout)
|
||||
};
|
||||
self.locals[index] = LocalRef::Operand(Some(op));
|
||||
self.locals[index] = LocalRef::Operand(op);
|
||||
self.debug_introduce_local(bx, index);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use rustc_target::abi::{Abi, Size, VariantIdx};
|
||||
use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx};
|
||||
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::place::PlaceRef;
|
||||
@ -79,7 +79,7 @@ impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
|
||||
trait DebugInfoOffsetLocation<'tcx, Bx> {
|
||||
fn deref(&self, bx: &mut Bx) -> Self;
|
||||
fn layout(&self) -> TyAndLayout<'tcx>;
|
||||
fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self;
|
||||
fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self;
|
||||
fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
|
||||
self.layout
|
||||
}
|
||||
|
||||
fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
|
||||
fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self {
|
||||
PlaceRef::project_field(*self, bx, field.index())
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
|
||||
*self
|
||||
}
|
||||
|
||||
fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
|
||||
fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self {
|
||||
self.field(bx.cx(), field.index())
|
||||
}
|
||||
|
||||
@ -312,7 +312,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
LocalRef::Place(place) | LocalRef::UnsizedPlace(place) => {
|
||||
bx.set_var_name(place.llval, name);
|
||||
}
|
||||
LocalRef::Operand(Some(operand)) => match operand.val {
|
||||
LocalRef::Operand(operand) => match operand.val {
|
||||
OperandValue::Ref(x, ..) | OperandValue::Immediate(x) => {
|
||||
bx.set_var_name(x, name);
|
||||
}
|
||||
@ -323,7 +323,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
bx.set_var_name(b, &(name.clone() + ".1"));
|
||||
}
|
||||
},
|
||||
LocalRef::Operand(None) => {}
|
||||
LocalRef::PendingOperand => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,9 +332,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
}
|
||||
|
||||
let base = match local_ref {
|
||||
LocalRef::Operand(None) => return,
|
||||
LocalRef::PendingOperand => return,
|
||||
|
||||
LocalRef::Operand(Some(operand)) => {
|
||||
LocalRef::Operand(operand) => {
|
||||
// Don't spill operands onto the stack in naked functions.
|
||||
// See: https://github.com/rust-lang/rust/issues/42779
|
||||
let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
|
||||
|
@ -123,7 +123,10 @@ enum LocalRef<'tcx, V> {
|
||||
/// Every time it is initialized, we have to reallocate the place
|
||||
/// and update the fat pointer. That's the reason why it is indirect.
|
||||
UnsizedPlace(PlaceRef<'tcx, V>),
|
||||
Operand(Option<OperandRef<'tcx, V>>),
|
||||
/// The backend [`OperandValue`] has already been generated.
|
||||
Operand(OperandRef<'tcx, V>),
|
||||
/// Will be a `Self::Operand` once we get to its definition.
|
||||
PendingOperand,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
|
||||
@ -135,9 +138,9 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
|
||||
// Zero-size temporaries aren't always initialized, which
|
||||
// doesn't matter because they don't contain data, but
|
||||
// we need something in the operand.
|
||||
LocalRef::Operand(Some(OperandRef::new_zst(bx, layout)))
|
||||
LocalRef::Operand(OperandRef::new_zst(bx, layout))
|
||||
} else {
|
||||
LocalRef::Operand(None)
|
||||
LocalRef::PendingOperand
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -337,7 +340,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
// We don't have to cast or keep the argument in the alloca.
|
||||
// FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
|
||||
// of putting everything in allocas just so we can use llvm.dbg.declare.
|
||||
let local = |op| LocalRef::Operand(Some(op));
|
||||
let local = |op| LocalRef::Operand(op);
|
||||
match arg.mode {
|
||||
PassMode::Ignore => {
|
||||
return local(OperandRef::new_zst(bx, arg.layout));
|
||||
|
@ -60,7 +60,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
||||
) -> OperandRef<'tcx, V> {
|
||||
assert!(layout.is_zst());
|
||||
OperandRef {
|
||||
val: OperandValue::Immediate(bx.const_undef(bx.immediate_backend_type(layout))),
|
||||
val: OperandValue::Immediate(bx.const_poison(bx.immediate_backend_type(layout))),
|
||||
layout,
|
||||
}
|
||||
}
|
||||
@ -145,7 +145,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
||||
let llty = bx.cx().backend_type(self.layout);
|
||||
debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty);
|
||||
// Reconstruct the immediate aggregate.
|
||||
let mut llpair = bx.cx().const_undef(llty);
|
||||
let mut llpair = bx.cx().const_poison(llty);
|
||||
let imm_a = bx.from_immediate(a);
|
||||
let imm_b = bx.from_immediate(b);
|
||||
llpair = bx.insert_value(llpair, imm_a, 0);
|
||||
@ -370,7 +370,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
|
||||
|
||||
match self.locals[place_ref.local] {
|
||||
LocalRef::Operand(Some(mut o)) => {
|
||||
LocalRef::Operand(mut o) => {
|
||||
// Moves out of scalar and scalar pair fields are trivial.
|
||||
for elem in place_ref.projection.iter() {
|
||||
match elem {
|
||||
@ -395,7 +395,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
Some(o)
|
||||
}
|
||||
LocalRef::Operand(None) => {
|
||||
LocalRef::PendingOperand => {
|
||||
bug!("use of {:?} before def", place_ref);
|
||||
}
|
||||
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
|
||||
|
@ -214,7 +214,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
let cast_to_size = cast_to_layout.layout.size();
|
||||
let cast_to = bx.cx().immediate_backend_type(cast_to_layout);
|
||||
if self.layout.abi.is_uninhabited() {
|
||||
return bx.cx().const_undef(cast_to);
|
||||
return bx.cx().const_poison(cast_to);
|
||||
}
|
||||
let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
|
||||
Variants::Single { index } => {
|
||||
@ -558,6 +558,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
bug!("using operand local {:?} as place", place_ref);
|
||||
}
|
||||
}
|
||||
LocalRef::PendingOperand => {
|
||||
bug!("using still-pending operand local {:?} as place", place_ref);
|
||||
}
|
||||
};
|
||||
for elem in place_ref.projection[base..].iter() {
|
||||
cg_base = match *elem {
|
||||
|
@ -13,7 +13,7 @@ use rustc_middle::ty::cast::{CastTy, IntTy};
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
|
||||
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
|
||||
use rustc_span::source_map::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::{self, VariantIdx};
|
||||
use rustc_target::abi::{self, FIRST_VARIANT};
|
||||
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
#[instrument(level = "trace", skip(self, bx))]
|
||||
@ -118,21 +118,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let variant_dest = dest.project_downcast(bx, variant_index);
|
||||
(variant_index, variant_dest, active_field_index)
|
||||
}
|
||||
_ => (VariantIdx::from_u32(0), dest, None),
|
||||
_ => (FIRST_VARIANT, dest, None),
|
||||
};
|
||||
if active_field_index.is_some() {
|
||||
assert_eq!(operands.len(), 1);
|
||||
}
|
||||
for (i, operand) in operands.iter().enumerate() {
|
||||
for (i, operand) in operands.iter_enumerated() {
|
||||
let op = self.codegen_operand(bx, operand);
|
||||
// Do not generate stores and GEPis for zero-sized fields.
|
||||
if !op.layout.is_zst() {
|
||||
let field_index = active_field_index.unwrap_or(i);
|
||||
let field = if let mir::AggregateKind::Array(_) = **kind {
|
||||
let llindex = bx.cx().const_usize(field_index as u64);
|
||||
let llindex = bx.cx().const_usize(field_index.as_u32().into());
|
||||
variant_dest.project_index(bx, llindex)
|
||||
} else {
|
||||
variant_dest.project_field(bx, field_index)
|
||||
variant_dest.project_field(bx, field_index.as_usize())
|
||||
};
|
||||
op.val.store(bx, field);
|
||||
}
|
||||
@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
assert!(bx.cx().is_backend_immediate(cast));
|
||||
let ll_t_out = bx.cx().immediate_backend_type(cast);
|
||||
if operand.layout.abi.is_uninhabited() {
|
||||
let val = OperandValue::Immediate(bx.cx().const_undef(ll_t_out));
|
||||
let val = OperandValue::Immediate(bx.cx().const_poison(ll_t_out));
|
||||
return OperandRef { val, layout: cast };
|
||||
}
|
||||
let r_t_in =
|
||||
@ -516,8 +516,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
mir::Rvalue::ThreadLocalRef(def_id) => {
|
||||
assert!(bx.cx().tcx().is_static(def_id));
|
||||
let static_ = bx.get_static(def_id);
|
||||
let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
|
||||
let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id)
|
||||
{
|
||||
let instance = ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
substs: ty::InternalSubsts::empty(),
|
||||
};
|
||||
let fn_ptr = bx.get_fn_addr(instance);
|
||||
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
|
||||
bx.call(fn_ty, Some(fn_abi), fn_ptr, &[], None)
|
||||
} else {
|
||||
bx.get_static(def_id)
|
||||
};
|
||||
OperandRef { val: OperandValue::Immediate(static_), layout }
|
||||
}
|
||||
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
|
||||
@ -545,7 +557,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
// ZST are passed as operands and require special handling
|
||||
// because codegen_place() panics if Local is operand.
|
||||
if let Some(index) = place.as_local() {
|
||||
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
||||
if let LocalRef::Operand(op) = self.locals[index] {
|
||||
if let ty::Array(_, n) = op.layout.ty.kind() {
|
||||
let n = n.eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
|
||||
return bx.cx().const_usize(n);
|
||||
|
@ -18,12 +18,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
LocalRef::UnsizedPlace(cg_indirect_dest) => {
|
||||
self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue)
|
||||
}
|
||||
LocalRef::Operand(None) => {
|
||||
LocalRef::PendingOperand => {
|
||||
let operand = self.codegen_rvalue_operand(bx, rvalue);
|
||||
self.locals[index] = LocalRef::Operand(Some(operand));
|
||||
self.locals[index] = LocalRef::Operand(operand);
|
||||
self.debug_introduce_local(bx, index);
|
||||
}
|
||||
LocalRef::Operand(Some(op)) => {
|
||||
LocalRef::Operand(op) => {
|
||||
if !op.layout.is_zst() {
|
||||
span_bug!(
|
||||
statement.source_info.span,
|
||||
|
@ -8,6 +8,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
|
||||
// Constant constructors
|
||||
fn const_null(&self, t: Self::Type) -> Self::Value;
|
||||
fn const_undef(&self, t: Self::Type) -> Self::Value;
|
||||
fn const_poison(&self, t: Self::Type) -> Self::Value;
|
||||
fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
|
||||
fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value;
|
||||
fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value;
|
||||
|
@ -39,17 +39,25 @@ const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
|
||||
const_eval_unallowed_mutable_refs =
|
||||
mutable references are not allowed in the final value of {$kind}s
|
||||
.teach_note =
|
||||
References in statics and constants may only refer to immutable values.\n\n
|
||||
References in statics and constants may only refer to immutable values.
|
||||
|
||||
|
||||
Statics are shared everywhere, and if they refer to mutable data one might violate memory
|
||||
safety since holding multiple mutable references to shared data is not allowed.\n\n
|
||||
safety since holding multiple mutable references to shared data is not allowed.
|
||||
|
||||
|
||||
If you really want global mutable state, try using static mut or a global UnsafeCell.
|
||||
|
||||
const_eval_unallowed_mutable_refs_raw =
|
||||
raw mutable references are not allowed in the final value of {$kind}s
|
||||
.teach_note =
|
||||
References in statics and constants may only refer to immutable values.\n\n
|
||||
References in statics and constants may only refer to immutable values.
|
||||
|
||||
|
||||
Statics are shared everywhere, and if they refer to mutable data one might violate memory
|
||||
safety since holding multiple mutable references to shared data is not allowed.\n\n
|
||||
safety since holding multiple mutable references to shared data is not allowed.
|
||||
|
||||
|
||||
If you really want global mutable state, try using static mut or a global UnsafeCell.
|
||||
|
||||
const_eval_non_const_fmt_macro_call =
|
||||
|
@ -544,6 +544,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||
RemainderByZero(op) => RemainderByZero(eval_to_int(op)?),
|
||||
ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind),
|
||||
ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind),
|
||||
MisalignedPointerDereference { ref required, ref found } => {
|
||||
MisalignedPointerDereference {
|
||||
required: eval_to_int(required)?,
|
||||
found: eval_to_int(found)?,
|
||||
}
|
||||
}
|
||||
};
|
||||
Err(ConstEvalErrKind::AssertFailure(err).into())
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use crate::interpret::{
|
||||
use crate::interpret::{MPlaceTy, Value};
|
||||
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
use rustc_target::abi::{Align, VariantIdx};
|
||||
use rustc_target::abi::{Align, FieldIdx, VariantIdx, FIRST_VARIANT};
|
||||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn branches<'tcx>(
|
||||
@ -412,7 +412,8 @@ fn valtree_into_mplace<'tcx>(
|
||||
|
||||
let inner_ty = match ty.kind() {
|
||||
ty::Adt(def, substs) => {
|
||||
def.variant(VariantIdx::from_u32(0)).fields[i].ty(tcx, substs)
|
||||
let i = FieldIdx::from_usize(i);
|
||||
def.variant(FIRST_VARIANT).fields[i].ty(tcx, substs)
|
||||
}
|
||||
ty::Tuple(inner_tys) => inner_tys[i],
|
||||
_ => bug!("unexpected unsized type {:?}", ty),
|
||||
|
@ -5,10 +5,11 @@
|
||||
use either::{Either, Left, Right};
|
||||
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_index::vec::IndexSlice;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, VariantIdx};
|
||||
use rustc_target::abi::{self, Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_VARIANT};
|
||||
|
||||
use super::{
|
||||
alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
|
||||
@ -787,7 +788,7 @@ where
|
||||
pub fn write_aggregate(
|
||||
&mut self,
|
||||
kind: &mir::AggregateKind<'tcx>,
|
||||
operands: &[mir::Operand<'tcx>],
|
||||
operands: &IndexSlice<FieldIdx, mir::Operand<'tcx>>,
|
||||
dest: &PlaceTy<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
self.write_uninit(&dest)?;
|
||||
@ -796,14 +797,14 @@ where
|
||||
let variant_dest = self.place_downcast(&dest, variant_index)?;
|
||||
(variant_index, variant_dest, active_field_index)
|
||||
}
|
||||
_ => (VariantIdx::from_u32(0), dest.clone(), None),
|
||||
_ => (FIRST_VARIANT, dest.clone(), None),
|
||||
};
|
||||
if active_field_index.is_some() {
|
||||
assert_eq!(operands.len(), 1);
|
||||
}
|
||||
for (field_index, operand) in operands.iter().enumerate() {
|
||||
for (field_index, operand) in operands.iter_enumerated() {
|
||||
let field_index = active_field_index.unwrap_or(field_index);
|
||||
let field_dest = self.place_field(&variant_dest, field_index)?;
|
||||
let field_dest = self.place_field(&variant_dest, field_index.as_usize())?;
|
||||
let op = self.eval_operand(operand, Some(field_dest.layout))?;
|
||||
self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?;
|
||||
}
|
||||
|
@ -382,6 +382,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
| ty::InstanceDef::FnPtrShim(..)
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..)
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
| ty::InstanceDef::Item(_) => {
|
||||
// We need MIR for this fn
|
||||
let Some((body, instance)) =
|
||||
@ -539,7 +541,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let mut receiver = args[0].clone();
|
||||
let receiver_place = loop {
|
||||
match receiver.layout.ty.kind() {
|
||||
ty::Ref(..) | ty::RawPtr(..) => break self.deref_operand(&receiver)?,
|
||||
ty::Ref(..) | ty::RawPtr(..) => {
|
||||
// We do *not* use `deref_operand` here: we don't want to conceptually
|
||||
// create a place that must be dereferenceable, since the receiver might
|
||||
// be a raw pointer and (for `*const dyn Trait`) we don't need to
|
||||
// actually access memory to resolve this method.
|
||||
// Also see <https://github.com/rust-lang/miri/issues/2786>.
|
||||
let val = self.read_immediate(&receiver)?;
|
||||
break self.ref_to_mplace(&val)?;
|
||||
}
|
||||
ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
|
||||
ty::Dynamic(.., ty::DynStar) => {
|
||||
// Not clear how to handle this, so far we assume the receiver is always a pointer.
|
||||
|
@ -16,7 +16,9 @@ use rustc_middle::mir::interpret::InterpError;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange};
|
||||
use rustc_target::abi::{
|
||||
Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
|
||||
};
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
@ -269,14 +271,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
match layout.variants {
|
||||
Variants::Single { index } => {
|
||||
// Inside a variant
|
||||
PathElem::Field(def.variant(index).fields[field].name)
|
||||
PathElem::Field(def.variant(index).fields[FieldIdx::from_usize(field)].name)
|
||||
}
|
||||
Variants::Multiple { .. } => bug!("we handled variants above"),
|
||||
}
|
||||
}
|
||||
|
||||
// other ADTs
|
||||
ty::Adt(def, _) => PathElem::Field(def.non_enum_variant().fields[field].name),
|
||||
ty::Adt(def, _) => {
|
||||
PathElem::Field(def.non_enum_variant().fields[FieldIdx::from_usize(field)].name)
|
||||
}
|
||||
|
||||
// arrays/slices
|
||||
ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field),
|
||||
|
@ -722,6 +722,32 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
// Check that all trait bounds that are marked as `~const` can be satisfied.
|
||||
//
|
||||
// Typeck only does a "non-const" check since it operates on HIR and cannot distinguish
|
||||
// which path expressions are getting called on and which path expressions are only used
|
||||
// as function pointers. This is required for correctness.
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
|
||||
let cause = ObligationCause::new(
|
||||
terminator.source_info.span,
|
||||
self.body.source.def_id().expect_local(),
|
||||
ObligationCauseCode::ItemObligation(callee),
|
||||
);
|
||||
let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
|
||||
ocx.register_obligations(traits::predicates_for_generics(
|
||||
|_, _| cause.clone(),
|
||||
self.param_env,
|
||||
normalized_predicates,
|
||||
));
|
||||
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
|
||||
// Attempting to call a trait method?
|
||||
if let Some(trait_id) = tcx.trait_of_item(callee) {
|
||||
trace!("attempting to call a trait method");
|
||||
@ -749,31 +775,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
selcx.select(&obligation)
|
||||
};
|
||||
|
||||
// do a well-formedness check on the trait method being called. This is because typeck only does a
|
||||
// "non-const" check. This is required for correctness here.
|
||||
{
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
|
||||
let cause = ObligationCause::new(
|
||||
terminator.source_info.span,
|
||||
self.body.source.def_id().expect_local(),
|
||||
ObligationCauseCode::ItemObligation(callee),
|
||||
);
|
||||
let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
|
||||
ocx.register_obligations(traits::predicates_for_generics(
|
||||
|_, _| cause.clone(),
|
||||
self.param_env,
|
||||
normalized_predicates,
|
||||
));
|
||||
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
}
|
||||
|
||||
match implsrc {
|
||||
Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
|
||||
debug!(
|
||||
|
@ -21,7 +21,7 @@ use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::{self, List, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::{cmp, iter, mem};
|
||||
@ -184,7 +184,7 @@ pub fn collect_temps_and_candidates<'tcx>(
|
||||
/// This wraps an `Item`, and has access to all fields of that `Item` via `Deref` coercion.
|
||||
struct Validator<'a, 'tcx> {
|
||||
ccx: &'a ConstCx<'a, 'tcx>,
|
||||
temps: &'a mut IndexVec<Local, TempState>,
|
||||
temps: &'a mut IndexSlice<Local, TempState>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> std::ops::Deref for Validator<'a, 'tcx> {
|
||||
@ -669,7 +669,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
// FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`.
|
||||
pub fn validate_candidates(
|
||||
ccx: &ConstCx<'_, '_>,
|
||||
temps: &mut IndexVec<Local, TempState>,
|
||||
temps: &mut IndexSlice<Local, TempState>,
|
||||
candidates: &[Candidate],
|
||||
) -> Vec<Candidate> {
|
||||
let mut validator = Validator { ccx, temps };
|
||||
@ -707,7 +707,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) {
|
||||
let last = self.promoted.basic_blocks.last().unwrap();
|
||||
let last = self.promoted.basic_blocks.last_index().unwrap();
|
||||
let data = &mut self.promoted[last];
|
||||
data.statements.push(Statement {
|
||||
source_info: SourceInfo::outermost(span),
|
||||
@ -800,7 +800,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
self.visit_operand(arg, loc);
|
||||
}
|
||||
|
||||
let last = self.promoted.basic_blocks.last().unwrap();
|
||||
let last = self.promoted.basic_blocks.last_index().unwrap();
|
||||
let new_target = self.new_block();
|
||||
|
||||
*self.promoted[last].terminator_mut() = Terminator {
|
||||
|
@ -17,7 +17,7 @@ use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt
|
||||
use rustc_mir_dataflow::impls::MaybeStorageLive;
|
||||
use rustc_mir_dataflow::storage::always_storage_live_locals;
|
||||
use rustc_mir_dataflow::{Analysis, ResultsCursor};
|
||||
use rustc_target::abi::{Size, VariantIdx};
|
||||
use rustc_target::abi::{Size, FIRST_VARIANT};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum EdgeKind {
|
||||
@ -359,8 +359,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
check_equal(self, location, *f_ty);
|
||||
}
|
||||
ty::Adt(adt_def, substs) => {
|
||||
let var = parent_ty.variant_index.unwrap_or(VariantIdx::from_u32(0));
|
||||
let Some(field) = adt_def.variant(var).fields.get(f.as_usize()) else {
|
||||
let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
|
||||
let Some(field) = adt_def.variant(var).fields.get(f) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
@ -677,8 +677,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
if let Rvalue::CopyForDeref(place) = rvalue {
|
||||
if !place.ty(&self.body.local_decls, self.tcx).ty.builtin_deref(true).is_some()
|
||||
{
|
||||
if place.ty(&self.body.local_decls, self.tcx).ty.builtin_deref(true).is_none() {
|
||||
self.fail(
|
||||
location,
|
||||
"`CopyForDeref` should only be used for dereferenceable types",
|
||||
|
@ -10,12 +10,12 @@ arrayvec = { version = "0.7", default-features = false }
|
||||
bitflags = "1.2.1"
|
||||
cfg-if = "1.0"
|
||||
ena = "0.14.2"
|
||||
indexmap = { version = "1.9.1" }
|
||||
indexmap = { version = "1.9.3" }
|
||||
jobserver_crate = { version = "0.1.13", package = "jobserver" }
|
||||
libc = "0.2"
|
||||
measureme = "10.0.0"
|
||||
rayon-core = { version = "0.4.0", package = "rustc-rayon-core", optional = true }
|
||||
rayon = { version = "0.4.0", package = "rustc-rayon", optional = true }
|
||||
rustc-rayon-core = { version = "0.5.0", optional = true }
|
||||
rustc-rayon = { version = "0.5.0", optional = true }
|
||||
rustc_graphviz = { path = "../rustc_graphviz" }
|
||||
rustc-hash = "1.1.0"
|
||||
rustc_index = { path = "../rustc_index", package = "rustc_index" }
|
||||
@ -51,4 +51,4 @@ features = [
|
||||
memmap2 = "0.2.1"
|
||||
|
||||
[features]
|
||||
rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rayon", "rayon-core"]
|
||||
rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rustc-rayon", "rustc-rayon-core"]
|
||||
|
@ -10,7 +10,7 @@
|
||||
//! <https://www.cs.princeton.edu/courses/archive/spr03/cs423/download/dominators.pdf>
|
||||
|
||||
use super::ControlFlowGraph;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[cfg(test)]
|
||||
@ -256,10 +256,10 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
|
||||
/// where `+>` is a proper ancestor and `*>` is just an ancestor.
|
||||
#[inline]
|
||||
fn eval(
|
||||
ancestor: &mut IndexVec<PreorderIndex, PreorderIndex>,
|
||||
ancestor: &mut IndexSlice<PreorderIndex, PreorderIndex>,
|
||||
lastlinked: Option<PreorderIndex>,
|
||||
semi: &IndexVec<PreorderIndex, PreorderIndex>,
|
||||
label: &mut IndexVec<PreorderIndex, PreorderIndex>,
|
||||
semi: &IndexSlice<PreorderIndex, PreorderIndex>,
|
||||
label: &mut IndexSlice<PreorderIndex, PreorderIndex>,
|
||||
node: PreorderIndex,
|
||||
) -> PreorderIndex {
|
||||
if is_processed(node, lastlinked) {
|
||||
@ -277,10 +277,10 @@ fn is_processed(v: PreorderIndex, lastlinked: Option<PreorderIndex>) -> bool {
|
||||
|
||||
#[inline]
|
||||
fn compress(
|
||||
ancestor: &mut IndexVec<PreorderIndex, PreorderIndex>,
|
||||
ancestor: &mut IndexSlice<PreorderIndex, PreorderIndex>,
|
||||
lastlinked: Option<PreorderIndex>,
|
||||
semi: &IndexVec<PreorderIndex, PreorderIndex>,
|
||||
label: &mut IndexVec<PreorderIndex, PreorderIndex>,
|
||||
semi: &IndexSlice<PreorderIndex, PreorderIndex>,
|
||||
label: &mut IndexSlice<PreorderIndex, PreorderIndex>,
|
||||
v: PreorderIndex,
|
||||
) {
|
||||
assert!(is_processed(v, lastlinked));
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{DirectedGraph, WithNumNodes, WithStartNode, WithSuccessors};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_index::vec::{IndexSlice, IndexVec};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
#[cfg(test)]
|
||||
@ -31,7 +31,7 @@ fn post_order_walk<G: DirectedGraph + WithSuccessors + WithNumNodes>(
|
||||
graph: &G,
|
||||
node: G::Node,
|
||||
result: &mut Vec<G::Node>,
|
||||
visited: &mut IndexVec<G::Node, bool>,
|
||||
visited: &mut IndexSlice<G::Node, bool>,
|
||||
) {
|
||||
struct PostOrderFrame<Node, Iter> {
|
||||
node: Node,
|
||||
|
@ -8,7 +8,7 @@
|
||||
use crate::fx::FxHashSet;
|
||||
use crate::graph::vec_graph::VecGraph;
|
||||
use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
|
||||
use std::ops::Range;
|
||||
|
||||
#[cfg(test)]
|
||||
@ -43,7 +43,7 @@ impl<N: Idx, S: Idx + Ord> Sccs<N, S> {
|
||||
SccsConstruction::construct(graph)
|
||||
}
|
||||
|
||||
pub fn scc_indices(&self) -> &IndexVec<N, S> {
|
||||
pub fn scc_indices(&self) -> &IndexSlice<N, S> {
|
||||
&self.scc_indices
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ impl<S: Idx> SccData<S> {
|
||||
self.ranges.len()
|
||||
}
|
||||
|
||||
pub fn ranges(&self) -> &IndexVec<S, Range<usize>> {
|
||||
pub fn ranges(&self) -> &IndexSlice<S, Range<usize>> {
|
||||
&self.ranges
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#![feature(never_type)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(test)]
|
||||
|
@ -5,7 +5,7 @@ use std::collections::hash_map::RawEntryMut;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(parallel_compiler, repr(align(64)))]
|
||||
struct CacheAligned<T>(T);
|
||||
|
||||
@ -21,7 +21,6 @@ const SHARD_BITS: usize = 0;
|
||||
pub const SHARDS: usize = 1 << SHARD_BITS;
|
||||
|
||||
/// An array of cache-line aligned inner locked structures with convenience methods.
|
||||
#[derive(Clone)]
|
||||
pub struct Sharded<T> {
|
||||
shards: [CacheAligned<Lock<T>>; SHARDS],
|
||||
}
|
||||
|
@ -1,21 +1,46 @@
|
||||
//! This module defines types which are thread safe if cfg!(parallel_compiler) is true.
|
||||
//! This module defines various operations and types that are implemented in
|
||||
//! one way for the serial compiler, and another way the parallel compiler.
|
||||
//!
|
||||
//! `Lrc` is an alias of `Arc` if cfg!(parallel_compiler) is true, `Rc` otherwise.
|
||||
//! Operations
|
||||
//! ----------
|
||||
//! The parallel versions of operations use Rayon to execute code in parallel,
|
||||
//! while the serial versions degenerate straightforwardly to serial execution.
|
||||
//! The operations include `join`, `parallel`, `par_iter`, and `par_for_each`.
|
||||
//!
|
||||
//! `Lock` is a mutex.
|
||||
//! It internally uses `parking_lot::Mutex` if cfg!(parallel_compiler) is true,
|
||||
//! `RefCell` otherwise.
|
||||
//! `rustc_erase_owner!` erases an `OwningRef` owner into `Erased` for the
|
||||
//! serial version and `Erased + Send + Sync` for the parallel version.
|
||||
//!
|
||||
//! `RwLock` is a read-write lock.
|
||||
//! It internally uses `parking_lot::RwLock` if cfg!(parallel_compiler) is true,
|
||||
//! `RefCell` otherwise.
|
||||
//! Types
|
||||
//! -----
|
||||
//! The parallel versions of types provide various kinds of synchronization,
|
||||
//! while the serial compiler versions do not.
|
||||
//!
|
||||
//! `MTLock` is a mutex which disappears if cfg!(parallel_compiler) is false.
|
||||
//! The following table shows how the types are implemented internally. Except
|
||||
//! where noted otherwise, the type in column one is defined as a
|
||||
//! newtype around the type from column two or three.
|
||||
//!
|
||||
//! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise.
|
||||
//! | Type | Serial version | Parallel version |
|
||||
//! | ----------------------- | ------------------- | ------------------------------- |
|
||||
//! | `Lrc<T>` | `rc::Rc<T>` | `sync::Arc<T>` |
|
||||
//! |` Weak<T>` | `rc::Weak<T>` | `sync::Weak<T>` |
|
||||
//! | | | |
|
||||
//! | `AtomicBool` | `Cell<bool>` | `atomic::AtomicBool` |
|
||||
//! | `AtomicU32` | `Cell<u32>` | `atomic::AtomicU32` |
|
||||
//! | `AtomicU64` | `Cell<u64>` | `atomic::AtomicU64` |
|
||||
//! | `AtomicUsize` | `Cell<usize>` | `atomic::AtomicUsize` |
|
||||
//! | | | |
|
||||
//! | `Lock<T>` | `RefCell<T>` | `parking_lot::Mutex<T>` |
|
||||
//! | `RwLock<T>` | `RefCell<T>` | `parking_lot::RwLock<T>` |
|
||||
//! | `MTLock<T>` [^1] | `T` | `Lock<T>` |
|
||||
//! | `MTLockRef<'a, T>` [^2] | `&'a mut MTLock<T>` | `&'a MTLock<T>` |
|
||||
//! | | | |
|
||||
//! | `ParallelIterator` | `Iterator` | `rayon::iter::ParallelIterator` |
|
||||
//!
|
||||
//! `rustc_erase_owner!` erases an OwningRef owner into Erased or Erased + Send + Sync
|
||||
//! depending on the value of cfg!(parallel_compiler).
|
||||
//! [^1] `MTLock` is similar to `Lock`, but the serial version avoids the cost
|
||||
//! of a `RefCell`. This is appropriate when interior mutability is not
|
||||
//! required.
|
||||
//!
|
||||
//! [^2] `MTLockRef` is a typedef.
|
||||
|
||||
use crate::owning_ref::{Erased, OwningRef};
|
||||
use std::collections::HashMap;
|
||||
@ -209,7 +234,7 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
pub type MTRef<'a, T> = &'a mut T;
|
||||
pub type MTLockRef<'a, T> = &'a mut MTLock<T>;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MTLock<T>(T);
|
||||
@ -267,7 +292,7 @@ cfg_if! {
|
||||
pub use std::sync::Arc as Lrc;
|
||||
pub use std::sync::Weak as Weak;
|
||||
|
||||
pub type MTRef<'a, T> = &'a T;
|
||||
pub type MTLockRef<'a, T> = &'a MTLock<T>;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MTLock<T>(Lock<T>);
|
||||
@ -553,18 +578,6 @@ impl<T> RwLock<T> {
|
||||
self.write()
|
||||
}
|
||||
|
||||
#[cfg(not(parallel_compiler))]
|
||||
#[inline(always)]
|
||||
pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> {
|
||||
ReadGuard::clone(rg)
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
#[inline(always)]
|
||||
pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> {
|
||||
ReadGuard::rwlock(&rg).read()
|
||||
}
|
||||
|
||||
#[cfg(not(parallel_compiler))]
|
||||
#[inline(always)]
|
||||
pub fn leak(&self) -> &T {
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(is_terminal)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(decl_macro)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
@ -16,7 +16,8 @@ or causing an integer overflow are two ways to induce this error.
|
||||
Ensure that the expressions given can be evaluated as the desired integer type.
|
||||
|
||||
See the [Discriminants] section of the Reference for more information about
|
||||
setting custom integer types on enums using the [`repr` attribute][repr-attribute].
|
||||
setting custom integer types on enums using the
|
||||
[`repr` attribute][repr-attribute].
|
||||
|
||||
[discriminants]: https://doc.rust-lang.org/reference/items/enumerations.html#discriminants
|
||||
[repr-attribute]: https://doc.rust-lang.org/reference/type-layout.html#representations
|
||||
|
@ -3,31 +3,33 @@ An attempt was made to retrieve an associated type, but the type was ambiguous.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0223
|
||||
trait MyTrait {type X; }
|
||||
trait Trait { type X; }
|
||||
|
||||
fn main() {
|
||||
let foo: MyTrait::X;
|
||||
let foo: Trait::X;
|
||||
}
|
||||
```
|
||||
|
||||
The problem here is that we're attempting to take the type of X from MyTrait.
|
||||
Unfortunately, the type of X is not defined, because it's only made concrete in
|
||||
implementations of the trait. A working version of this code might look like:
|
||||
The problem here is that we're attempting to take the associated type of `X`
|
||||
from `Trait`. Unfortunately, the type of `X` is not defined, because it's only
|
||||
made concrete in implementations of the trait. A working version of this code
|
||||
might look like:
|
||||
|
||||
```
|
||||
trait MyTrait {type X; }
|
||||
struct MyStruct;
|
||||
trait Trait { type X; }
|
||||
|
||||
impl MyTrait for MyStruct {
|
||||
struct Struct;
|
||||
impl Trait for Struct {
|
||||
type X = u32;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo: <MyStruct as MyTrait>::X;
|
||||
let foo: <Struct as Trait>::X;
|
||||
}
|
||||
```
|
||||
|
||||
This syntax specifies that we want the X type from MyTrait, as made concrete in
|
||||
MyStruct. The reason that we cannot simply use `MyStruct::X` is that MyStruct
|
||||
might implement two different traits with identically-named associated types.
|
||||
This syntax allows disambiguation between the two.
|
||||
This syntax specifies that we want the associated type `X` from `Struct`'s
|
||||
implementation of `Trait`.
|
||||
|
||||
Due to internal limitations of the current compiler implementation we cannot
|
||||
simply use `Struct::X`.
|
||||
|
@ -59,6 +59,6 @@ In the definition of `bar`, the lifetime parameter `'a` is late-bound, while
|
||||
where `'a` is universally quantified and `'b` is substituted by a specific
|
||||
lifetime. It is not allowed to explicitly specify early-bound lifetime
|
||||
arguments when late-bound lifetime parameters are present (as for `bar_fn2`,
|
||||
see [issue #42868](https://github.com/rust-lang/rust/issues/42868)), although the
|
||||
types that are constrained by early-bound parameters can be specified (as for
|
||||
`bar_fn3`).
|
||||
see [issue #42868](https://github.com/rust-lang/rust/issues/42868)), although
|
||||
the types that are constrained by early-bound parameters can be specified (as
|
||||
for `bar_fn3`).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#![feature(let_chains)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
|
@ -202,7 +202,10 @@ impl AnnotateSnippetEmitterWriter {
|
||||
annotations: annotations
|
||||
.iter()
|
||||
.map(|annotation| SourceAnnotation {
|
||||
range: (annotation.start_col, annotation.end_col),
|
||||
range: (
|
||||
annotation.start_col.display,
|
||||
annotation.end_col.display,
|
||||
),
|
||||
label: annotation.label.as_deref().unwrap_or_default(),
|
||||
annotation_type: annotation_type_for_level(*level),
|
||||
})
|
||||
|
@ -12,7 +12,9 @@ use Destination::*;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{FileLines, SourceFile, Span};
|
||||
|
||||
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
|
||||
use crate::snippet::{
|
||||
Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
|
||||
};
|
||||
use crate::styled_buffer::StyledBuffer;
|
||||
use crate::translation::{to_fluent_args, Translate};
|
||||
use crate::{
|
||||
@ -858,7 +860,7 @@ impl EmitterWriter {
|
||||
let mut short_start = true;
|
||||
for ann in &line.annotations {
|
||||
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
|
||||
if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) {
|
||||
if source_string.chars().take(ann.start_col.display).all(|c| c.is_whitespace()) {
|
||||
let style = if ann.is_primary {
|
||||
Style::UnderlinePrimary
|
||||
} else {
|
||||
@ -1093,15 +1095,15 @@ impl EmitterWriter {
|
||||
'_',
|
||||
line_offset + pos,
|
||||
width_offset + depth,
|
||||
(code_offset + annotation.start_col).saturating_sub(left),
|
||||
(code_offset + annotation.start_col.display).saturating_sub(left),
|
||||
style,
|
||||
);
|
||||
}
|
||||
_ if self.teach => {
|
||||
buffer.set_style_range(
|
||||
line_offset,
|
||||
(code_offset + annotation.start_col).saturating_sub(left),
|
||||
(code_offset + annotation.end_col).saturating_sub(left),
|
||||
(code_offset + annotation.start_col.display).saturating_sub(left),
|
||||
(code_offset + annotation.end_col.display).saturating_sub(left),
|
||||
style,
|
||||
annotation.is_primary,
|
||||
);
|
||||
@ -1133,7 +1135,7 @@ impl EmitterWriter {
|
||||
for p in line_offset + 1..=line_offset + pos {
|
||||
buffer.putc(
|
||||
p,
|
||||
(code_offset + annotation.start_col).saturating_sub(left),
|
||||
(code_offset + annotation.start_col.display).saturating_sub(left),
|
||||
'|',
|
||||
style,
|
||||
);
|
||||
@ -1169,9 +1171,9 @@ impl EmitterWriter {
|
||||
let style =
|
||||
if annotation.is_primary { Style::LabelPrimary } else { Style::LabelSecondary };
|
||||
let (pos, col) = if pos == 0 {
|
||||
(pos + 1, (annotation.end_col + 1).saturating_sub(left))
|
||||
(pos + 1, (annotation.end_col.display + 1).saturating_sub(left))
|
||||
} else {
|
||||
(pos + 2, annotation.start_col.saturating_sub(left))
|
||||
(pos + 2, annotation.start_col.display.saturating_sub(left))
|
||||
};
|
||||
if let Some(ref label) = annotation.label {
|
||||
buffer.puts(line_offset + pos, code_offset + col, label, style);
|
||||
@ -1208,7 +1210,7 @@ impl EmitterWriter {
|
||||
} else {
|
||||
('-', Style::UnderlineSecondary)
|
||||
};
|
||||
for p in annotation.start_col..annotation.end_col {
|
||||
for p in annotation.start_col.display..annotation.end_col.display {
|
||||
buffer.putc(
|
||||
line_offset + 1,
|
||||
(code_offset + p).saturating_sub(left),
|
||||
@ -1459,7 +1461,7 @@ impl EmitterWriter {
|
||||
&annotated_file.file.name,
|
||||
line.line_index
|
||||
),
|
||||
annotations[0].start_col + 1,
|
||||
annotations[0].start_col.file + 1,
|
||||
),
|
||||
Style::LineAndColumn,
|
||||
);
|
||||
@ -1546,7 +1548,7 @@ impl EmitterWriter {
|
||||
buffer.prepend(buffer_msg_line_offset + 1, "::: ", Style::LineNumber);
|
||||
let loc = if let Some(first_line) = annotated_file.lines.first() {
|
||||
let col = if let Some(first_annotation) = first_line.annotations.first() {
|
||||
format!(":{}", first_annotation.start_col + 1)
|
||||
format!(":{}", first_annotation.start_col.file + 1)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
@ -1607,8 +1609,8 @@ impl EmitterWriter {
|
||||
let mut span_left_margin = usize::MAX;
|
||||
for line in &annotated_file.lines {
|
||||
for ann in &line.annotations {
|
||||
span_left_margin = min(span_left_margin, ann.start_col);
|
||||
span_left_margin = min(span_left_margin, ann.end_col);
|
||||
span_left_margin = min(span_left_margin, ann.start_col.display);
|
||||
span_left_margin = min(span_left_margin, ann.end_col.display);
|
||||
}
|
||||
}
|
||||
if span_left_margin == usize::MAX {
|
||||
@ -1625,11 +1627,12 @@ impl EmitterWriter {
|
||||
annotated_file.file.get_line(line.line_index - 1).map_or(0, |s| s.len()),
|
||||
);
|
||||
for ann in &line.annotations {
|
||||
span_right_margin = max(span_right_margin, ann.start_col);
|
||||
span_right_margin = max(span_right_margin, ann.end_col);
|
||||
span_right_margin = max(span_right_margin, ann.start_col.display);
|
||||
span_right_margin = max(span_right_margin, ann.end_col.display);
|
||||
// FIXME: account for labels not in the same line
|
||||
let label_right = ann.label.as_ref().map_or(0, |l| l.len() + 1);
|
||||
label_right_margin = max(label_right_margin, ann.end_col + label_right);
|
||||
label_right_margin =
|
||||
max(label_right_margin, ann.end_col.display + label_right);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2232,7 +2235,7 @@ impl EmitterWriter {
|
||||
}
|
||||
} else if is_multiline {
|
||||
buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
|
||||
match &highlight_parts[..] {
|
||||
match &highlight_parts {
|
||||
[SubstitutionHighlight { start: 0, end }] if *end == line_to_add.len() => {
|
||||
buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
|
||||
}
|
||||
@ -2352,8 +2355,8 @@ impl FileWithAnnotatedLines {
|
||||
depth: 1,
|
||||
line_start: lo.line,
|
||||
line_end: hi.line,
|
||||
start_col: lo.col_display,
|
||||
end_col: hi.col_display,
|
||||
start_col: AnnotationColumn::from_loc(&lo),
|
||||
end_col: AnnotationColumn::from_loc(&hi),
|
||||
is_primary,
|
||||
label,
|
||||
overlaps_exactly: false,
|
||||
@ -2361,8 +2364,8 @@ impl FileWithAnnotatedLines {
|
||||
multiline_annotations.push((lo.file, ml));
|
||||
} else {
|
||||
let ann = Annotation {
|
||||
start_col: lo.col_display,
|
||||
end_col: hi.col_display,
|
||||
start_col: AnnotationColumn::from_loc(&lo),
|
||||
end_col: AnnotationColumn::from_loc(&hi),
|
||||
is_primary,
|
||||
label,
|
||||
annotation_type: AnnotationType::Singleline,
|
||||
@ -2551,7 +2554,13 @@ fn num_overlap(
|
||||
(b_start..b_end + extra).contains(&a_start) || (a_start..a_end + extra).contains(&b_start)
|
||||
}
|
||||
fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
|
||||
num_overlap(a1.start_col, a1.end_col + padding, a2.start_col, a2.end_col, false)
|
||||
num_overlap(
|
||||
a1.start_col.display,
|
||||
a1.end_col.display + padding,
|
||||
a2.start_col.display,
|
||||
a2.end_col.display,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
fn emit_to_destination(
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code for annotating snippets.
|
||||
|
||||
use crate::Level;
|
||||
use crate::{Level, Loc};
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct Line {
|
||||
@ -8,13 +8,39 @@ pub struct Line {
|
||||
pub annotations: Vec<Annotation>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Default)]
|
||||
pub struct AnnotationColumn {
|
||||
/// the (0-indexed) column for *display* purposes, counted in characters, not utf-8 bytes
|
||||
pub display: usize,
|
||||
/// the (0-indexed) column in the file, counted in characters, not utf-8 bytes.
|
||||
///
|
||||
/// this may be different from `self.display`,
|
||||
/// e.g. if the file contains hard tabs, because we convert tabs to spaces for error messages.
|
||||
///
|
||||
/// for example:
|
||||
/// ```text
|
||||
/// (hard tab)hello
|
||||
/// ^ this is display column 4, but file column 1
|
||||
/// ```
|
||||
///
|
||||
/// we want to keep around the correct file offset so that column numbers in error messages
|
||||
/// are correct. (motivated by <https://github.com/rust-lang/rust/issues/109537>)
|
||||
pub file: usize,
|
||||
}
|
||||
|
||||
impl AnnotationColumn {
|
||||
pub fn from_loc(loc: &Loc) -> AnnotationColumn {
|
||||
AnnotationColumn { display: loc.col_display, file: loc.col.0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct MultilineAnnotation {
|
||||
pub depth: usize,
|
||||
pub line_start: usize,
|
||||
pub line_end: usize,
|
||||
pub start_col: usize,
|
||||
pub end_col: usize,
|
||||
pub start_col: AnnotationColumn,
|
||||
pub end_col: AnnotationColumn,
|
||||
pub is_primary: bool,
|
||||
pub label: Option<String>,
|
||||
pub overlaps_exactly: bool,
|
||||
@ -36,7 +62,12 @@ impl MultilineAnnotation {
|
||||
pub fn as_start(&self) -> Annotation {
|
||||
Annotation {
|
||||
start_col: self.start_col,
|
||||
end_col: self.start_col + 1,
|
||||
end_col: AnnotationColumn {
|
||||
// these might not correspond to the same place anymore,
|
||||
// but that's okay for our purposes
|
||||
display: self.start_col.display + 1,
|
||||
file: self.start_col.file + 1,
|
||||
},
|
||||
is_primary: self.is_primary,
|
||||
label: None,
|
||||
annotation_type: AnnotationType::MultilineStart(self.depth),
|
||||
@ -45,7 +76,12 @@ impl MultilineAnnotation {
|
||||
|
||||
pub fn as_end(&self) -> Annotation {
|
||||
Annotation {
|
||||
start_col: self.end_col.saturating_sub(1),
|
||||
start_col: AnnotationColumn {
|
||||
// these might not correspond to the same place anymore,
|
||||
// but that's okay for our purposes
|
||||
display: self.end_col.display.saturating_sub(1),
|
||||
file: self.end_col.file.saturating_sub(1),
|
||||
},
|
||||
end_col: self.end_col,
|
||||
is_primary: self.is_primary,
|
||||
label: self.label.clone(),
|
||||
@ -55,8 +91,8 @@ impl MultilineAnnotation {
|
||||
|
||||
pub fn as_line(&self) -> Annotation {
|
||||
Annotation {
|
||||
start_col: 0,
|
||||
end_col: 0,
|
||||
start_col: Default::default(),
|
||||
end_col: Default::default(),
|
||||
is_primary: self.is_primary,
|
||||
label: None,
|
||||
annotation_type: AnnotationType::MultilineLine(self.depth),
|
||||
@ -92,14 +128,14 @@ pub enum AnnotationType {
|
||||
|
||||
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct Annotation {
|
||||
/// Start column, 0-based indexing -- counting *characters*, not
|
||||
/// utf-8 bytes. Note that it is important that this field goes
|
||||
/// Start column.
|
||||
/// Note that it is important that this field goes
|
||||
/// first, so that when we sort, we sort orderings by start
|
||||
/// column.
|
||||
pub start_col: usize,
|
||||
pub start_col: AnnotationColumn,
|
||||
|
||||
/// End column within the line (exclusive)
|
||||
pub end_col: usize,
|
||||
pub end_col: AnnotationColumn,
|
||||
|
||||
/// Is this annotation derived from primary span
|
||||
pub is_primary: bool,
|
||||
@ -118,12 +154,13 @@ impl Annotation {
|
||||
matches!(self.annotation_type, AnnotationType::MultilineLine(_))
|
||||
}
|
||||
|
||||
/// Length of this annotation as displayed in the stderr output
|
||||
pub fn len(&self) -> usize {
|
||||
// Account for usize underflows
|
||||
if self.end_col > self.start_col {
|
||||
self.end_col - self.start_col
|
||||
if self.end_col.display > self.start_col.display {
|
||||
self.end_col.display - self.start_col.display
|
||||
} else {
|
||||
self.start_col - self.end_col
|
||||
self.start_col.display - self.end_col.display
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -793,7 +793,9 @@ impl SyntaxExtension {
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| (None, helper_attrs));
|
||||
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
|
||||
let stability = attr::find_stability(&sess, attrs, span);
|
||||
let const_stability = attr::find_const_stability(&sess, attrs, span);
|
||||
let body_stability = attr::find_body_stability(&sess, attrs);
|
||||
if let Some((_, sp)) = const_stability {
|
||||
sess.emit_err(errors::MacroConstStability {
|
||||
span: sp,
|
||||
|
@ -36,7 +36,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
);
|
||||
let args = if !args.is_empty() {
|
||||
let args = args.into_iter().map(ast::AngleBracketedArg::Arg).collect();
|
||||
ast::AngleBracketedArgs { args, span }.into()
|
||||
Some(ast::AngleBracketedArgs { args, span }.into())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -54,7 +54,7 @@ impl base::BangProcMacro for BangProcMacro {
|
||||
) -> Result<TokenStream, ErrorGuaranteed> {
|
||||
let _timer =
|
||||
ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
|
||||
recorder.record_arg_with_span(ecx.expansion_descr(), span);
|
||||
recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
|
||||
});
|
||||
|
||||
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
|
||||
@ -85,7 +85,7 @@ impl base::AttrProcMacro for AttrProcMacro {
|
||||
) -> Result<TokenStream, ErrorGuaranteed> {
|
||||
let _timer =
|
||||
ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
|
||||
recorder.record_arg_with_span(ecx.expansion_descr(), span);
|
||||
recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
|
||||
});
|
||||
|
||||
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
|
||||
@ -134,7 +134,11 @@ impl MultiItemModifier for DeriveProcMacro {
|
||||
let stream = {
|
||||
let _timer =
|
||||
ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
|
||||
recorder.record_arg_with_span(ecx.expansion_descr(), span);
|
||||
recorder.record_arg_with_span(
|
||||
ecx.sess.source_map(),
|
||||
ecx.expansion_descr(),
|
||||
span,
|
||||
);
|
||||
});
|
||||
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
|
||||
let strategy = exec_strategy(ecx);
|
||||
|
@ -225,7 +225,7 @@ declare_features! (
|
||||
(active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None),
|
||||
/// Allows using compiler's own crates.
|
||||
(active, rustc_private, "1.0.0", Some(27812), None),
|
||||
/// Allows using internal rustdoc features like `doc(primitive)` or `doc(keyword)`.
|
||||
/// Allows using internal rustdoc features like `doc(keyword)`.
|
||||
(active, rustdoc_internals, "1.58.0", Some(90418), None),
|
||||
/// Allows using the `rustdoc::missing_doc_code_examples` lint
|
||||
(active, rustdoc_missing_doc_code_examples, "1.31.0", Some(101730), None),
|
||||
@ -495,6 +495,8 @@ declare_features! (
|
||||
(active, repr_simd, "1.4.0", Some(27731), None),
|
||||
/// Allows return-position `impl Trait` in traits.
|
||||
(incomplete, return_position_impl_trait_in_trait, "1.65.0", Some(91611), None),
|
||||
/// Allows bounding the return type of AFIT/RPITIT.
|
||||
(incomplete, return_type_notation, "CURRENT_RUSTC_VERSION", Some(109417), None),
|
||||
/// Allows `extern "rust-cold"`.
|
||||
(active, rust_cold_cc, "1.63.0", Some(97544), None),
|
||||
/// Allows the use of SIMD types in functions declared in `extern` blocks.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user