Merge from rustc
This commit is contained in:
commit
6b19af8060
859 changed files with 11721 additions and 6201 deletions
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
|
|
@ -1,3 +1,4 @@
|
|||
<!-- homu-ignore:start -->
|
||||
<!--
|
||||
If this PR is related to an unstable feature or an otherwise tracked effort,
|
||||
please link to the relevant tracking issue here. If you don't know of a related
|
||||
|
|
@ -7,4 +8,5 @@ This PR will get automatically assigned to a reviewer. In case you would like
|
|||
a specific user to review your work, you can assign it to them by using
|
||||
|
||||
r? <reviewer name>
|
||||
-->
|
||||
-->
|
||||
<!-- homu-ignore:end -->
|
||||
|
|
|
|||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
|
@ -95,8 +95,6 @@ jobs:
|
|||
path-type: inherit
|
||||
install: >
|
||||
make
|
||||
dos2unix
|
||||
diffutils
|
||||
|
||||
- name: disable git crlf conversion
|
||||
run: git config --global core.autocrlf false
|
||||
|
|
|
|||
1
.mailmap
1
.mailmap
|
|
@ -379,6 +379,7 @@ Markus Westerlind <marwes91@gmail.com> Markus <marwes91@gmail.com>
|
|||
Martin Carton <cartonmartin+git@gmail.com>
|
||||
Martin Habovštiak <martin.habovstiak@gmail.com>
|
||||
Martin Hafskjold Thoresen <martinhath@gmail.com>
|
||||
Martin Nordholts <martin.nordholts@codetale.se> <enselic@gmail.com>
|
||||
Matej Lach <matej.lach@gmail.com> Matej Ľach <matej.lach@gmail.com>
|
||||
Mateusz Mikuła <mati865@gmail.com>
|
||||
Mateusz Mikuła <mati865@gmail.com> <mati865@users.noreply.github.com>
|
||||
|
|
|
|||
233
Cargo.lock
233
Cargo.lock
|
|
@ -87,7 +87,7 @@ version = "4.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459"
|
||||
dependencies = [
|
||||
"html5ever 0.27.0",
|
||||
"html5ever",
|
||||
"maplit",
|
||||
"once_cell",
|
||||
"tendril",
|
||||
|
|
@ -131,9 +131,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.11.3"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "086b0afab3b349e5691143adbfb26983821e3eec4ba4c51957104d372c2e1b7d"
|
||||
checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"unicode-width",
|
||||
|
|
@ -542,7 +542,7 @@ checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
|
|||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz-build",
|
||||
"phf 0.11.2",
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -552,8 +552,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
|
||||
dependencies = [
|
||||
"parse-zoneinfo",
|
||||
"phf 0.11.2",
|
||||
"phf_codegen 0.11.2",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -568,9 +568,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.6"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7"
|
||||
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -588,9 +588,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.6"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df"
|
||||
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -628,7 +628,7 @@ checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
|
|||
|
||||
[[package]]
|
||||
name = "clippy"
|
||||
version = "0.1.80"
|
||||
version = "0.1.81"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"clippy_config",
|
||||
|
|
@ -655,7 +655,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_config"
|
||||
version = "0.1.80"
|
||||
version = "0.1.81"
|
||||
dependencies = [
|
||||
"rustc-semver",
|
||||
"serde",
|
||||
|
|
@ -678,7 +678,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.80"
|
||||
version = "0.1.81"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"cargo_metadata 0.18.1",
|
||||
|
|
@ -688,7 +688,7 @@ dependencies = [
|
|||
"itertools 0.12.1",
|
||||
"quine-mc_cluskey",
|
||||
"regex",
|
||||
"regex-syntax 0.8.3",
|
||||
"regex-syntax 0.8.4",
|
||||
"rustc-semver",
|
||||
"semver",
|
||||
"serde",
|
||||
|
|
@ -703,7 +703,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.80"
|
||||
version = "0.1.81"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"clippy_config",
|
||||
|
|
@ -1023,7 +1023,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.80"
|
||||
version = "0.1.81"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"quote",
|
||||
|
|
@ -1083,13 +1083,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.17"
|
||||
version = "0.99.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||
checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1694,6 +1694,12 @@ name = "hermit-abi"
|
|||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
|
|
@ -1732,20 +1738,6 @@ dependencies = [
|
|||
"utf8-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html5ever"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
|
||||
dependencies = [
|
||||
"log",
|
||||
"mac",
|
||||
"markup5ever 0.11.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html5ever"
|
||||
version = "0.27.0"
|
||||
|
|
@ -1754,7 +1746,7 @@ checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4"
|
|||
dependencies = [
|
||||
"log",
|
||||
"mac",
|
||||
"markup5ever 0.12.1",
|
||||
"markup5ever",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
|
|
@ -1798,6 +1790,18 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_list"
|
||||
version = "1.5.0"
|
||||
|
|
@ -1851,6 +1855,51 @@ version = "1.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_normalizer_data",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"smallvec",
|
||||
"utf16_iter",
|
||||
"utf8_iter",
|
||||
"write16",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_locid_transform",
|
||||
"icu_properties_data",
|
||||
"icu_provider",
|
||||
"tinystr",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider"
|
||||
version = "1.5.0"
|
||||
|
|
@ -1900,12 +1949,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||
checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
"icu_normalizer",
|
||||
"icu_properties",
|
||||
"smallvec",
|
||||
"utf8_iter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2175,7 +2226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.5",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2225,7 +2276,7 @@ dependencies = [
|
|||
name = "linkchecker"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"html5ever 0.26.0",
|
||||
"html5ever",
|
||||
"regex",
|
||||
]
|
||||
|
||||
|
|
@ -2310,20 +2361,6 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
|
||||
dependencies = [
|
||||
"log",
|
||||
"phf 0.10.1",
|
||||
"phf_codegen 0.10.0",
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
"tendril",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.12.1"
|
||||
|
|
@ -2331,8 +2368,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45"
|
||||
dependencies = [
|
||||
"log",
|
||||
"phf 0.11.2",
|
||||
"phf_codegen 0.11.2",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
"tendril",
|
||||
|
|
@ -2387,9 +2424,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mdbook-i18n-helpers"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1f71f5961d6f3376e1ff3e5989c2e3ecccc3e8a00f3a3acde446847f84852e4"
|
||||
checksum = "8c8f972ab672d366c3dad77ea5aa7bae68db2d25fbeb889849f97469d7b658e4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
|
|
@ -2636,7 +2673,7 @@ version = "1.16.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.3.9",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
@ -2865,7 +2902,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.5.1",
|
||||
"redox_syscall 0.5.2",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
|
@ -2945,15 +2982,6 @@ dependencies = [
|
|||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
|
||||
dependencies = [
|
||||
"phf_shared 0.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.2"
|
||||
|
|
@ -2963,16 +2991,6 @@ dependencies = [
|
|||
"phf_shared 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
|
||||
dependencies = [
|
||||
"phf_generator 0.10.0",
|
||||
"phf_shared 0.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.11.2"
|
||||
|
|
@ -3344,9 +3362,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
]
|
||||
|
|
@ -3405,9 +3423,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-lite"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e"
|
||||
checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
|
|
@ -3423,9 +3441,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "remote-test-client"
|
||||
|
|
@ -3452,7 +3470,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "run_make_support"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"gimli 0.28.1",
|
||||
"object 0.34.0",
|
||||
|
|
@ -4205,7 +4223,6 @@ dependencies = [
|
|||
"rustc_middle",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_type_ir",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
]
|
||||
|
|
@ -5346,7 +5363,7 @@ dependencies = [
|
|||
"dlmalloc",
|
||||
"fortanix-sgx-abi",
|
||||
"hashbrown",
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.4.0",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object 0.36.0",
|
||||
|
|
@ -5479,7 +5496,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"onig",
|
||||
"plist",
|
||||
"regex-syntax 0.8.3",
|
||||
"regex-syntax 0.8.4",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
|
@ -5992,7 +6009,7 @@ version = "0.23.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29e5f4ffcbab82453958fbf59990e981b8e8a177dcd60c2bd8f9b52c3036a6e1"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.11.3",
|
||||
"annotate-snippets 0.11.4",
|
||||
"anyhow",
|
||||
"bstr",
|
||||
"cargo-platform",
|
||||
|
|
@ -6073,12 +6090,6 @@ dependencies = [
|
|||
"ucd-parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
|
|
@ -6180,9 +6191,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||
checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
|
|
@ -6195,12 +6206,24 @@ version = "0.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "utf16_iter"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
|
|
@ -6380,9 +6403,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-bindgen"
|
||||
version = "0.56.0"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28e3ea6330cf17fdcdce8bf08d0549ce93769dca9bedc6c39c36c8c0e17db46"
|
||||
checksum = "1ccb96113d6277ba543c0f77e1c5494af8094bf9daf9b85acdc3f1b620e7c7b4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"rayon",
|
||||
|
|
@ -6403,9 +6426,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-metadata"
|
||||
version = "0.56.0"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3993f7827fff10c454e3a24847075598c7c08108304b8b07943c2c73d78f3b34"
|
||||
checksum = "8308d076825b9d9e5abc64f8113e96d02b2aeeba869b20fdd65c7e70cda13dfc"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
|
|
@ -6564,6 +6587,12 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "write16"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.5.5"
|
||||
|
|
|
|||
|
|
@ -100,12 +100,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
move_site_vec.iter().map(|move_site| move_site.moi).collect();
|
||||
|
||||
if move_out_indices.is_empty() {
|
||||
let root_place = PlaceRef { projection: &[], ..used_place };
|
||||
let root_local = used_place.local;
|
||||
|
||||
if !self.uninitialized_error_reported.insert(root_place) {
|
||||
if !self.uninitialized_error_reported.insert(root_local) {
|
||||
debug!(
|
||||
"report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
|
||||
root_place
|
||||
root_local
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
@ -284,7 +284,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
&& let CallKind::FnCall { fn_trait_id, self_ty } = kind
|
||||
&& let ty::Param(_) = self_ty.kind()
|
||||
&& ty == self_ty
|
||||
&& Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait()
|
||||
&& self.infcx.tcx.is_lang_item(fn_trait_id, LangItem::FnOnce)
|
||||
{
|
||||
// this is a type parameter `T: FnOnce()`, don't suggest `T: FnOnce() + Clone`.
|
||||
true
|
||||
|
|
@ -708,9 +708,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
|
||||
&& pred.self_ty() == ty
|
||||
{
|
||||
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
|
||||
if tcx.is_lang_item(pred.def_id(), LangItem::Fn) {
|
||||
return Some(hir::Mutability::Not);
|
||||
} else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
|
||||
} else if tcx.is_lang_item(pred.def_id(), LangItem::FnMut) {
|
||||
return Some(hir::Mutability::Mut);
|
||||
}
|
||||
}
|
||||
|
|
@ -1832,7 +1832,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if let hir::ExprKind::MethodCall(..) = ex.kind
|
||||
&& let Some(method_def_id) =
|
||||
self.typeck_results.type_dependent_def_id(ex.hir_id)
|
||||
&& self.tcx.lang_items().clone_trait() == Some(self.tcx.parent(method_def_id))
|
||||
&& self.tcx.is_lang_item(self.tcx.parent(method_def_id), LangItem::Clone)
|
||||
{
|
||||
self.clones.push(ex);
|
||||
}
|
||||
|
|
@ -2888,7 +2888,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
..
|
||||
} = explanation
|
||||
{
|
||||
if let Some(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
if let Err(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
borrow,
|
||||
borrow_span,
|
||||
span,
|
||||
|
|
@ -3075,7 +3075,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
|
||||
explanation
|
||||
{
|
||||
if let Some(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
if let Err(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
borrow,
|
||||
proper_span,
|
||||
span,
|
||||
|
|
@ -3159,8 +3159,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let is_format_arguments_item = if let Some(expr_ty) = expr_ty
|
||||
&& let ty::Adt(adt, _) = expr_ty.kind()
|
||||
{
|
||||
self.infcx.tcx.lang_items().get(LangItem::FormatArguments)
|
||||
== Some(adt.did())
|
||||
self.infcx.tcx.is_lang_item(adt.did(), LangItem::FormatArguments)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
|
@ -3237,11 +3236,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
return_span: Span,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
opt_place_desc: Option<&String>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
let return_kind = match category {
|
||||
ConstraintCategory::Return(_) => "return",
|
||||
ConstraintCategory::Yield => "yield",
|
||||
_ => return None,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
|
||||
// FIXME use a better heuristic than Spans
|
||||
|
|
@ -3317,7 +3316,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
Some(err)
|
||||
Err(err)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ use crate::session_diagnostics::{
|
|||
};
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_errors::{DiagCtxt, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::CoroutineKind;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::BoundRegionConversionTime;
|
||||
use rustc_infer::traits::SelectionError;
|
||||
|
|
@ -116,7 +116,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
{
|
||||
if let ty::FnDef(id, _) = *const_.ty().kind() {
|
||||
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
|
||||
if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
|
||||
if self.infcx.tcx.is_lang_item(self.infcx.tcx.parent(id), LangItem::FnOnce) {
|
||||
let closure = match args.first() {
|
||||
Some(Spanned {
|
||||
node: Operand::Copy(place) | Operand::Move(place), ..
|
||||
|
|
@ -767,13 +767,12 @@ impl<'tcx> BorrowedContentSource<'tcx> {
|
|||
ty::FnDef(def_id, args) => {
|
||||
let trait_id = tcx.trait_of_item(def_id)?;
|
||||
|
||||
let lang_items = tcx.lang_items();
|
||||
if Some(trait_id) == lang_items.deref_trait()
|
||||
|| Some(trait_id) == lang_items.deref_mut_trait()
|
||||
if tcx.is_lang_item(trait_id, LangItem::Deref)
|
||||
|| tcx.is_lang_item(trait_id, LangItem::DerefMut)
|
||||
{
|
||||
Some(BorrowedContentSource::OverloadedDeref(args.type_at(0)))
|
||||
} else if Some(trait_id) == lang_items.index_trait()
|
||||
|| Some(trait_id) == lang_items.index_mut_trait()
|
||||
} else if tcx.is_lang_item(trait_id, LangItem::Index)
|
||||
|| tcx.is_lang_item(trait_id, LangItem::IndexMut)
|
||||
{
|
||||
Some(BorrowedContentSource::OverloadedIndex(args.type_at(0)))
|
||||
} else {
|
||||
|
|
@ -1041,7 +1040,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
.unwrap_or_else(|| "value".to_owned());
|
||||
match kind {
|
||||
CallKind::FnCall { fn_trait_id, self_ty }
|
||||
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
|
||||
if self.infcx.tcx.is_lang_item(fn_trait_id, LangItem::FnOnce) =>
|
||||
{
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
|
|
@ -1268,7 +1267,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let ty = moved_place.ty(self.body, tcx).ty;
|
||||
|
||||
if let ty::Adt(def, args) = ty.peel_refs().kind()
|
||||
&& Some(def.did()) == tcx.lang_items().pin_type()
|
||||
&& tcx.is_lang_item(def.did(), LangItem::Pin)
|
||||
&& let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind()
|
||||
&& let self_ty = self.infcx.instantiate_binder_with_fresh_vars(
|
||||
fn_call_span,
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
|
|||
fn_self_span_reported: FxIndexSet<Span>,
|
||||
/// This field keeps track of errors reported in the checking of uninitialized variables,
|
||||
/// so that we don't report seemingly duplicate errors.
|
||||
uninitialized_error_reported: FxIndexSet<PlaceRef<'tcx>>,
|
||||
uninitialized_error_reported: FxIndexSet<Local>,
|
||||
/// This field keeps track of all the local variables that are declared mut and are mutated.
|
||||
/// Used for the warning issued by an unused mutable local variable.
|
||||
used_mut: FxIndexSet<Local>,
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
|
||||
fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
|
||||
let const_ = constant.const_;
|
||||
constant.const_ = self.renumber_regions(const_, || RegionCtxt::Location(location));
|
||||
debug!("constant: {:#?}", constant);
|
||||
|
|
|
|||
|
|
@ -301,10 +301,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
self.sanitize_place(place, location, context);
|
||||
}
|
||||
|
||||
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
|
||||
debug!(?constant, ?location, "visit_constant");
|
||||
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
|
||||
debug!(?constant, ?location, "visit_const_operand");
|
||||
|
||||
self.super_constant(constant, location);
|
||||
self.super_const_operand(constant, location);
|
||||
let ty = self.sanitize_type(constant, constant.const_.ty());
|
||||
|
||||
self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
|
||||
|
|
@ -328,7 +328,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
if let Some(annotation_index) = constant.user_ty {
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
constant.const_.ty(),
|
||||
ty::Variance::Invariant,
|
||||
ty::Invariant,
|
||||
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
||||
locations,
|
||||
ConstraintCategory::Boring,
|
||||
|
|
@ -451,7 +451,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
ty,
|
||||
ty::Variance::Invariant,
|
||||
ty::Invariant,
|
||||
user_ty,
|
||||
Locations::All(*span),
|
||||
ConstraintCategory::TypeAnnotation,
|
||||
|
|
@ -1095,7 +1095,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
) -> Result<(), NoSolution> {
|
||||
// Use this order of parameters because the sup type is usually the
|
||||
// "expected" type in diagnostics.
|
||||
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
|
||||
self.relate_types(sup, ty::Contravariant, sub, locations, category)
|
||||
}
|
||||
|
||||
#[instrument(skip(self, category), level = "debug")]
|
||||
|
|
@ -1106,7 +1106,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
locations: Locations,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
) -> Result<(), NoSolution> {
|
||||
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
|
||||
self.relate_types(expected, ty::Invariant, found, locations, category)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
|
|
@ -1146,7 +1146,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
trace!(?curr_projected_ty);
|
||||
|
||||
let ty = curr_projected_ty.ty;
|
||||
self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?;
|
||||
self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1248,7 +1248,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
if let Some(annotation_index) = self.rvalue_user_ty(rv) {
|
||||
if let Err(terr) = self.relate_type_and_user_type(
|
||||
rv_ty,
|
||||
ty::Variance::Invariant,
|
||||
ty::Invariant,
|
||||
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
|
|
|
|||
|
|
@ -50,14 +50,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
locations: Locations,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
) -> Result<(), NoSolution> {
|
||||
NllTypeRelating::new(
|
||||
self,
|
||||
locations,
|
||||
category,
|
||||
UniverseInfo::other(),
|
||||
ty::Variance::Invariant,
|
||||
)
|
||||
.relate(a, b)?;
|
||||
NllTypeRelating::new(self, locations, category, UniverseInfo::other(), ty::Invariant)
|
||||
.relate(a, b)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -106,15 +100,15 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
|
|||
|
||||
fn ambient_covariance(&self) -> bool {
|
||||
match self.ambient_variance {
|
||||
ty::Variance::Covariant | ty::Variance::Invariant => true,
|
||||
ty::Variance::Contravariant | ty::Variance::Bivariant => false,
|
||||
ty::Covariant | ty::Invariant => true,
|
||||
ty::Contravariant | ty::Bivariant => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn ambient_contravariance(&self) -> bool {
|
||||
match self.ambient_variance {
|
||||
ty::Variance::Contravariant | ty::Variance::Invariant => true,
|
||||
ty::Variance::Covariant | ty::Variance::Bivariant => false,
|
||||
ty::Contravariant | ty::Invariant => true,
|
||||
ty::Covariant | ty::Bivariant => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -336,11 +330,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
|
|||
|
||||
debug!(?self.ambient_variance);
|
||||
// In a bivariant context this always succeeds.
|
||||
let r = if self.ambient_variance == ty::Variance::Bivariant {
|
||||
Ok(a)
|
||||
} else {
|
||||
self.relate(a, b)
|
||||
};
|
||||
let r = if self.ambient_variance == ty::Bivariant { Ok(a) } else { self.relate(a, b) };
|
||||
|
||||
self.ambient_variance = old_ambient_variance;
|
||||
|
||||
|
|
@ -474,7 +464,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
|
|||
}
|
||||
|
||||
match self.ambient_variance {
|
||||
ty::Variance::Covariant => {
|
||||
ty::Covariant => {
|
||||
// Covariance, so we want `for<..> A <: for<..> B` --
|
||||
// therefore we compare any instantiation of A (i.e., A
|
||||
// instantiated with existentials) against every
|
||||
|
|
@ -489,7 +479,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
|
|||
})?;
|
||||
}
|
||||
|
||||
ty::Variance::Contravariant => {
|
||||
ty::Contravariant => {
|
||||
// Contravariance, so we want `for<..> A :> for<..> B` --
|
||||
// therefore we compare every instantiation of A (i.e., A
|
||||
// instantiated with universals) against any
|
||||
|
|
@ -504,7 +494,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
|
|||
})?;
|
||||
}
|
||||
|
||||
ty::Variance::Invariant => {
|
||||
ty::Invariant => {
|
||||
// Invariant, so we want `for<..> A == for<..> B` --
|
||||
// therefore we want `exists<..> A == for<..> B` and
|
||||
// `exists<..> B == for<..> A`.
|
||||
|
|
@ -525,7 +515,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
|
|||
})?;
|
||||
}
|
||||
|
||||
ty::Variance::Bivariant => {}
|
||||
ty::Bivariant => {}
|
||||
}
|
||||
|
||||
Ok(a)
|
||||
|
|
@ -584,23 +574,23 @@ impl<'bccx, 'tcx> PredicateEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx,
|
|||
|
||||
fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
|
||||
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
|
||||
ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
|
||||
ty::Covariant => ty::PredicateKind::AliasRelate(
|
||||
a.into(),
|
||||
b.into(),
|
||||
ty::AliasRelationDirection::Subtype,
|
||||
),
|
||||
// a :> b is b <: a
|
||||
ty::Variance::Contravariant => ty::PredicateKind::AliasRelate(
|
||||
ty::Contravariant => ty::PredicateKind::AliasRelate(
|
||||
b.into(),
|
||||
a.into(),
|
||||
ty::AliasRelationDirection::Subtype,
|
||||
),
|
||||
ty::Variance::Invariant => ty::PredicateKind::AliasRelate(
|
||||
ty::Invariant => ty::PredicateKind::AliasRelate(
|
||||
a.into(),
|
||||
b.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
ty::Variance::Bivariant => {
|
||||
ty::Bivariant => {
|
||||
unreachable!("cannot defer an alias-relate goal with Bivariant variance (yet?)")
|
||||
}
|
||||
})]);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::fmt::Write;
|
|||
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::asm::*;
|
||||
use target_lexicon::BinaryFormat;
|
||||
|
|
@ -927,7 +928,7 @@ fn call_inline_asm<'tcx>(
|
|||
fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option<types::Type> {
|
||||
match ty.kind() {
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/f3c66088610c1b80110297c2d9a8b5f9265b013f/compiler/rustc_hir_analysis/src/check/intrinsicck.rs#L136-L151
|
||||
ty::Adt(adt, args) if Some(adt.did()) == fx.tcx.lang_items().maybe_uninit() => {
|
||||
ty::Adt(adt, args) if fx.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
|
||||
let fields = &adt.non_enum_variant().fields;
|
||||
let ty = fields[FieldIdx::from_u32(1)].ty(fx.tcx, args);
|
||||
let ty::Adt(ty, args) = ty.kind() else {
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@ pub(crate) fn unsized_info<'tcx>(
|
|||
}
|
||||
|
||||
// trait upcasting coercion
|
||||
let vptr_entry_idx =
|
||||
fx.tcx.vtable_trait_upcasting_coercion_new_vptr_slot((source, target));
|
||||
let vptr_entry_idx = fx.tcx.supertrait_vtable_slot((source, target));
|
||||
|
||||
if let Some(entry_idx) = vptr_entry_idx {
|
||||
let entry_idx = u32::try_from(entry_idx).unwrap();
|
||||
|
|
|
|||
|
|
@ -959,6 +959,43 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
|||
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
|
||||
Abi::Vector { .. },
|
||||
) if layout.size.bytes() == 64 => bx.bitcast(value, bx.cx.type_vector(bx.cx.type_f64(), 8)),
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) if bx.sess().asm_arch == Some(InlineAsmArch::X86)
|
||||
&& s.primitive() == Primitive::Float(Float::F128) =>
|
||||
{
|
||||
bx.bitcast(value, bx.type_vector(bx.type_i32(), 4))
|
||||
}
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) if s.primitive() == Primitive::Float(Float::F16) => {
|
||||
let value = bx.insert_element(
|
||||
bx.const_undef(bx.type_vector(bx.type_f16(), 8)),
|
||||
value,
|
||||
bx.const_usize(0),
|
||||
);
|
||||
bx.bitcast(value, bx.type_vector(bx.type_i16(), 8))
|
||||
}
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Vector { element, count: count @ (8 | 16) },
|
||||
) if element.primitive() == Primitive::Float(Float::F16) => {
|
||||
bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
|
||||
}
|
||||
(
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
|
||||
Abi::Scalar(s),
|
||||
|
|
@ -1036,6 +1073,39 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
|||
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
|
||||
Abi::Vector { .. },
|
||||
) if layout.size.bytes() == 64 => bx.bitcast(value, layout.llvm_type(bx.cx)),
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) if bx.sess().asm_arch == Some(InlineAsmArch::X86)
|
||||
&& s.primitive() == Primitive::Float(Float::F128) =>
|
||||
{
|
||||
bx.bitcast(value, bx.type_f128())
|
||||
}
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) if s.primitive() == Primitive::Float(Float::F16) => {
|
||||
let value = bx.bitcast(value, bx.type_vector(bx.type_f16(), 8));
|
||||
bx.extract_element(value, bx.const_usize(0))
|
||||
}
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Vector { element, count: count @ (8 | 16) },
|
||||
) if element.primitive() == Primitive::Float(Float::F16) => {
|
||||
bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
|
||||
}
|
||||
(
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
|
||||
Abi::Scalar(s),
|
||||
|
|
@ -1109,6 +1179,36 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
|||
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
|
||||
Abi::Vector { .. },
|
||||
) if layout.size.bytes() == 64 => cx.type_vector(cx.type_f64(), 8),
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) if cx.sess().asm_arch == Some(InlineAsmArch::X86)
|
||||
&& s.primitive() == Primitive::Float(Float::F128) =>
|
||||
{
|
||||
cx.type_vector(cx.type_i32(), 4)
|
||||
}
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) if s.primitive() == Primitive::Float(Float::F16) => cx.type_vector(cx.type_i16(), 8),
|
||||
(
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::xmm_reg
|
||||
| X86InlineAsmRegClass::ymm_reg
|
||||
| X86InlineAsmRegClass::zmm_reg,
|
||||
),
|
||||
Abi::Vector { element, count: count @ (8 | 16) },
|
||||
) if element.primitive() == Primitive::Float(Float::F16) => {
|
||||
cx.type_vector(cx.type_i16(), count)
|
||||
}
|
||||
(
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
|
||||
Abi::Scalar(s),
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ use rustc_middle::ty::{
|
|||
};
|
||||
use rustc_session::config::{self, DebugInfo, Lto};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::FileName;
|
||||
use rustc_span::{hygiene, FileName, DUMMY_SP};
|
||||
use rustc_span::{FileNameDisplayPreference, SourceFile};
|
||||
use rustc_symbol_mangling::typeid_for_trait_ref;
|
||||
use rustc_target::abi::{Align, Size};
|
||||
|
|
@ -1306,7 +1306,7 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo
|
|||
// We may want to remove the namespace scope if we're in an extern block (see
|
||||
// https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
|
||||
let var_scope = get_namespace_for_item(cx, def_id);
|
||||
let span = tcx.def_span(def_id);
|
||||
let span = hygiene::walk_chain_collapsed(tcx.def_span(def_id), DUMMY_SP);
|
||||
|
||||
let (file_metadata, line_number) = if !span.is_dummy() {
|
||||
let loc = cx.lookup_debug_loc(span.lo());
|
||||
|
|
|
|||
|
|
@ -394,10 +394,15 @@ fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &ll
|
|||
(*feature, desc)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Since we add this at the end ...
|
||||
rustc_target_features.extend_from_slice(&[(
|
||||
"crt-static",
|
||||
"Enables C Run-time Libraries to be statically linked",
|
||||
)]);
|
||||
// ... we need to sort the list again.
|
||||
rustc_target_features.sort();
|
||||
|
||||
llvm_target_features.retain(|(f, _d)| !known_llvm_target_features.contains(f));
|
||||
|
||||
let max_feature_len = llvm_target_features
|
||||
|
|
|
|||
|
|
@ -163,8 +163,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
// trait upcasting coercion
|
||||
|
||||
let vptr_entry_idx =
|
||||
cx.tcx().vtable_trait_upcasting_coercion_new_vptr_slot((source, target));
|
||||
let vptr_entry_idx = cx.tcx().supertrait_vtable_slot((source, target));
|
||||
|
||||
if let Some(entry_idx) = vptr_entry_idx {
|
||||
let ptr_size = bx.data_layout().pointer_size;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
|
||||
|
||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
|
|
@ -801,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
// const-eval.
|
||||
|
||||
// const-eval of the `begin_panic` fn assumes the argument is `&str`
|
||||
if Some(callee) == tcx.lang_items().begin_panic_fn() {
|
||||
if tcx.is_lang_item(callee, LangItem::BeginPanic) {
|
||||
match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
|
||||
ty::Ref(_, ty, _) if ty.is_str() => return,
|
||||
_ => self.check_op(ops::PanicNonStr),
|
||||
|
|
@ -819,7 +819,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if Some(callee) == tcx.lang_items().exchange_malloc_fn() {
|
||||
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
|
||||
self.check_op(ops::HeapAllocation);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
|||
} else {
|
||||
let mut sugg = None;
|
||||
|
||||
if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
|
||||
if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
|
||||
match (args[0].unpack(), args[1].unpack()) {
|
||||
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
|
||||
if self_ty == rhs_ty
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::mem;
|
||||
|
||||
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg};
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
|
||||
use rustc_middle::mir::AssertKind;
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
|
|
@ -9,7 +8,7 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_middle::ty::{layout::LayoutError, ConstInt};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
use super::CompileTimeInterpreter;
|
||||
use super::CompileTimeMachine;
|
||||
use crate::errors::{self, FrameNote, ReportErrorExt};
|
||||
use crate::interpret::{err_inval, err_machine_stop};
|
||||
use crate::interpret::{ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType};
|
||||
|
|
@ -156,11 +155,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Emit a lint from a const-eval situation.
|
||||
/// Emit a lint from a const-eval situation, with a backtrace.
|
||||
// Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future!
|
||||
pub(super) fn lint<'tcx, L>(
|
||||
tcx: TyCtxtAt<'tcx>,
|
||||
machine: &CompileTimeInterpreter<'tcx>,
|
||||
machine: &CompileTimeMachine<'tcx>,
|
||||
lint: &'static rustc_session::lint::Lint,
|
||||
decorator: impl FnOnce(Vec<errors::FrameNote>) -> L,
|
||||
) where
|
||||
|
|
@ -168,12 +167,5 @@ pub(super) fn lint<'tcx, L>(
|
|||
{
|
||||
let (span, frames) = get_span_and_frames(tcx, &machine.stack);
|
||||
|
||||
tcx.emit_node_span_lint(
|
||||
lint,
|
||||
// We use the root frame for this so the crate that defines the const defines whether the
|
||||
// lint is emitted.
|
||||
machine.stack.first().and_then(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
|
||||
span,
|
||||
decorator(frames),
|
||||
);
|
||||
tcx.emit_node_span_lint(lint, machine.best_lint_scope(*tcx), span, decorator(frames));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use rustc_span::def_id::LocalDefId;
|
|||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::{self, Abi};
|
||||
|
||||
use super::{CanAccessMutGlobal, CompileTimeEvalContext, CompileTimeInterpreter};
|
||||
use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
|
||||
use crate::const_eval::CheckAlignment;
|
||||
use crate::errors::ConstEvalError;
|
||||
use crate::errors::{self, DanglingPtrInFinal};
|
||||
|
|
@ -32,7 +32,7 @@ use crate::CTRL_C_RECEIVED;
|
|||
// Returns a pointer to where the result lives
|
||||
#[instrument(level = "trace", skip(ecx, body))]
|
||||
fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
ecx: &mut CompileTimeInterpCx<'tcx>,
|
||||
cid: GlobalId<'tcx>,
|
||||
body: &'tcx mir::Body<'tcx>,
|
||||
) -> InterpResult<'tcx, R> {
|
||||
|
|
@ -114,7 +114,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
|
|||
let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind };
|
||||
ecx.tcx.emit_node_span_lint(
|
||||
lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
|
||||
ecx.best_lint_scope(),
|
||||
ecx.machine.best_lint_scope(*ecx.tcx),
|
||||
err_diag.span,
|
||||
err_diag,
|
||||
)
|
||||
|
|
@ -139,13 +139,13 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
|
|||
root_span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
can_access_mut_global: CanAccessMutGlobal,
|
||||
) -> CompileTimeEvalContext<'tcx> {
|
||||
) -> CompileTimeInterpCx<'tcx> {
|
||||
debug!("mk_eval_cx: {:?}", param_env);
|
||||
InterpCx::new(
|
||||
tcx,
|
||||
root_span,
|
||||
param_env,
|
||||
CompileTimeInterpreter::new(can_access_mut_global, CheckAlignment::No),
|
||||
CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ pub fn mk_eval_cx_for_const_val<'tcx>(
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
val: mir::ConstValue<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<(CompileTimeEvalContext<'tcx>, OpTy<'tcx>)> {
|
||||
) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
|
||||
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
|
||||
let op = ecx.const_val_to_op(val, ty, None).ok()?;
|
||||
Some((ecx, op))
|
||||
|
|
@ -170,7 +170,7 @@ pub fn mk_eval_cx_for_const_val<'tcx>(
|
|||
/// encounter an `Indirect` they cannot handle.
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
pub(super) fn op_to_const<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx>,
|
||||
ecx: &CompileTimeInterpCx<'tcx>,
|
||||
op: &OpTy<'tcx>,
|
||||
for_diagnostics: bool,
|
||||
) -> ConstValue<'tcx> {
|
||||
|
|
@ -328,14 +328,14 @@ pub trait InterpretationResult<'tcx> {
|
|||
/// evaluation query.
|
||||
fn make_result(
|
||||
mplace: MPlaceTy<'tcx>,
|
||||
ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
|
||||
fn make_result(
|
||||
mplace: MPlaceTy<'tcx>,
|
||||
_ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
_ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
|
||||
) -> Self {
|
||||
ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
|
||||
}
|
||||
|
|
@ -383,7 +383,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
|
|||
// they do not have to behave "as if" they were evaluated at runtime.
|
||||
// For consts however we want to ensure they behave "as if" they were evaluated at runtime,
|
||||
// so we have to reject reading mutable global memory.
|
||||
CompileTimeInterpreter::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
|
||||
CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
|
||||
);
|
||||
let res = ecx.load_mir(cid.instance.def, cid.promoted);
|
||||
res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)).map_err(|error| {
|
||||
|
|
@ -417,7 +417,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
|
|||
|
||||
#[inline(always)]
|
||||
fn const_validate_mplace<'tcx>(
|
||||
ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
|
||||
mplace: &MPlaceTy<'tcx>,
|
||||
cid: GlobalId<'tcx>,
|
||||
) -> Result<(), ErrorHandled> {
|
||||
|
|
@ -447,7 +447,7 @@ fn const_validate_mplace<'tcx>(
|
|||
|
||||
#[inline(always)]
|
||||
fn report_validation_error<'tcx>(
|
||||
ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
|
||||
error: InterpErrorInfo<'tcx>,
|
||||
alloc_id: AllocId,
|
||||
) -> ErrorHandled {
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@ use rustc_data_structures::fx::IndexEntry;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::{self as hir, CRATE_HIR_ID};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::AssertMessage;
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::lint::builtin::WRITES_THROUGH_IMMUTABLE_POINTER;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -44,7 +45,7 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20;
|
|||
const PROGRESS_INDICATOR_START: usize = 4_000_000;
|
||||
|
||||
/// Extra machine state for CTFE, and the Machine instance
|
||||
pub struct CompileTimeInterpreter<'tcx> {
|
||||
pub struct CompileTimeMachine<'tcx> {
|
||||
/// The number of terminators that have been evaluated.
|
||||
///
|
||||
/// This is used to produce lints informing the user that the compiler is not stuck.
|
||||
|
|
@ -89,12 +90,12 @@ impl From<bool> for CanAccessMutGlobal {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> CompileTimeInterpreter<'tcx> {
|
||||
impl<'tcx> CompileTimeMachine<'tcx> {
|
||||
pub(crate) fn new(
|
||||
can_access_mut_global: CanAccessMutGlobal,
|
||||
check_alignment: CheckAlignment,
|
||||
) -> Self {
|
||||
CompileTimeInterpreter {
|
||||
CompileTimeMachine {
|
||||
num_evaluated_steps: 0,
|
||||
stack: Vec::new(),
|
||||
can_access_mut_global,
|
||||
|
|
@ -163,7 +164,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) type CompileTimeEvalContext<'tcx> = InterpCx<'tcx, CompileTimeInterpreter<'tcx>>;
|
||||
pub(crate) type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum MemoryKind {
|
||||
|
|
@ -195,7 +196,7 @@ impl interpret::MayLeak for ! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> CompileTimeEvalContext<'tcx> {
|
||||
impl<'tcx> CompileTimeInterpCx<'tcx> {
|
||||
fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
|
||||
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
|
||||
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
|
||||
|
|
@ -229,7 +230,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
|
|||
let def_id = instance.def_id();
|
||||
|
||||
if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
|
||||
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
|
||||
|| self.tcx.is_lang_item(def_id, LangItem::BeginPanic)
|
||||
{
|
||||
let args = self.copy_fn_args(args);
|
||||
// &str or &&str
|
||||
|
|
@ -244,7 +245,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
|
|||
let span = self.find_closest_untracked_caller_location();
|
||||
let (file, line, col) = self.location_triple_for_span(span);
|
||||
return Err(ConstEvalErrKind::Panic { msg, file, line, col }.into());
|
||||
} else if Some(def_id) == self.tcx.lang_items().panic_fmt() {
|
||||
} else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) {
|
||||
// For panic_fmt, call const_panic_fmt instead.
|
||||
let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
|
||||
let new_instance = ty::Instance::expect_resolve(
|
||||
|
|
@ -255,7 +256,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
|
|||
);
|
||||
|
||||
return Ok(Some(new_instance));
|
||||
} else if Some(def_id) == self.tcx.lang_items().align_offset_fn() {
|
||||
} else if self.tcx.is_lang_item(def_id, LangItem::AlignOffset) {
|
||||
let args = self.copy_fn_args(args);
|
||||
// For align_offset, we replace the function call if the pointer has no address.
|
||||
match self.align_offset(instance, &args, dest, ret)? {
|
||||
|
|
@ -369,7 +370,16 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
|
||||
impl<'tcx> CompileTimeMachine<'tcx> {
|
||||
#[inline(always)]
|
||||
/// Find the first stack frame that is within the current crate, if any.
|
||||
/// Otherwise, return the crate's HirId
|
||||
pub fn best_lint_scope(&self, tcx: TyCtxt<'tcx>) -> hir::HirId {
|
||||
self.stack.iter().find_map(|frame| frame.lint_root(tcx)).unwrap_or(CRATE_HIR_ID)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
|
||||
compile_time_machine!(<'tcx>);
|
||||
|
||||
type MemoryKind = MemoryKind;
|
||||
|
|
@ -600,7 +610,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
|
|||
// By default, we stop after a million steps, but the user can disable this lint
|
||||
// to be able to run until the heat death of the universe or power loss, whichever
|
||||
// comes first.
|
||||
let hir_id = ecx.best_lint_scope();
|
||||
let hir_id = ecx.machine.best_lint_scope(*ecx.tcx);
|
||||
let is_error = ecx
|
||||
.tcx
|
||||
.lint_level_at_node(
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_target::abi::{Abi, VariantIdx};
|
|||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const};
|
||||
use super::machine::CompileTimeEvalContext;
|
||||
use super::machine::CompileTimeInterpCx;
|
||||
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
|
||||
use crate::const_eval::CanAccessMutGlobal;
|
||||
use crate::errors::MaxNumNodesInConstErr;
|
||||
|
|
@ -21,7 +21,7 @@ use crate::interpret::{
|
|||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn branches<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx>,
|
||||
ecx: &CompileTimeInterpCx<'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
n: usize,
|
||||
variant: Option<VariantIdx>,
|
||||
|
|
@ -59,7 +59,7 @@ fn branches<'tcx>(
|
|||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn slice_branches<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx>,
|
||||
ecx: &CompileTimeInterpCx<'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
num_nodes: &mut usize,
|
||||
) -> ValTreeCreationResult<'tcx> {
|
||||
|
|
@ -77,7 +77,7 @@ fn slice_branches<'tcx>(
|
|||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn const_to_valtree_inner<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx>,
|
||||
ecx: &CompileTimeInterpCx<'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
num_nodes: &mut usize,
|
||||
) -> ValTreeCreationResult<'tcx> {
|
||||
|
|
@ -219,7 +219,7 @@ fn reconstruct_place_meta<'tcx>(
|
|||
|
||||
#[instrument(skip(ecx), level = "debug", ret)]
|
||||
fn create_valtree_place<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
ecx: &mut CompileTimeInterpCx<'tcx>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
valtree: ty::ValTree<'tcx>,
|
||||
) -> MPlaceTy<'tcx> {
|
||||
|
|
@ -364,7 +364,7 @@ pub fn valtree_to_const_value<'tcx>(
|
|||
|
||||
/// Put a valtree into memory and return a reference to that.
|
||||
fn valtree_to_ref<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
ecx: &mut CompileTimeInterpCx<'tcx>,
|
||||
valtree: ty::ValTree<'tcx>,
|
||||
pointee_ty: Ty<'tcx>,
|
||||
) -> Immediate {
|
||||
|
|
@ -380,7 +380,7 @@ fn valtree_to_ref<'tcx>(
|
|||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn valtree_into_mplace<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
ecx: &mut CompileTimeInterpCx<'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
valtree: ty::ValTree<'tcx>,
|
||||
) {
|
||||
|
|
@ -457,6 +457,6 @@ fn valtree_into_mplace<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx>, place: &MPlaceTy<'tcx>) {
|
||||
fn dump_place<'tcx>(ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>) {
|
||||
trace!("{:?}", ecx.dump_place(&PlaceTy::from(place.clone())));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -241,10 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
variant_index: VariantIdx,
|
||||
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
|
||||
match self.layout_of(ty)?.variants {
|
||||
abi::Variants::Single { index } => {
|
||||
assert_eq!(index, variant_index);
|
||||
Ok(None)
|
||||
}
|
||||
abi::Variants::Single { .. } => Ok(None),
|
||||
|
||||
abi::Variants::Multiple {
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ use std::{fmt, mem};
|
|||
use either::{Either, Left, Right};
|
||||
use tracing::{debug, info, info_span, instrument, trace};
|
||||
|
||||
use hir::CRATE_HIR_ID;
|
||||
use rustc_errors::DiagCtxt;
|
||||
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
|
||||
use rustc_index::IndexVec;
|
||||
|
|
@ -250,7 +249,7 @@ impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
|
|||
impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
|
||||
/// Get the current location within the Frame.
|
||||
///
|
||||
/// If this is `Left`, we are not currently executing any particular statement in
|
||||
/// If this is `Right`, we are not currently executing any particular statement in
|
||||
/// this frame (can happen e.g. during frame initialization, and during unwinding on
|
||||
/// frames without cleanup code).
|
||||
///
|
||||
|
|
@ -271,13 +270,18 @@ impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn lint_root(&self) -> Option<hir::HirId> {
|
||||
self.current_source_info().and_then(|source_info| {
|
||||
match &self.body.source_scopes[source_info.scope].local_data {
|
||||
pub fn lint_root(&self, tcx: TyCtxt<'tcx>) -> Option<hir::HirId> {
|
||||
// We first try to get a HirId via the current source scope,
|
||||
// and fall back to `body.source`.
|
||||
self.current_source_info()
|
||||
.and_then(|source_info| match &self.body.source_scopes[source_info.scope].local_data {
|
||||
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
|
||||
mir::ClearCrossCrate::Clear => None,
|
||||
}
|
||||
})
|
||||
})
|
||||
.or_else(|| {
|
||||
let def_id = self.body.source.def_id().as_local();
|
||||
def_id.map(|def_id| tcx.local_def_id_to_hir_id(def_id))
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the address of the buffer where the locals are stored. This is used by `Place` as a
|
||||
|
|
@ -500,6 +504,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the span of the currently executed statement/terminator.
|
||||
/// This is the span typically used for error reporting.
|
||||
#[inline(always)]
|
||||
pub fn cur_span(&self) -> Span {
|
||||
// This deliberately does *not* honor `requires_caller_location` since it is used for much
|
||||
|
|
@ -507,16 +513,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
self.stack().last().map_or(self.tcx.span, |f| f.current_span())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
/// Find the first stack frame that is within the current crate, if any, otherwise return the crate's HirId
|
||||
pub fn best_lint_scope(&self) -> hir::HirId {
|
||||
self.stack()
|
||||
.iter()
|
||||
.find_map(|frame| frame.body.source.def_id().as_local())
|
||||
.map_or(CRATE_HIR_ID, |def_id| self.tcx.local_def_id_to_hir_id(def_id))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn stack(&self) -> &[Frame<'tcx, M::Provenance, M::FrameExtra>] {
|
||||
M::stack(self)
|
||||
}
|
||||
|
|
@ -632,7 +628,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
|
||||
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
|
||||
/// frame which is not `#[track_caller]`. This is the fancy version of `cur_span`.
|
||||
/// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
|
||||
/// and is primarily intended for the panic machinery.
|
||||
pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
|
||||
for frame in self.stack().iter().rev() {
|
||||
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
|
||||
|
|
@ -1057,7 +1054,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
|
||||
|
||||
ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)),
|
||||
ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)),
|
||||
|
||||
ty::Pat(ty, ..) => is_very_trivially_sized(*ty),
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ pub trait HasStaticRootDefId {
|
|||
fn static_def_id(&self) -> Option<LocalDefId>;
|
||||
}
|
||||
|
||||
impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_> {
|
||||
impl HasStaticRootDefId for const_eval::CompileTimeMachine<'_> {
|
||||
fn static_def_id(&self) -> Option<LocalDefId> {
|
||||
Some(self.static_root_ids?.1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
|
||||
// Test bounds.
|
||||
// It is sufficient to check this for the end pointer. Also check for overflow!
|
||||
if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) {
|
||||
if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) {
|
||||
throw_ub!(PointerOutOfBounds {
|
||||
alloc_id,
|
||||
alloc_size,
|
||||
|
|
|
|||
|
|
@ -112,25 +112,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
|
||||
// Shift ops can have an RHS with a different numeric type.
|
||||
if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) {
|
||||
let size = left.layout.size.bits();
|
||||
let l_bits = left.layout.size.bits();
|
||||
// Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is
|
||||
// the one MIR operator that does *not* directly map to a single LLVM operation.)
|
||||
let (shift_amount, overflow) = if right.layout.abi.is_signed() {
|
||||
let shift_amount = r_signed();
|
||||
let overflow = shift_amount < 0 || shift_amount >= i128::from(size);
|
||||
// Deliberately wrapping `as` casts: shift_amount *can* be negative, but the result
|
||||
// of the `as` will be equal modulo `size` (since it is a power of two).
|
||||
let masked_amount = (shift_amount as u128) % u128::from(size);
|
||||
assert_eq!(overflow, shift_amount != i128::try_from(masked_amount).unwrap());
|
||||
(masked_amount, overflow)
|
||||
let rem = shift_amount.rem_euclid(l_bits.into());
|
||||
// `rem` is guaranteed positive, so the `unwrap` cannot fail
|
||||
(u128::try_from(rem).unwrap(), rem != shift_amount)
|
||||
} else {
|
||||
let shift_amount = r_unsigned();
|
||||
let overflow = shift_amount >= u128::from(size);
|
||||
let masked_amount = shift_amount % u128::from(size);
|
||||
assert_eq!(overflow, shift_amount != masked_amount);
|
||||
(masked_amount, overflow)
|
||||
let rem = shift_amount.rem_euclid(l_bits.into());
|
||||
(rem, rem != shift_amount)
|
||||
};
|
||||
let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit
|
||||
let shift_amount = u32::try_from(shift_amount).unwrap(); // we brought this in the range `0..size` so this will always fit
|
||||
// Compute the shifted result.
|
||||
let result = if left.layout.abi.is_signed() {
|
||||
let l = l_signed();
|
||||
|
|
@ -362,14 +357,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
let left = left.to_scalar();
|
||||
let right = right.to_scalar();
|
||||
Ok(match fty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F16 => {
|
||||
self.binary_float_op(bin_op, layout, left.to_f16()?, right.to_f16()?)
|
||||
}
|
||||
FloatTy::F32 => {
|
||||
self.binary_float_op(bin_op, layout, left.to_f32()?, right.to_f32()?)
|
||||
}
|
||||
FloatTy::F64 => {
|
||||
self.binary_float_op(bin_op, layout, left.to_f64()?, right.to_f64()?)
|
||||
}
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
FloatTy::F128 => {
|
||||
self.binary_float_op(bin_op, layout, left.to_f128()?, right.to_f128()?)
|
||||
}
|
||||
})
|
||||
}
|
||||
_ if left.layout.ty.is_integral() => {
|
||||
|
|
@ -429,11 +428,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
ty::Float(fty) => {
|
||||
let val = val.to_scalar();
|
||||
if un_op != Neg {
|
||||
span_bug!(self.cur_span(), "Invalid float op {:?}", un_op);
|
||||
}
|
||||
|
||||
// No NaN adjustment here, `-` is a bitwise operation!
|
||||
let res = match (un_op, fty) {
|
||||
(Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?),
|
||||
(Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?),
|
||||
_ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op),
|
||||
let res = match fty {
|
||||
FloatTy::F16 => Scalar::from_f16(-val.to_f16()?),
|
||||
FloatTy::F32 => Scalar::from_f32(-val.to_f32()?),
|
||||
FloatTy::F64 => Scalar::from_f64(-val.to_f64()?),
|
||||
FloatTy::F128 => Scalar::from_f128(-val.to_f128()?),
|
||||
};
|
||||
Ok(ImmTy::from_scalar(res, layout))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ where
|
|||
) -> InterpResult<'tcx, P> {
|
||||
let len = base.len(self)?; // also asserts that we have a type where this makes sense
|
||||
let actual_to = if from_end {
|
||||
if from.checked_add(to).map_or(true, |to| to > len) {
|
||||
if from.checked_add(to).is_none_or(|to| to > len) {
|
||||
// This can only be reached in ConstProp and non-rustc-MIR.
|
||||
throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::const_eval::{CompileTimeEvalContext, CompileTimeInterpreter, InterpretationResult};
|
||||
use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{Allocation, InterpResult, Pointer};
|
||||
|
|
@ -84,7 +84,7 @@ where
|
|||
impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> {
|
||||
fn make_result(
|
||||
mplace: MPlaceTy<'tcx>,
|
||||
ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
|
||||
ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
|
||||
) -> Self {
|
||||
let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
|
||||
let alloc = ecx.memory.alloc_map.swap_remove(&alloc_id).unwrap().1;
|
||||
|
|
@ -93,7 +93,7 @@ impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx>
|
|||
}
|
||||
|
||||
pub(crate) fn create_static_alloc<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
ecx: &mut CompileTimeInterpCx<'tcx>,
|
||||
static_def_id: LocalDefId,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ use rustc_target::abi::{
|
|||
use std::hash::Hash;
|
||||
|
||||
use super::{
|
||||
err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, CheckInAllocMsg,
|
||||
err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, AllocKind, CheckInAllocMsg,
|
||||
GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
|
||||
Pointer, Projectable, Scalar, ValueVisitor,
|
||||
};
|
||||
|
|
@ -413,8 +413,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
|
||||
ptr_kind
|
||||
},
|
||||
// This cannot happen during const-eval (because interning already detects
|
||||
// dangling pointers), but it can happen in Miri.
|
||||
Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree {
|
||||
ptr_kind,
|
||||
},
|
||||
|
|
@ -493,9 +491,17 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
// Mutability check.
|
||||
// Dangling and Mutability check.
|
||||
let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id);
|
||||
if alloc_kind == AllocKind::Dead {
|
||||
// This can happen for zero-sized references. We can't have *any* references to non-existing
|
||||
// allocations though, interning rejects them all as the rest of rustc isn't happy with them...
|
||||
// so we throw an error, even though this isn't really UB.
|
||||
// A potential future alternative would be to resurrect this as a zero-sized allocation
|
||||
// (which codegen will then compile to an aligned dummy pointer anyway).
|
||||
throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
|
||||
}
|
||||
// If this allocation has size zero, there is no actual mutability here.
|
||||
let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id);
|
||||
if size != Size::ZERO {
|
||||
let alloc_actual_mutbl = mutability(self.ecx, alloc_id);
|
||||
// Mutable pointer to immutable memory is no good.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(is_none_or)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustdoc_internals)]
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ use rustc_middle::ty::{self, Mutability};
|
|||
use rustc_span::symbol::Symbol;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeEvalContext};
|
||||
use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeInterpCx};
|
||||
use crate::interpret::*;
|
||||
|
||||
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
|
||||
fn alloc_caller_location<'tcx>(
|
||||
ecx: &mut CompileTimeEvalContext<'tcx>,
|
||||
ecx: &mut CompileTimeInterpCx<'tcx>,
|
||||
filename: Symbol,
|
||||
line: u32,
|
||||
col: u32,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, Val
|
|||
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
||||
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
|
||||
|
||||
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeInterpreter};
|
||||
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
|
||||
use crate::interpret::{InterpCx, MemoryKind, OpTy};
|
||||
|
||||
/// Determines if this type permits "raw" initialization by just transmuting some memory into an
|
||||
|
|
@ -45,7 +45,7 @@ fn might_permit_raw_init_strict<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
kind: ValidityRequirement,
|
||||
) -> Result<bool, &'tcx LayoutError<'tcx>> {
|
||||
let machine = CompileTimeInterpreter::new(CanAccessMutGlobal::No, CheckAlignment::Error);
|
||||
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
|
||||
|
||||
let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ elsa = "=1.7.1"
|
|||
ena = "0.14.3"
|
||||
indexmap = { version = "2.0.0" }
|
||||
jobserver_crate = { version = "0.1.28", package = "jobserver" }
|
||||
libc = "0.2"
|
||||
measureme = "11"
|
||||
rustc-hash = "1.1.0"
|
||||
rustc-rayon = { version = "0.5.0", optional = true }
|
||||
|
|
@ -41,6 +40,11 @@ features = [
|
|||
"Win32_System_Threading",
|
||||
]
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
# tidy-alphabetical-start
|
||||
libc = "0.2"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
# tidy-alphabetical-start
|
||||
memmap2 = "0.2.1"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ cfg_match! {
|
|||
mod linux;
|
||||
use linux as imp;
|
||||
}
|
||||
cfg(target_os = "redox") => {
|
||||
mod linux;
|
||||
use linux as imp;
|
||||
}
|
||||
cfg(unix) => {
|
||||
mod unix;
|
||||
use unix as imp;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,14 @@ use rustc_session::parse::ParseSess;
|
|||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers";
|
||||
|
||||
/// A meta-variable expression, for expansions based on properties of meta-variables.
|
||||
#[derive(Debug, Clone, PartialEq, Encodable, Decodable)]
|
||||
#[derive(Debug, PartialEq, Encodable, Decodable)]
|
||||
pub(crate) enum MetaVarExpr {
|
||||
/// Unification of two or more identifiers.
|
||||
Concat(Box<[MetaVarExprConcatElem]>),
|
||||
|
||||
/// The number of repetitions of an identifier.
|
||||
Count(Ident, usize),
|
||||
|
||||
|
|
@ -42,6 +47,31 @@ impl MetaVarExpr {
|
|||
check_trailing_token(&mut tts, psess)?;
|
||||
let mut iter = args.trees();
|
||||
let rslt = match ident.as_str() {
|
||||
"concat" => {
|
||||
let mut result = Vec::new();
|
||||
loop {
|
||||
let is_var = try_eat_dollar(&mut iter);
|
||||
let element_ident = parse_ident(&mut iter, psess, outer_span)?;
|
||||
let element = if is_var {
|
||||
MetaVarExprConcatElem::Var(element_ident)
|
||||
} else {
|
||||
MetaVarExprConcatElem::Ident(element_ident)
|
||||
};
|
||||
result.push(element);
|
||||
if iter.look_ahead(0).is_none() {
|
||||
break;
|
||||
}
|
||||
if !try_eat_comma(&mut iter) {
|
||||
return Err(psess.dcx.struct_span_err(outer_span, "expected comma"));
|
||||
}
|
||||
}
|
||||
if result.len() < 2 {
|
||||
return Err(psess
|
||||
.dcx
|
||||
.struct_span_err(ident.span, "`concat` must have at least two elements"));
|
||||
}
|
||||
MetaVarExpr::Concat(result.into())
|
||||
}
|
||||
"count" => parse_count(&mut iter, psess, ident.span)?,
|
||||
"ignore" => {
|
||||
eat_dollar(&mut iter, psess, ident.span)?;
|
||||
|
|
@ -68,11 +98,21 @@ impl MetaVarExpr {
|
|||
pub(crate) fn ident(&self) -> Option<Ident> {
|
||||
match *self {
|
||||
MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(ident),
|
||||
MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
|
||||
MetaVarExpr::Concat { .. } | MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Decodable, Encodable, PartialEq)]
|
||||
pub(crate) enum MetaVarExprConcatElem {
|
||||
/// There is NO preceding dollar sign, which means that this identifier should be interpreted
|
||||
/// as a literal.
|
||||
Ident(Ident),
|
||||
/// There is a preceding dollar sign, which means that this identifier should be expanded
|
||||
/// and interpreted as a variable.
|
||||
Var(Ident),
|
||||
}
|
||||
|
||||
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
|
||||
fn check_trailing_token<'psess>(
|
||||
iter: &mut RefTokenTreeCursor<'_>,
|
||||
|
|
@ -138,26 +178,30 @@ fn parse_depth<'psess>(
|
|||
fn parse_ident<'psess>(
|
||||
iter: &mut RefTokenTreeCursor<'_>,
|
||||
psess: &'psess ParseSess,
|
||||
span: Span,
|
||||
fallback_span: Span,
|
||||
) -> PResult<'psess, Ident> {
|
||||
if let Some(tt) = iter.next()
|
||||
&& let TokenTree::Token(token, _) = tt
|
||||
{
|
||||
if let Some((elem, IdentIsRaw::No)) = token.ident() {
|
||||
return Ok(elem);
|
||||
let Some(tt) = iter.next() else {
|
||||
return Err(psess.dcx.struct_span_err(fallback_span, "expected identifier"));
|
||||
};
|
||||
let TokenTree::Token(token, _) = tt else {
|
||||
return Err(psess.dcx.struct_span_err(tt.span(), "expected identifier"));
|
||||
};
|
||||
if let Some((elem, is_raw)) = token.ident() {
|
||||
if let IdentIsRaw::Yes = is_raw {
|
||||
return Err(psess.dcx.struct_span_err(elem.span, RAW_IDENT_ERR));
|
||||
}
|
||||
let token_str = pprust::token_to_string(token);
|
||||
let mut err =
|
||||
psess.dcx.struct_span_err(span, format!("expected identifier, found `{}`", &token_str));
|
||||
err.span_suggestion(
|
||||
token.span,
|
||||
format!("try removing `{}`", &token_str),
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return Err(err);
|
||||
return Ok(elem);
|
||||
}
|
||||
Err(psess.dcx.struct_span_err(span, "expected identifier"))
|
||||
let token_str = pprust::token_to_string(token);
|
||||
let mut err =
|
||||
psess.dcx.struct_span_err(token.span, format!("expected identifier, found `{token_str}`"));
|
||||
err.span_suggestion(
|
||||
token.span,
|
||||
format!("try removing `{token_str}`"),
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
Err(err)
|
||||
}
|
||||
|
||||
/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
|
||||
|
|
@ -170,6 +214,17 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
/// Tries to move the iterator forward returning `true` if there is a dollar sign. If not, then the
|
||||
/// iterator is not modified and the result is `false`.
|
||||
fn try_eat_dollar(iter: &mut RefTokenTreeCursor<'_>) -> bool {
|
||||
if let Some(TokenTree::Token(token::Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0)
|
||||
{
|
||||
let _ = iter.next();
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Expects that the next item is a dollar sign.
|
||||
fn eat_dollar<'psess>(
|
||||
iter: &mut RefTokenTreeCursor<'_>,
|
||||
|
|
|
|||
|
|
@ -155,6 +155,13 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, sp
|
|||
}
|
||||
}
|
||||
|
||||
fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Session, span: Span) {
|
||||
if !features.macro_metavar_expr_concat {
|
||||
let msg = "the `concat` meta-variable expression is unstable";
|
||||
feature_err(sess, sym::macro_metavar_expr_concat, span, msg).emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a `tokenstream::TokenTree` and returns a `self::TokenTree`. Specifically, this takes a
|
||||
/// generic `TokenTree`, such as is used in the rest of the compiler, and returns a `TokenTree`
|
||||
/// for use in parsing a macro.
|
||||
|
|
@ -217,11 +224,19 @@ fn parse_tree<'a>(
|
|||
return TokenTree::token(token::Dollar, dollar_span);
|
||||
}
|
||||
Ok(elem) => {
|
||||
maybe_emit_macro_metavar_expr_feature(
|
||||
features,
|
||||
sess,
|
||||
delim_span.entire(),
|
||||
);
|
||||
if let MetaVarExpr::Concat(_) = elem {
|
||||
maybe_emit_macro_metavar_expr_concat_feature(
|
||||
features,
|
||||
sess,
|
||||
delim_span.entire(),
|
||||
);
|
||||
} else {
|
||||
maybe_emit_macro_metavar_expr_feature(
|
||||
features,
|
||||
sess,
|
||||
delim_span.entire(),
|
||||
);
|
||||
}
|
||||
return TokenTree::MetaVarExpr(delim_span, elem);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,18 +3,19 @@ use crate::errors::{
|
|||
NoSyntaxVarsExprRepeat, VarStillRepeating,
|
||||
};
|
||||
use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
|
||||
use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR};
|
||||
use crate::mbe::{self, KleeneOp, MetaVarExpr};
|
||||
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||
use rustc_ast::token::IdentIsRaw;
|
||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{pluralize, Diag, DiagCtxt, PResult};
|
||||
use rustc_parse::parser::ParseNtResult;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
||||
use rustc_span::{with_metavar_spans, Span, SyntaxContext};
|
||||
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::{with_metavar_spans, Span, Symbol, SyntaxContext};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::mem;
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ impl MutVisitor for Marker {
|
|||
// it's some advanced case with macro-generated macros. So if we cache the marked version
|
||||
// of that context once, we'll typically have a 100% cache hit rate after that.
|
||||
let Marker(expn_id, transparency, ref mut cache) = *self;
|
||||
span.update_ctxt(|ctxt| {
|
||||
*span = span.map_ctxt(|ctxt| {
|
||||
*cache
|
||||
.entry(ctxt)
|
||||
.or_insert_with(|| ctxt.apply_mark(expn_id.to_expn_id(), transparency))
|
||||
|
|
@ -675,6 +676,23 @@ fn transcribe_metavar_expr<'a>(
|
|||
span
|
||||
};
|
||||
match *expr {
|
||||
MetaVarExpr::Concat(ref elements) => {
|
||||
let mut concatenated = String::new();
|
||||
for element in elements.into_iter() {
|
||||
let string = match element {
|
||||
MetaVarExprConcatElem::Ident(ident) => ident.to_string(),
|
||||
MetaVarExprConcatElem::Var(ident) => extract_ident(dcx, *ident, interp)?,
|
||||
};
|
||||
concatenated.push_str(&string);
|
||||
}
|
||||
// The current implementation marks the span as coming from the macro regardless of
|
||||
// contexts of the concatenated identifiers but this behavior may change in the
|
||||
// future.
|
||||
result.push(TokenTree::Token(
|
||||
Token::from_ast_ident(Ident::new(Symbol::intern(&concatenated), visited_span())),
|
||||
Spacing::Alone,
|
||||
));
|
||||
}
|
||||
MetaVarExpr::Count(original_ident, depth) => {
|
||||
let matched = matched_from_ident(dcx, original_ident, interp)?;
|
||||
let count = count_repetitions(dcx, depth, matched, repeats, sp)?;
|
||||
|
|
@ -709,3 +727,33 @@ fn transcribe_metavar_expr<'a>(
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Extracts an identifier that can be originated from a `$var:ident` variable or from a token tree.
|
||||
fn extract_ident<'a>(
|
||||
dcx: &'a DiagCtxt,
|
||||
ident: Ident,
|
||||
interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
|
||||
) -> PResult<'a, String> {
|
||||
if let NamedMatch::MatchedSingle(pnr) = matched_from_ident(dcx, ident, interp)? {
|
||||
if let ParseNtResult::Ident(nt_ident, is_raw) = pnr {
|
||||
if let IdentIsRaw::Yes = is_raw {
|
||||
return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
|
||||
}
|
||||
return Ok(nt_ident.to_string());
|
||||
}
|
||||
if let ParseNtResult::Tt(TokenTree::Token(
|
||||
Token { kind: TokenKind::Ident(token_ident, is_raw), .. },
|
||||
_,
|
||||
)) = pnr
|
||||
{
|
||||
if let IdentIsRaw::Yes = is_raw {
|
||||
return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
|
||||
}
|
||||
return Ok(token_ident.to_string());
|
||||
}
|
||||
}
|
||||
Err(dcx.struct_span_err(
|
||||
ident.span,
|
||||
"`${concat(..)}` currently only accepts identifiers or meta-variables as parameters",
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -516,6 +516,8 @@ declare_features! (
|
|||
(unstable, lint_reasons, "1.31.0", Some(54503)),
|
||||
/// Give access to additional metadata about declarative macro meta-variables.
|
||||
(unstable, macro_metavar_expr, "1.61.0", Some(83527)),
|
||||
/// Provides a way to concatenate identifiers using metavariable expressions.
|
||||
(unstable, macro_metavar_expr_concat, "CURRENT_RUSTC_VERSION", Some(124225)),
|
||||
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
|
||||
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
|
||||
/// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are
|
||||
|
|
|
|||
|
|
@ -1633,6 +1633,13 @@ pub struct ConstBlock {
|
|||
}
|
||||
|
||||
/// An expression.
|
||||
///
|
||||
/// For more details, see the [rust lang reference].
|
||||
/// Note that the reference does not document nightly-only features.
|
||||
/// There may be also slight differences in the names and representation of AST nodes between
|
||||
/// the compiler and the reference.
|
||||
///
|
||||
/// [rust lang reference]: https://doc.rust-lang.org/reference/expressions.html
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Expr<'hir> {
|
||||
pub hir_id: HirId,
|
||||
|
|
@ -2464,6 +2471,15 @@ pub enum AssocItemConstraintKind<'hir> {
|
|||
Bound { bounds: &'hir [GenericBound<'hir>] },
|
||||
}
|
||||
|
||||
impl<'hir> AssocItemConstraintKind<'hir> {
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
AssocItemConstraintKind::Equality { .. } => "binding",
|
||||
AssocItemConstraintKind::Bound { .. } => "constraint",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Ty<'hir> {
|
||||
pub hir_id: HirId,
|
||||
|
|
@ -3147,6 +3163,13 @@ impl ItemId {
|
|||
/// An item
|
||||
///
|
||||
/// The name might be a dummy name in case of anonymous items
|
||||
///
|
||||
/// For more details, see the [rust lang reference].
|
||||
/// Note that the reference does not document nightly-only features.
|
||||
/// There may be also slight differences in the names and representation of AST nodes between
|
||||
/// the compiler and the reference.
|
||||
///
|
||||
/// [rust lang reference]: https://doc.rust-lang.org/reference/items.html
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Item<'hir> {
|
||||
pub ident: Ident,
|
||||
|
|
@ -3749,6 +3772,21 @@ impl<'hir> Node<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`.
|
||||
pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
|
||||
match self {
|
||||
Node::Item(Item { kind: ItemKind::Impl(impl_block), .. })
|
||||
if impl_block
|
||||
.of_trait
|
||||
.and_then(|trait_ref| trait_ref.trait_def_id())
|
||||
.is_some_and(|trait_id| trait_id == trait_def_id) =>
|
||||
{
|
||||
Some(impl_block)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
|
||||
match self {
|
||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||
|
|
|
|||
|
|
@ -244,7 +244,9 @@ language_item_table! {
|
|||
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
|
||||
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
CoroutineReturn, sym::coroutine_return, coroutine_return, Target::AssocTy, GenericRequirement::Exact(1);
|
||||
CoroutineYield, sym::coroutine_yield, coroutine_yield, Target::AssocTy, GenericRequirement::Exact(1);
|
||||
CoroutineResume, sym::coroutine_resume, coroutine_resume, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ impl<'tcx> Bounds<'tcx> {
|
|||
span,
|
||||
);
|
||||
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
|
||||
if tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
|
||||
if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
|
||||
self.clauses.insert(0, clause);
|
||||
} else {
|
||||
self.clauses.push(clause);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_ast::InlineAsmTemplatePiece;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
|
||||
use rustc_session::lint;
|
||||
|
|
@ -62,8 +62,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64),
|
||||
ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128),
|
||||
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize),
|
||||
ty::Float(FloatTy::F16) => Some(InlineAsmType::F16),
|
||||
ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
|
||||
ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
|
||||
ty::Float(FloatTy::F128) => Some(InlineAsmType::F128),
|
||||
ty::FnPtr(_) => Some(asm_ty_isize),
|
||||
ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize),
|
||||
ty::Adt(adt, args) if adt.repr().simd() => {
|
||||
|
|
@ -105,8 +107,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
width => bug!("unsupported pointer width: {width}"),
|
||||
})
|
||||
}
|
||||
ty::Float(FloatTy::F16) => Some(InlineAsmType::VecF16(size)),
|
||||
ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)),
|
||||
ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(size)),
|
||||
ty::Float(FloatTy::F128) => Some(InlineAsmType::VecF128(size)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -134,7 +138,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
// `!` is allowed for input but not for output (issue #87802)
|
||||
ty::Never if is_input => return None,
|
||||
_ if ty.references_error() => return None,
|
||||
ty::Adt(adt, args) if Some(adt.did()) == self.tcx.lang_items().maybe_uninit() => {
|
||||
ty::Adt(adt, args) if self.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
|
||||
let fields = &adt.non_enum_variant().fields;
|
||||
let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args);
|
||||
// FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`?
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
use crate::errors;
|
||||
use rustc_errors::{codes::*, struct_span_code_err};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_session::parse::feature_err;
|
||||
|
|
@ -49,7 +50,7 @@ fn enforce_trait_manually_implementable(
|
|||
) -> Result<(), ErrorGuaranteed> {
|
||||
let impl_header_span = tcx.def_span(impl_def_id);
|
||||
|
||||
if tcx.lang_items().freeze_trait() == Some(trait_def_id) {
|
||||
if tcx.is_lang_item(trait_def_id, LangItem::Freeze) {
|
||||
if !tcx.features().freeze_impls {
|
||||
feature_err(
|
||||
&tcx.sess,
|
||||
|
|
@ -75,7 +76,7 @@ fn enforce_trait_manually_implementable(
|
|||
|
||||
// Maintain explicit error code for `Unsize`, since it has a useful
|
||||
// explanation about using `CoerceUnsized` instead.
|
||||
if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
|
||||
if tcx.is_lang_item(trait_def_id, LangItem::Unsize) {
|
||||
err.code(E0328);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1217,7 +1217,6 @@ pub fn prohibit_assoc_item_constraint(
|
|||
// otherwise suggest the removal of the binding.
|
||||
if let Some((def_id, segment, _)) = segment
|
||||
&& segment.args().parenthesized == hir::GenericArgsParentheses::No
|
||||
&& let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
|
||||
{
|
||||
// Suggests removal of the offending binding
|
||||
let suggest_removal = |e: &mut Diag<'_>| {
|
||||
|
|
@ -1263,7 +1262,7 @@ pub fn prohibit_assoc_item_constraint(
|
|||
if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
|
||||
e.span_suggestion_verbose(
|
||||
removal_span,
|
||||
"consider removing this associated item binding",
|
||||
format!("consider removing this associated item {}", constraint.kind.descr()),
|
||||
suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
@ -1286,19 +1285,73 @@ pub fn prohibit_assoc_item_constraint(
|
|||
// Check if the type has a generic param with the same name
|
||||
// as the assoc type name in the associated item binding.
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let matching_param =
|
||||
generics.own_params.iter().find(|p| p.name.as_str() == constraint.ident.as_str());
|
||||
let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
|
||||
|
||||
// Now emit the appropriate suggestion
|
||||
if let Some(matching_param) = matching_param {
|
||||
match (&matching_param.kind, term) {
|
||||
(GenericParamDefKind::Type { .. }, hir::Term::Ty(ty)) => {
|
||||
suggest_direct_use(&mut err, ty.span);
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, hir::Term::Const(c)) => {
|
||||
match (constraint.kind, &matching_param.kind) {
|
||||
(
|
||||
hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
|
||||
GenericParamDefKind::Type { .. },
|
||||
) => suggest_direct_use(&mut err, ty.span),
|
||||
(
|
||||
hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
|
||||
GenericParamDefKind::Const { .. },
|
||||
) => {
|
||||
let span = tcx.hir().span(c.hir_id);
|
||||
suggest_direct_use(&mut err, span);
|
||||
}
|
||||
(hir::AssocItemConstraintKind::Bound { bounds }, _) => {
|
||||
// Suggest `impl<T: Bound> Trait<T> for Foo` when finding
|
||||
// `impl Trait<T: Bound> for Foo`
|
||||
|
||||
// Get the parent impl block based on the binding we have
|
||||
// and the trait DefId
|
||||
let impl_block = tcx
|
||||
.hir()
|
||||
.parent_iter(constraint.hir_id)
|
||||
.find_map(|(_, node)| node.impl_block_of_trait(def_id));
|
||||
|
||||
let type_with_constraints =
|
||||
tcx.sess.source_map().span_to_snippet(constraint.span);
|
||||
|
||||
if let Some(impl_block) = impl_block
|
||||
&& let Ok(type_with_constraints) = type_with_constraints
|
||||
{
|
||||
// Filter out the lifetime parameters because
|
||||
// they should be declared before the type parameter
|
||||
let lifetimes: String = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
if let hir::GenericBound::Outlives(lifetime) = bound {
|
||||
Some(format!("{lifetime}, "))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
// Figure out a span and suggestion string based on
|
||||
// whether there are any existing parameters
|
||||
let param_decl = if let Some(param_span) =
|
||||
impl_block.generics.span_for_param_suggestion()
|
||||
{
|
||||
(param_span, format!(", {lifetimes}{type_with_constraints}"))
|
||||
} else {
|
||||
(
|
||||
impl_block.generics.span.shrink_to_lo(),
|
||||
format!("<{lifetimes}{type_with_constraints}>"),
|
||||
)
|
||||
};
|
||||
let suggestions =
|
||||
vec![param_decl, (constraint.span, format!("{}", matching_param.name))];
|
||||
|
||||
err.multipart_suggestion_verbose(
|
||||
format!("declare the type parameter right after the `impl` keyword"),
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => suggest_removal(&mut err),
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -531,6 +531,7 @@ pub(crate) fn check_generic_arg_count(
|
|||
|
||||
let num_default_params = expected_max - expected_min;
|
||||
|
||||
let mut all_params_are_binded = false;
|
||||
let gen_args_info = if provided > expected_max {
|
||||
invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
|
||||
let num_redundant_args = provided - expected_max;
|
||||
|
|
@ -547,6 +548,20 @@ pub(crate) fn check_generic_arg_count(
|
|||
} else {
|
||||
let num_missing_args = expected_max - provided;
|
||||
|
||||
let constraint_names: Vec<_> =
|
||||
gen_args.constraints.iter().map(|b| b.ident.name).collect();
|
||||
let param_names: Vec<_> = gen_params
|
||||
.own_params
|
||||
.iter()
|
||||
.filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
|
||||
.map(|param| param.name)
|
||||
.collect();
|
||||
if constraint_names == param_names {
|
||||
// We set this to true and delay emitting `WrongNumberOfGenericArgs`
|
||||
// to provide a succinct error for cases like issue #113073
|
||||
all_params_are_binded = true;
|
||||
};
|
||||
|
||||
GenericArgsInfo::MissingTypesOrConsts {
|
||||
num_missing_args,
|
||||
num_default_params,
|
||||
|
|
@ -567,7 +582,7 @@ pub(crate) fn check_generic_arg_count(
|
|||
def_id,
|
||||
)
|
||||
.diagnostic()
|
||||
.emit()
|
||||
.emit_unless(all_params_are_binded)
|
||||
});
|
||||
|
||||
Err(reported)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to `
|
|||
|
||||
hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
|
||||
|
||||
hir_typeck_dependency_on_unit_never_type_fallback = this function depends on never type fallback being `()`
|
||||
.note = in edition 2024, the requirement `{$obligation}` will fail
|
||||
.help = specify the types explicitly
|
||||
|
||||
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
|
||||
|
||||
hir_typeck_expected_default_return_type = expected `()` because of default return type
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ret_ty = ret_coercion.borrow().expected_ty();
|
||||
let ret_ty = self.infcx.shallow_resolve(ret_ty);
|
||||
self.can_coerce(arm_ty, ret_ty)
|
||||
&& prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
|
||||
&& prior_arm.is_none_or(|(_, ty, _)| self.can_coerce(ty, ret_ty))
|
||||
// The match arms need to unify for the case of `impl Trait`.
|
||||
&& !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
|||
use crate::errors;
|
||||
use rustc_ast::util::parser::PREC_POSTFIX;
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{self, CtorKind, Namespace, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_hir_analysis::autoderef::Autoderef;
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_infer::{
|
||||
|
|
@ -41,7 +41,7 @@ pub fn check_legal_trait_for_method_call(
|
|||
trait_id: DefId,
|
||||
body_id: DefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if tcx.lang_items().drop_trait() == Some(trait_id)
|
||||
if tcx.is_lang_item(trait_id, LangItem::Drop)
|
||||
&& tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
|
||||
{
|
||||
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
|
||||
|
|
@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return;
|
||||
};
|
||||
|
||||
let pick = self.confirm_method(
|
||||
let pick = self.confirm_method_for_diagnostic(
|
||||
call_expr.span,
|
||||
callee_expr,
|
||||
call_expr,
|
||||
|
|
|
|||
|
|
@ -913,7 +913,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
if self
|
||||
.tcx
|
||||
.upvars_mentioned(closure_def_id_a.expect_local())
|
||||
.map_or(true, |u| u.is_empty()) =>
|
||||
.is_none_or(|u| u.is_empty()) =>
|
||||
{
|
||||
// We coerce the closure, which has fn type
|
||||
// `extern "rust-call" fn((arg0,arg1,...)) -> _`
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diag};
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
|
|
@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Requires that the two types unify, and prints an error message if
|
||||
/// they don't.
|
||||
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
if let Some(e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
if let Err(e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
e.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -176,7 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
sp: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
|
||||
}
|
||||
|
||||
|
|
@ -186,18 +186,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
None
|
||||
}
|
||||
Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
|
||||
}
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.at(cause, self.param_env)
|
||||
.sup(DefineOpaqueTypes::Yes, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
.map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
|
||||
}
|
||||
|
||||
pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
if let Some(err) = self.demand_eqtype_diag(sp, expected, actual) {
|
||||
if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -207,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
sp: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
|
||||
}
|
||||
|
||||
|
|
@ -216,14 +213,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
None
|
||||
}
|
||||
Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
|
||||
}
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.at(cause, self.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
.map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
|
||||
}
|
||||
|
||||
pub fn demand_coerce(
|
||||
|
|
@ -234,12 +228,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
allow_two_phase: AllowTwoPhase,
|
||||
) -> Ty<'tcx> {
|
||||
let (ty, err) =
|
||||
self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
|
||||
if let Some(err) = err {
|
||||
err.emit();
|
||||
match self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase)
|
||||
{
|
||||
Ok(ty) => ty,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
// Return the original type instead of an error type here, otherwise the type of `x` in
|
||||
// `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not
|
||||
// report errors, even though `x` is definitely `u32`.
|
||||
expected
|
||||
}
|
||||
}
|
||||
ty
|
||||
}
|
||||
|
||||
/// Checks that the type of `expr` can be coerced to `expected`.
|
||||
|
|
@ -254,11 +253,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expected: Ty<'tcx>,
|
||||
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
allow_two_phase: AllowTwoPhase,
|
||||
) -> (Ty<'tcx>, Option<Diag<'tcx>>) {
|
||||
) -> Result<Ty<'tcx>, Diag<'tcx>> {
|
||||
let expected = self.resolve_vars_with_obligations(expected);
|
||||
|
||||
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
|
||||
Ok(ty) => return (ty, None),
|
||||
Ok(ty) => return Ok(ty),
|
||||
Err(e) => e,
|
||||
};
|
||||
|
||||
|
|
@ -275,7 +274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
|
||||
|
||||
(expected, Some(err))
|
||||
Err(err)
|
||||
}
|
||||
|
||||
/// Notes the point at which a variable is constrained to some type incompatible
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_errors::{
|
|||
SubdiagMessageOp, Subdiagnostic,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{
|
||||
edition::{Edition, LATEST_STABLE_EDITION},
|
||||
symbol::Ident,
|
||||
|
|
@ -183,6 +183,15 @@ pub enum NeverTypeFallbackFlowingIntoUnsafe {
|
|||
Deref,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[help]
|
||||
#[diag(hir_typeck_dependency_on_unit_never_type_fallback)]
|
||||
pub struct DependencyOnUnitNeverTypeFallback<'tcx> {
|
||||
#[note]
|
||||
pub obligation_span: Span,
|
||||
pub obligation: ty::Predicate<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
hir_typeck_add_missing_parentheses_in_range,
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ty = adj_ty;
|
||||
}
|
||||
|
||||
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
||||
if let Err(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
||||
let _ = self.emit_type_mismatch_suggestions(
|
||||
&mut err,
|
||||
expr.peel_drop_temps(),
|
||||
|
|
@ -1132,7 +1132,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
|
||||
// The likely cause of this is `if foo = bar { .. }`.
|
||||
let actual_ty = self.tcx.types.unit;
|
||||
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
|
||||
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap_err();
|
||||
let lhs_ty = self.check_expr(lhs);
|
||||
let rhs_ty = self.check_expr(rhs);
|
||||
let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
|
||||
|
|
@ -1236,7 +1236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// This is (basically) inlined `check_expr_coercible_to_type`, but we want
|
||||
// to suggest an additional fixup here in `suggest_deref_binop`.
|
||||
let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty);
|
||||
if let (_, Some(mut diag)) =
|
||||
if let Err(mut diag) =
|
||||
self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)
|
||||
{
|
||||
suggest_deref_binop(&mut diag, rhs_ty);
|
||||
|
|
@ -1557,7 +1557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
|
||||
// don't copy that one element, we move it. Only check for Copy if the length is larger.
|
||||
if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
|
||||
if count.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) {
|
||||
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
|
||||
let code = traits::ObligationCauseCode::RepeatElementCopy {
|
||||
is_constable,
|
||||
|
|
@ -1738,10 +1738,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Make sure to give a type to the field even if there's
|
||||
// an error, so we can continue type-checking.
|
||||
let ty = self.check_expr_with_hint(field.expr, field_type);
|
||||
let (_, diag) =
|
||||
self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
|
||||
let diag = self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
|
||||
|
||||
if let Some(diag) = diag {
|
||||
if let Err(diag) = diag {
|
||||
if idx == hir_fields.len() - 1 {
|
||||
if remaining_fields.is_empty() {
|
||||
self.suggest_fru_from_range_and_emit(field, variant, args, diag);
|
||||
|
|
@ -3151,7 +3150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
error.obligation.predicate.kind().skip_binder(),
|
||||
) {
|
||||
(ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)), _)
|
||||
if self.tcx.lang_items().index_trait() == Some(predicate.trait_ref.def_id) =>
|
||||
if self.tcx.is_lang_item(predicate.trait_ref.def_id, LangItem::Index) =>
|
||||
{
|
||||
seen_preds.insert(error.obligation.predicate.kind().skip_binder());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
|
|||
use rustc_session::lint;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::{def_id::LocalDefId, Span};
|
||||
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum DivergingFallbackBehavior {
|
||||
|
|
@ -344,6 +345,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
// `!`.
|
||||
let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len());
|
||||
let unsafe_infer_vars = OnceCell::new();
|
||||
|
||||
self.lint_obligations_broken_by_never_type_fallback_change(behavior, &diverging_vids);
|
||||
|
||||
for &diverging_vid in &diverging_vids {
|
||||
let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
|
||||
let root_vid = self.root_var(diverging_vid);
|
||||
|
|
@ -468,6 +472,56 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lint_obligations_broken_by_never_type_fallback_change(
|
||||
&self,
|
||||
behavior: DivergingFallbackBehavior,
|
||||
diverging_vids: &[ty::TyVid],
|
||||
) {
|
||||
let DivergingFallbackBehavior::ToUnit = behavior else { return };
|
||||
|
||||
// Fallback happens if and only if there are diverging variables
|
||||
if diverging_vids.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Returns errors which happen if fallback is set to `fallback`
|
||||
let remaining_errors_if_fallback_to = |fallback| {
|
||||
self.probe(|_| {
|
||||
let obligations = self.fulfillment_cx.borrow().pending_obligations();
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
|
||||
ocx.register_obligations(obligations.iter().cloned());
|
||||
|
||||
for &diverging_vid in diverging_vids {
|
||||
let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
|
||||
|
||||
ocx.eq(&ObligationCause::dummy(), self.param_env, diverging_ty, fallback)
|
||||
.expect("expected diverging var to be unconstrained");
|
||||
}
|
||||
|
||||
ocx.select_where_possible()
|
||||
})
|
||||
};
|
||||
|
||||
// If we have no errors with `fallback = ()`, but *do* have errors with `fallback = !`,
|
||||
// then this code will be broken by the never type fallback change.qba
|
||||
let unit_errors = remaining_errors_if_fallback_to(self.tcx.types.unit);
|
||||
if unit_errors.is_empty()
|
||||
&& let mut never_errors = remaining_errors_if_fallback_to(self.tcx.types.never)
|
||||
&& let [ref mut never_error, ..] = never_errors.as_mut_slice()
|
||||
{
|
||||
self.adjust_fulfillment_error_for_expr_obligation(never_error);
|
||||
self.tcx.emit_node_span_lint(
|
||||
lint::builtin::DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
|
||||
self.tcx.local_def_id_to_hir_id(self.body_id),
|
||||
self.tcx.def_span(self.body_id),
|
||||
errors::DependencyOnUnitNeverTypeFallback {
|
||||
obligation_span: never_error.obligation.cause.span,
|
||||
obligation: never_error.obligation.predicate,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a graph whose nodes are (unresolved) inference variables and where
|
||||
/// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`.
|
||||
fn create_coercion_graph(&self) -> VecGraph<ty::TyVid, true> {
|
||||
|
|
|
|||
|
|
@ -1418,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
|
||||
let self_ty = self.normalize(span, self_ty);
|
||||
match self.at(&self.misc(span), self.param_env).eq(
|
||||
DefineOpaqueTypes::No,
|
||||
DefineOpaqueTypes::Yes,
|
||||
impl_ty,
|
||||
self_ty,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1578,7 +1578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// type of the place it is referencing, and not some
|
||||
// supertype thereof.
|
||||
let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
|
||||
if let Some(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
|
||||
if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
|
||||
self.emit_type_mismatch_suggestions(
|
||||
&mut diag,
|
||||
init.peel_drop_temps(),
|
||||
|
|
@ -1624,7 +1624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let previous_diverges = self.diverges.get();
|
||||
let else_ty = self.check_block_with_expected(blk, NoExpectation);
|
||||
let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
|
||||
if let Some(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
|
||||
if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
|
||||
{
|
||||
err.emit();
|
||||
}
|
||||
|
|
@ -2240,7 +2240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
for (idx, (generic_param, param)) in
|
||||
params_with_generics.iter().enumerate().filter(|(idx, _)| {
|
||||
check_for_matched_generics
|
||||
|| expected_idx.map_or(true, |expected_idx| expected_idx == *idx)
|
||||
|| expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
|
||||
})
|
||||
{
|
||||
let Some(generic_param) = generic_param else {
|
||||
|
|
|
|||
|
|
@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
// Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for
|
||||
// `as_ref` and `as_deref` compatibility.
|
||||
let error_tys_equate_as_ref = error_tys.map_or(true, |(found, expected)| {
|
||||
let error_tys_equate_as_ref = error_tys.is_none_or(|(found, expected)| {
|
||||
self.can_eq(
|
||||
self.param_env,
|
||||
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, found),
|
||||
|
|
@ -489,10 +489,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
return true;
|
||||
} else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
|
||||
&& Some(adt.did()) == self.tcx.lang_items().string()
|
||||
&& self.tcx.is_lang_item(adt.did(), LangItem::String)
|
||||
&& peeled.is_str()
|
||||
// `Result::map`, conversely, does not take ref of the error type.
|
||||
&& error_tys.map_or(true, |(found, expected)| {
|
||||
&& error_tys.is_none_or(|(found, expected)| {
|
||||
self.can_eq(self.param_env, found, expected)
|
||||
})
|
||||
{
|
||||
|
|
@ -3147,7 +3147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
if let ty::Adt(adt, _) = expected_ty.kind()
|
||||
&& self.tcx.lang_items().range_struct() == Some(adt.did())
|
||||
&& self.tcx.is_lang_item(adt.did(), LangItem::Range)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(is_none_or)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(try_blocks)]
|
||||
|
|
|
|||
|
|
@ -497,7 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
args,
|
||||
})),
|
||||
);
|
||||
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
|
||||
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -634,8 +634,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
|
||||
debug!("assemble_probe: self_ty={:?}", self_ty);
|
||||
let raw_self_ty = self_ty.value.value;
|
||||
match *raw_self_ty.kind() {
|
||||
ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
|
||||
|
|
@ -713,13 +713,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
|
||||
if !self.impl_dups.insert(impl_def_id) {
|
||||
return; // already visited
|
||||
}
|
||||
|
||||
debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
|
||||
|
||||
for item in self.impl_or_trait_item(impl_def_id) {
|
||||
if !self.has_applicable_self(&item) {
|
||||
// No receiver declared. Not a candidate.
|
||||
|
|
@ -737,9 +736,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
|
||||
debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty);
|
||||
|
||||
let principal = match self_ty.kind() {
|
||||
ty::Dynamic(ref data, ..) => Some(data),
|
||||
_ => None,
|
||||
|
|
@ -768,9 +766,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
});
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
|
||||
// FIXME: do we want to commit to this behavior for param bounds?
|
||||
debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
|
||||
|
||||
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
|
||||
let bound_predicate = predicate.kind();
|
||||
|
|
@ -826,6 +824,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
|
||||
let mut duplicates = FxHashSet::default();
|
||||
let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
|
||||
|
|
@ -842,6 +841,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_all_traits(&mut self) {
|
||||
let mut duplicates = FxHashSet::default();
|
||||
for trait_info in suggest::all_traits(self.tcx) {
|
||||
|
|
@ -863,12 +863,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_trait(
|
||||
&mut self,
|
||||
import_ids: &SmallVec<[LocalDefId; 1]>,
|
||||
trait_def_id: DefId,
|
||||
) {
|
||||
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
|
||||
let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
|
||||
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
|
||||
|
||||
|
|
@ -958,6 +958,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// THE ACTUAL SEARCH
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn pick(mut self) -> PickResult<'tcx> {
|
||||
assert!(self.method_name.is_some());
|
||||
|
||||
|
|
@ -1386,6 +1387,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
|
||||
fn consider_probe(
|
||||
&self,
|
||||
self_ty: Ty<'tcx>,
|
||||
|
|
@ -1415,15 +1417,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, impl_ty, impl_args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
|
|
@ -1484,19 +1479,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
match self_ty.kind() {
|
||||
// HACK: opaque types will match anything for which their bounds hold.
|
||||
// Thus we need to prevent them from trying to match the `&_` autoref
|
||||
// candidates that get created for `&self` trait methods.
|
||||
ty::Alias(ty::Opaque, alias_ty)
|
||||
if self.infcx.can_define_opaque_ty(alias_ty.def_id)
|
||||
&& !xform_self_ty.is_ty_var() =>
|
||||
{
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
_ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
},
|
||||
}
|
||||
let obligation = traits::Obligation::new(
|
||||
self.tcx,
|
||||
|
|
@ -1536,15 +1535,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
|
|
@ -1665,6 +1657,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
|
||||
/// candidate method where the method name may have been misspelled. Similarly to other
|
||||
/// edit distance based suggestions, we provide at most one such suggestion.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(crate) fn probe_for_similar_candidate(
|
||||
&mut self,
|
||||
) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
|
||||
|
|
|
|||
|
|
@ -1102,7 +1102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
unsatisfied_predicates.iter().any(|(pred, _, _)| {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
|
||||
self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
|
||||
&& pred.polarity == ty::PredicatePolarity::Positive
|
||||
}
|
||||
_ => false,
|
||||
|
|
@ -1375,10 +1375,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ty.is_str()
|
||||
|| matches!(
|
||||
ty.kind(),
|
||||
ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
|
||||
ty::Adt(adt, _) if self.tcx.is_lang_item(adt.did(), LangItem::String)
|
||||
)
|
||||
}
|
||||
ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
|
||||
ty::Adt(adt, _) => self.tcx.is_lang_item(adt.did(), LangItem::String),
|
||||
_ => false,
|
||||
};
|
||||
if is_string_or_ref_str && item_name.name == sym::iter {
|
||||
|
|
@ -2723,7 +2723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
|
||||
err.help("use `with` or `try_with` to access thread local storage");
|
||||
} else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
|
||||
} else if tcx.is_lang_item(kind.did(), LangItem::MaybeUninit) {
|
||||
err.help(format!(
|
||||
"if this `{name}` has been initialized, \
|
||||
use one of the `assume_init` methods to access the inner value"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_errors::{
|
|||
};
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind};
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind};
|
||||
use rustc_infer::infer;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
|
|
@ -105,15 +105,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
ti: &TopInfo<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
let mut diag =
|
||||
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
|
||||
if let Some(expr) = ti.origin_expr {
|
||||
self.suggest_fn_call(&mut diag, expr, expected, |output| {
|
||||
self.can_eq(self.param_env, output, actual)
|
||||
});
|
||||
}
|
||||
Some(diag)
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
|
||||
.map_err(|mut diag| {
|
||||
if let Some(expr) = ti.origin_expr {
|
||||
self.suggest_fn_call(&mut diag, expr, expected, |output| {
|
||||
self.can_eq(self.param_env, output, actual)
|
||||
});
|
||||
}
|
||||
diag
|
||||
})
|
||||
}
|
||||
|
||||
fn demand_eqtype_pat(
|
||||
|
|
@ -122,10 +123,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
ti: &TopInfo<'tcx>,
|
||||
) {
|
||||
if let Some(err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
|
||||
err.emit();
|
||||
}
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -492,7 +491,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let tcx = self.tcx;
|
||||
let expected = self.resolve_vars_if_possible(expected);
|
||||
pat_ty = match expected.kind() {
|
||||
ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => expected,
|
||||
ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => expected,
|
||||
ty::Str => Ty::new_static_str(tcx),
|
||||
_ => pat_ty,
|
||||
};
|
||||
|
|
@ -509,7 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
//
|
||||
// then that's equivalent to there existing a LUB.
|
||||
let cause = self.pattern_cause(ti, span);
|
||||
if let Some(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
|
||||
if let Err(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
|
||||
err.emit_unless(
|
||||
ti.span
|
||||
.filter(|&s| {
|
||||
|
|
@ -562,7 +561,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Subtyping doesn't matter here, as the value is some kind of scalar.
|
||||
let demand_eqtype = |x: &mut _, y| {
|
||||
if let Some((ref mut fail, x_ty, x_span)) = *x
|
||||
&& let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
|
||||
&& let Err(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
|
||||
{
|
||||
if let Some((_, y_ty, y_span)) = y {
|
||||
self.endpoint_has_type(&mut err, y_span, y_ty);
|
||||
|
|
@ -736,7 +735,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Otherwise, the type of x is the expected type `T`.
|
||||
ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
|
||||
};
|
||||
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
|
||||
|
||||
// We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local.
|
||||
let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
|
||||
|
||||
// If there are multiple arms, make sure they all agree on
|
||||
// what the type of the binding `x` ought to be.
|
||||
|
|
@ -763,7 +764,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ti: &TopInfo<'tcx>,
|
||||
) {
|
||||
let var_ty = self.local_ty(span, var_id);
|
||||
if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
|
||||
if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
|
||||
let hir = self.tcx.hir();
|
||||
let var_ty = self.resolve_vars_if_possible(var_ty);
|
||||
let msg = format!("first introduced with type `{var_ty}` here");
|
||||
|
|
@ -986,13 +987,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
// Type-check the path.
|
||||
self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
|
||||
let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
|
||||
|
||||
// Type-check subpatterns.
|
||||
if self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
|
||||
pat_ty
|
||||
} else {
|
||||
Ty::new_misc_error(self.tcx)
|
||||
match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
|
||||
Ok(()) => pat_ty,
|
||||
Err(guar) => Ty::new_error(self.tcx, guar),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1050,7 +1050,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Type-check the path.
|
||||
let (pat_ty, pat_res) =
|
||||
self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
|
||||
if let Some(err) =
|
||||
if let Err(err) =
|
||||
self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
|
||||
{
|
||||
self.emit_bad_pat_path(err, pat, res, pat_res, pat_ty, segments);
|
||||
|
|
@ -1223,12 +1223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Type-check the tuple struct pattern against the expected type.
|
||||
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
|
||||
let had_err = if let Some(err) = diag {
|
||||
err.emit();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let had_err = diag.map_err(|diag| diag.emit());
|
||||
|
||||
// Type-check subpatterns.
|
||||
if subpats.len() == variant.fields.len()
|
||||
|
|
@ -1249,6 +1244,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
None,
|
||||
);
|
||||
}
|
||||
if let Err(e) = had_err {
|
||||
on_error(e);
|
||||
return Ty::new_error(tcx, e);
|
||||
}
|
||||
} else {
|
||||
let e = self.emit_err_pat_wrong_number_of_fields(
|
||||
pat.span,
|
||||
|
|
@ -1273,7 +1272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
subpats: &'tcx [Pat<'tcx>],
|
||||
fields: &'tcx [ty::FieldDef],
|
||||
expected: Ty<'tcx>,
|
||||
had_err: bool,
|
||||
had_err: Result<(), ErrorGuaranteed>,
|
||||
) -> ErrorGuaranteed {
|
||||
let subpats_ending = pluralize!(subpats.len());
|
||||
let fields_ending = pluralize!(fields.len());
|
||||
|
|
@ -1330,7 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// #67037: only do this if we could successfully type-check the expected type against
|
||||
// the tuple struct pattern. Otherwise the args could get out of range on e.g.,
|
||||
// `let P() = U;` where `P != U` with `struct P<T>(T);`.
|
||||
(ty::Adt(_, args), [field], false) => {
|
||||
(ty::Adt(_, args), [field], Ok(())) => {
|
||||
let field_ty = self.field_ty(pat_span, field, args);
|
||||
match field_ty.kind() {
|
||||
ty::Tuple(fields) => fields.len() == subpats.len(),
|
||||
|
|
@ -1445,8 +1444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
|
||||
let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
|
||||
let pat_ty = Ty::new_tup(tcx, element_tys);
|
||||
if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
|
||||
let reported = err.emit();
|
||||
if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, pat_info.top_info) {
|
||||
// Walk subpatterns with an expected type of `err` in this case to silence
|
||||
// further errors being emitted when using the bindings. #50333
|
||||
let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
|
||||
|
|
@ -1470,7 +1468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
has_rest_pat: bool,
|
||||
pat_info: PatInfo<'tcx, '_>,
|
||||
) -> bool {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let ty::Adt(adt, args) = adt_ty.kind() else {
|
||||
|
|
@ -1486,7 +1484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Keep track of which fields have already appeared in the pattern.
|
||||
let mut used_fields = FxHashMap::default();
|
||||
let mut no_field_errors = true;
|
||||
let mut result = Ok(());
|
||||
|
||||
let mut inexistent_fields = vec![];
|
||||
// Typecheck each field.
|
||||
|
|
@ -1495,8 +1493,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ident = tcx.adjust_ident(field.ident, variant.def_id);
|
||||
let field_ty = match used_fields.entry(ident) {
|
||||
Occupied(occupied) => {
|
||||
no_field_errors = false;
|
||||
let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
|
||||
result = Err(guar);
|
||||
Ty::new_error(tcx, guar)
|
||||
}
|
||||
Vacant(vacant) => {
|
||||
|
|
@ -1511,7 +1509,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
})
|
||||
.unwrap_or_else(|| {
|
||||
inexistent_fields.push(field);
|
||||
no_field_errors = false;
|
||||
Ty::new_misc_error(tcx)
|
||||
})
|
||||
}
|
||||
|
|
@ -1585,37 +1582,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
match (inexistent_fields_err, unmentioned_err) {
|
||||
(Some(i), Some(u)) => {
|
||||
if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
// We don't want to show the nonexistent fields error when this was
|
||||
// `Foo { a, b }` when it should have been `Foo(a, b)`.
|
||||
i.delay_as_bug();
|
||||
u.delay_as_bug();
|
||||
e.emit();
|
||||
Err(e)
|
||||
} else {
|
||||
i.emit();
|
||||
u.emit();
|
||||
Err(u.emit())
|
||||
}
|
||||
}
|
||||
(None, Some(u)) => {
|
||||
if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
u.delay_as_bug();
|
||||
e.emit();
|
||||
Err(e)
|
||||
} else {
|
||||
u.emit();
|
||||
Err(u.emit())
|
||||
}
|
||||
}
|
||||
(Some(err), None) => {
|
||||
err.emit();
|
||||
(Some(err), None) => Err(err.emit()),
|
||||
(None, None) => {
|
||||
self.error_tuple_variant_index_shorthand(variant, pat, fields)?;
|
||||
result
|
||||
}
|
||||
(None, None)
|
||||
if let Some(err) =
|
||||
self.error_tuple_variant_index_shorthand(variant, pat, fields) =>
|
||||
{
|
||||
err.emit();
|
||||
}
|
||||
(None, None) => {}
|
||||
}
|
||||
no_field_errors
|
||||
}
|
||||
|
||||
fn error_tuple_variant_index_shorthand(
|
||||
|
|
@ -1623,7 +1614,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
variant: &VariantDef,
|
||||
pat: &'_ Pat<'_>,
|
||||
fields: &[hir::PatField<'_>],
|
||||
) -> Option<Diag<'_>> {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
// if this is a tuple struct, then all field names will be numbers
|
||||
// so if any fields in a struct pattern use shorthand syntax, they will
|
||||
// be invalid identifiers (for example, Foo { 0, 1 }).
|
||||
|
|
@ -1645,10 +1636,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return Some(err);
|
||||
return Err(err.emit());
|
||||
}
|
||||
}
|
||||
None
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {
|
||||
|
|
@ -1804,14 +1795,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pat: &Pat<'_>,
|
||||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
variant: &ty::VariantDef,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
|
||||
(variant.ctor_kind(), &pat.kind)
|
||||
{
|
||||
let is_tuple_struct_match = !pattern_fields.is_empty()
|
||||
&& pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number);
|
||||
if is_tuple_struct_match {
|
||||
return None;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
|
||||
|
|
@ -1839,9 +1830,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
format!("({sugg})"),
|
||||
appl,
|
||||
);
|
||||
return Some(err);
|
||||
return Err(err.emit());
|
||||
}
|
||||
None
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_suggested_tuple_struct_pattern(
|
||||
|
|
@ -2065,20 +2056,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pat_info: PatInfo<'tcx, '_>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
|
||||
Ok(()) => {
|
||||
let (box_ty, inner_ty) = self
|
||||
.check_dereferenceable(span, expected, inner)
|
||||
.and_then(|()| {
|
||||
// Here, `demand::subtype` is good enough, but I don't
|
||||
// think any errors can be introduced by using `demand::eqtype`.
|
||||
let inner_ty = self.next_ty_var(inner.span);
|
||||
let box_ty = Ty::new_box(tcx, inner_ty);
|
||||
self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info);
|
||||
(box_ty, inner_ty)
|
||||
}
|
||||
Err(guar) => {
|
||||
self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info)?;
|
||||
Ok((box_ty, inner_ty))
|
||||
})
|
||||
.unwrap_or_else(|guar| {
|
||||
let err = Ty::new_error(tcx, guar);
|
||||
(err, err)
|
||||
}
|
||||
};
|
||||
});
|
||||
self.check_pat(inner, inner_ty, pat_info);
|
||||
box_ty
|
||||
}
|
||||
|
|
@ -2222,7 +2213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
if let Err(mut err) = err {
|
||||
self.borrow_pat_suggestion(&mut err, pat);
|
||||
err.emit();
|
||||
}
|
||||
|
|
@ -2327,7 +2318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.try_resolve_slice_ty_to_array_ty(before, slice, span)
|
||||
{
|
||||
debug!(?resolved_arr_ty);
|
||||
self.demand_eqtype(span, expected, resolved_arr_ty);
|
||||
let _ = self.demand_eqtype(span, expected, resolved_arr_ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,21 @@ impl Parse for Newtype {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a new index from a given `u16`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Will panic if `value` exceeds `MAX`.
|
||||
#[inline]
|
||||
#vis const fn from_u16(value: u16) -> Self {
|
||||
let value = value as u32;
|
||||
assert!(value <= #max);
|
||||
// SAFETY: We just checked that `value <= max`.
|
||||
unsafe {
|
||||
Self::from_u32_unchecked(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new index from a given `u32`.
|
||||
///
|
||||
/// # Safety
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ rustc_macros = { path = "../rustc_macros" }
|
|||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_type_ir = { path = "../rustc_type_ir" }
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -212,19 +212,63 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
|||
T: ToTrace<'tcx>,
|
||||
{
|
||||
match variance {
|
||||
ty::Variance::Covariant => self.sub(define_opaque_types, expected, actual),
|
||||
ty::Variance::Invariant => self.eq(define_opaque_types, expected, actual),
|
||||
ty::Variance::Contravariant => self.sup(define_opaque_types, expected, actual),
|
||||
ty::Covariant => self.sub(define_opaque_types, expected, actual),
|
||||
ty::Invariant => self.eq(define_opaque_types, expected, actual),
|
||||
ty::Contravariant => self.sup(define_opaque_types, expected, actual),
|
||||
|
||||
// We could make this make sense but it's not readily
|
||||
// exposed and I don't feel like dealing with it. Note
|
||||
// that bivariance in general does a bit more than just
|
||||
// *nothing*, it checks that the types are the same
|
||||
// "modulo variance" basically.
|
||||
ty::Variance::Bivariant => panic!("Bivariant given to `relate()`"),
|
||||
ty::Bivariant => panic!("Bivariant given to `relate()`"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Used in the new solver since we don't care about tracking an `ObligationCause`.
|
||||
pub fn relate_no_trace<T>(
|
||||
self,
|
||||
expected: T,
|
||||
variance: ty::Variance,
|
||||
actual: T,
|
||||
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
|
||||
where
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
let mut fields = CombineFields::new(
|
||||
self.infcx,
|
||||
TypeTrace::dummy(self.cause),
|
||||
self.param_env,
|
||||
DefineOpaqueTypes::Yes,
|
||||
);
|
||||
fields.sub().relate_with_variance(
|
||||
variance,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
expected,
|
||||
actual,
|
||||
)?;
|
||||
Ok(fields.goals)
|
||||
}
|
||||
|
||||
/// Used in the new solver since we don't care about tracking an `ObligationCause`.
|
||||
pub fn eq_structurally_relating_aliases_no_trace<T>(
|
||||
self,
|
||||
expected: T,
|
||||
actual: T,
|
||||
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
|
||||
where
|
||||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
let mut fields = CombineFields::new(
|
||||
self.infcx,
|
||||
TypeTrace::dummy(self.cause),
|
||||
self.param_env,
|
||||
DefineOpaqueTypes::Yes,
|
||||
);
|
||||
fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?;
|
||||
Ok(fields.goals)
|
||||
}
|
||||
|
||||
/// Computes the least-upper-bound, or mutual supertype, of two
|
||||
/// values. The order of the arguments doesn't matter, but since
|
||||
/// this can result in an error (e.g., if asked to compute LUB of
|
||||
|
|
@ -303,7 +347,7 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -315,7 +359,10 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
|
|||
a: Self,
|
||||
b: Self,
|
||||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace { cause: cause.clone(), values: Regions(ExpectedFound::new(a_is_expected, a, b)) }
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -328,7 +375,7 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -344,13 +391,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
|
|||
cause: cause.clone(),
|
||||
values: match (a.unpack(), b.unpack()) {
|
||||
(GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
|
||||
Regions(ExpectedFound::new(a_is_expected, a, b))
|
||||
ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b))
|
||||
}
|
||||
(GenericArgKind::Type(a), GenericArgKind::Type(b)) => {
|
||||
Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
|
||||
ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
|
||||
}
|
||||
(GenericArgKind::Const(a), GenericArgKind::Const(b)) => {
|
||||
Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
|
||||
ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
|
||||
}
|
||||
|
||||
(
|
||||
|
|
@ -379,7 +426,10 @@ impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
|
|||
a: Self,
|
||||
b: Self,
|
||||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) }
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +442,7 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
|
||||
values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -406,7 +456,7 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -418,7 +468,10 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
|
|||
a: Self,
|
||||
b: Self,
|
||||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace { cause: cause.clone(), values: Aliases(ExpectedFound::new(a_is_expected, a, b)) }
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -431,7 +484,7 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: PolySigs(ExpectedFound::new(
|
||||
values: ValuePairs::PolySigs(ExpectedFound::new(
|
||||
a_is_expected,
|
||||
ty::Binder::dummy(a),
|
||||
ty::Binder::dummy(b),
|
||||
|
|
@ -449,7 +502,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: PolySigs(ExpectedFound::new(a_is_expected, a, b)),
|
||||
values: ValuePairs::PolySigs(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -463,7 +516,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)),
|
||||
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -477,7 +530,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)),
|
||||
values: ValuePairs::ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ use rustc_errors::{
|
|||
codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString,
|
||||
ErrorGuaranteed, IntoDiagArg, StringPart,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{self as hir, ParamName};
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
|
|
@ -1707,6 +1707,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
ValuePairs::ExistentialProjection(_) => {
|
||||
(false, Mismatch::Fixed("existential projection"))
|
||||
}
|
||||
ValuePairs::Dummy => {
|
||||
bug!("do not expect to report a type error from a ValuePairs::Dummy")
|
||||
}
|
||||
};
|
||||
let Some(vals) = self.values_str(values) else {
|
||||
// Derived error. Cancel the emitter.
|
||||
|
|
@ -2250,12 +2253,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
values: ValuePairs<'tcx>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
||||
match values {
|
||||
infer::Regions(exp_found) => self.expected_found_str(exp_found),
|
||||
infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
|
||||
infer::Aliases(exp_found) => self.expected_found_str(exp_found),
|
||||
infer::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
|
||||
infer::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
|
||||
infer::TraitRefs(exp_found) => {
|
||||
ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
|
||||
ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found),
|
||||
ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
|
||||
ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
|
||||
ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
|
||||
ValuePairs::TraitRefs(exp_found) => {
|
||||
let pretty_exp_found = ty::error::ExpectedFound {
|
||||
expected: exp_found.expected.print_trait_sugared(),
|
||||
found: exp_found.found.print_trait_sugared(),
|
||||
|
|
@ -2267,7 +2270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
ret => ret,
|
||||
}
|
||||
}
|
||||
infer::PolySigs(exp_found) => {
|
||||
ValuePairs::PolySigs(exp_found) => {
|
||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||
if exp_found.references_error() {
|
||||
return None;
|
||||
|
|
@ -2275,6 +2278,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
|
||||
Some((exp, fnd, None))
|
||||
}
|
||||
ValuePairs::Dummy => {
|
||||
bug!("do not expect to report a type error from a ValuePairs::Dummy")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2423,7 +2429,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
let (type_scope, type_param_sugg_span) = match bound_kind {
|
||||
GenericKind::Param(param) => {
|
||||
let generics = self.tcx.generics_of(generic_param_scope);
|
||||
let def_id = generics.type_param(param, self.tcx).def_id.expect_local();
|
||||
let type_param = generics.type_param(param, self.tcx);
|
||||
let def_id = type_param.def_id.expect_local();
|
||||
let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id;
|
||||
// Get the `hir::Param` to verify whether it already has any bounds.
|
||||
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
|
||||
|
|
@ -2433,7 +2440,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
|
||||
// If `param` corresponds to `Self`, no usable suggestion span.
|
||||
None if generics.has_self && param.index == 0 => None,
|
||||
None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false, None)),
|
||||
None => {
|
||||
let span = if let Some(param) =
|
||||
hir_generics.params.iter().find(|param| param.def_id == def_id)
|
||||
&& let ParamName::Plain(ident) = param.name
|
||||
{
|
||||
ident.span.shrink_to_hi()
|
||||
} else {
|
||||
let span = self.tcx.def_span(def_id);
|
||||
span.shrink_to_hi()
|
||||
};
|
||||
Some((span, false, None))
|
||||
}
|
||||
};
|
||||
(scope, sugg_span)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ impl<T> Trait<T> for X {
|
|||
for pred in hir_generics.bounds_for_param(def_id) {
|
||||
if self.constrain_generic_bound_associated_type_structured_suggestion(
|
||||
diag,
|
||||
&trait_ref,
|
||||
trait_ref,
|
||||
pred.bounds,
|
||||
assoc,
|
||||
assoc_args,
|
||||
|
|
@ -715,7 +715,7 @@ fn foo(&self) -> Self::T { String::new() }
|
|||
|
||||
self.constrain_generic_bound_associated_type_structured_suggestion(
|
||||
diag,
|
||||
&trait_ref,
|
||||
trait_ref,
|
||||
opaque_hir_ty.bounds,
|
||||
assoc,
|
||||
assoc_args,
|
||||
|
|
@ -869,7 +869,7 @@ fn foo(&self) -> Self::T { String::new() }
|
|||
fn constrain_generic_bound_associated_type_structured_suggestion(
|
||||
&self,
|
||||
diag: &mut Diag<'_>,
|
||||
trait_ref: &ty::TraitRef<'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
bounds: hir::GenericBounds<'_>,
|
||||
assoc: ty::AssocItem,
|
||||
assoc_args: &[ty::GenericArg<'tcx>],
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ pub use rustc_middle::ty::IntVarValue;
|
|||
pub use BoundRegionConversionTime::*;
|
||||
pub use RegionVariableOrigin::*;
|
||||
pub use SubregionOrigin::*;
|
||||
pub use ValuePairs::*;
|
||||
|
||||
use crate::infer::relate::RelateResult;
|
||||
use crate::infer::relate::{Relate, RelateResult};
|
||||
use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
|
||||
use error_reporting::TypeErrCtxt;
|
||||
use free_regions::RegionRelations;
|
||||
|
|
@ -35,6 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
|
|||
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::traits::select;
|
||||
use rustc_middle::traits::solve::{Goal, NoSolution};
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
|
|
@ -44,7 +44,7 @@ use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
|
|||
use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use snapshot::undo_log::InferCtxtUndoLogs;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt;
|
||||
|
|
@ -352,6 +352,13 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
|
||||
match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
|
||||
Err(universe) => Some(universe),
|
||||
Ok(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
|
||||
// Same issue as with `universe_of_ty`
|
||||
match self.probe_const_var(ct) {
|
||||
|
|
@ -360,19 +367,12 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
|
||||
match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
|
||||
Err(universe) => Some(universe),
|
||||
Ok(_) => None,
|
||||
}
|
||||
fn root_ty_var(&self, var: TyVid) -> TyVid {
|
||||
self.root_var(var)
|
||||
}
|
||||
|
||||
fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
|
||||
}
|
||||
|
||||
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
|
||||
self.defining_opaque_types
|
||||
fn root_const_var(&self, var: ConstVid) -> ConstVid {
|
||||
self.root_const_var(var)
|
||||
}
|
||||
|
||||
fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> Ty<'tcx> {
|
||||
|
|
@ -405,6 +405,76 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
|
||||
}
|
||||
|
||||
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
|
||||
self.defining_opaque_types
|
||||
}
|
||||
|
||||
fn next_ty_infer(&self) -> Ty<'tcx> {
|
||||
self.next_ty_var(DUMMY_SP)
|
||||
}
|
||||
|
||||
fn next_const_infer(&self) -> ty::Const<'tcx> {
|
||||
self.next_const_var(DUMMY_SP)
|
||||
}
|
||||
|
||||
fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
|
||||
self.fresh_args_for_item(DUMMY_SP, def_id)
|
||||
}
|
||||
|
||||
fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
|
||||
&self,
|
||||
value: ty::Binder<'tcx, T>,
|
||||
) -> T {
|
||||
self.instantiate_binder_with_fresh_vars(
|
||||
DUMMY_SP,
|
||||
BoundRegionConversionTime::HigherRankedType,
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
|
||||
&self,
|
||||
value: ty::Binder<'tcx, T>,
|
||||
f: impl FnOnce(T) -> U,
|
||||
) -> U {
|
||||
self.enter_forall(value, f)
|
||||
}
|
||||
|
||||
fn relate<T: Relate<TyCtxt<'tcx>>>(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
lhs: T,
|
||||
variance: ty::Variance,
|
||||
rhs: T,
|
||||
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
||||
self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs)
|
||||
}
|
||||
|
||||
fn eq_structurally_relating_aliases<T: Relate<TyCtxt<'tcx>>>(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
lhs: T,
|
||||
rhs: T,
|
||||
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
||||
self.at(&ObligationCause::dummy(), param_env)
|
||||
.eq_structurally_relating_aliases_no_trace(lhs, rhs)
|
||||
}
|
||||
|
||||
fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
self.resolve_vars_if_possible(value)
|
||||
}
|
||||
|
||||
fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
|
||||
self.probe(|_| probe())
|
||||
}
|
||||
}
|
||||
|
||||
/// See the `error_reporting` module for more details.
|
||||
|
|
@ -417,6 +487,7 @@ pub enum ValuePairs<'tcx> {
|
|||
PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
|
||||
ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
|
||||
ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
|
||||
Dummy,
|
||||
}
|
||||
|
||||
impl<'tcx> ValuePairs<'tcx> {
|
||||
|
|
@ -810,13 +881,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
.collect();
|
||||
vars.extend(
|
||||
(0..inner.int_unification_table().len())
|
||||
.map(|i| ty::IntVid::from_u32(i as u32))
|
||||
.map(|i| ty::IntVid::from_usize(i))
|
||||
.filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
|
||||
.map(|v| Ty::new_int_var(self.tcx, v)),
|
||||
);
|
||||
vars.extend(
|
||||
(0..inner.float_unification_table().len())
|
||||
.map(|i| ty::FloatVid::from_u32(i as u32))
|
||||
.map(|i| ty::FloatVid::from_usize(i))
|
||||
.filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
|
||||
.map(|v| Ty::new_float_var(self.tcx, v)),
|
||||
);
|
||||
|
|
@ -1812,7 +1883,7 @@ impl<'tcx> TypeTrace<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1824,7 +1895,7 @@ impl<'tcx> TypeTrace<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
|
||||
values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1836,9 +1907,13 @@ impl<'tcx> TypeTrace<'tcx> {
|
|||
) -> TypeTrace<'tcx> {
|
||||
TypeTrace {
|
||||
cause: cause.clone(),
|
||||
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||
}
|
||||
}
|
||||
|
||||
fn dummy(cause: &ObligationCause<'tcx>) -> TypeTrace<'tcx> {
|
||||
TypeTrace { cause: cause.clone(), values: ValuePairs::Dummy }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> SubregionOrigin<'tcx> {
|
||||
|
|
|
|||
|
|
@ -345,7 +345,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
.args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(i, _)| variances[*i] == ty::Variance::Invariant)
|
||||
.filter(|(i, _)| variances[*i] == ty::Invariant)
|
||||
.filter_map(|(_, arg)| match arg.unpack() {
|
||||
GenericArgKind::Lifetime(r) => Some(r),
|
||||
GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
|
||||
|
|
@ -441,7 +441,7 @@ where
|
|||
let variances = self.tcx.variances_of(*def_id);
|
||||
|
||||
for (v, s) in std::iter::zip(variances, args.iter()) {
|
||||
if *v != ty::Variance::Bivariant {
|
||||
if *v != ty::Bivariant {
|
||||
s.visit_with(self);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,9 +102,7 @@ where
|
|||
};
|
||||
|
||||
for (idx, s) in args.iter().enumerate() {
|
||||
if variances.map(|variances| variances[idx])
|
||||
!= Some(ty::Variance::Bivariant)
|
||||
{
|
||||
if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) {
|
||||
s.visit_with(self);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,16 +83,16 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// mention `?0`.
|
||||
if self.next_trait_solver() {
|
||||
let (lhs, rhs, direction) = match instantiation_variance {
|
||||
ty::Variance::Invariant => {
|
||||
ty::Invariant => {
|
||||
(generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate)
|
||||
}
|
||||
ty::Variance::Covariant => {
|
||||
ty::Covariant => {
|
||||
(generalized_ty.into(), source_ty.into(), AliasRelationDirection::Subtype)
|
||||
}
|
||||
ty::Variance::Contravariant => {
|
||||
ty::Contravariant => {
|
||||
(source_ty.into(), generalized_ty.into(), AliasRelationDirection::Subtype)
|
||||
}
|
||||
ty::Variance::Bivariant => unreachable!("bivariant generalization"),
|
||||
ty::Bivariant => unreachable!("bivariant generalization"),
|
||||
};
|
||||
|
||||
relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
|
||||
|
|
@ -192,7 +192,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
relation.span(),
|
||||
relation.structurally_relate_aliases(),
|
||||
target_vid,
|
||||
ty::Variance::Invariant,
|
||||
ty::Invariant,
|
||||
source_ct,
|
||||
)?;
|
||||
|
||||
|
|
@ -210,14 +210,14 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// generalized const and the source.
|
||||
if target_is_expected {
|
||||
relation.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
generalized_ct,
|
||||
source_ct,
|
||||
)?;
|
||||
} else {
|
||||
relation.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
source_ct,
|
||||
generalized_ct,
|
||||
|
|
@ -411,7 +411,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
|
|||
a_arg: ty::GenericArgsRef<'tcx>,
|
||||
b_arg: ty::GenericArgsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
|
||||
if self.ambient_variance == ty::Variance::Invariant {
|
||||
if self.ambient_variance == ty::Invariant {
|
||||
// Avoid fetching the variance if we are in an invariant
|
||||
// context; no need, and it can induce dependency cycles
|
||||
// (e.g., #41849).
|
||||
|
|
@ -667,7 +667,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
|
|||
// structural.
|
||||
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
|
||||
let args = self.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
args,
|
||||
args,
|
||||
|
|
|
|||
|
|
@ -94,12 +94,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
|
|||
// When higher-ranked types are involved, computing the GLB is
|
||||
// very challenging, switch to invariance. This is obviously
|
||||
// overly conservative but works ok in practice.
|
||||
self.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a,
|
||||
b,
|
||||
)?;
|
||||
self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
|
||||
Ok(a)
|
||||
} else {
|
||||
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||
|
|
|
|||
|
|
@ -94,12 +94,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
|
|||
// When higher-ranked types are involved, computing the LUB is
|
||||
// very challenging, switch to invariance. This is obviously
|
||||
// overly conservative but works ok in practice.
|
||||
self.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a,
|
||||
b,
|
||||
)?;
|
||||
self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
|
||||
Ok(a)
|
||||
} else {
|
||||
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||
|
|
|
|||
|
|
@ -4,11 +4,9 @@
|
|||
|
||||
pub use rustc_middle::ty::relate::*;
|
||||
|
||||
pub use self::_match::MatchAgainstFreshVars;
|
||||
pub use self::combine::CombineFields;
|
||||
pub use self::combine::PredicateEmittingRelation;
|
||||
|
||||
pub mod _match;
|
||||
pub(super) mod combine;
|
||||
mod generalize;
|
||||
mod glb;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
|
|||
a_arg: ty::GenericArgsRef<'tcx>,
|
||||
b_arg: ty::GenericArgsRef<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
|
||||
if self.ambient_variance == ty::Variance::Invariant {
|
||||
if self.ambient_variance == ty::Invariant {
|
||||
// Avoid fetching the variance if we are in an invariant
|
||||
// context; no need, and it can induce dependency cycles
|
||||
// (e.g., #41849).
|
||||
|
|
@ -325,23 +325,23 @@ impl<'tcx> PredicateEmittingRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
|
|||
|
||||
fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
|
||||
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
|
||||
ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
|
||||
ty::Covariant => ty::PredicateKind::AliasRelate(
|
||||
a.into(),
|
||||
b.into(),
|
||||
ty::AliasRelationDirection::Subtype,
|
||||
),
|
||||
// a :> b is b <: a
|
||||
ty::Variance::Contravariant => ty::PredicateKind::AliasRelate(
|
||||
ty::Contravariant => ty::PredicateKind::AliasRelate(
|
||||
b.into(),
|
||||
a.into(),
|
||||
ty::AliasRelationDirection::Subtype,
|
||||
),
|
||||
ty::Variance::Invariant => ty::PredicateKind::AliasRelate(
|
||||
ty::Invariant => ty::PredicateKind::AliasRelate(
|
||||
a.into(),
|
||||
b.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
ty::Variance::Bivariant => {
|
||||
ty::Bivariant => {
|
||||
unreachable!("Expected bivariance to be handled in relate_with_variance")
|
||||
}
|
||||
})]);
|
||||
|
|
|
|||
|
|
@ -285,8 +285,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
let obligations =
|
||||
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
|
||||
elaboratable.child_with_derived_cause(
|
||||
clause
|
||||
.instantiate_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
|
||||
clause.instantiate_supertrait(tcx, bound_clause.rebind(data.trait_ref)),
|
||||
span,
|
||||
bound_clause.rebind(data),
|
||||
index,
|
||||
|
|
|
|||
|
|
@ -550,6 +550,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho
|
|||
.bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
|
||||
.exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration
|
||||
.const_anon = use a const-anon item to suppress this lint
|
||||
.macro_to_change = the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed
|
||||
|
||||
lint_non_local_definitions_impl_move_help =
|
||||
move the `impl` block outside of this {$body_kind_descr} {$depth ->
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
LateContext, LateLintPass, LintContext,
|
||||
};
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::lint::FutureIncompatibilityReason;
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
|
|
@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
|
|||
// the trait is a `Deref` implementation
|
||||
&& let Some(trait_) = &impl_.of_trait
|
||||
&& let Some(did) = trait_.trait_def_id()
|
||||
&& Some(did) == tcx.lang_items().deref_trait()
|
||||
&& tcx.is_lang_item(did, LangItem::Deref)
|
||||
// the self type is `dyn t_principal`
|
||||
&& let self_ty = tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind()
|
||||
|
|
|
|||
|
|
@ -1362,6 +1362,7 @@ pub enum NonLocalDefinitionsDiag {
|
|||
has_trait: bool,
|
||||
self_ty_str: String,
|
||||
of_trait_str: Option<String>,
|
||||
macro_to_change: Option<(String, &'static str)>,
|
||||
},
|
||||
MacroRules {
|
||||
depth: u32,
|
||||
|
|
@ -1387,6 +1388,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
|
|||
has_trait,
|
||||
self_ty_str,
|
||||
of_trait_str,
|
||||
macro_to_change,
|
||||
} => {
|
||||
diag.primary_message(fluent::lint_non_local_definitions_impl);
|
||||
diag.arg("depth", depth);
|
||||
|
|
@ -1397,6 +1399,15 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
|
|||
diag.arg("of_trait_str", of_trait_str);
|
||||
}
|
||||
|
||||
if let Some((macro_to_change, macro_kind)) = macro_to_change {
|
||||
diag.arg("macro_to_change", macro_to_change);
|
||||
diag.arg("macro_kind", macro_kind);
|
||||
diag.note(fluent::lint_macro_to_change);
|
||||
}
|
||||
if let Some(cargo_update) = cargo_update {
|
||||
diag.subdiagnostic(&diag.dcx, cargo_update);
|
||||
}
|
||||
|
||||
if has_trait {
|
||||
diag.note(fluent::lint_bounds);
|
||||
diag.note(fluent::lint_with_trait);
|
||||
|
|
@ -1422,9 +1433,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
|
|||
);
|
||||
}
|
||||
|
||||
if let Some(cargo_update) = cargo_update {
|
||||
diag.subdiagnostic(&diag.dcx, cargo_update);
|
||||
}
|
||||
if let Some(const_anon) = const_anon {
|
||||
diag.note(fluent::lint_exception);
|
||||
if let Some(const_anon) = const_anon {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused};
|
|||
use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
|
|
@ -53,8 +53,8 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
|
|||
if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
|
||||
let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id);
|
||||
|
||||
if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
|
||||
|| Some(def_id) == cx.tcx.lang_items().panic_fn()
|
||||
if cx.tcx.is_lang_item(def_id, LangItem::BeginPanic)
|
||||
|| cx.tcx.is_lang_item(def_id, LangItem::Panic)
|
||||
|| f_diagnostic_name == Some(sym::panic_str_2015)
|
||||
{
|
||||
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
|
||||
|
|
@ -153,7 +153,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
ty::Ref(_, r, _) if r.is_str(),
|
||||
) || matches!(
|
||||
ty.ty_adt_def(),
|
||||
Some(ty_def) if Some(ty_def.did()) == cx.tcx.lang_items().string(),
|
||||
Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String),
|
||||
);
|
||||
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
|
|
|
|||
|
|
@ -258,6 +258,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
|
|||
Some((cx.tcx.def_span(parent), may_move))
|
||||
};
|
||||
|
||||
let macro_to_change =
|
||||
if let ExpnKind::Macro(kind, name) = item.span.ctxt().outer_expn_data().kind {
|
||||
Some((name.to_string(), kind.descr()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
cx.emit_span_lint(
|
||||
NON_LOCAL_DEFINITIONS,
|
||||
ms,
|
||||
|
|
@ -274,6 +281,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
|
|||
move_to,
|
||||
may_remove,
|
||||
has_trait: impl_.of_trait.is_some(),
|
||||
macro_to_change,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ declare_lint! {
|
|||
/// Since Rust 1.80.0, boxed slices implement `IntoIterator`. However, to avoid
|
||||
/// breakage, `boxed_slice.into_iter()` in Rust 2015, 2018, and 2021 code will still
|
||||
/// behave as `(&boxed_slice).into_iter()`, returning an iterator over
|
||||
/// references, just like in Rust 1.80.0 and earlier.
|
||||
/// references, just like in Rust 1.79.0 and earlier.
|
||||
/// This only applies to the method call syntax `boxed_slice.into_iter()`, not to
|
||||
/// any other syntax such as `for _ in boxed_slice` or `IntoIterator::into_iter(boxed_slice)`.
|
||||
pub BOXED_SLICE_INTO_ITER,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::lints::{DropGlue, DropTraitConstraintsDiag};
|
|||
use crate::LateContext;
|
||||
use crate::LateLintPass;
|
||||
use crate::LintContext;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
|||
continue;
|
||||
};
|
||||
let def_id = trait_predicate.trait_ref.def_id;
|
||||
if cx.tcx.lang_items().drop_trait() == Some(def_id) {
|
||||
if cx.tcx.is_lang_item(def_id, LangItem::Drop) {
|
||||
// Explicitly allow `impl Drop`, a drop-guards-as-unnameable-type pattern.
|
||||
if trait_predicate.trait_ref.self_ty().is_impl_trait() {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ use rustc_ast as ast;
|
|||
use rustc_ast::util::{classify, parser};
|
||||
use rustc_ast::{ExprKind, StmtKind};
|
||||
use rustc_errors::{pluralize, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_infer::traits::util::elaborate;
|
||||
use rustc_middle::ty::adjustment;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
|
@ -289,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
is_ty_must_use(cx, boxed_ty, expr, span)
|
||||
.map(|inner| MustUsePath::Boxed(Box::new(inner)))
|
||||
}
|
||||
ty::Adt(def, args) if cx.tcx.lang_items().pin_type() == Some(def.did()) => {
|
||||
ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {
|
||||
let pinned_ty = args.type_at(0);
|
||||
is_ty_must_use(cx, pinned_ty, expr, span)
|
||||
.map(|inner| MustUsePath::Pinned(Box::new(inner)))
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ declare_lint_pass! {
|
|||
CONST_EVALUATABLE_UNCHECKED,
|
||||
CONST_ITEM_MUTATION,
|
||||
DEAD_CODE,
|
||||
DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
|
||||
DEPRECATED,
|
||||
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
|
||||
DEPRECATED_IN_FUTURE,
|
||||
|
|
@ -3257,7 +3258,11 @@ declare_lint! {
|
|||
/// See the [Checking Conditional Configurations][check-cfg] section for more
|
||||
/// details.
|
||||
///
|
||||
/// See the [Cargo Specifics][unexpected_cfgs_lint_config] section for configuring this lint in
|
||||
/// `Cargo.toml`.
|
||||
///
|
||||
/// [check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html
|
||||
/// [unexpected_cfgs_lint_config]: https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html#check-cfg-in-lintsrust-table
|
||||
pub UNEXPECTED_CFGS,
|
||||
Warn,
|
||||
"detects unexpected names and values in `#[cfg]` conditions",
|
||||
|
|
@ -4195,6 +4200,59 @@ declare_lint! {
|
|||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `dependency_on_unit_never_type_fallback` lint detects cases where code compiles with
|
||||
/// [never type fallback] being [`()`], but will stop compiling with fallback being [`!`].
|
||||
///
|
||||
/// [never type fallback]: https://doc.rust-lang.org/nightly/core/primitive.never.html#never-type-fallback
|
||||
/// [`!`]: https://doc.rust-lang.org/core/primitive.never.html
|
||||
/// [`()`]: https://doc.rust-lang.org/core/primitive.unit.html
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(dependency_on_unit_never_type_fallback)]
|
||||
/// fn main() {
|
||||
/// if true {
|
||||
/// // return has type `!` which, is some cases, causes never type fallback
|
||||
/// return
|
||||
/// } else {
|
||||
/// // the type produced by this call is not specified explicitly,
|
||||
/// // so it will be inferred from the previous branch
|
||||
/// Default::default()
|
||||
/// };
|
||||
/// // depending on the fallback, this may compile (because `()` implements `Default`),
|
||||
/// // or it may not (because `!` does not implement `Default`)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Due to historic reasons never type fallback was `()`, meaning that `!` got spontaneously
|
||||
/// coerced to `()`. There are plans to change that, but they may make the code such as above
|
||||
/// not compile. Instead of depending on the fallback, you should specify the type explicitly:
|
||||
/// ```
|
||||
/// if true {
|
||||
/// return
|
||||
/// } else {
|
||||
/// // type is explicitly specified, fallback can't hurt us no more
|
||||
/// <() as Default>::default()
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// See [Tracking Issue for making `!` fall back to `!`](https://github.com/rust-lang/rust/issues/123748).
|
||||
pub DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
|
||||
Warn,
|
||||
"never type fallback affecting unsafe function calls",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
|
||||
reference: "issue #123748 <https://github.com/rust-lang/rust/issues/123748>",
|
||||
};
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `byte_slice_in_packed_struct_with_derive` lint detects cases where a byte slice field
|
||||
/// (`[u8]`) or string slice field (`str`) is used in a `packed` struct that derives one or
|
||||
|
|
|
|||
|
|
@ -539,7 +539,7 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
|
|||
} else {
|
||||
SpanData::decode(self)
|
||||
};
|
||||
Span::new(data.lo, data.hi, data.ctxt, data.parent)
|
||||
data.span()
|
||||
}
|
||||
|
||||
fn decode_symbol(&mut self) -> Symbol {
|
||||
|
|
@ -669,7 +669,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
|
|||
let lo = lo + source_file.translated_source_file.start_pos;
|
||||
let hi = hi + source_file.translated_source_file.start_pos;
|
||||
|
||||
// Do not try to decode parent for foreign spans.
|
||||
// Do not try to decode parent for foreign spans (it wasn't encoded in the first place).
|
||||
SpanData { lo, hi, ctxt, parent: None }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2020,7 +2020,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
|
||||
// if this is an impl of `CoerceUnsized`, create its
|
||||
// "unsized info", else just store None
|
||||
if Some(trait_ref.def_id) == tcx.lang_items().coerce_unsized_trait() {
|
||||
if tcx.is_lang_item(trait_ref.def_id, LangItem::CoerceUnsized) {
|
||||
let coerce_unsized_info = tcx.coerce_unsized_info(def_id).unwrap();
|
||||
record!(self.tables.coerce_unsized_info[def_id] <- coerce_unsized_info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn is_lang_item(self, def_id: DefId, lang_item: LangItem) -> bool {
|
||||
self.lang_items().get(lang_item) == Some(def_id)
|
||||
}
|
||||
|
||||
/// Given a [`DefId`] of one of the [`Fn`], [`FnMut`] or [`FnOnce`] traits,
|
||||
/// returns a corresponding [`ty::ClosureKind`].
|
||||
/// For any other [`DefId`] return `None`.
|
||||
|
|
|
|||
|
|
@ -69,6 +69,13 @@ impl<Prov: Provenance> fmt::LowerHex for Scalar<Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Prov> From<Half> for Scalar<Prov> {
|
||||
#[inline(always)]
|
||||
fn from(f: Half) -> Self {
|
||||
Scalar::from_f16(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Prov> From<Single> for Scalar<Prov> {
|
||||
#[inline(always)]
|
||||
fn from(f: Single) -> Self {
|
||||
|
|
@ -83,6 +90,13 @@ impl<Prov> From<Double> for Scalar<Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Prov> From<Quad> for Scalar<Prov> {
|
||||
#[inline(always)]
|
||||
fn from(f: Quad) -> Self {
|
||||
Scalar::from_f128(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Prov> From<ScalarInt> for Scalar<Prov> {
|
||||
#[inline(always)]
|
||||
fn from(ptr: ScalarInt) -> Self {
|
||||
|
|
|
|||
|
|
@ -1287,7 +1287,7 @@ fn use_verbose(ty: Ty<'_>, fn_def: bool) -> bool {
|
|||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _location: Location) {
|
||||
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _location: Location) {
|
||||
let ConstOperand { span, user_ty, const_ } = constant;
|
||||
if use_verbose(const_.ty(), true) {
|
||||
self.push("mir::ConstOperand");
|
||||
|
|
@ -1415,7 +1415,7 @@ pub fn write_allocations<'tcx>(
|
|||
struct CollectAllocIds(BTreeSet<AllocId>);
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
||||
fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
|
||||
fn visit_const_operand(&mut self, c: &ConstOperand<'tcx>, _: Location) {
|
||||
match c.const_ {
|
||||
Const::Ty(_, _) | Const::Unevaluated(..) => {}
|
||||
Const::Val(val, _) => {
|
||||
|
|
|
|||
|
|
@ -1490,7 +1490,8 @@ pub enum BinOp {
|
|||
BitOr,
|
||||
/// The `<<` operator (shift left)
|
||||
///
|
||||
/// The offset is (uniquely) determined as follows:
|
||||
/// The offset is given by `RHS.rem_euclid(LHS::BITS)`.
|
||||
/// In other words, it is (uniquely) determined as follows:
|
||||
/// - it is "equal modulo LHS::BITS" to the RHS
|
||||
/// - it is in the range `0..LHS::BITS`
|
||||
Shl,
|
||||
|
|
@ -1498,7 +1499,8 @@ pub enum BinOp {
|
|||
ShlUnchecked,
|
||||
/// The `>>` operator (shift right)
|
||||
///
|
||||
/// The offset is (uniquely) determined as follows:
|
||||
/// The offset is given by `RHS.rem_euclid(LHS::BITS)`.
|
||||
/// In other words, it is (uniquely) determined as follows:
|
||||
/// - it is "equal modulo LHS::BITS" to the RHS
|
||||
/// - it is in the range `0..LHS::BITS`
|
||||
///
|
||||
|
|
|
|||
|
|
@ -184,12 +184,12 @@ macro_rules! make_mir_visitor {
|
|||
|
||||
/// This is called for every constant in the MIR body and every `required_consts`
|
||||
/// (i.e., including consts that have been dead-code-eliminated).
|
||||
fn visit_constant(
|
||||
fn visit_const_operand(
|
||||
&mut self,
|
||||
constant: & $($mutability)? ConstOperand<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
self.super_constant(constant, location);
|
||||
self.super_const_operand(constant, location);
|
||||
}
|
||||
|
||||
fn visit_ty_const(
|
||||
|
|
@ -597,7 +597,7 @@ macro_rules! make_mir_visitor {
|
|||
}
|
||||
InlineAsmOperand::Const { value }
|
||||
| InlineAsmOperand::SymFn { value } => {
|
||||
self.visit_constant(value, location);
|
||||
self.visit_const_operand(value, location);
|
||||
}
|
||||
InlineAsmOperand::Out { place: None, .. }
|
||||
| InlineAsmOperand::SymStatic { def_id: _ }
|
||||
|
|
@ -788,7 +788,7 @@ macro_rules! make_mir_visitor {
|
|||
);
|
||||
}
|
||||
Operand::Constant(constant) => {
|
||||
self.visit_constant(constant, location);
|
||||
self.visit_const_operand(constant, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -867,7 +867,7 @@ macro_rules! make_mir_visitor {
|
|||
}
|
||||
}
|
||||
match value {
|
||||
VarDebugInfoContents::Const(c) => self.visit_constant(c, location),
|
||||
VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
|
||||
VarDebugInfoContents::Place(place) =>
|
||||
self.visit_place(
|
||||
place,
|
||||
|
|
@ -882,7 +882,7 @@ macro_rules! make_mir_visitor {
|
|||
_scope: $(& $mutability)? SourceScope
|
||||
) {}
|
||||
|
||||
fn super_constant(
|
||||
fn super_const_operand(
|
||||
&mut self,
|
||||
constant: & $($mutability)? ConstOperand<'tcx>,
|
||||
location: Location
|
||||
|
|
@ -1057,7 +1057,7 @@ macro_rules! super_body {
|
|||
|
||||
for const_ in &$($mutability)? $body.required_consts {
|
||||
let location = Location::START;
|
||||
$self.visit_constant(const_, location);
|
||||
$self.visit_const_operand(const_, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -360,6 +360,14 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for ty::TraitRef<'tcx> {
|
||||
type Cache<V> = DefaultCache<Self, V>;
|
||||
|
||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
tcx.def_span(self.def_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
|
||||
type Cache<V> = DefaultCache<Self, V>;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ use crate::traits::{
|
|||
};
|
||||
use crate::ty::fast_reject::SimplifiedType;
|
||||
use crate::ty::layout::ValidityRequirement;
|
||||
use crate::ty::print::PrintTraitRefExt;
|
||||
use crate::ty::util::AlwaysRequiresDrop;
|
||||
use crate::ty::TyCtxtFeed;
|
||||
use crate::ty::{
|
||||
|
|
@ -1271,7 +1272,11 @@ rustc_queries! {
|
|||
desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) }
|
||||
}
|
||||
|
||||
query vtable_trait_upcasting_coercion_new_vptr_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option<usize> {
|
||||
query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize {
|
||||
desc { |tcx| "finding the slot within the vtable of `{}` for the implementation of `{}`", key.self_ty(), key.print_only_trait_name() }
|
||||
}
|
||||
|
||||
query supertrait_vtable_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option<usize> {
|
||||
desc { |tcx| "finding the slot within vtable for trait object `{}` vtable ptr during trait upcasting coercion from `{}` vtable",
|
||||
key.1, key.0 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> {
|
|||
|
||||
#[derive(Copy, Clone, Debug, HashStable)]
|
||||
pub struct MethodAutoderefStepsResult<'tcx> {
|
||||
/// The valid autoderef steps that could be find.
|
||||
/// The valid autoderef steps that could be found.
|
||||
pub steps: &'tcx [CandidateStep<'tcx>],
|
||||
/// If Some(T), a type autoderef reported an error on.
|
||||
pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ impl<'tcx> Elaborator<'tcx> {
|
|||
let super_predicates =
|
||||
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
|
||||
|&(pred, _)| {
|
||||
let clause = pred.instantiate_supertrait(self.tcx, &trait_ref);
|
||||
let clause = pred.instantiate_supertrait(self.tcx, trait_ref);
|
||||
self.visited.insert(clause).then_some(clause)
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ use rustc_data_structures::intern::Interned;
|
|||
use rustc_data_structures::stable_hasher::HashingControls;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
|
|
@ -204,6 +204,23 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
|
|||
fn def_id(self) -> DefId {
|
||||
self.did()
|
||||
}
|
||||
|
||||
fn is_phantom_data(self) -> bool {
|
||||
self.is_phantom_data()
|
||||
}
|
||||
|
||||
fn all_field_tys(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> ty::EarlyBinder<'tcx, impl Iterator<Item = Ty<'tcx>>> {
|
||||
ty::EarlyBinder::bind(
|
||||
self.all_fields().map(move |field| tcx.type_of(field.did).skip_binder()),
|
||||
)
|
||||
}
|
||||
|
||||
fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
self.sized_constraint(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
|
||||
|
|
@ -257,16 +274,16 @@ impl AdtDefData {
|
|||
if tcx.has_attr(did, sym::fundamental) {
|
||||
flags |= AdtFlags::IS_FUNDAMENTAL;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().phantom_data() {
|
||||
if tcx.is_lang_item(did, LangItem::PhantomData) {
|
||||
flags |= AdtFlags::IS_PHANTOM_DATA;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().owned_box() {
|
||||
if tcx.is_lang_item(did, LangItem::OwnedBox) {
|
||||
flags |= AdtFlags::IS_BOX;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().manually_drop() {
|
||||
if tcx.is_lang_item(did, LangItem::ManuallyDrop) {
|
||||
flags |= AdtFlags::IS_MANUALLY_DROP;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().unsafe_cell_type() {
|
||||
if tcx.is_lang_item(did, LangItem::UnsafeCell) {
|
||||
flags |= AdtFlags::IS_UNSAFE_CELL;
|
||||
}
|
||||
if is_anonymous {
|
||||
|
|
|
|||
|
|
@ -70,9 +70,9 @@ use rustc_span::{Span, DUMMY_SP};
|
|||
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_type_ir::fold::TypeFoldable;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::TyKind::*;
|
||||
use rustc_type_ir::WithCachedTypeInfo;
|
||||
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
|
||||
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
|
|
@ -154,7 +154,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
|
||||
type VariancesOf = &'tcx [ty::Variance];
|
||||
|
||||
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
|
||||
fn variances_of(self, def_id: DefId) -> Self::VariancesOf {
|
||||
self.variances_of(def_id)
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
|
||||
fn trait_ref_and_own_args_for_alias(
|
||||
self,
|
||||
def_id: Self::DefId,
|
||||
def_id: DefId,
|
||||
args: Self::GenericArgs,
|
||||
) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
|
||||
assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst);
|
||||
|
|
@ -246,7 +246,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
self.mk_type_list_from_iter(args)
|
||||
}
|
||||
|
||||
fn parent(self, def_id: Self::DefId) -> Self::DefId {
|
||||
fn parent(self, def_id: DefId) -> DefId {
|
||||
self.parent(def_id)
|
||||
}
|
||||
|
||||
|
|
@ -259,15 +259,85 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
fn features(self) -> Self::Features {
|
||||
self.features()
|
||||
}
|
||||
|
||||
fn bound_coroutine_hidden_types(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> impl IntoIterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'tcx, Ty<'tcx>>>> {
|
||||
self.bound_coroutine_hidden_types(def_id)
|
||||
}
|
||||
|
||||
fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> {
|
||||
self.fn_sig(def_id)
|
||||
}
|
||||
|
||||
fn coroutine_movability(self, def_id: DefId) -> rustc_ast::Movability {
|
||||
self.coroutine_movability(def_id)
|
||||
}
|
||||
|
||||
fn coroutine_for_closure(self, def_id: DefId) -> DefId {
|
||||
self.coroutine_for_closure(def_id)
|
||||
}
|
||||
|
||||
fn generics_require_sized_self(self, def_id: DefId) -> bool {
|
||||
self.generics_require_sized_self(def_id)
|
||||
}
|
||||
|
||||
fn item_bounds(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Clause<'tcx>>> {
|
||||
self.item_bounds(def_id).map_bound(IntoIterator::into_iter)
|
||||
}
|
||||
|
||||
fn super_predicates_of(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Clause<'tcx>>> {
|
||||
ty::EarlyBinder::bind(
|
||||
self.super_predicates_of(def_id).instantiate_identity(self).predicates.into_iter(),
|
||||
)
|
||||
}
|
||||
|
||||
fn has_target_features(self, def_id: DefId) -> bool {
|
||||
!self.codegen_fn_attrs(def_id).target_features.is_empty()
|
||||
}
|
||||
|
||||
fn require_lang_item(self, lang_item: TraitSolverLangItem) -> DefId {
|
||||
self.require_lang_item(
|
||||
match lang_item {
|
||||
TraitSolverLangItem::Future => hir::LangItem::Future,
|
||||
TraitSolverLangItem::FutureOutput => hir::LangItem::FutureOutput,
|
||||
TraitSolverLangItem::AsyncFnKindHelper => hir::LangItem::AsyncFnKindHelper,
|
||||
TraitSolverLangItem::AsyncFnKindUpvars => hir::LangItem::AsyncFnKindUpvars,
|
||||
},
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator<Item = DefId> {
|
||||
self.associated_items(def_id)
|
||||
.in_definition_order()
|
||||
.filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type))
|
||||
.map(|assoc_item| assoc_item.def_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
|
||||
fn rust() -> Self {
|
||||
abi::Abi::Rust
|
||||
}
|
||||
|
||||
fn is_rust(self) -> bool {
|
||||
matches!(self, abi::Abi::Rust)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
|
||||
fn safe() -> Self {
|
||||
hir::Safety::Safe
|
||||
}
|
||||
|
||||
fn is_safe(self) -> bool {
|
||||
matches!(self, hir::Safety::Safe)
|
||||
}
|
||||
|
|
@ -281,6 +351,10 @@ impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_featu
|
|||
fn generic_const_exprs(self) -> bool {
|
||||
self.generic_const_exprs
|
||||
}
|
||||
|
||||
fn coroutine_clone(self) -> bool {
|
||||
self.coroutine_clone
|
||||
}
|
||||
}
|
||||
|
||||
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ pub struct GenericArg<'tcx> {
|
|||
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::GenericArg<TyCtxt<'tcx>> for GenericArg<'tcx> {}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
|
||||
fn type_at(self, i: usize) -> Ty<'tcx> {
|
||||
self.type_at(i)
|
||||
|
|
|
|||
|
|
@ -699,26 +699,25 @@ impl<'tcx> Instance<'tcx> {
|
|||
};
|
||||
let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
|
||||
|
||||
let lang_items = tcx.lang_items();
|
||||
let coroutine_callable_item = if Some(trait_id) == lang_items.future_trait() {
|
||||
let coroutine_callable_item = if tcx.is_lang_item(trait_id, LangItem::Future) {
|
||||
assert_matches!(
|
||||
coroutine_kind,
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
|
||||
);
|
||||
hir::LangItem::FuturePoll
|
||||
} else if Some(trait_id) == lang_items.iterator_trait() {
|
||||
} else if tcx.is_lang_item(trait_id, LangItem::Iterator) {
|
||||
assert_matches!(
|
||||
coroutine_kind,
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||
);
|
||||
hir::LangItem::IteratorNext
|
||||
} else if Some(trait_id) == lang_items.async_iterator_trait() {
|
||||
} else if tcx.is_lang_item(trait_id, LangItem::AsyncIterator) {
|
||||
assert_matches!(
|
||||
coroutine_kind,
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
|
||||
);
|
||||
hir::LangItem::AsyncIteratorPollNext
|
||||
} else if Some(trait_id) == lang_items.coroutine_trait() {
|
||||
} else if tcx.is_lang_item(trait_id, LangItem::Coroutine) {
|
||||
assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
|
||||
hir::LangItem::CoroutineResume
|
||||
} else {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue