mirror of
https://git.proxmox.com/git/rustc
synced 2025-12-04 19:10:54 +00:00
New upstream version 1.77.2+dfsg1
This commit is contained in:
parent
4b01247206
commit
c0240ec034
313
Cargo.lock
generated
313
Cargo.lock
generated
@ -119,6 +119,16 @@ dependencies = [
|
|||||||
"yansi-term",
|
"yansi-term",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "annotate-snippets"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0a433302f833baa830c0092100c481c7ea768c5981a3c36f549517a502f246dd"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -202,9 +212,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "askama"
|
name = "askama"
|
||||||
version = "0.12.0"
|
version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e"
|
checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama_derive",
|
"askama_derive",
|
||||||
"askama_escape",
|
"askama_escape",
|
||||||
@ -212,14 +222,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "askama_derive"
|
name = "askama_derive"
|
||||||
version = "0.12.1"
|
version = "0.12.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94"
|
checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"askama_parser",
|
||||||
"basic-toml",
|
"basic-toml",
|
||||||
"mime",
|
"mime",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"nom",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
@ -232,6 +242,15 @@ version = "0.10.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama_parser"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0"
|
||||||
|
dependencies = [
|
||||||
|
"nom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -285,9 +304,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.4.0"
|
version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
@ -363,9 +382,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
@ -537,7 +556,7 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clippy"
|
name = "clippy"
|
||||||
version = "0.1.76"
|
version = "0.1.77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"clippy_config",
|
"clippy_config",
|
||||||
@ -565,7 +584,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clippy_config"
|
name = "clippy_config"
|
||||||
version = "0.1.76"
|
version = "0.1.77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc-semver",
|
"rustc-semver",
|
||||||
"serde",
|
"serde",
|
||||||
@ -577,21 +596,21 @@ dependencies = [
|
|||||||
name = "clippy_dev"
|
name = "clippy_dev"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.7.20",
|
"aho-corasick 1.0.2",
|
||||||
"clap",
|
"clap",
|
||||||
"indoc",
|
"indoc",
|
||||||
"itertools",
|
"itertools",
|
||||||
"opener 0.5.2",
|
"opener",
|
||||||
"shell-escape",
|
"shell-escape",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clippy_lints"
|
name = "clippy_lints"
|
||||||
version = "0.1.76"
|
version = "0.1.77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"cargo_metadata 0.15.4",
|
"cargo_metadata 0.18.0",
|
||||||
"clippy_config",
|
"clippy_config",
|
||||||
"clippy_utils",
|
"clippy_utils",
|
||||||
"declare_clippy_lint",
|
"declare_clippy_lint",
|
||||||
@ -613,7 +632,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clippy_utils"
|
name = "clippy_utils"
|
||||||
version = "0.1.76"
|
version = "0.1.77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"clippy_config",
|
"clippy_config",
|
||||||
@ -704,9 +723,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compiler_builtins"
|
name = "compiler_builtins"
|
||||||
version = "0.1.103"
|
version = "0.1.105"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242"
|
checksum = "3686cc48897ce1950aa70fd595bd2dc9f767a3c4cca4cd17b2cb52a2d37e6eb4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"rustc-std-workspace-core",
|
"rustc-std-workspace-core",
|
||||||
@ -868,12 +887,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctrlc"
|
name = "ctrlc"
|
||||||
version = "3.4.0"
|
version = "3.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e"
|
checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix",
|
"nix",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -984,7 +1003,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "declare_clippy_lint"
|
name = "declare_clippy_lint"
|
||||||
version = "0.1.76"
|
version = "0.1.77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1249,7 +1268,6 @@ name = "error_index_generator"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mdbook",
|
"mdbook",
|
||||||
"rustc_error_codes",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2072,9 +2090,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.27"
|
version = "0.1.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
|
checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@ -2177,16 +2195,6 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libloading"
|
|
||||||
version = "0.7.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@ -2342,7 +2350,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opener 0.6.1",
|
"opener",
|
||||||
"pathdiff",
|
"pathdiff",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
"regex",
|
"regex",
|
||||||
@ -2356,9 +2364,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "measureme"
|
name = "measureme"
|
||||||
version = "10.1.2"
|
version = "11.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe"
|
checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
@ -2465,16 +2473,16 @@ dependencies = [
|
|||||||
"ctrlc",
|
"ctrlc",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"jemalloc-sys",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"libffi",
|
"libffi",
|
||||||
"libloading 0.8.1",
|
"libloading",
|
||||||
"log",
|
"log",
|
||||||
"measureme",
|
"measureme",
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"serde",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"ui_test",
|
"ui_test",
|
||||||
]
|
]
|
||||||
@ -2512,14 +2520,13 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.2"
|
version = "0.27.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
|
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"static_assertions",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2588,9 +2595,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.32.1"
|
version = "0.32.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
|
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
@ -2618,16 +2625,6 @@ version = "1.18.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opener"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005"
|
|
||||||
dependencies = [
|
|
||||||
"bstr",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opener"
|
name = "opener"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
@ -2641,11 +2638,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.55"
|
version = "0.10.63"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
|
checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"libc",
|
"libc",
|
||||||
@ -2673,9 +2670,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.90"
|
version = "0.9.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
|
checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@ -3006,11 +3003,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pulldown-cmark"
|
name = "pulldown-cmark"
|
||||||
version = "0.9.3"
|
version = "0.9.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
|
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"memchr",
|
"memchr",
|
||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
@ -3280,9 +3277,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-build-sysroot"
|
name = "rustc-build-sysroot"
|
||||||
version = "0.4.2"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ed2a90dfa5232ed5ff21d53d4df655f315ab316ea06fc508f1c74bcedb1ce6c"
|
checksum = "39dcf8d82b1f79a179bdb284dc44db440a9666eefa5a6df5ef282d6db930d544"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
@ -3370,7 +3367,7 @@ dependencies = [
|
|||||||
name = "rustc_abi"
|
name = "rustc_abi"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"rand",
|
"rand",
|
||||||
"rand_xoshiro",
|
"rand_xoshiro",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
@ -3401,7 +3398,7 @@ dependencies = [
|
|||||||
name = "rustc_ast"
|
name = "rustc_ast"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"memchr",
|
"memchr",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
@ -3552,7 +3549,7 @@ dependencies = [
|
|||||||
name = "rustc_codegen_llvm"
|
name = "rustc_codegen_llvm"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"itertools",
|
"itertools",
|
||||||
"libc",
|
"libc",
|
||||||
"measureme",
|
"measureme",
|
||||||
@ -3587,7 +3584,7 @@ name = "rustc_codegen_ssa"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ar_archive_writer",
|
"ar_archive_writer",
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"cc",
|
"cc",
|
||||||
"itertools",
|
"itertools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
@ -3654,11 +3651,11 @@ name = "rustc_data_structures"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
|
"either",
|
||||||
"elsa",
|
"elsa",
|
||||||
"ena",
|
"ena",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"itertools",
|
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
"measureme",
|
"measureme",
|
||||||
@ -3703,7 +3700,6 @@ dependencies = [
|
|||||||
"rustc_codegen_ssa",
|
"rustc_codegen_ssa",
|
||||||
"rustc_const_eval",
|
"rustc_const_eval",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_error_codes",
|
|
||||||
"rustc_errors",
|
"rustc_errors",
|
||||||
"rustc_expand",
|
"rustc_expand",
|
||||||
"rustc_feature",
|
"rustc_feature",
|
||||||
@ -3738,6 +3734,7 @@ dependencies = [
|
|||||||
"rustc_trait_selection",
|
"rustc_trait_selection",
|
||||||
"rustc_ty_utils",
|
"rustc_ty_utils",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"shlex",
|
||||||
"time",
|
"time",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows",
|
"windows",
|
||||||
@ -3770,14 +3767,16 @@ dependencies = [
|
|||||||
name = "rustc_errors"
|
name = "rustc_errors"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotate-snippets",
|
"annotate-snippets 0.10.1",
|
||||||
"derive_setters",
|
"derive_setters",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_ast_pretty",
|
"rustc_ast_pretty",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
|
"rustc_error_codes",
|
||||||
"rustc_error_messages",
|
"rustc_error_messages",
|
||||||
"rustc_fluent_macro",
|
"rustc_fluent_macro",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
|
"rustc_index",
|
||||||
"rustc_lint_defs",
|
"rustc_lint_defs",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_serialize",
|
"rustc_serialize",
|
||||||
@ -3797,7 +3796,6 @@ dependencies = [
|
|||||||
name = "rustc_expand"
|
name = "rustc_expand"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel",
|
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_ast_passes",
|
"rustc_ast_passes",
|
||||||
"rustc_ast_pretty",
|
"rustc_ast_pretty",
|
||||||
@ -3831,7 +3829,7 @@ dependencies = [
|
|||||||
name = "rustc_fluent_macro"
|
name = "rustc_fluent_macro"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotate-snippets",
|
"annotate-snippets 0.10.1",
|
||||||
"fluent-bundle",
|
"fluent-bundle",
|
||||||
"fluent-syntax",
|
"fluent-syntax",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -3869,6 +3867,7 @@ dependencies = [
|
|||||||
name = "rustc_hir_analysis"
|
name = "rustc_hir_analysis"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
"rustc_arena",
|
"rustc_arena",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_attr",
|
"rustc_attr",
|
||||||
@ -3877,6 +3876,7 @@ dependencies = [
|
|||||||
"rustc_feature",
|
"rustc_feature",
|
||||||
"rustc_fluent_macro",
|
"rustc_fluent_macro",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
|
"rustc_hir_pretty",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
"rustc_infer",
|
"rustc_infer",
|
||||||
"rustc_lint_defs",
|
"rustc_lint_defs",
|
||||||
@ -3906,6 +3906,7 @@ dependencies = [
|
|||||||
name = "rustc_hir_typeck"
|
name = "rustc_hir_typeck"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_attr",
|
"rustc_attr",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
@ -3992,7 +3993,7 @@ dependencies = [
|
|||||||
name = "rustc_interface"
|
name = "rustc_interface"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libloading 0.7.4",
|
"libloading",
|
||||||
"rustc-rayon",
|
"rustc-rayon",
|
||||||
"rustc-rayon-core",
|
"rustc-rayon-core",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
@ -4121,8 +4122,8 @@ dependencies = [
|
|||||||
name = "rustc_metadata"
|
name = "rustc_metadata"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"libloading 0.7.4",
|
"libloading",
|
||||||
"odht",
|
"odht",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_attr",
|
"rustc_attr",
|
||||||
@ -4151,7 +4152,7 @@ dependencies = [
|
|||||||
name = "rustc_middle"
|
name = "rustc_middle"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"either",
|
"either",
|
||||||
"field-offset",
|
"field-offset",
|
||||||
@ -4189,6 +4190,7 @@ name = "rustc_mir_build"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
|
"itertools",
|
||||||
"rustc_apfloat",
|
"rustc_apfloat",
|
||||||
"rustc_arena",
|
"rustc_arena",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
@ -4286,7 +4288,7 @@ dependencies = [
|
|||||||
name = "rustc_parse"
|
name = "rustc_parse"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_ast_pretty",
|
"rustc_ast_pretty",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
@ -4340,6 +4342,7 @@ dependencies = [
|
|||||||
name = "rustc_pattern_analysis"
|
name = "rustc_pattern_analysis"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"rustc-hash",
|
||||||
"rustc_apfloat",
|
"rustc_apfloat",
|
||||||
"rustc_arena",
|
"rustc_arena",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
@ -4354,7 +4357,6 @@ dependencies = [
|
|||||||
"rustc_target",
|
"rustc_target",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"tracing",
|
"tracing",
|
||||||
"typed-arena",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4423,7 +4425,7 @@ dependencies = [
|
|||||||
name = "rustc_resolve"
|
name = "rustc_resolve"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
"rustc_arena",
|
"rustc_arena",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
@ -4462,7 +4464,7 @@ dependencies = [
|
|||||||
name = "rustc_session"
|
name = "rustc_session"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"getopts",
|
"getopts",
|
||||||
"libc",
|
"libc",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
@ -4520,7 +4522,7 @@ dependencies = [
|
|||||||
name = "rustc_symbol_mangling"
|
name = "rustc_symbol_mangling"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"punycode",
|
"punycode",
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
@ -4538,7 +4540,7 @@ dependencies = [
|
|||||||
name = "rustc_target"
|
name = "rustc_target"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"object",
|
"object",
|
||||||
"rustc_abi",
|
"rustc_abi",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
@ -4562,6 +4564,8 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
|
|||||||
name = "rustc_trait_selection"
|
name = "rustc_trait_selection"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"itertools",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_attr",
|
"rustc_attr",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
@ -4636,12 +4640,13 @@ dependencies = [
|
|||||||
name = "rustc_type_ir"
|
name = "rustc_type_ir"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.1",
|
||||||
"derivative",
|
"derivative",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_serialize",
|
"rustc_serialize",
|
||||||
|
"rustc_span",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4734,7 +4739,7 @@ dependencies = [
|
|||||||
name = "rustfmt-nightly"
|
name = "rustfmt-nightly"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotate-snippets",
|
"annotate-snippets 0.9.1",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytecount",
|
"bytecount",
|
||||||
"cargo_metadata 0.15.4",
|
"cargo_metadata 0.15.4",
|
||||||
@ -4766,7 +4771,7 @@ version = "0.38.19"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed"
|
checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.0",
|
"bitflags 2.4.1",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
@ -4781,12 +4786,12 @@ checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruzstd"
|
name = "ruzstd"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc"
|
checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"thiserror-core",
|
"derive_more",
|
||||||
"twox-hash",
|
"twox-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -5204,9 +5209,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysinfo"
|
name = "sysinfo"
|
||||||
version = "0.29.2"
|
version = "0.29.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9557d0845b86eea8182f7b10dff120214fb6cd9fd937b6f4917714e546a38695"
|
checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
@ -5336,9 +5341,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thin-vec"
|
name = "thin-vec"
|
||||||
version = "0.2.12"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8"
|
checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
@ -5349,26 +5354,6 @@ dependencies = [
|
|||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-core"
|
|
||||||
version = "1.0.38"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-core-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-core-impl"
|
|
||||||
version = "1.0.38"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.47"
|
version = "1.0.47"
|
||||||
@ -5690,12 +5675,6 @@ dependencies = [
|
|||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typed-arena"
|
|
||||||
version = "2.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
@ -5724,7 +5703,7 @@ version = "0.21.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d"
|
checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotate-snippets",
|
"annotate-snippets 0.9.1",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bstr",
|
"bstr",
|
||||||
"cargo-platform",
|
"cargo-platform",
|
||||||
@ -5747,9 +5726,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unic-langid"
|
name = "unic-langid"
|
||||||
version = "0.9.1"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f"
|
checksum = "238722e6d794ed130f91f4ea33e01fcff4f188d92337a21297892521c72df516"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unic-langid-impl",
|
"unic-langid-impl",
|
||||||
"unic-langid-macros",
|
"unic-langid-macros",
|
||||||
@ -5757,18 +5736,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unic-langid-impl"
|
name = "unic-langid-impl"
|
||||||
version = "0.9.1"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff"
|
checksum = "4bd55a2063fdea4ef1f8633243a7b0524cbeef1905ae04c31a1c9b9775c55bc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tinystr",
|
"tinystr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unic-langid-macros"
|
name = "unic-langid-macros"
|
||||||
version = "0.9.1"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "055e618bf694161ffff0466d95cef3e1a5edc59f6ba1888e97801f2b4ebdc4fe"
|
checksum = "5c854cefb82ff2816410ce606acbad1b3af065140907b29be9229040752b83ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"tinystr",
|
"tinystr",
|
||||||
@ -5778,13 +5757,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unic-langid-macros-impl"
|
name = "unic-langid-macros-impl"
|
||||||
version = "0.9.1"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f5cdec05b907f4e2f6843f4354f4ce6a5bebe1a56df320a49134944477ce4d8"
|
checksum = "fea2a4c80deb4fb3ca51f66b5e2dd91e3642bbce52234bcf22e41668281208e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 2.0.32",
|
||||||
"unic-langid-impl",
|
"unic-langid-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -5855,9 +5834,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"rustc-std-workspace-core",
|
"rustc-std-workspace-core",
|
||||||
@ -6141,6 +6120,15 @@ dependencies = [
|
|||||||
"windows-targets 0.48.1",
|
"windows-targets 0.48.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@ -6171,6 +6159,21 @@ dependencies = [
|
|||||||
"windows_x86_64_msvc 0.48.0",
|
"windows_x86_64_msvc 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.52.0",
|
||||||
|
"windows_aarch64_msvc 0.52.0",
|
||||||
|
"windows_i686_gnu 0.52.0",
|
||||||
|
"windows_i686_msvc 0.52.0",
|
||||||
|
"windows_x86_64_gnu 0.52.0",
|
||||||
|
"windows_x86_64_gnullvm 0.52.0",
|
||||||
|
"windows_x86_64_msvc 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@ -6183,6 +6186,12 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@ -6195,6 +6204,12 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@ -6207,6 +6222,12 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@ -6219,6 +6240,12 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@ -6231,6 +6258,12 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@ -6243,6 +6276,12 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@ -6255,6 +6294,12 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
|
|||||||
10
Cargo.toml
10
Cargo.toml
@ -64,7 +64,7 @@ exclude = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[profile.release.package.compiler_builtins]
|
[profile.release.package.compiler_builtins]
|
||||||
# The compiler-builtins crate cannot reference libcore, and it's own CI will
|
# The compiler-builtins crate cannot reference libcore, and its own CI will
|
||||||
# verify that this is the case. This requires, however, that the crate is built
|
# verify that this is the case. This requires, however, that the crate is built
|
||||||
# without overflow checks and debug assertions. Forcefully disable debug
|
# without overflow checks and debug assertions. Forcefully disable debug
|
||||||
# assertions and overflow checks here which should ensure that even if these
|
# assertions and overflow checks here which should ensure that even if these
|
||||||
@ -104,6 +104,14 @@ gimli.debug = 0
|
|||||||
miniz_oxide.debug = 0
|
miniz_oxide.debug = 0
|
||||||
object.debug = 0
|
object.debug = 0
|
||||||
|
|
||||||
|
# These are very thin wrappers around executing lld with the right binary name.
|
||||||
|
# Basically nothing within them can go wrong without having been explicitly logged anyway.
|
||||||
|
# We ship these in every rustc tarball and even after compression they add up
|
||||||
|
# to around 0.6MB of data every user needs to download (and 15MB on disk).
|
||||||
|
[profile.release.package.lld-wrapper]
|
||||||
|
debug = 0
|
||||||
|
strip = true
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
# See comments in `library/rustc-std-workspace-core/README.md` for what's going on
|
# See comments in `library/rustc-std-workspace-core/README.md` for what's going on
|
||||||
# here
|
# here
|
||||||
|
|||||||
251
README.md
251
README.md
@ -16,8 +16,6 @@ If you wish to _contribute_ to the compiler, you should read
|
|||||||
|
|
||||||
- [Quick Start](#quick-start)
|
- [Quick Start](#quick-start)
|
||||||
- [Installing from Source](#installing-from-source)
|
- [Installing from Source](#installing-from-source)
|
||||||
- [Building Documentation](#building-documentation)
|
|
||||||
- [Notes](#notes)
|
|
||||||
- [Getting Help](#getting-help)
|
- [Getting Help](#getting-help)
|
||||||
- [Contributing](#contributing)
|
- [Contributing](#contributing)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
@ -34,253 +32,8 @@ Read ["Installation"] from [The Book].
|
|||||||
|
|
||||||
## Installing from Source
|
## Installing from Source
|
||||||
|
|
||||||
The Rust build system uses a Python script called `x.py` to build the compiler,
|
If you really want to install from source (though this is not recommended), see
|
||||||
which manages the bootstrapping process. It lives at the root of the project.
|
[INSTALL.md](INSTALL.md).
|
||||||
It also uses a file named `config.toml` to determine various configuration
|
|
||||||
settings for the build. You can see a full list of options in
|
|
||||||
`config.example.toml`.
|
|
||||||
|
|
||||||
The `x.py` command can be run directly on most Unix systems in the following
|
|
||||||
format:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./x.py <subcommand> [flags]
|
|
||||||
```
|
|
||||||
|
|
||||||
This is how the documentation and examples assume you are running `x.py`.
|
|
||||||
See the [rustc dev guide][rustcguidebuild] if this does not work on your
|
|
||||||
platform.
|
|
||||||
|
|
||||||
More information about `x.py` can be found by running it with the `--help` flag
|
|
||||||
or reading the [rustc dev guide][rustcguidebuild].
|
|
||||||
|
|
||||||
[gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.html
|
|
||||||
[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#what-is-xpy
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
Make sure you have installed the dependencies:
|
|
||||||
|
|
||||||
* `python` 3 or 2.7
|
|
||||||
* `git`
|
|
||||||
* A C compiler (when building for the host, `cc` is enough; cross-compiling may
|
|
||||||
need additional compilers)
|
|
||||||
* `curl` (not needed on Windows)
|
|
||||||
* `pkg-config` if you are compiling on Linux and targeting Linux
|
|
||||||
* `libiconv` (already included with glibc on Debian-based distros)
|
|
||||||
|
|
||||||
To build Cargo, you'll also need OpenSSL (`libssl-dev` or `openssl-devel` on
|
|
||||||
most Unix distros).
|
|
||||||
|
|
||||||
If building LLVM from source, you'll need additional tools:
|
|
||||||
|
|
||||||
* `g++`, `clang++`, or MSVC with versions listed on
|
|
||||||
[LLVM's documentation](https://llvm.org/docs/GettingStarted.html#host-c-toolchain-both-compiler-and-standard-library)
|
|
||||||
* `ninja`, or GNU `make` 3.81 or later (Ninja is recommended, especially on
|
|
||||||
Windows)
|
|
||||||
* `cmake` 3.13.4 or later
|
|
||||||
* `libstdc++-static` may be required on some Linux distributions such as Fedora
|
|
||||||
and Ubuntu
|
|
||||||
|
|
||||||
On tier 1 or tier 2 with host tools platforms, you can also choose to download
|
|
||||||
LLVM by setting `llvm.download-ci-llvm = true`.
|
|
||||||
Otherwise, you'll need LLVM installed and `llvm-config` in your path.
|
|
||||||
See [the rustc-dev-guide for more info][sysllvm].
|
|
||||||
|
|
||||||
[sysllvm]: https://rustc-dev-guide.rust-lang.org/building/new-target.html#using-pre-built-llvm
|
|
||||||
|
|
||||||
|
|
||||||
### Building on a Unix-like system
|
|
||||||
|
|
||||||
#### Build steps
|
|
||||||
|
|
||||||
1. Clone the [source] with `git`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/rust-lang/rust.git
|
|
||||||
cd rust
|
|
||||||
```
|
|
||||||
|
|
||||||
[source]: https://github.com/rust-lang/rust
|
|
||||||
|
|
||||||
2. Configure the build settings:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./configure
|
|
||||||
```
|
|
||||||
|
|
||||||
If you plan to use `x.py install` to create an installation, it is
|
|
||||||
recommended that you set the `prefix` value in the `[install]` section to a
|
|
||||||
directory: `./configure --set install.prefix=<path>`
|
|
||||||
|
|
||||||
3. Build and install:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./x.py build && ./x.py install
|
|
||||||
```
|
|
||||||
|
|
||||||
When complete, `./x.py install` will place several programs into
|
|
||||||
`$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
|
|
||||||
API-documentation tool. By default, it will also include [Cargo], Rust's
|
|
||||||
package manager. You can disable this behavior by passing
|
|
||||||
`--set build.extended=false` to `./configure`.
|
|
||||||
|
|
||||||
[Cargo]: https://github.com/rust-lang/cargo
|
|
||||||
|
|
||||||
#### Configure and Make
|
|
||||||
|
|
||||||
This project provides a configure script and makefile (the latter of which just
|
|
||||||
invokes `x.py`). `./configure` is the recommended way to programmatically
|
|
||||||
generate a `config.toml`. `make` is not recommended (we suggest using `x.py`
|
|
||||||
directly), but it is supported and we try not to break it unnecessarily.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./configure
|
|
||||||
make && sudo make install
|
|
||||||
```
|
|
||||||
|
|
||||||
`configure` generates a `config.toml` which can also be used with normal `x.py`
|
|
||||||
invocations.
|
|
||||||
|
|
||||||
### Building on Windows
|
|
||||||
|
|
||||||
On Windows, we suggest using [winget] to install dependencies by running the
|
|
||||||
following in a terminal:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
winget install -e Python.Python.3
|
|
||||||
winget install -e Kitware.CMake
|
|
||||||
winget install -e Git.Git
|
|
||||||
```
|
|
||||||
|
|
||||||
Then edit your system's `PATH` variable and add: `C:\Program Files\CMake\bin`.
|
|
||||||
See
|
|
||||||
[this guide on editing the system `PATH`](https://www.java.com/en/download/help/path.html)
|
|
||||||
from the Java documentation.
|
|
||||||
|
|
||||||
[winget]: https://github.com/microsoft/winget-cli
|
|
||||||
|
|
||||||
There are two prominent ABIs in use on Windows: the native (MSVC) ABI used by
|
|
||||||
Visual Studio and the GNU ABI used by the GCC toolchain. Which version of Rust
|
|
||||||
you need depends largely on what C/C++ libraries you want to interoperate with.
|
|
||||||
Use the MSVC build of Rust to interop with software produced by Visual Studio
|
|
||||||
and the GNU build to interop with GNU software built using the MinGW/MSYS2
|
|
||||||
toolchain.
|
|
||||||
|
|
||||||
#### MinGW
|
|
||||||
|
|
||||||
[MSYS2][msys2] can be used to easily build Rust on Windows:
|
|
||||||
|
|
||||||
[msys2]: https://www.msys2.org/
|
|
||||||
|
|
||||||
1. Download the latest [MSYS2 installer][msys2] and go through the installer.
|
|
||||||
|
|
||||||
2. Run `mingw32_shell.bat` or `mingw64_shell.bat` from the MSYS2 installation
|
|
||||||
directory (e.g. `C:\msys64`), depending on whether you want 32-bit or 64-bit
|
|
||||||
Rust. (As of the latest version of MSYS2 you have to run `msys2_shell.cmd
|
|
||||||
-mingw32` or `msys2_shell.cmd -mingw64` from the command line instead.)
|
|
||||||
|
|
||||||
3. From this terminal, install the required tools:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# Update package mirrors (may be needed if you have a fresh install of MSYS2)
|
|
||||||
pacman -Sy pacman-mirrors
|
|
||||||
|
|
||||||
# Install build tools needed for Rust. If you're building a 32-bit compiler,
|
|
||||||
# then replace "x86_64" below with "i686". If you've already got Git, Python,
|
|
||||||
# or CMake installed and in PATH you can remove them from this list.
|
|
||||||
# Note that it is important that you do **not** use the 'python2', 'cmake',
|
|
||||||
# and 'ninja' packages from the 'msys2' subsystem.
|
|
||||||
# The build has historically been known to fail with these packages.
|
|
||||||
pacman -S git \
|
|
||||||
make \
|
|
||||||
diffutils \
|
|
||||||
tar \
|
|
||||||
mingw-w64-x86_64-python \
|
|
||||||
mingw-w64-x86_64-cmake \
|
|
||||||
mingw-w64-x86_64-gcc \
|
|
||||||
mingw-w64-x86_64-ninja
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Navigate to Rust's source code (or clone it), then build it:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
python x.py setup user && python x.py build && python x.py install
|
|
||||||
```
|
|
||||||
|
|
||||||
#### MSVC
|
|
||||||
|
|
||||||
MSVC builds of Rust additionally require an installation of Visual Studio 2017
|
|
||||||
(or later) so `rustc` can use its linker. The simplest way is to get
|
|
||||||
[Visual Studio], check the "C++ build tools" and "Windows 10 SDK" workload.
|
|
||||||
|
|
||||||
[Visual Studio]: https://visualstudio.microsoft.com/downloads/
|
|
||||||
|
|
||||||
(If you're installing CMake yourself, be careful that "C++ CMake tools for
|
|
||||||
Windows" doesn't get included under "Individual components".)
|
|
||||||
|
|
||||||
With these dependencies installed, you can build the compiler in a `cmd.exe`
|
|
||||||
shell with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
python x.py setup user
|
|
||||||
python x.py build
|
|
||||||
```
|
|
||||||
|
|
||||||
Right now, building Rust only works with some known versions of Visual Studio.
|
|
||||||
If you have a more recent version installed and the build system doesn't
|
|
||||||
understand, you may need to force rustbuild to use an older version.
|
|
||||||
This can be done by manually calling the appropriate vcvars file before running
|
|
||||||
the bootstrap.
|
|
||||||
|
|
||||||
```batch
|
|
||||||
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
|
||||||
python x.py build
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Specifying an ABI
|
|
||||||
|
|
||||||
Each specific ABI can also be used from either environment (for example, using
|
|
||||||
the GNU ABI in PowerShell) by using an explicit build triple. The available
|
|
||||||
Windows build triples are:
|
|
||||||
- GNU ABI (using GCC)
|
|
||||||
- `i686-pc-windows-gnu`
|
|
||||||
- `x86_64-pc-windows-gnu`
|
|
||||||
- The MSVC ABI
|
|
||||||
- `i686-pc-windows-msvc`
|
|
||||||
- `x86_64-pc-windows-msvc`
|
|
||||||
|
|
||||||
The build triple can be specified by either specifying `--build=<triple>` when
|
|
||||||
invoking `x.py` commands, or by creating a `config.toml` file (as described in
|
|
||||||
[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing
|
|
||||||
`--set build.build=<triple>` to `./configure`.
|
|
||||||
|
|
||||||
## Building Documentation
|
|
||||||
|
|
||||||
If you'd like to build the documentation, it's almost the same:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./x.py doc
|
|
||||||
```
|
|
||||||
|
|
||||||
The generated documentation will appear under `doc` in the `build` directory for
|
|
||||||
the ABI used. That is, if the ABI was `x86_64-pc-windows-msvc`, the directory
|
|
||||||
will be `build\x86_64-pc-windows-msvc\doc`.
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
Since the Rust compiler is written in Rust, it must be built by a precompiled
|
|
||||||
"snapshot" version of itself (made in an earlier stage of development).
|
|
||||||
As such, source builds require an Internet connection to fetch snapshots, and an
|
|
||||||
OS that can execute the available snapshot binaries.
|
|
||||||
|
|
||||||
See https://doc.rust-lang.org/nightly/rustc/platform-support.html for a list of
|
|
||||||
supported platforms.
|
|
||||||
Only "host tools" platforms have a pre-compiled snapshot binary available; to
|
|
||||||
compile for a platform without host tools you must cross-compile.
|
|
||||||
|
|
||||||
You may find that other platforms work, but these are our officially supported
|
|
||||||
build environments that are most likely to work.
|
|
||||||
|
|
||||||
## Getting Help
|
## Getting Help
|
||||||
|
|
||||||
|
|||||||
136
RELEASES.md
136
RELEASES.md
@ -1,3 +1,137 @@
|
|||||||
|
Version 1.77.2 (2024-04-09)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
<a id="1.77.2"></a>
|
||||||
|
|
||||||
|
- [CVE-2024-24576: fix escaping of Windows batch file arguments in `std::process::Command`](https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html)
|
||||||
|
|
||||||
|
Version 1.77.1 (2024-03-28)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
<a id="1.77.1"></a>
|
||||||
|
|
||||||
|
- [Revert stripping debuginfo by default for Windows](https://github.com/rust-lang/cargo/pull/13654)
|
||||||
|
This fixes a regression in 1.77 by reverting to the previous default.
|
||||||
|
Platforms other than Windows are not affected.
|
||||||
|
- Internal: [Fix heading anchor rendering in doc pages](https://github.com/rust-lang/rust/pull/122693)
|
||||||
|
|
||||||
|
Version 1.77.0 (2024-03-21)
|
||||||
|
==========================
|
||||||
|
|
||||||
|
<a id="1.77.0-Language"></a>
|
||||||
|
|
||||||
|
Language
|
||||||
|
--------
|
||||||
|
|
||||||
|
- [Reveal opaque types within the defining body for exhaustiveness checking.](https://github.com/rust-lang/rust/pull/116821/)
|
||||||
|
- [Stabilize C-string literals.](https://github.com/rust-lang/rust/pull/117472/)
|
||||||
|
- [Stabilize THIR unsafeck.](https://github.com/rust-lang/rust/pull/117673/)
|
||||||
|
- [Add lint `static_mut_refs` to warn on references to mutable statics.](https://github.com/rust-lang/rust/pull/117556/)
|
||||||
|
- [Support async recursive calls (as long as they have indirection).](https://github.com/rust-lang/rust/pull/117703/)
|
||||||
|
- [Undeprecate lint `unstable_features` and make use of it in the compiler.](https://github.com/rust-lang/rust/pull/118639/)
|
||||||
|
- [Make inductive cycles in coherence ambiguous always.](https://github.com/rust-lang/rust/pull/118649/)
|
||||||
|
- [Get rid of type-driven traversal in const-eval interning](https://github.com/rust-lang/rust/pull/119044/),
|
||||||
|
only as a [future compatiblity lint](https://github.com/rust-lang/rust/pull/122204) for now.
|
||||||
|
- [Deny braced macro invocations in let-else.](https://github.com/rust-lang/rust/pull/119062/)
|
||||||
|
|
||||||
|
<a id="1.77.0-Compiler"></a>
|
||||||
|
|
||||||
|
Compiler
|
||||||
|
--------
|
||||||
|
|
||||||
|
- [Include lint `soft_unstable` in future breakage reports.](https://github.com/rust-lang/rust/pull/116274/)
|
||||||
|
- [Make `i128` and `u128` 16-byte aligned on x86-based targets.](https://github.com/rust-lang/rust/pull/116672/)
|
||||||
|
- [Use `--verbose` in diagnostic output.](https://github.com/rust-lang/rust/pull/119129/)
|
||||||
|
- [Improve spacing between printed tokens.](https://github.com/rust-lang/rust/pull/120227/)
|
||||||
|
- [Merge the `unused_tuple_struct_fields` lint into `dead_code`.](https://github.com/rust-lang/rust/pull/118297/)
|
||||||
|
- [Error on incorrect implied bounds in well-formedness check](https://github.com/rust-lang/rust/pull/118553/),
|
||||||
|
with a temporary exception for Bevy.
|
||||||
|
- [Fix coverage instrumentation/reports for non-ASCII source code.](https://github.com/rust-lang/rust/pull/119033/)
|
||||||
|
- [Fix `fn`/`const` items implied bounds and well-formedness check.](https://github.com/rust-lang/rust/pull/120019/)
|
||||||
|
- [Promote `riscv32{im|imafc}-unknown-none-elf` targets to tier 2.](https://github.com/rust-lang/rust/pull/118704/)
|
||||||
|
- Add several new tier 3 targets:
|
||||||
|
- [`aarch64-unknown-illumos`](https://github.com/rust-lang/rust/pull/112936/)
|
||||||
|
- [`hexagon-unknown-none-elf`](https://github.com/rust-lang/rust/pull/117601/)
|
||||||
|
- [`riscv32imafc-esp-espidf`](https://github.com/rust-lang/rust/pull/119738/)
|
||||||
|
- [`riscv32im-risc0-zkvm-elf`](https://github.com/rust-lang/rust/pull/117958/)
|
||||||
|
|
||||||
|
Refer to Rust's [platform support page][platform-support-doc]
|
||||||
|
for more information on Rust's tiered platform support.
|
||||||
|
|
||||||
|
<a id="1.77.0-Libraries"></a>
|
||||||
|
|
||||||
|
Libraries
|
||||||
|
---------
|
||||||
|
|
||||||
|
- [Implement `From<&[T; N]>` for `Cow<[T]>`.](https://github.com/rust-lang/rust/pull/113489/)
|
||||||
|
- [Remove special-case handling of `vec.split_off(0)`.](https://github.com/rust-lang/rust/pull/119917/)
|
||||||
|
|
||||||
|
<a id="1.77.0-Stabilized-APIs"></a>
|
||||||
|
|
||||||
|
Stabilized APIs
|
||||||
|
---------------
|
||||||
|
|
||||||
|
- [`array::each_ref`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_ref)
|
||||||
|
- [`array::each_mut`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_mut)
|
||||||
|
- [`core::net`](https://doc.rust-lang.org/stable/core/net/index.html)
|
||||||
|
- [`f32::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round_ties_even)
|
||||||
|
- [`f64::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round_ties_even)
|
||||||
|
- [`mem::offset_of!`](https://doc.rust-lang.org/stable/std/mem/macro.offset_of.html)
|
||||||
|
- [`slice::first_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first_chunk)
|
||||||
|
- [`slice::first_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first_chunk_mut)
|
||||||
|
- [`slice::split_first_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first_chunk)
|
||||||
|
- [`slice::split_first_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first_chunk_mut)
|
||||||
|
- [`slice::last_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last_chunk)
|
||||||
|
- [`slice::last_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last_chunk_mut)
|
||||||
|
- [`slice::split_last_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_last_chunk)
|
||||||
|
- [`slice::split_last_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_last_chunk_mut)
|
||||||
|
- [`slice::chunk_by`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.chunk_by)
|
||||||
|
- [`slice::chunk_by_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.chunk_by_mut)
|
||||||
|
- [`Bound::map`](https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.map)
|
||||||
|
- [`File::create_new`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.create_new)
|
||||||
|
- [`Mutex::clear_poison`](https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#method.clear_poison)
|
||||||
|
- [`RwLock::clear_poison`](https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html#method.clear_poison)
|
||||||
|
|
||||||
|
<a id="1.77.0-Cargo"></a>
|
||||||
|
|
||||||
|
Cargo
|
||||||
|
-----
|
||||||
|
|
||||||
|
- [Extend the build directive syntax with `cargo::`.](https://github.com/rust-lang/cargo/pull/12201/)
|
||||||
|
- [Stabilize metadata `id` format as `PackageIDSpec`.](https://github.com/rust-lang/cargo/pull/12914/)
|
||||||
|
- [Pull out as `cargo-util-schemas` as a crate.](https://github.com/rust-lang/cargo/pull/13178/)
|
||||||
|
- [Strip all debuginfo when debuginfo is not requested.](https://github.com/rust-lang/cargo/pull/13257/)
|
||||||
|
- [Inherit jobserver from env for all kinds of runners.](https://github.com/rust-lang/cargo/pull/12776/)
|
||||||
|
- [Deprecate rustc plugin support in cargo.](https://github.com/rust-lang/cargo/pull/13248/)
|
||||||
|
|
||||||
|
<a id="1.77.0-Rustdoc"></a>
|
||||||
|
|
||||||
|
Rustdoc
|
||||||
|
-----
|
||||||
|
|
||||||
|
- [Allows links in markdown headings.](https://github.com/rust-lang/rust/pull/117662/)
|
||||||
|
- [Search for tuples and unit by type with `()`.](https://github.com/rust-lang/rust/pull/118194/)
|
||||||
|
- [Clean up the source sidebar's hide button.](https://github.com/rust-lang/rust/pull/119066/)
|
||||||
|
- [Prevent JS injection from `localStorage`.](https://github.com/rust-lang/rust/pull/120250/)
|
||||||
|
|
||||||
|
<a id="1.77.0-Misc"></a>
|
||||||
|
|
||||||
|
Misc
|
||||||
|
----
|
||||||
|
|
||||||
|
- [Recommend version-sorting for all sorting in style guide.](https://github.com/rust-lang/rust/pull/115046/)
|
||||||
|
|
||||||
|
<a id="1.77.0-Internal-Changes"></a>
|
||||||
|
|
||||||
|
Internal Changes
|
||||||
|
----------------
|
||||||
|
|
||||||
|
These changes do not affect any public interfaces of Rust, but they represent
|
||||||
|
significant improvements to the performance or internals of rustc and related
|
||||||
|
tools.
|
||||||
|
|
||||||
|
- [Add more weirdness to `weird-exprs.rs`.](https://github.com/rust-lang/rust/pull/119028/)
|
||||||
|
|
||||||
Version 1.76.0 (2024-02-08)
|
Version 1.76.0 (2024-02-08)
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
@ -7,7 +141,7 @@ Language
|
|||||||
--------
|
--------
|
||||||
- [Document Rust ABI compatibility between various types](https://github.com/rust-lang/rust/pull/115476/)
|
- [Document Rust ABI compatibility between various types](https://github.com/rust-lang/rust/pull/115476/)
|
||||||
- [Also: guarantee that char and u32 are ABI-compatible](https://github.com/rust-lang/rust/pull/118032/)
|
- [Also: guarantee that char and u32 are ABI-compatible](https://github.com/rust-lang/rust/pull/118032/)
|
||||||
- [Warn against ambiguous wide pointer comparisons](https://github.com/rust-lang/rust/pull/117758/)
|
- [Add lint `ambiguous_wide_pointer_comparisons` that supersedes `clippy::vtable_address_comparisons`](https://github.com/rust-lang/rust/pull/117758)
|
||||||
|
|
||||||
<a id="1.76.0-Compiler"></a>
|
<a id="1.76.0-Compiler"></a>
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
bitflags = "1.2.1"
|
bitflags = "2.4.1"
|
||||||
rand = { version = "0.8.4", default-features = false, optional = true }
|
rand = { version = "0.8.4", default-features = false, optional = true }
|
||||||
rand_xoshiro = { version = "0.6.0", optional = true }
|
rand_xoshiro = { version = "0.6.0", optional = true }
|
||||||
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,7 @@ use rustc_data_structures::stable_hasher::StableOrd;
|
|||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use rustc_macros::{Decodable, Encodable};
|
use rustc_macros::{Decodable_Generic, Encodable_Generic};
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use std::iter::Step;
|
use std::iter::Step;
|
||||||
|
|
||||||
@ -29,10 +29,12 @@ pub use layout::LayoutCalculator;
|
|||||||
/// instead of implementing everything in `rustc_middle`.
|
/// instead of implementing everything in `rustc_middle`.
|
||||||
pub trait HashStableContext {}
|
pub trait HashStableContext {}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Default)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||||
|
pub struct ReprFlags(u8);
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(Default)]
|
impl ReprFlags: u8 {
|
||||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
|
||||||
pub struct ReprFlags: u8 {
|
|
||||||
const IS_C = 1 << 0;
|
const IS_C = 1 << 0;
|
||||||
const IS_SIMD = 1 << 1;
|
const IS_SIMD = 1 << 1;
|
||||||
const IS_TRANSPARENT = 1 << 2;
|
const IS_TRANSPARENT = 1 << 2;
|
||||||
@ -42,14 +44,22 @@ bitflags! {
|
|||||||
// the seed stored in `ReprOptions.layout_seed`
|
// the seed stored in `ReprOptions.layout_seed`
|
||||||
const RANDOMIZE_LAYOUT = 1 << 4;
|
const RANDOMIZE_LAYOUT = 1 << 4;
|
||||||
// Any of these flags being set prevent field reordering optimisation.
|
// Any of these flags being set prevent field reordering optimisation.
|
||||||
const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits
|
const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits()
|
||||||
| ReprFlags::IS_SIMD.bits
|
| ReprFlags::IS_SIMD.bits()
|
||||||
| ReprFlags::IS_LINEAR.bits;
|
| ReprFlags::IS_LINEAR.bits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the same as `rustc_data_structures::external_bitflags_debug` but without the
|
||||||
|
// `rustc_data_structures` to make it build on stable.
|
||||||
|
impl std::fmt::Debug for ReprFlags {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
bitflags::parser::to_writer(self, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||||
pub enum IntegerType {
|
pub enum IntegerType {
|
||||||
/// Pointer-sized integer type, i.e. `isize` and `usize`. The field shows signedness, e.g.
|
/// Pointer-sized integer type, i.e. `isize` and `usize`. The field shows signedness, e.g.
|
||||||
/// `Pointer(true)` means `isize`.
|
/// `Pointer(true)` means `isize`.
|
||||||
@ -70,7 +80,7 @@ impl IntegerType {
|
|||||||
|
|
||||||
/// Represents the repr options provided by the user.
|
/// Represents the repr options provided by the user.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
||||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||||
pub struct ReprOptions {
|
pub struct ReprOptions {
|
||||||
pub int: Option<IntegerType>,
|
pub int: Option<IntegerType>,
|
||||||
pub align: Option<Align>,
|
pub align: Option<Align>,
|
||||||
@ -409,7 +419,7 @@ impl FromStr for Endian {
|
|||||||
|
|
||||||
/// Size of a type in bytes.
|
/// Size of a type in bytes.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||||
pub struct Size {
|
pub struct Size {
|
||||||
raw: u64,
|
raw: u64,
|
||||||
}
|
}
|
||||||
@ -633,7 +643,7 @@ impl Step for Size {
|
|||||||
|
|
||||||
/// Alignment of a type in bytes (always a power of two).
|
/// Alignment of a type in bytes (always a power of two).
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||||
pub struct Align {
|
pub struct Align {
|
||||||
pow2: u8,
|
pow2: u8,
|
||||||
}
|
}
|
||||||
@ -774,7 +784,7 @@ impl AbiAndPrefAlign {
|
|||||||
|
|
||||||
/// Integers, also used for enum discriminants.
|
/// Integers, also used for enum discriminants.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))]
|
||||||
pub enum Integer {
|
pub enum Integer {
|
||||||
I8,
|
I8,
|
||||||
I16,
|
I16,
|
||||||
|
|||||||
@ -484,6 +484,19 @@ impl DroplessArena {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used by `Lift` to check whether this slice is allocated
|
||||||
|
/// in this arena.
|
||||||
|
#[inline]
|
||||||
|
pub fn contains_slice<T>(&self, slice: &[T]) -> bool {
|
||||||
|
for chunk in self.chunks.borrow_mut().iter_mut() {
|
||||||
|
let ptr = slice.as_ptr().cast::<u8>().cast_mut();
|
||||||
|
if chunk.start() <= ptr && chunk.end() >= ptr {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// Allocates a string slice that is copied into the `DroplessArena`, returning a
|
/// Allocates a string slice that is copied into the `DroplessArena`, returning a
|
||||||
/// reference to it. Will panic if passed an empty string.
|
/// reference to it. Will panic if passed an empty string.
|
||||||
///
|
///
|
||||||
|
|||||||
@ -5,7 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
bitflags = "1.2.1"
|
bitflags = "2.4.1"
|
||||||
memchr = "2.5.0"
|
memchr = "2.5.0"
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
rustc_index = { path = "../rustc_index" }
|
rustc_index = { path = "../rustc_index" }
|
||||||
|
|||||||
@ -20,17 +20,18 @@
|
|||||||
|
|
||||||
pub use crate::format::*;
|
pub use crate::format::*;
|
||||||
pub use crate::util::parser::ExprPrecedence;
|
pub use crate::util::parser::ExprPrecedence;
|
||||||
|
pub use rustc_span::AttrId;
|
||||||
pub use GenericArgs::*;
|
pub use GenericArgs::*;
|
||||||
pub use UnsafeSource::*;
|
pub use UnsafeSource::*;
|
||||||
|
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::token::{self, CommentKind, Delimiter};
|
use crate::token::{self, CommentKind, Delimiter};
|
||||||
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
|
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
|
||||||
|
use rustc_data_structures::packed::Pu128;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
|
||||||
use rustc_span::source_map::{respan, Spanned};
|
use rustc_span::source_map::{respan, Spanned};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
||||||
@ -286,41 +287,16 @@ impl ParenthesizedArgs {
|
|||||||
|
|
||||||
pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
|
pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
|
||||||
|
|
||||||
/// A modifier on a bound, e.g., `?Trait` or `~const Trait`.
|
/// Modifiers on a trait bound like `~const`, `?` and `!`.
|
||||||
///
|
|
||||||
/// Negative bounds should also be handled here.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
||||||
pub enum TraitBoundModifier {
|
pub struct TraitBoundModifiers {
|
||||||
/// No modifiers
|
pub constness: BoundConstness,
|
||||||
None,
|
pub polarity: BoundPolarity,
|
||||||
|
|
||||||
/// `!Trait`
|
|
||||||
Negative,
|
|
||||||
|
|
||||||
/// `?Trait`
|
|
||||||
Maybe,
|
|
||||||
|
|
||||||
/// `~const Trait`
|
|
||||||
MaybeConst(Span),
|
|
||||||
|
|
||||||
/// `~const !Trait`
|
|
||||||
//
|
|
||||||
// This parses but will be rejected during AST validation.
|
|
||||||
MaybeConstNegative,
|
|
||||||
|
|
||||||
/// `~const ?Trait`
|
|
||||||
//
|
|
||||||
// This parses but will be rejected during AST validation.
|
|
||||||
MaybeConstMaybe,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraitBoundModifier {
|
impl TraitBoundModifiers {
|
||||||
pub fn to_constness(self) -> Const {
|
pub const NONE: Self =
|
||||||
match self {
|
Self { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
|
||||||
Self::MaybeConst(span) => Const::Yes(span),
|
|
||||||
_ => Const::No,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The AST represents all type param bounds as types.
|
/// The AST represents all type param bounds as types.
|
||||||
@ -329,7 +305,7 @@ impl TraitBoundModifier {
|
|||||||
/// detects `Copy`, `Send` and `Sync`.
|
/// detects `Copy`, `Send` and `Sync`.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub enum GenericBound {
|
pub enum GenericBound {
|
||||||
Trait(PolyTraitRef, TraitBoundModifier),
|
Trait(PolyTraitRef, TraitBoundModifiers),
|
||||||
Outlives(Lifetime),
|
Outlives(Lifetime),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,7 +626,8 @@ impl Pat {
|
|||||||
| PatKind::Range(..)
|
| PatKind::Range(..)
|
||||||
| PatKind::Ident(..)
|
| PatKind::Ident(..)
|
||||||
| PatKind::Path(..)
|
| PatKind::Path(..)
|
||||||
| PatKind::MacCall(_) => {}
|
| PatKind::MacCall(_)
|
||||||
|
| PatKind::Err(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,8 +756,7 @@ pub enum PatKind {
|
|||||||
Ident(BindingAnnotation, Ident, Option<P<Pat>>),
|
Ident(BindingAnnotation, Ident, Option<P<Pat>>),
|
||||||
|
|
||||||
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
|
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
|
||||||
/// The `bool` is `true` in the presence of a `..`.
|
Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
|
||||||
Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, /* recovered */ bool),
|
|
||||||
|
|
||||||
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
|
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
|
||||||
TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>),
|
TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>),
|
||||||
@ -835,6 +811,18 @@ pub enum PatKind {
|
|||||||
|
|
||||||
/// A macro pattern; pre-expansion.
|
/// A macro pattern; pre-expansion.
|
||||||
MacCall(P<MacCall>),
|
MacCall(P<MacCall>),
|
||||||
|
|
||||||
|
/// Placeholder for a pattern that wasn't syntactically well formed in some way.
|
||||||
|
Err(ErrorGuaranteed),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the `..` is present in a struct fields pattern.
|
||||||
|
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)]
|
||||||
|
pub enum PatFieldsRest {
|
||||||
|
/// `module::StructName { field, ..}`
|
||||||
|
Rest,
|
||||||
|
/// `module::StructName { field }`
|
||||||
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The kind of borrow in an `AddrOf` expression,
|
/// The kind of borrow in an `AddrOf` expression,
|
||||||
@ -1193,7 +1181,7 @@ impl Expr {
|
|||||||
match &self.kind {
|
match &self.kind {
|
||||||
ExprKind::Path(None, path) => Some(GenericBound::Trait(
|
ExprKind::Path(None, path) => Some(GenericBound::Trait(
|
||||||
PolyTraitRef::new(ThinVec::new(), path.clone(), self.span),
|
PolyTraitRef::new(ThinVec::new(), path.clone(), self.span),
|
||||||
TraitBoundModifier::None,
|
TraitBoundModifiers::NONE,
|
||||||
)),
|
)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@ -1274,7 +1262,7 @@ impl Expr {
|
|||||||
ExprKind::Let(..) => ExprPrecedence::Let,
|
ExprKind::Let(..) => ExprPrecedence::Let,
|
||||||
ExprKind::If(..) => ExprPrecedence::If,
|
ExprKind::If(..) => ExprPrecedence::If,
|
||||||
ExprKind::While(..) => ExprPrecedence::While,
|
ExprKind::While(..) => ExprPrecedence::While,
|
||||||
ExprKind::ForLoop(..) => ExprPrecedence::ForLoop,
|
ExprKind::ForLoop { .. } => ExprPrecedence::ForLoop,
|
||||||
ExprKind::Loop(..) => ExprPrecedence::Loop,
|
ExprKind::Loop(..) => ExprPrecedence::Loop,
|
||||||
ExprKind::Match(..) => ExprPrecedence::Match,
|
ExprKind::Match(..) => ExprPrecedence::Match,
|
||||||
ExprKind::Closure(..) => ExprPrecedence::Closure,
|
ExprKind::Closure(..) => ExprPrecedence::Closure,
|
||||||
@ -1436,10 +1424,10 @@ pub enum ExprKind {
|
|||||||
While(P<Expr>, P<Block>, Option<Label>),
|
While(P<Expr>, P<Block>, Option<Label>),
|
||||||
/// A `for` loop, with an optional label.
|
/// A `for` loop, with an optional label.
|
||||||
///
|
///
|
||||||
/// `'label: for pat in expr { block }`
|
/// `'label: for await? pat in iter { block }`
|
||||||
///
|
///
|
||||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||||
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Label>),
|
ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, kind: ForLoopKind },
|
||||||
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
|
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
|
||||||
///
|
///
|
||||||
/// `'label: loop { block }`
|
/// `'label: loop { block }`
|
||||||
@ -1542,6 +1530,13 @@ pub enum ExprKind {
|
|||||||
Err,
|
Err,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used to differentiate between `for` loops and `for await` loops.
|
||||||
|
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||||
|
pub enum ForLoopKind {
|
||||||
|
For,
|
||||||
|
ForAwait,
|
||||||
|
}
|
||||||
|
|
||||||
/// Used to differentiate between `async {}` blocks and `gen {}` blocks.
|
/// Used to differentiate between `async {}` blocks and `gen {}` blocks.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||||
pub enum GenBlockKind {
|
pub enum GenBlockKind {
|
||||||
@ -1839,7 +1834,7 @@ pub enum LitKind {
|
|||||||
/// A character literal (`'a'`).
|
/// A character literal (`'a'`).
|
||||||
Char(char),
|
Char(char),
|
||||||
/// An integer literal (`1`).
|
/// An integer literal (`1`).
|
||||||
Int(u128, LitIntType),
|
Int(Pu128, LitIntType),
|
||||||
/// A float literal (`1.0`, `1f64` or `1E10f64`). The pre-suffix part is
|
/// A float literal (`1.0`, `1f64` or `1E10f64`). The pre-suffix part is
|
||||||
/// stored as a symbol rather than `f64` so that `LitKind` can impl `Eq`
|
/// stored as a symbol rather than `f64` so that `LitKind` can impl `Eq`
|
||||||
/// and `Hash`.
|
/// and `Hash`.
|
||||||
@ -2181,9 +2176,10 @@ pub enum InlineAsmRegOrRegClass {
|
|||||||
RegClass(Symbol),
|
RegClass(Symbol),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
|
||||||
|
pub struct InlineAsmOptions(u16);
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
#[derive(Encodable, Decodable, HashStable_Generic)]
|
impl InlineAsmOptions: u16 {
|
||||||
pub struct InlineAsmOptions: u16 {
|
|
||||||
const PURE = 1 << 0;
|
const PURE = 1 << 0;
|
||||||
const NOMEM = 1 << 1;
|
const NOMEM = 1 << 1;
|
||||||
const READONLY = 1 << 2;
|
const READONLY = 1 << 2;
|
||||||
@ -2196,6 +2192,12 @@ bitflags::bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for InlineAsmOptions {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
bitflags::parser::to_writer(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
|
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
|
||||||
pub enum InlineAsmTemplatePiece {
|
pub enum InlineAsmTemplatePiece {
|
||||||
String(String),
|
String(String),
|
||||||
@ -2516,7 +2518,9 @@ impl fmt::Debug for ImplPolarity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
|
/// The polarity of a trait bound.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
||||||
|
#[derive(HashStable_Generic)]
|
||||||
pub enum BoundPolarity {
|
pub enum BoundPolarity {
|
||||||
/// `Type: Trait`
|
/// `Type: Trait`
|
||||||
Positive,
|
Positive,
|
||||||
@ -2526,6 +2530,38 @@ pub enum BoundPolarity {
|
|||||||
Maybe(Span),
|
Maybe(Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BoundPolarity {
|
||||||
|
pub fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Positive => "",
|
||||||
|
Self::Negative(_) => "!",
|
||||||
|
Self::Maybe(_) => "?",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The constness of a trait bound.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
||||||
|
#[derive(HashStable_Generic)]
|
||||||
|
pub enum BoundConstness {
|
||||||
|
/// `Type: Trait`
|
||||||
|
Never,
|
||||||
|
/// `Type: const Trait`
|
||||||
|
Always(Span),
|
||||||
|
/// `Type: ~const Trait`
|
||||||
|
Maybe(Span),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BoundConstness {
|
||||||
|
pub fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Never => "",
|
||||||
|
Self::Always(_) => "const",
|
||||||
|
Self::Maybe(_) => "~const",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub enum FnRetTy {
|
pub enum FnRetTy {
|
||||||
/// Returns type is not specified.
|
/// Returns type is not specified.
|
||||||
@ -2651,22 +2687,6 @@ pub enum AttrStyle {
|
|||||||
Inner,
|
Inner,
|
||||||
}
|
}
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
|
||||||
#[orderable]
|
|
||||||
#[debug_format = "AttrId({})"]
|
|
||||||
pub struct AttrId {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Encoder> Encodable<S> for AttrId {
|
|
||||||
fn encode(&self, _s: &mut S) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D: Decoder> Decodable<D> for AttrId {
|
|
||||||
default fn decode(_: &mut D) -> AttrId {
|
|
||||||
panic!("cannot decode `AttrId` with `{}`", std::any::type_name::<D>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A list of attributes.
|
/// A list of attributes.
|
||||||
pub type AttrVec = ThinVec<Attribute>;
|
pub type AttrVec = ThinVec<Attribute>;
|
||||||
|
|
||||||
@ -2858,6 +2878,7 @@ impl Item {
|
|||||||
| ItemKind::ForeignMod(_)
|
| ItemKind::ForeignMod(_)
|
||||||
| ItemKind::GlobalAsm(_)
|
| ItemKind::GlobalAsm(_)
|
||||||
| ItemKind::MacCall(_)
|
| ItemKind::MacCall(_)
|
||||||
|
| ItemKind::Delegation(_)
|
||||||
| ItemKind::MacroDef(_) => None,
|
| ItemKind::MacroDef(_) => None,
|
||||||
ItemKind::Static(_) => None,
|
ItemKind::Static(_) => None,
|
||||||
ItemKind::Const(i) => Some(&i.generics),
|
ItemKind::Const(i) => Some(&i.generics),
|
||||||
@ -3004,6 +3025,15 @@ pub struct Fn {
|
|||||||
pub body: Option<P<Block>>,
|
pub body: Option<P<Block>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
|
pub struct Delegation {
|
||||||
|
/// Path resolution id.
|
||||||
|
pub id: NodeId,
|
||||||
|
pub qself: Option<P<QSelf>>,
|
||||||
|
pub path: Path,
|
||||||
|
pub body: Option<P<Block>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct StaticItem {
|
pub struct StaticItem {
|
||||||
pub ty: P<Ty>,
|
pub ty: P<Ty>,
|
||||||
@ -3089,6 +3119,11 @@ pub enum ItemKind {
|
|||||||
|
|
||||||
/// A macro definition.
|
/// A macro definition.
|
||||||
MacroDef(MacroDef),
|
MacroDef(MacroDef),
|
||||||
|
|
||||||
|
/// A delegation item (`reuse`).
|
||||||
|
///
|
||||||
|
/// E.g. `reuse <Type as Trait>::name { target_expr_template }`.
|
||||||
|
Delegation(Box<Delegation>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemKind {
|
impl ItemKind {
|
||||||
@ -3096,7 +3131,8 @@ impl ItemKind {
|
|||||||
use ItemKind::*;
|
use ItemKind::*;
|
||||||
match self {
|
match self {
|
||||||
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
|
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
|
||||||
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a",
|
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
|
||||||
|
| Delegation(..) => "a",
|
||||||
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
|
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3120,6 +3156,7 @@ impl ItemKind {
|
|||||||
ItemKind::MacCall(..) => "item macro invocation",
|
ItemKind::MacCall(..) => "item macro invocation",
|
||||||
ItemKind::MacroDef(..) => "macro definition",
|
ItemKind::MacroDef(..) => "macro definition",
|
||||||
ItemKind::Impl { .. } => "implementation",
|
ItemKind::Impl { .. } => "implementation",
|
||||||
|
ItemKind::Delegation(..) => "delegated function",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3161,6 +3198,8 @@ pub enum AssocItemKind {
|
|||||||
Type(Box<TyAlias>),
|
Type(Box<TyAlias>),
|
||||||
/// A macro expanding to associated items.
|
/// A macro expanding to associated items.
|
||||||
MacCall(P<MacCall>),
|
MacCall(P<MacCall>),
|
||||||
|
/// An associated delegation item.
|
||||||
|
Delegation(Box<Delegation>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AssocItemKind {
|
impl AssocItemKind {
|
||||||
@ -3169,7 +3208,7 @@ impl AssocItemKind {
|
|||||||
Self::Const(box ConstItem { defaultness, .. })
|
Self::Const(box ConstItem { defaultness, .. })
|
||||||
| Self::Fn(box Fn { defaultness, .. })
|
| Self::Fn(box Fn { defaultness, .. })
|
||||||
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
|
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
|
||||||
Self::MacCall(..) => Defaultness::Final,
|
Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3181,6 +3220,7 @@ impl From<AssocItemKind> for ItemKind {
|
|||||||
AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
|
AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
|
||||||
AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
|
AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
|
||||||
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
|
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
|
||||||
|
AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3194,6 +3234,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
|
|||||||
ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
|
ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
|
||||||
ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
|
ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
|
||||||
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
|
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
|
||||||
|
ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
|
||||||
_ => return Err(item_kind),
|
_ => return Err(item_kind),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -3259,7 +3300,7 @@ mod size_asserts {
|
|||||||
static_assert_size!(ForeignItem, 96);
|
static_assert_size!(ForeignItem, 96);
|
||||||
static_assert_size!(ForeignItemKind, 24);
|
static_assert_size!(ForeignItemKind, 24);
|
||||||
static_assert_size!(GenericArg, 24);
|
static_assert_size!(GenericArg, 24);
|
||||||
static_assert_size!(GenericBound, 64);
|
static_assert_size!(GenericBound, 72);
|
||||||
static_assert_size!(Generics, 40);
|
static_assert_size!(Generics, 40);
|
||||||
static_assert_size!(Impl, 136);
|
static_assert_size!(Impl, 136);
|
||||||
static_assert_size!(Item, 136);
|
static_assert_size!(Item, 136);
|
||||||
|
|||||||
@ -13,13 +13,11 @@
|
|||||||
#![feature(rustdoc_internals)]
|
#![feature(rustdoc_internals)]
|
||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(const_trait_impl)]
|
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
#![recursion_limit = "256"]
|
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
|
||||||
|
|||||||
@ -1117,6 +1117,14 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
|
|||||||
}
|
}
|
||||||
ItemKind::MacCall(m) => vis.visit_mac_call(m),
|
ItemKind::MacCall(m) => vis.visit_mac_call(m),
|
||||||
ItemKind::MacroDef(def) => vis.visit_macro_def(def),
|
ItemKind::MacroDef(def) => vis.visit_macro_def(def),
|
||||||
|
ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
|
||||||
|
vis.visit_id(id);
|
||||||
|
vis.visit_qself(qself);
|
||||||
|
vis.visit_path(path);
|
||||||
|
if let Some(body) = body {
|
||||||
|
vis.visit_block(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1155,6 +1163,14 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
|
|||||||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||||
}
|
}
|
||||||
AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||||
|
AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
|
||||||
|
visitor.visit_id(id);
|
||||||
|
visitor.visit_qself(qself);
|
||||||
|
visitor.visit_path(path);
|
||||||
|
if let Some(body) = body {
|
||||||
|
visitor.visit_block(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
visitor.visit_span(span);
|
visitor.visit_span(span);
|
||||||
visit_lazy_tts(tokens, visitor);
|
visit_lazy_tts(tokens, visitor);
|
||||||
@ -1251,7 +1267,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
|||||||
let Pat { id, kind, span, tokens } = pat.deref_mut();
|
let Pat { id, kind, span, tokens } = pat.deref_mut();
|
||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
match kind {
|
match kind {
|
||||||
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
|
PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
|
||||||
PatKind::Ident(_binding_mode, ident, sub) => {
|
PatKind::Ident(_binding_mode, ident, sub) => {
|
||||||
vis.visit_ident(ident);
|
vis.visit_ident(ident);
|
||||||
visit_opt(sub, |sub| vis.visit_pat(sub));
|
visit_opt(sub, |sub| vis.visit_pat(sub));
|
||||||
@ -1389,7 +1405,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||||||
vis.visit_block(body);
|
vis.visit_block(body);
|
||||||
visit_opt(label, |label| vis.visit_label(label));
|
visit_opt(label, |label| vis.visit_label(label));
|
||||||
}
|
}
|
||||||
ExprKind::ForLoop(pat, iter, body, label) => {
|
ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
|
||||||
vis.visit_pat(pat);
|
vis.visit_pat(pat);
|
||||||
vis.visit_expr(iter);
|
vis.visit_expr(iter);
|
||||||
vis.visit_block(body);
|
vis.visit_block(body);
|
||||||
|
|||||||
@ -528,15 +528,6 @@ impl Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the token can appear at the start of a generic bound.
|
|
||||||
pub fn can_begin_bound(&self) -> bool {
|
|
||||||
self.is_path_start()
|
|
||||||
|| self.is_lifetime()
|
|
||||||
|| self.is_keyword(kw::For)
|
|
||||||
|| self == &Question
|
|
||||||
|| self == &OpenDelim(Delimiter::Parenthesis)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the token can appear at the start of an item.
|
/// Returns `true` if the token can appear at the start of an item.
|
||||||
pub fn can_begin_item(&self) -> bool {
|
pub fn can_begin_item(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
|
|||||||
@ -21,12 +21,12 @@ use crate::AttrVec;
|
|||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::sync::{self, Lrc};
|
use rustc_data_structures::sync::{self, Lrc};
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
use rustc_serialize::{Decodable, Encodable};
|
||||||
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
|
use rustc_span::{sym, Span, SpanDecoder, SpanEncoder, Symbol, DUMMY_SP};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::{cmp, fmt, iter, mem};
|
use std::{cmp, fmt, iter};
|
||||||
|
|
||||||
/// When the main Rust parser encounters a syntax-extension invocation, it
|
/// When the main Rust parser encounters a syntax-extension invocation, it
|
||||||
/// parses the arguments to the invocation as a token tree. This is a very
|
/// parses the arguments to the invocation as a token tree. This is a very
|
||||||
@ -81,14 +81,6 @@ impl TokenTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Modify the `TokenTree`'s span in-place.
|
|
||||||
pub fn set_span(&mut self, span: Span) {
|
|
||||||
match self {
|
|
||||||
TokenTree::Token(token, _) => token.span = span,
|
|
||||||
TokenTree::Delimited(dspan, ..) => *dspan = DelimSpan::from_single(span),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a `TokenTree::Token` with alone spacing.
|
/// Create a `TokenTree::Token` with alone spacing.
|
||||||
pub fn token_alone(kind: TokenKind, span: Span) -> TokenTree {
|
pub fn token_alone(kind: TokenKind, span: Span) -> TokenTree {
|
||||||
TokenTree::Token(Token::new(kind, span), Spacing::Alone)
|
TokenTree::Token(Token::new(kind, span), Spacing::Alone)
|
||||||
@ -158,14 +150,14 @@ impl fmt::Debug for LazyAttrTokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Encoder> Encodable<S> for LazyAttrTokenStream {
|
impl<S: SpanEncoder> Encodable<S> for LazyAttrTokenStream {
|
||||||
fn encode(&self, s: &mut S) {
|
fn encode(&self, s: &mut S) {
|
||||||
// Used by AST json printing.
|
// Used by AST json printing.
|
||||||
Encodable::encode(&self.to_attr_token_stream(), s);
|
Encodable::encode(&self.to_attr_token_stream(), s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Decoder> Decodable<D> for LazyAttrTokenStream {
|
impl<D: SpanDecoder> Decodable<D> for LazyAttrTokenStream {
|
||||||
fn decode(_d: &mut D) -> Self {
|
fn decode(_d: &mut D) -> Self {
|
||||||
panic!("Attempted to decode LazyAttrTokenStream");
|
panic!("Attempted to decode LazyAttrTokenStream");
|
||||||
}
|
}
|
||||||
@ -461,19 +453,6 @@ impl TokenStream {
|
|||||||
t1.next().is_none() && t2.next().is_none()
|
t1.next().is_none() && t2.next().is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies the supplied function to each `TokenTree` and its index in `self`, returning a new `TokenStream`
|
|
||||||
///
|
|
||||||
/// It is equivalent to `TokenStream::new(self.trees().cloned().enumerate().map(|(i, tt)| f(i, tt)).collect())`.
|
|
||||||
pub fn map_enumerated_owned(
|
|
||||||
mut self,
|
|
||||||
mut f: impl FnMut(usize, TokenTree) -> TokenTree,
|
|
||||||
) -> TokenStream {
|
|
||||||
let owned = Lrc::make_mut(&mut self.0); // clone if necessary
|
|
||||||
// rely on vec's in-place optimizations to avoid another allocation
|
|
||||||
*owned = mem::take(owned).into_iter().enumerate().map(|(i, tree)| f(i, tree)).collect();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a token stream containing a single token with alone spacing. The
|
/// Create a token stream containing a single token with alone spacing. The
|
||||||
/// spacing used for the final token in a constructed stream doesn't matter
|
/// spacing used for the final token in a constructed stream doesn't matter
|
||||||
/// because it's never used. In practice we arbitrarily use
|
/// because it's never used. In practice we arbitrarily use
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// Predicates on exprs and stmts that the pretty-printer and parser use
|
// Predicates on exprs and stmts that the pretty-printer and parser use
|
||||||
|
|
||||||
use crate::ast;
|
use crate::{ast, token::Delimiter};
|
||||||
|
|
||||||
/// Does this expression require a semicolon to be treated
|
/// Does this expression require a semicolon to be treated
|
||||||
/// as a statement? The negation of this: 'can this expression
|
/// as a statement? The negation of this: 'can this expression
|
||||||
@ -19,7 +19,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
|
|||||||
| ast::ExprKind::Block(..)
|
| ast::ExprKind::Block(..)
|
||||||
| ast::ExprKind::While(..)
|
| ast::ExprKind::While(..)
|
||||||
| ast::ExprKind::Loop(..)
|
| ast::ExprKind::Loop(..)
|
||||||
| ast::ExprKind::ForLoop(..)
|
| ast::ExprKind::ForLoop { .. }
|
||||||
| ast::ExprKind::TryBlock(..)
|
| ast::ExprKind::TryBlock(..)
|
||||||
| ast::ExprKind::ConstBlock(..)
|
| ast::ExprKind::ConstBlock(..)
|
||||||
)
|
)
|
||||||
@ -48,11 +48,23 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
|||||||
Closure(closure) => {
|
Closure(closure) => {
|
||||||
expr = &closure.body;
|
expr = &closure.body;
|
||||||
}
|
}
|
||||||
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
Gen(..)
|
||||||
| TryBlock(..) | While(..) | ConstBlock(_) => break Some(expr),
|
| Block(..)
|
||||||
|
| ForLoop { .. }
|
||||||
|
| If(..)
|
||||||
|
| Loop(..)
|
||||||
|
| Match(..)
|
||||||
|
| Struct(..)
|
||||||
|
| TryBlock(..)
|
||||||
|
| While(..)
|
||||||
|
| ConstBlock(_) => break Some(expr),
|
||||||
|
|
||||||
// FIXME: These can end in `}`, but changing these would break stable code.
|
MacCall(mac) => {
|
||||||
InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
|
break (mac.args.delim == Delimiter::Brace).then_some(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
|
||||||
|
// These should have been denied pre-expansion.
|
||||||
break None;
|
break None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,12 +3,10 @@
|
|||||||
use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
|
use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
|
||||||
use crate::token::{self, Token};
|
use crate::token::{self, Token};
|
||||||
use rustc_lexer::unescape::{
|
use rustc_lexer::unescape::{
|
||||||
byte_from_char, unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit,
|
byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode,
|
||||||
Mode,
|
|
||||||
};
|
};
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use std::ops::Range;
|
|
||||||
use std::{ascii, fmt, str};
|
use std::{ascii, fmt, str};
|
||||||
|
|
||||||
// Escapes a string, represented as a symbol. Reuses the original symbol,
|
// Escapes a string, represented as a symbol. Reuses the original symbol,
|
||||||
@ -39,7 +37,6 @@ pub enum LitError {
|
|||||||
InvalidFloatSuffix,
|
InvalidFloatSuffix,
|
||||||
NonDecimalFloat(u32),
|
NonDecimalFloat(u32),
|
||||||
IntTooLarge(u32),
|
IntTooLarge(u32),
|
||||||
NulInCStr(Range<usize>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LitKind {
|
impl LitKind {
|
||||||
@ -50,6 +47,9 @@ impl LitKind {
|
|||||||
return Err(LitError::InvalidSuffix);
|
return Err(LitError::InvalidSuffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For byte/char/string literals, chars and escapes have already been
|
||||||
|
// checked in the lexer (in `cook_lexer_literal`). So we can assume all
|
||||||
|
// chars and escapes are valid here.
|
||||||
Ok(match kind {
|
Ok(match kind {
|
||||||
token::Bool => {
|
token::Bool => {
|
||||||
assert!(symbol.is_bool_lit());
|
assert!(symbol.is_bool_lit());
|
||||||
@ -58,12 +58,12 @@ impl LitKind {
|
|||||||
token::Byte => {
|
token::Byte => {
|
||||||
return unescape_byte(symbol.as_str())
|
return unescape_byte(symbol.as_str())
|
||||||
.map(LitKind::Byte)
|
.map(LitKind::Byte)
|
||||||
.map_err(|_| LitError::LexerError);
|
.map_err(|_| panic!("failed to unescape byte literal"));
|
||||||
}
|
}
|
||||||
token::Char => {
|
token::Char => {
|
||||||
return unescape_char(symbol.as_str())
|
return unescape_char(symbol.as_str())
|
||||||
.map(LitKind::Char)
|
.map(LitKind::Char)
|
||||||
.map_err(|_| LitError::LexerError);
|
.map_err(|_| panic!("failed to unescape char literal"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are some valid suffixes for integer and float literals,
|
// There are some valid suffixes for integer and float literals,
|
||||||
@ -79,26 +79,22 @@ impl LitKind {
|
|||||||
let s = symbol.as_str();
|
let s = symbol.as_str();
|
||||||
// Vanilla strings are so common we optimize for the common case where no chars
|
// Vanilla strings are so common we optimize for the common case where no chars
|
||||||
// requiring special behaviour are present.
|
// requiring special behaviour are present.
|
||||||
let symbol = if s.contains(['\\', '\r']) {
|
let symbol = if s.contains('\\') {
|
||||||
let mut buf = String::with_capacity(s.len());
|
let mut buf = String::with_capacity(s.len());
|
||||||
let mut error = Ok(());
|
|
||||||
// Force-inlining here is aggressive but the closure is
|
// Force-inlining here is aggressive but the closure is
|
||||||
// called on every char in the string, so it can be
|
// called on every char in the string, so it can be hot in
|
||||||
// hot in programs with many long strings.
|
// programs with many long strings containing escapes.
|
||||||
unescape_literal(
|
unescape_unicode(
|
||||||
s,
|
s,
|
||||||
Mode::Str,
|
Mode::Str,
|
||||||
&mut #[inline(always)]
|
&mut #[inline(always)]
|
||||||
|_, unescaped_char| match unescaped_char {
|
|_, c| match c {
|
||||||
Ok(c) => buf.push(c),
|
Ok(c) => buf.push(c),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if err.is_fatal() {
|
assert!(!err.is_fatal(), "failed to unescape string literal")
|
||||||
error = Err(LitError::LexerError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
error?;
|
|
||||||
Symbol::intern(&buf)
|
Symbol::intern(&buf)
|
||||||
} else {
|
} else {
|
||||||
symbol
|
symbol
|
||||||
@ -106,92 +102,46 @@ impl LitKind {
|
|||||||
LitKind::Str(symbol, ast::StrStyle::Cooked)
|
LitKind::Str(symbol, ast::StrStyle::Cooked)
|
||||||
}
|
}
|
||||||
token::StrRaw(n) => {
|
token::StrRaw(n) => {
|
||||||
// Raw strings have no escapes, so we only need to check for invalid chars, and we
|
// Raw strings have no escapes so no work is needed here.
|
||||||
// can reuse the symbol on success.
|
|
||||||
let mut error = Ok(());
|
|
||||||
unescape_literal(symbol.as_str(), Mode::RawStr, &mut |_, unescaped_char| {
|
|
||||||
match unescaped_char {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => {
|
|
||||||
if err.is_fatal() {
|
|
||||||
error = Err(LitError::LexerError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
error?;
|
|
||||||
LitKind::Str(symbol, ast::StrStyle::Raw(n))
|
LitKind::Str(symbol, ast::StrStyle::Raw(n))
|
||||||
}
|
}
|
||||||
token::ByteStr => {
|
token::ByteStr => {
|
||||||
let s = symbol.as_str();
|
let s = symbol.as_str();
|
||||||
let mut buf = Vec::with_capacity(s.len());
|
let mut buf = Vec::with_capacity(s.len());
|
||||||
let mut error = Ok(());
|
unescape_unicode(s, Mode::ByteStr, &mut |_, c| match c {
|
||||||
unescape_literal(s, Mode::ByteStr, &mut |_, c| match c {
|
|
||||||
Ok(c) => buf.push(byte_from_char(c)),
|
Ok(c) => buf.push(byte_from_char(c)),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if err.is_fatal() {
|
assert!(!err.is_fatal(), "failed to unescape string literal")
|
||||||
error = Err(LitError::LexerError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
error?;
|
|
||||||
LitKind::ByteStr(buf.into(), StrStyle::Cooked)
|
LitKind::ByteStr(buf.into(), StrStyle::Cooked)
|
||||||
}
|
}
|
||||||
token::ByteStrRaw(n) => {
|
token::ByteStrRaw(n) => {
|
||||||
// Raw strings have no escapes, so we only need to check for invalid chars, and we
|
// Raw strings have no escapes so we can convert the symbol
|
||||||
// can convert the symbol directly to a `Lrc<u8>` on success.
|
// directly to a `Lrc<u8>`.
|
||||||
let s = symbol.as_str();
|
let buf = symbol.as_str().to_owned().into_bytes();
|
||||||
let mut error = Ok(());
|
LitKind::ByteStr(buf.into(), StrStyle::Raw(n))
|
||||||
unescape_literal(s, Mode::RawByteStr, &mut |_, c| match c {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => {
|
|
||||||
if err.is_fatal() {
|
|
||||||
error = Err(LitError::LexerError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
LitKind::ByteStr(s.to_owned().into_bytes().into(), StrStyle::Raw(n))
|
|
||||||
}
|
}
|
||||||
token::CStr => {
|
token::CStr => {
|
||||||
let s = symbol.as_str();
|
let s = symbol.as_str();
|
||||||
let mut buf = Vec::with_capacity(s.len());
|
let mut buf = Vec::with_capacity(s.len());
|
||||||
let mut error = Ok(());
|
unescape_mixed(s, Mode::CStr, &mut |_span, c| match c {
|
||||||
unescape_c_string(s, Mode::CStr, &mut |span, c| match c {
|
Ok(MixedUnit::Char(c)) => {
|
||||||
Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => {
|
|
||||||
error = Err(LitError::NulInCStr(span));
|
|
||||||
}
|
|
||||||
Ok(CStrUnit::Byte(b)) => buf.push(b),
|
|
||||||
Ok(CStrUnit::Char(c)) => {
|
|
||||||
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
|
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
|
||||||
}
|
}
|
||||||
|
Ok(MixedUnit::HighByte(b)) => buf.push(b),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if err.is_fatal() {
|
assert!(!err.is_fatal(), "failed to unescape C string literal")
|
||||||
error = Err(LitError::LexerError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
error?;
|
|
||||||
buf.push(0);
|
buf.push(0);
|
||||||
LitKind::CStr(buf.into(), StrStyle::Cooked)
|
LitKind::CStr(buf.into(), StrStyle::Cooked)
|
||||||
}
|
}
|
||||||
token::CStrRaw(n) => {
|
token::CStrRaw(n) => {
|
||||||
// Raw strings have no escapes, so we only need to check for invalid chars, and we
|
// Raw strings have no escapes so we can convert the symbol
|
||||||
// can convert the symbol directly to a `Lrc<u8>` on success.
|
// directly to a `Lrc<u8>` after appending the terminating NUL
|
||||||
let s = symbol.as_str();
|
// char.
|
||||||
let mut error = Ok(());
|
let mut buf = symbol.as_str().to_owned().into_bytes();
|
||||||
unescape_c_string(s, Mode::RawCStr, &mut |span, c| match c {
|
|
||||||
Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => {
|
|
||||||
error = Err(LitError::NulInCStr(span));
|
|
||||||
}
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => {
|
|
||||||
if err.is_fatal() {
|
|
||||||
error = Err(LitError::LexerError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
error?;
|
|
||||||
let mut buf = s.to_owned().into_bytes();
|
|
||||||
buf.push(0);
|
buf.push(0);
|
||||||
LitKind::CStr(buf.into(), StrStyle::Raw(n))
|
LitKind::CStr(buf.into(), StrStyle::Raw(n))
|
||||||
}
|
}
|
||||||
@ -374,7 +324,7 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
|
|||||||
};
|
};
|
||||||
|
|
||||||
let s = &s[if base != 10 { 2 } else { 0 }..];
|
let s = &s[if base != 10 { 2 } else { 0 }..];
|
||||||
u128::from_str_radix(s, base).map(|i| LitKind::Int(i, ty)).map_err(|_| {
|
u128::from_str_radix(s, base).map(|i| LitKind::Int(i.into(), ty)).map_err(|_| {
|
||||||
// Small bases are lexed as if they were base 10, e.g, the string
|
// Small bases are lexed as if they were base 10, e.g, the string
|
||||||
// might be `0b10201`. This will cause the conversion above to fail,
|
// might be `0b10201`. This will cause the conversion above to fail,
|
||||||
// but these kinds of errors are already reported by the lexer.
|
// but these kinds of errors are already reported by the lexer.
|
||||||
|
|||||||
@ -375,6 +375,15 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
|||||||
}
|
}
|
||||||
ItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
ItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||||
ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id),
|
ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id),
|
||||||
|
ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
|
||||||
|
if let Some(qself) = qself {
|
||||||
|
visitor.visit_ty(&qself.ty);
|
||||||
|
}
|
||||||
|
visitor.visit_path(path, *id);
|
||||||
|
if let Some(body) = body {
|
||||||
|
visitor.visit_block(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
walk_list!(visitor, visit_attribute, &item.attrs);
|
walk_list!(visitor, visit_attribute, &item.attrs);
|
||||||
}
|
}
|
||||||
@ -493,7 +502,7 @@ where
|
|||||||
}
|
}
|
||||||
GenericArgs::Parenthesized(data) => {
|
GenericArgs::Parenthesized(data) => {
|
||||||
walk_list!(visitor, visit_ty, &data.inputs);
|
walk_list!(visitor, visit_ty, &data.inputs);
|
||||||
walk_fn_ret_ty(visitor, &data.output);
|
visitor.visit_fn_ret_ty(&data.output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -559,7 +568,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
|
|||||||
walk_list!(visitor, visit_expr, lower_bound);
|
walk_list!(visitor, visit_expr, lower_bound);
|
||||||
walk_list!(visitor, visit_expr, upper_bound);
|
walk_list!(visitor, visit_expr, upper_bound);
|
||||||
}
|
}
|
||||||
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
|
PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
|
||||||
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
|
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
|
||||||
walk_list!(visitor, visit_pat, elems);
|
walk_list!(visitor, visit_pat, elems);
|
||||||
}
|
}
|
||||||
@ -704,6 +713,15 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
|
|||||||
AssocItemKind::MacCall(mac) => {
|
AssocItemKind::MacCall(mac) => {
|
||||||
visitor.visit_mac_call(mac);
|
visitor.visit_mac_call(mac);
|
||||||
}
|
}
|
||||||
|
AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
|
||||||
|
if let Some(qself) = qself {
|
||||||
|
visitor.visit_ty(&qself.ty);
|
||||||
|
}
|
||||||
|
visitor.visit_path(path, *id);
|
||||||
|
if let Some(body) = body {
|
||||||
|
visitor.visit_block(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,11 +862,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
}
|
}
|
||||||
ExprKind::ForLoop(pattern, subexpression, block, opt_label) => {
|
ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
|
||||||
walk_list!(visitor, visit_label, opt_label);
|
walk_list!(visitor, visit_label, label);
|
||||||
visitor.visit_pat(pattern);
|
visitor.visit_pat(pat);
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(iter);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(body);
|
||||||
}
|
}
|
||||||
ExprKind::Loop(block, opt_label, _) => {
|
ExprKind::Loop(block, opt_label, _) => {
|
||||||
walk_list!(visitor, visit_label, opt_label);
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
|
|||||||
@ -14,10 +14,6 @@ ast_lowering_assoc_ty_parentheses =
|
|||||||
ast_lowering_async_coroutines_not_supported =
|
ast_lowering_async_coroutines_not_supported =
|
||||||
`async` coroutines are not yet supported
|
`async` coroutines are not yet supported
|
||||||
|
|
||||||
ast_lowering_async_non_move_closure_not_supported =
|
|
||||||
`async` non-`move` closures with parameters are not currently supported
|
|
||||||
.help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
|
|
||||||
|
|
||||||
ast_lowering_att_syntax_only_x86 =
|
ast_lowering_att_syntax_only_x86 =
|
||||||
the `att_syntax` option is only supported on x86
|
the `att_syntax` option is only supported on x86
|
||||||
|
|
||||||
@ -35,7 +31,7 @@ ast_lowering_bad_return_type_notation_output =
|
|||||||
|
|
||||||
ast_lowering_base_expression_double_dot =
|
ast_lowering_base_expression_double_dot =
|
||||||
base expression required after `..`
|
base expression required after `..`
|
||||||
.label = add a base expression here
|
.suggestion = add a base expression here
|
||||||
|
|
||||||
ast_lowering_clobber_abi_not_supported =
|
ast_lowering_clobber_abi_not_supported =
|
||||||
`clobber_abi` is not supported on this target
|
`clobber_abi` is not supported on this target
|
||||||
@ -56,6 +52,9 @@ ast_lowering_functional_record_update_destructuring_assignment =
|
|||||||
functional record updates are not allowed in destructuring assignments
|
functional record updates are not allowed in destructuring assignments
|
||||||
.suggestion = consider removing the trailing pattern
|
.suggestion = consider removing the trailing pattern
|
||||||
|
|
||||||
|
ast_lowering_generic_param_default_in_binder =
|
||||||
|
defaults for generic parameters are not allowed in `for<...>` binders
|
||||||
|
|
||||||
ast_lowering_generic_type_with_parentheses =
|
ast_lowering_generic_type_with_parentheses =
|
||||||
parenthesized type parameters may only be used with a `Fn` trait
|
parenthesized type parameters may only be used with a `Fn` trait
|
||||||
.label = only `Fn` traits may use parentheses
|
.label = only `Fn` traits may use parentheses
|
||||||
@ -103,7 +102,8 @@ ast_lowering_misplaced_double_dot =
|
|||||||
.note = only allowed in tuple, tuple struct, and slice patterns
|
.note = only allowed in tuple, tuple struct, and slice patterns
|
||||||
|
|
||||||
ast_lowering_misplaced_impl_trait =
|
ast_lowering_misplaced_impl_trait =
|
||||||
`impl Trait` only allowed in function and inherent method argument and return types, not in {$position}
|
`impl Trait` is not allowed in {$position}
|
||||||
|
.note = `impl Trait` is only allowed in arguments and return types of functions and methods
|
||||||
|
|
||||||
ast_lowering_misplaced_relax_trait_bound =
|
ast_lowering_misplaced_relax_trait_bound =
|
||||||
`?Trait` bounds are only permitted at the point where a type parameter is declared
|
`?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
|
|||||||
@ -32,7 +32,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
let asm_arch =
|
let asm_arch =
|
||||||
if self.tcx.sess.opts.actually_rustdoc { None } else { self.tcx.sess.asm_arch };
|
if self.tcx.sess.opts.actually_rustdoc { None } else { self.tcx.sess.asm_arch };
|
||||||
if asm_arch.is_none() && !self.tcx.sess.opts.actually_rustdoc {
|
if asm_arch.is_none() && !self.tcx.sess.opts.actually_rustdoc {
|
||||||
self.tcx.sess.emit_err(InlineAsmUnsupportedTarget { span: sp });
|
self.dcx().emit_err(InlineAsmUnsupportedTarget { span: sp });
|
||||||
}
|
}
|
||||||
if let Some(asm_arch) = asm_arch {
|
if let Some(asm_arch) = asm_arch {
|
||||||
// Inline assembly is currently only stable for these architectures.
|
// Inline assembly is currently only stable for these architectures.
|
||||||
@ -48,7 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
);
|
);
|
||||||
if !is_stable && !self.tcx.features().asm_experimental_arch {
|
if !is_stable && !self.tcx.features().asm_experimental_arch {
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess.parse_sess,
|
&self.tcx.sess,
|
||||||
sym::asm_experimental_arch,
|
sym::asm_experimental_arch,
|
||||||
sp,
|
sp,
|
||||||
"inline assembly is not stable yet on this architecture",
|
"inline assembly is not stable yet on this architecture",
|
||||||
@ -60,16 +60,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
&& !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64))
|
&& !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64))
|
||||||
&& !self.tcx.sess.opts.actually_rustdoc
|
&& !self.tcx.sess.opts.actually_rustdoc
|
||||||
{
|
{
|
||||||
self.tcx.sess.emit_err(AttSyntaxOnlyX86 { span: sp });
|
self.dcx().emit_err(AttSyntaxOnlyX86 { span: sp });
|
||||||
}
|
}
|
||||||
if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind {
|
if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind {
|
||||||
feature_err(
|
feature_err(&self.tcx.sess, sym::asm_unwind, sp, "the `may_unwind` option is unstable")
|
||||||
&self.tcx.sess.parse_sess,
|
.emit();
|
||||||
sym::asm_unwind,
|
|
||||||
sp,
|
|
||||||
"the `may_unwind` option is unstable",
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut clobber_abis = FxIndexMap::default();
|
let mut clobber_abis = FxIndexMap::default();
|
||||||
@ -87,7 +82,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
!= source_map.span_to_snippet(*abi_span))
|
!= source_map.span_to_snippet(*abi_span))
|
||||||
.then_some(());
|
.then_some(());
|
||||||
|
|
||||||
self.tcx.sess.emit_err(AbiSpecifiedMultipleTimes {
|
self.dcx().emit_err(AbiSpecifiedMultipleTimes {
|
||||||
abi_span: *abi_span,
|
abi_span: *abi_span,
|
||||||
prev_name: *prev_name,
|
prev_name: *prev_name,
|
||||||
prev_span: *prev_sp,
|
prev_span: *prev_sp,
|
||||||
@ -100,14 +95,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(&[]) => {
|
Err(&[]) => {
|
||||||
self.tcx.sess.emit_err(ClobberAbiNotSupported { abi_span: *abi_span });
|
self.dcx().emit_err(ClobberAbiNotSupported { abi_span: *abi_span });
|
||||||
}
|
}
|
||||||
Err(supported_abis) => {
|
Err(supported_abis) => {
|
||||||
let mut abis = format!("`{}`", supported_abis[0]);
|
let mut abis = format!("`{}`", supported_abis[0]);
|
||||||
for m in &supported_abis[1..] {
|
for m in &supported_abis[1..] {
|
||||||
let _ = write!(abis, ", `{m}`");
|
let _ = write!(abis, ", `{m}`");
|
||||||
}
|
}
|
||||||
self.tcx.sess.emit_err(InvalidAbiClobberAbi {
|
self.dcx().emit_err(InvalidAbiClobberAbi {
|
||||||
abi_span: *abi_span,
|
abi_span: *abi_span,
|
||||||
supported_abis: abis,
|
supported_abis: abis,
|
||||||
});
|
});
|
||||||
@ -128,7 +123,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
InlineAsmRegOrRegClass::Reg(reg) => {
|
InlineAsmRegOrRegClass::Reg(reg) => {
|
||||||
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
|
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
|
||||||
asm::InlineAsmReg::parse(asm_arch, reg).unwrap_or_else(|error| {
|
asm::InlineAsmReg::parse(asm_arch, reg).unwrap_or_else(|error| {
|
||||||
sess.emit_err(InvalidRegister { op_span: *op_sp, reg, error });
|
self.dcx().emit_err(InvalidRegister {
|
||||||
|
op_span: *op_sp,
|
||||||
|
reg,
|
||||||
|
error,
|
||||||
|
});
|
||||||
asm::InlineAsmReg::Err
|
asm::InlineAsmReg::Err
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -139,7 +138,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch {
|
asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch {
|
||||||
asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else(
|
asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else(
|
||||||
|error| {
|
|error| {
|
||||||
sess.emit_err(InvalidRegisterClass {
|
self.dcx().emit_err(InvalidRegisterClass {
|
||||||
op_span: *op_sp,
|
op_span: *op_sp,
|
||||||
reg_class,
|
reg_class,
|
||||||
error,
|
error,
|
||||||
@ -179,7 +178,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
InlineAsmOperand::Const { anon_const } => {
|
InlineAsmOperand::Const { anon_const } => {
|
||||||
if !self.tcx.features().asm_const {
|
if !self.tcx.features().asm_const {
|
||||||
feature_err(
|
feature_err(
|
||||||
&sess.parse_sess,
|
sess,
|
||||||
sym::asm_const,
|
sym::asm_const,
|
||||||
*op_sp,
|
*op_sp,
|
||||||
"const operands for inline assembly are unstable",
|
"const operands for inline assembly are unstable",
|
||||||
@ -276,7 +275,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
class_name: class.name(),
|
class_name: class.name(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
sess.emit_err(InvalidAsmTemplateModifierRegClass {
|
self.dcx().emit_err(InvalidAsmTemplateModifierRegClass {
|
||||||
placeholder_span,
|
placeholder_span,
|
||||||
op_span: op_sp,
|
op_span: op_sp,
|
||||||
sub,
|
sub,
|
||||||
@ -284,14 +283,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::InlineAsmOperand::Const { .. } => {
|
hir::InlineAsmOperand::Const { .. } => {
|
||||||
sess.emit_err(InvalidAsmTemplateModifierConst {
|
self.dcx().emit_err(InvalidAsmTemplateModifierConst {
|
||||||
placeholder_span,
|
placeholder_span,
|
||||||
op_span: op_sp,
|
op_span: op_sp,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
hir::InlineAsmOperand::SymFn { .. }
|
hir::InlineAsmOperand::SymFn { .. }
|
||||||
| hir::InlineAsmOperand::SymStatic { .. } => {
|
| hir::InlineAsmOperand::SymStatic { .. } => {
|
||||||
sess.emit_err(InvalidAsmTemplateModifierSym {
|
self.dcx().emit_err(InvalidAsmTemplateModifierSym {
|
||||||
placeholder_span,
|
placeholder_span,
|
||||||
op_span: op_sp,
|
op_span: op_sp,
|
||||||
});
|
});
|
||||||
@ -315,7 +314,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// require that the operand name an explicit register, not a
|
// require that the operand name an explicit register, not a
|
||||||
// register class.
|
// register class.
|
||||||
if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() {
|
if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() {
|
||||||
sess.emit_err(RegisterClassOnlyClobber {
|
self.dcx().emit_err(RegisterClassOnlyClobber {
|
||||||
op_span: op_sp,
|
op_span: op_sp,
|
||||||
reg_class_name: reg_class.name(),
|
reg_class_name: reg_class.name(),
|
||||||
});
|
});
|
||||||
@ -384,7 +383,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sess.emit_err(RegisterConflict {
|
self.dcx().emit_err(RegisterConflict {
|
||||||
op_span1: op_sp,
|
op_span1: op_sp,
|
||||||
op_span2: op_sp2,
|
op_span2: op_sp2,
|
||||||
reg1_name: reg_str(idx),
|
reg1_name: reg_str(idx),
|
||||||
|
|||||||
348
compiler/rustc_ast_lowering/src/delegation.rs
Normal file
348
compiler/rustc_ast_lowering/src/delegation.rs
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
//! This module implements expansion of delegation items with early resolved paths.
|
||||||
|
//! It includes a delegation to a free functions:
|
||||||
|
//!
|
||||||
|
//! ```ignore (illustrative)
|
||||||
|
//! reuse module::name { target_expr_template }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! And delegation to a trait methods:
|
||||||
|
//!
|
||||||
|
//! ```ignore (illustrative)
|
||||||
|
//! reuse <Type as Trait>::name { target_expr_template }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! After expansion for both cases we get:
|
||||||
|
//!
|
||||||
|
//! ```ignore (illustrative)
|
||||||
|
//! fn name(
|
||||||
|
//! arg0: InferDelegation(sig_id, Input(0)),
|
||||||
|
//! arg1: InferDelegation(sig_id, Input(1)),
|
||||||
|
//! ...,
|
||||||
|
//! argN: InferDelegation(sig_id, Input(N)),
|
||||||
|
//! ) -> InferDelegation(sig_id, Output) {
|
||||||
|
//! callee_path(target_expr_template(arg0), arg1, ..., argN)
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Where `callee_path` is a path in delegation item e.g. `<Type as Trait>::name`.
|
||||||
|
//! `sig_id` is a id of item from which the signature is inherited. It may be a delegation
|
||||||
|
//! item id (`item_id`) in case of impl trait or path resolution id (`path_id`) otherwise.
|
||||||
|
//!
|
||||||
|
//! Since we do not have a proper way to obtain function type information by path resolution
|
||||||
|
//! in AST, we mark each function parameter type as `InferDelegation` and inherit it in `AstConv`.
|
||||||
|
//!
|
||||||
|
//! Similarly generics, predicates and header are set to the "default" values.
|
||||||
|
//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
|
||||||
|
//! also be emitted in `AstConv`.
|
||||||
|
|
||||||
|
use crate::{ImplTraitPosition, ResolverAstLoweringExt};
|
||||||
|
|
||||||
|
use super::{ImplTraitContext, LoweringContext, ParamMode};
|
||||||
|
|
||||||
|
use ast::visit::Visitor;
|
||||||
|
use hir::def::{DefKind, PartialRes, Res};
|
||||||
|
use hir::{BodyId, HirId};
|
||||||
|
use rustc_ast as ast;
|
||||||
|
use rustc_ast::*;
|
||||||
|
use rustc_errors::ErrorGuaranteed;
|
||||||
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_middle::span_bug;
|
||||||
|
use rustc_middle::ty::ResolverAstLowering;
|
||||||
|
use rustc_span::{symbol::Ident, Span};
|
||||||
|
use rustc_target::spec::abi;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
|
pub(crate) struct DelegationResults<'hir> {
|
||||||
|
pub body_id: hir::BodyId,
|
||||||
|
pub sig: hir::FnSig<'hir>,
|
||||||
|
pub generics: &'hir hir::Generics<'hir>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
pub(crate) fn delegation_has_self(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool {
|
||||||
|
let sig_id = self.get_delegation_sig_id(item_id, path_id, span);
|
||||||
|
let Ok(sig_id) = sig_id else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if let Some(local_sig_id) = sig_id.as_local() {
|
||||||
|
self.resolver.has_self.contains(&local_sig_id)
|
||||||
|
} else {
|
||||||
|
match self.tcx.def_kind(sig_id) {
|
||||||
|
DefKind::Fn => false,
|
||||||
|
DefKind::AssocFn => self.tcx.associated_item(sig_id).fn_has_self_parameter,
|
||||||
|
_ => span_bug!(span, "unexpected DefKind for delegation item"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lower_delegation(
|
||||||
|
&mut self,
|
||||||
|
delegation: &Delegation,
|
||||||
|
item_id: NodeId,
|
||||||
|
) -> DelegationResults<'hir> {
|
||||||
|
let span = delegation.path.segments.last().unwrap().ident.span;
|
||||||
|
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
|
||||||
|
match sig_id {
|
||||||
|
Ok(sig_id) => {
|
||||||
|
let decl = self.lower_delegation_decl(sig_id, span);
|
||||||
|
let sig = self.lower_delegation_sig(span, decl);
|
||||||
|
let body_id = self.lower_delegation_body(sig.decl, delegation);
|
||||||
|
|
||||||
|
let generics = self.lower_delegation_generics(span);
|
||||||
|
DelegationResults { body_id, sig, generics }
|
||||||
|
}
|
||||||
|
Err(err) => self.generate_delegation_error(err, span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_delegation_sig_id(
|
||||||
|
&self,
|
||||||
|
item_id: NodeId,
|
||||||
|
path_id: NodeId,
|
||||||
|
span: Span,
|
||||||
|
) -> Result<DefId, ErrorGuaranteed> {
|
||||||
|
let sig_id = if self.is_in_trait_impl { item_id } else { path_id };
|
||||||
|
let sig_id = self
|
||||||
|
.resolver
|
||||||
|
.get_partial_res(sig_id)
|
||||||
|
.map(|r| r.expect_full_res().opt_def_id())
|
||||||
|
.unwrap_or(None);
|
||||||
|
|
||||||
|
sig_id.ok_or_else(|| {
|
||||||
|
self.tcx
|
||||||
|
.dcx()
|
||||||
|
.span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir> {
|
||||||
|
self.arena.alloc(hir::Generics {
|
||||||
|
params: &[],
|
||||||
|
predicates: &[],
|
||||||
|
has_where_clause_predicates: false,
|
||||||
|
where_clause_span: span,
|
||||||
|
span: span,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_delegation_decl(
|
||||||
|
&mut self,
|
||||||
|
sig_id: DefId,
|
||||||
|
param_span: Span,
|
||||||
|
) -> &'hir hir::FnDecl<'hir> {
|
||||||
|
let args_count = if let Some(local_sig_id) = sig_id.as_local() {
|
||||||
|
// Map may be filled incorrectly due to recursive delegation.
|
||||||
|
// Error will be emmited later in astconv.
|
||||||
|
self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
|
||||||
|
} else {
|
||||||
|
self.tcx.fn_arg_names(sig_id).len()
|
||||||
|
};
|
||||||
|
let inputs = self.arena.alloc_from_iter((0..args_count).into_iter().map(|arg| hir::Ty {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
|
||||||
|
span: self.lower_span(param_span),
|
||||||
|
}));
|
||||||
|
|
||||||
|
let output = self.arena.alloc(hir::Ty {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
|
||||||
|
span: self.lower_span(param_span),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.arena.alloc(hir::FnDecl {
|
||||||
|
inputs,
|
||||||
|
output: hir::FnRetTy::Return(output),
|
||||||
|
c_variadic: false,
|
||||||
|
lifetime_elision_allowed: true,
|
||||||
|
implicit_self: hir::ImplicitSelfKind::None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_delegation_sig(
|
||||||
|
&mut self,
|
||||||
|
span: Span,
|
||||||
|
decl: &'hir hir::FnDecl<'hir>,
|
||||||
|
) -> hir::FnSig<'hir> {
|
||||||
|
hir::FnSig {
|
||||||
|
decl,
|
||||||
|
header: hir::FnHeader {
|
||||||
|
unsafety: hir::Unsafety::Normal,
|
||||||
|
constness: hir::Constness::NotConst,
|
||||||
|
asyncness: hir::IsAsync::NotAsync,
|
||||||
|
abi: abi::Abi::Rust,
|
||||||
|
},
|
||||||
|
span: self.lower_span(span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
|
||||||
|
let pat_node_id = self.next_node_id();
|
||||||
|
let pat_id = self.lower_node_id(pat_node_id);
|
||||||
|
let pat = self.arena.alloc(hir::Pat {
|
||||||
|
hir_id: pat_id,
|
||||||
|
kind: hir::PatKind::Binding(hir::BindingAnnotation::NONE, pat_id, Ident::empty(), None),
|
||||||
|
span: ty.span,
|
||||||
|
default_binding_modes: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
(hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
|
||||||
|
let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
|
||||||
|
ident: Ident::empty(),
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
res: Res::Local(param_id),
|
||||||
|
args: None,
|
||||||
|
infer_args: false,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let path =
|
||||||
|
self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
|
||||||
|
|
||||||
|
hir::Expr {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
|
||||||
|
span: ty.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_delegation_body(
|
||||||
|
&mut self,
|
||||||
|
decl: &'hir hir::FnDecl<'hir>,
|
||||||
|
delegation: &Delegation,
|
||||||
|
) -> BodyId {
|
||||||
|
let path = self.lower_qpath(
|
||||||
|
delegation.id,
|
||||||
|
&delegation.qself,
|
||||||
|
&delegation.path,
|
||||||
|
ParamMode::Optional,
|
||||||
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let block = delegation.body.as_deref();
|
||||||
|
|
||||||
|
self.lower_body(|this| {
|
||||||
|
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
|
||||||
|
let mut args: Vec<hir::Expr<'hir>> = Vec::new();
|
||||||
|
|
||||||
|
for (idx, param_ty) in decl.inputs.iter().enumerate() {
|
||||||
|
let (param, pat_node_id) = this.generate_param(param_ty);
|
||||||
|
parameters.push(param);
|
||||||
|
|
||||||
|
let arg = if let Some(block) = block
|
||||||
|
&& idx == 0
|
||||||
|
{
|
||||||
|
let mut self_resolver = SelfResolver {
|
||||||
|
resolver: this.resolver,
|
||||||
|
path_id: delegation.id,
|
||||||
|
self_param_id: pat_node_id,
|
||||||
|
};
|
||||||
|
self_resolver.visit_block(block);
|
||||||
|
let block = this.lower_block(block, false);
|
||||||
|
hir::Expr {
|
||||||
|
hir_id: this.next_id(),
|
||||||
|
kind: hir::ExprKind::Block(block, None),
|
||||||
|
span: block.span,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let pat_hir_id = this.lower_node_id(pat_node_id);
|
||||||
|
this.generate_arg(param_ty, pat_hir_id)
|
||||||
|
};
|
||||||
|
args.push(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
let args = self.arena.alloc_from_iter(args);
|
||||||
|
let final_expr = this.generate_call(path, args);
|
||||||
|
(this.arena.alloc_from_iter(parameters), final_expr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_call(
|
||||||
|
&mut self,
|
||||||
|
path: hir::QPath<'hir>,
|
||||||
|
args: &'hir [hir::Expr<'hir>],
|
||||||
|
) -> hir::Expr<'hir> {
|
||||||
|
let callee = self.arena.alloc(hir::Expr {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::ExprKind::Path(path),
|
||||||
|
span: path.span(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let expr = self.arena.alloc(hir::Expr {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::ExprKind::Call(callee, args),
|
||||||
|
span: path.span(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let block = self.arena.alloc(hir::Block {
|
||||||
|
stmts: &[],
|
||||||
|
expr: Some(expr),
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
rules: hir::BlockCheckMode::DefaultBlock,
|
||||||
|
span: path.span(),
|
||||||
|
targeted_by_break: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
hir::Expr {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::ExprKind::Block(block, None),
|
||||||
|
span: path.span(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_delegation_error(
|
||||||
|
&mut self,
|
||||||
|
err: ErrorGuaranteed,
|
||||||
|
span: Span,
|
||||||
|
) -> DelegationResults<'hir> {
|
||||||
|
let generics = self.lower_delegation_generics(span);
|
||||||
|
|
||||||
|
let decl = self.arena.alloc(hir::FnDecl {
|
||||||
|
inputs: &[],
|
||||||
|
output: hir::FnRetTy::DefaultReturn(span),
|
||||||
|
c_variadic: false,
|
||||||
|
lifetime_elision_allowed: true,
|
||||||
|
implicit_self: hir::ImplicitSelfKind::None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let sig = self.lower_delegation_sig(span, decl);
|
||||||
|
let body_id = self.lower_body(|this| {
|
||||||
|
let expr =
|
||||||
|
hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
|
||||||
|
(&[], expr)
|
||||||
|
});
|
||||||
|
DelegationResults { generics, body_id, sig }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SelfResolver<'a> {
|
||||||
|
resolver: &'a mut ResolverAstLowering,
|
||||||
|
path_id: NodeId,
|
||||||
|
self_param_id: NodeId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SelfResolver<'a> {
|
||||||
|
fn try_replace_id(&mut self, id: NodeId) {
|
||||||
|
if let Some(res) = self.resolver.partial_res_map.get(&id)
|
||||||
|
&& let Some(Res::Local(sig_id)) = res.full_res()
|
||||||
|
&& sig_id == self.path_id
|
||||||
|
{
|
||||||
|
let new_res = PartialRes::new(Res::Local(self.self_param_id));
|
||||||
|
self.resolver.partial_res_map.insert(id, new_res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> {
|
||||||
|
fn visit_path(&mut self, path: &'ast Path, id: NodeId) {
|
||||||
|
self.try_replace_id(id);
|
||||||
|
visit::walk_path(self, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_path_segment(&mut self, seg: &'ast PathSegment) {
|
||||||
|
self.try_replace_id(seg.id);
|
||||||
|
visit::walk_path_segment(self, seg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
use rustc_errors::DiagnosticArgFromDisplay;
|
use rustc_errors::{codes::*, DiagnosticArgFromDisplay};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")]
|
#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)]
|
||||||
pub struct GenericTypeWithParentheses {
|
pub struct GenericTypeWithParentheses {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
@ -22,7 +22,7 @@ pub struct UseAngleBrackets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_lowering_invalid_abi, code = "E0703")]
|
#[diag(ast_lowering_invalid_abi, code = E0703)]
|
||||||
#[note]
|
#[note]
|
||||||
pub struct InvalidAbi {
|
pub struct InvalidAbi {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
@ -89,7 +89,8 @@ pub enum AssocTyParenthesesSub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_lowering_misplaced_impl_trait, code = "E0562")]
|
#[diag(ast_lowering_misplaced_impl_trait, code = E0562)]
|
||||||
|
#[note]
|
||||||
pub struct MisplacedImplTrait<'a> {
|
pub struct MisplacedImplTrait<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -113,15 +114,15 @@ pub struct UnderscoreExprLhsAssign {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_base_expression_double_dot)]
|
#[diag(ast_lowering_base_expression_double_dot, code = E0797)]
|
||||||
pub struct BaseExpressionDoubleDot {
|
pub struct BaseExpressionDoubleDot {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[suggestion(code = "/* expr */", applicability = "has-placeholders", style = "verbose")]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = "E0728")]
|
#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)]
|
||||||
pub struct AwaitOnlyInAsyncFnAndBlocks {
|
pub struct AwaitOnlyInAsyncFnAndBlocks {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
@ -131,27 +132,19 @@ pub struct AwaitOnlyInAsyncFnAndBlocks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_coroutine_too_many_parameters, code = "E0628")]
|
#[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)]
|
||||||
pub struct CoroutineTooManyParameters {
|
pub struct CoroutineTooManyParameters {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub fn_decl_span: Span,
|
pub fn_decl_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_closure_cannot_be_static, code = "E0697")]
|
#[diag(ast_lowering_closure_cannot_be_static, code = E0697)]
|
||||||
pub struct ClosureCannotBeStatic {
|
pub struct ClosureCannotBeStatic {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub fn_decl_span: Span,
|
pub fn_decl_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
|
||||||
#[help]
|
|
||||||
#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
|
|
||||||
pub struct AsyncNonMoveClosureNotSupported {
|
|
||||||
#[primary_span]
|
|
||||||
pub fn_decl_span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_functional_record_update_destructuring_assignment)]
|
#[diag(ast_lowering_functional_record_update_destructuring_assignment)]
|
||||||
pub struct FunctionalRecordUpdateDestructuringAssignment {
|
pub struct FunctionalRecordUpdateDestructuringAssignment {
|
||||||
@ -161,14 +154,14 @@ pub struct FunctionalRecordUpdateDestructuringAssignment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_async_coroutines_not_supported, code = "E0727")]
|
#[diag(ast_lowering_async_coroutines_not_supported, code = E0727)]
|
||||||
pub struct AsyncCoroutinesNotSupported {
|
pub struct AsyncCoroutinesNotSupported {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_inline_asm_unsupported_target, code = "E0472")]
|
#[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)]
|
||||||
pub struct InlineAsmUnsupportedTarget {
|
pub struct InlineAsmUnsupportedTarget {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -395,3 +388,10 @@ pub enum BadReturnTypeNotation {
|
|||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_lowering_generic_param_default_in_binder)]
|
||||||
|
pub(crate) struct GenericParamDefaultInBinder {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use super::errors::{
|
use super::errors::{
|
||||||
AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
|
AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
|
||||||
BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
|
ClosureCannotBeStatic, CoroutineTooManyParameters,
|
||||||
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
|
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
|
||||||
NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure,
|
NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure,
|
||||||
UnderscoreExprLhsAssign,
|
UnderscoreExprLhsAssign,
|
||||||
@ -13,7 +13,6 @@ use rustc_ast::*;
|
|||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_middle::span_bug;
|
|
||||||
use rustc_session::errors::report_lit_error;
|
use rustc_session::errors::report_lit_error;
|
||||||
use rustc_span::source_map::{respan, Spanned};
|
use rustc_span::source_map::{respan, Spanned};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
@ -56,12 +55,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
// Desugar `ExprForLoop`
|
// Desugar `ExprForLoop`
|
||||||
// from: `[opt_ident]: for <pat> in <head> <body>`
|
// from: `[opt_ident]: for await? <pat> in <iter> <body>`
|
||||||
//
|
//
|
||||||
// This also needs special handling because the HirId of the returned `hir::Expr` will not
|
// This also needs special handling because the HirId of the returned `hir::Expr` will not
|
||||||
// correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
|
// correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
|
||||||
ExprKind::ForLoop(pat, head, body, opt_label) => {
|
ExprKind::ForLoop { pat, iter, body, label, kind } => {
|
||||||
return self.lower_expr_for(e, pat, head, body, *opt_label);
|
return self.lower_expr_for(e, pat, iter, body, *label, *kind);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@ -154,7 +153,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
ExprKind::Let(pat, scrutinee, span, is_recovered) => {
|
ExprKind::Let(pat, scrutinee, span, is_recovered) => {
|
||||||
hir::ExprKind::Let(self.arena.alloc(hir::Let {
|
hir::ExprKind::Let(self.arena.alloc(hir::Let {
|
||||||
hir_id: self.next_id(),
|
|
||||||
span: self.lower_span(*span),
|
span: self.lower_span(*span),
|
||||||
pat: self.lower_pat(pat),
|
pat: self.lower_pat(pat),
|
||||||
ty: None,
|
ty: None,
|
||||||
@ -183,14 +181,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
|
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
|
||||||
hir::MatchSource::Normal,
|
hir::MatchSource::Normal,
|
||||||
),
|
),
|
||||||
ExprKind::Gen(capture_clause, block, GenBlockKind::Async) => self.make_async_expr(
|
|
||||||
*capture_clause,
|
|
||||||
e.id,
|
|
||||||
None,
|
|
||||||
e.span,
|
|
||||||
hir::CoroutineSource::Block,
|
|
||||||
|this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)),
|
|
||||||
),
|
|
||||||
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
|
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
|
||||||
ExprKind::Closure(box Closure {
|
ExprKind::Closure(box Closure {
|
||||||
binder,
|
binder,
|
||||||
@ -226,6 +216,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
*fn_arg_span,
|
*fn_arg_span,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
ExprKind::Gen(capture_clause, block, genblock_kind) => {
|
||||||
|
let desugaring_kind = match genblock_kind {
|
||||||
|
GenBlockKind::Async => hir::CoroutineDesugaring::Async,
|
||||||
|
GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,
|
||||||
|
GenBlockKind::AsyncGen => hir::CoroutineDesugaring::AsyncGen,
|
||||||
|
};
|
||||||
|
self.make_desugared_coroutine_expr(
|
||||||
|
*capture_clause,
|
||||||
|
e.id,
|
||||||
|
None,
|
||||||
|
e.span,
|
||||||
|
desugaring_kind,
|
||||||
|
hir::CoroutineSource::Block,
|
||||||
|
|this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)),
|
||||||
|
)
|
||||||
|
}
|
||||||
ExprKind::Block(blk, opt_label) => {
|
ExprKind::Block(blk, opt_label) => {
|
||||||
let opt_label = self.lower_label(*opt_label);
|
let opt_label = self.lower_label(*opt_label);
|
||||||
hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
|
hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
|
||||||
@ -249,7 +255,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
|
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
|
||||||
}
|
}
|
||||||
ExprKind::Underscore => {
|
ExprKind::Underscore => {
|
||||||
let guar = self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
|
let guar = self.dcx().emit_err(UnderscoreExprLhsAssign { span: e.span });
|
||||||
hir::ExprKind::Err(guar)
|
hir::ExprKind::Err(guar)
|
||||||
}
|
}
|
||||||
ExprKind::Path(qself, path) => {
|
ExprKind::Path(qself, path) => {
|
||||||
@ -294,8 +300,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let rest = match &se.rest {
|
let rest = match &se.rest {
|
||||||
StructRest::Base(e) => Some(self.lower_expr(e)),
|
StructRest::Base(e) => Some(self.lower_expr(e)),
|
||||||
StructRest::Rest(sp) => {
|
StructRest::Rest(sp) => {
|
||||||
let guar =
|
let guar = self.dcx().emit_err(BaseExpressionDoubleDot { span: *sp });
|
||||||
self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
|
|
||||||
Some(&*self.arena.alloc(self.expr_err(*sp, guar)))
|
Some(&*self.arena.alloc(self.expr_err(*sp, guar)))
|
||||||
}
|
}
|
||||||
StructRest::None => None,
|
StructRest::None => None,
|
||||||
@ -314,30 +319,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
rest,
|
rest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ExprKind::Gen(capture_clause, block, GenBlockKind::Gen) => self.make_gen_expr(
|
|
||||||
*capture_clause,
|
|
||||||
e.id,
|
|
||||||
None,
|
|
||||||
e.span,
|
|
||||||
hir::CoroutineSource::Block,
|
|
||||||
|this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)),
|
|
||||||
),
|
|
||||||
ExprKind::Gen(capture_clause, block, GenBlockKind::AsyncGen) => self
|
|
||||||
.make_async_gen_expr(
|
|
||||||
*capture_clause,
|
|
||||||
e.id,
|
|
||||||
None,
|
|
||||||
e.span,
|
|
||||||
hir::CoroutineSource::Block,
|
|
||||||
|this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)),
|
|
||||||
),
|
|
||||||
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
|
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
|
||||||
ExprKind::Err => hir::ExprKind::Err(
|
ExprKind::Err => {
|
||||||
self.tcx.sess.span_delayed_bug(e.span, "lowered ExprKind::Err"),
|
hir::ExprKind::Err(self.dcx().span_delayed_bug(e.span, "lowered ExprKind::Err"))
|
||||||
),
|
}
|
||||||
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
|
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
|
||||||
|
|
||||||
ExprKind::Paren(_) | ExprKind::ForLoop(..) => {
|
ExprKind::Paren(_) | ExprKind::ForLoop { .. } => {
|
||||||
unreachable!("already handled")
|
unreachable!("already handled")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,20 +544,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
||||||
let pat = self.lower_pat(&arm.pat);
|
let pat = self.lower_pat(&arm.pat);
|
||||||
let mut guard = arm.guard.as_ref().map(|cond| {
|
let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond));
|
||||||
if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind {
|
|
||||||
hir::Guard::IfLet(self.arena.alloc(hir::Let {
|
|
||||||
hir_id: self.next_id(),
|
|
||||||
span: self.lower_span(*span),
|
|
||||||
pat: self.lower_pat(pat),
|
|
||||||
ty: None,
|
|
||||||
init: self.lower_expr(scrutinee),
|
|
||||||
is_recovered: *is_recovered,
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
hir::Guard::If(self.lower_expr(cond))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let hir_id = self.next_id();
|
let hir_id = self.next_id();
|
||||||
let span = self.lower_span(arm.span);
|
let span = self.lower_span(arm.span);
|
||||||
self.lower_attrs(hir_id, &arm.attrs);
|
self.lower_attrs(hir_id, &arm.attrs);
|
||||||
@ -584,14 +559,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
if self.tcx.features().never_patterns {
|
if self.tcx.features().never_patterns {
|
||||||
// If the feature is off we already emitted the error after parsing.
|
// If the feature is off we already emitted the error after parsing.
|
||||||
let suggestion = span.shrink_to_hi();
|
let suggestion = span.shrink_to_hi();
|
||||||
self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
|
self.dcx().emit_err(MatchArmWithNoBody { span, suggestion });
|
||||||
}
|
}
|
||||||
} else if let Some(body) = &arm.body {
|
} else if let Some(body) = &arm.body {
|
||||||
self.tcx.sess.emit_err(NeverPatternWithBody { span: body.span });
|
self.dcx().emit_err(NeverPatternWithBody { span: body.span });
|
||||||
guard = None;
|
|
||||||
} else if let Some(g) = &arm.guard {
|
} else if let Some(g) = &arm.guard {
|
||||||
self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span });
|
self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
|
||||||
guard = None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We add a fake `loop {}` arm body so that it typecks to `!`.
|
// We add a fake `loop {}` arm body so that it typecks to `!`.
|
||||||
@ -613,110 +586,71 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
hir::Arm { hir_id, pat, guard, body, span }
|
hir::Arm { hir_id, pat, guard, body, span }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lower an `async` construct to a coroutine that implements `Future`.
|
/// Lower/desugar a coroutine construct.
|
||||||
|
///
|
||||||
|
/// In particular, this creates the correct async resume argument and `_task_context`.
|
||||||
///
|
///
|
||||||
/// This results in:
|
/// This results in:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// static move? |_task_context| -> <ret_ty> {
|
/// static move? |<_task_context?>| -> <return_ty> {
|
||||||
/// <body>
|
/// <body>
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub(super) fn make_async_expr(
|
pub(super) fn make_desugared_coroutine_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
capture_clause: CaptureBy,
|
capture_clause: CaptureBy,
|
||||||
closure_node_id: NodeId,
|
closure_node_id: NodeId,
|
||||||
ret_ty: Option<hir::FnRetTy<'hir>>,
|
return_ty: Option<hir::FnRetTy<'hir>>,
|
||||||
span: Span,
|
|
||||||
async_coroutine_source: hir::CoroutineSource,
|
|
||||||
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
|
||||||
) -> hir::ExprKind<'hir> {
|
|
||||||
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
|
|
||||||
|
|
||||||
// Resume argument type: `ResumeTy`
|
|
||||||
let unstable_span = self.mark_span_with_reason(
|
|
||||||
DesugaringKind::Async,
|
|
||||||
self.lower_span(span),
|
|
||||||
Some(self.allow_gen_future.clone()),
|
|
||||||
);
|
|
||||||
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span);
|
|
||||||
let input_ty = hir::Ty {
|
|
||||||
hir_id: self.next_id(),
|
|
||||||
kind: hir::TyKind::Path(resume_ty),
|
|
||||||
span: unstable_span,
|
|
||||||
};
|
|
||||||
|
|
||||||
// The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`.
|
|
||||||
let fn_decl = self.arena.alloc(hir::FnDecl {
|
|
||||||
inputs: arena_vec![self; input_ty],
|
|
||||||
output,
|
|
||||||
c_variadic: false,
|
|
||||||
implicit_self: hir::ImplicitSelfKind::None,
|
|
||||||
lifetime_elision_allowed: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
|
|
||||||
let (pat, task_context_hid) = self.pat_ident_binding_mode(
|
|
||||||
span,
|
|
||||||
Ident::with_dummy_span(sym::_task_context),
|
|
||||||
hir::BindingAnnotation::MUT,
|
|
||||||
);
|
|
||||||
let param = hir::Param {
|
|
||||||
hir_id: self.next_id(),
|
|
||||||
pat,
|
|
||||||
ty_span: self.lower_span(span),
|
|
||||||
span: self.lower_span(span),
|
|
||||||
};
|
|
||||||
let params = arena_vec![self; param];
|
|
||||||
|
|
||||||
let body = self.lower_body(move |this| {
|
|
||||||
this.coroutine_kind = Some(hir::CoroutineKind::Async(async_coroutine_source));
|
|
||||||
|
|
||||||
let old_ctx = this.task_context;
|
|
||||||
this.task_context = Some(task_context_hid);
|
|
||||||
let res = body(this);
|
|
||||||
this.task_context = old_ctx;
|
|
||||||
(params, res)
|
|
||||||
});
|
|
||||||
|
|
||||||
// `static |_task_context| -> <ret_ty> { body }`:
|
|
||||||
hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
|
|
||||||
def_id: self.local_def_id(closure_node_id),
|
|
||||||
binder: hir::ClosureBinder::Default,
|
|
||||||
capture_clause,
|
|
||||||
bound_generic_params: &[],
|
|
||||||
fn_decl,
|
|
||||||
body,
|
|
||||||
fn_decl_span: self.lower_span(span),
|
|
||||||
fn_arg_span: None,
|
|
||||||
movability: Some(hir::Movability::Static),
|
|
||||||
constness: hir::Constness::NotConst,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Lower a `gen` construct to a generator that implements `Iterator`.
|
|
||||||
///
|
|
||||||
/// This results in:
|
|
||||||
///
|
|
||||||
/// ```text
|
|
||||||
/// static move? |()| -> () {
|
|
||||||
/// <body>
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub(super) fn make_gen_expr(
|
|
||||||
&mut self,
|
|
||||||
capture_clause: CaptureBy,
|
|
||||||
closure_node_id: NodeId,
|
|
||||||
_yield_ty: Option<hir::FnRetTy<'hir>>,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
|
desugaring_kind: hir::CoroutineDesugaring,
|
||||||
coroutine_source: hir::CoroutineSource,
|
coroutine_source: hir::CoroutineSource,
|
||||||
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::ExprKind<'hir> {
|
||||||
let output = hir::FnRetTy::DefaultReturn(self.lower_span(span));
|
let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source);
|
||||||
|
|
||||||
|
// The `async` desugaring takes a resume argument and maintains a `task_context`,
|
||||||
|
// whereas a generator does not.
|
||||||
|
let (inputs, params, task_context): (&[_], &[_], _) = match desugaring_kind {
|
||||||
|
hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen => {
|
||||||
|
// Resume argument type: `ResumeTy`
|
||||||
|
let unstable_span = self.mark_span_with_reason(
|
||||||
|
DesugaringKind::Async,
|
||||||
|
self.lower_span(span),
|
||||||
|
Some(self.allow_gen_future.clone()),
|
||||||
|
);
|
||||||
|
let resume_ty = self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span);
|
||||||
|
let input_ty = hir::Ty {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
kind: hir::TyKind::Path(resume_ty),
|
||||||
|
span: unstable_span,
|
||||||
|
};
|
||||||
|
let inputs = arena_vec![self; input_ty];
|
||||||
|
|
||||||
|
// Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
|
||||||
|
let (pat, task_context_hid) = self.pat_ident_binding_mode(
|
||||||
|
span,
|
||||||
|
Ident::with_dummy_span(sym::_task_context),
|
||||||
|
hir::BindingAnnotation::MUT,
|
||||||
|
);
|
||||||
|
let param = hir::Param {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
pat,
|
||||||
|
ty_span: self.lower_span(span),
|
||||||
|
span: self.lower_span(span),
|
||||||
|
};
|
||||||
|
let params = arena_vec![self; param];
|
||||||
|
|
||||||
|
(inputs, params, Some(task_context_hid))
|
||||||
|
}
|
||||||
|
hir::CoroutineDesugaring::Gen => (&[], &[], None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let output =
|
||||||
|
return_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
|
||||||
|
|
||||||
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
|
|
||||||
let fn_decl = self.arena.alloc(hir::FnDecl {
|
let fn_decl = self.arena.alloc(hir::FnDecl {
|
||||||
inputs: &[],
|
inputs,
|
||||||
output,
|
output,
|
||||||
c_variadic: false,
|
c_variadic: false,
|
||||||
implicit_self: hir::ImplicitSelfKind::None,
|
implicit_self: hir::ImplicitSelfKind::None,
|
||||||
@ -724,94 +658,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let body = self.lower_body(move |this| {
|
let body = self.lower_body(move |this| {
|
||||||
this.coroutine_kind = Some(hir::CoroutineKind::Gen(coroutine_source));
|
this.coroutine_kind = Some(coroutine_kind);
|
||||||
|
|
||||||
let res = body(this);
|
|
||||||
(&[], res)
|
|
||||||
});
|
|
||||||
|
|
||||||
// `static |()| -> () { body }`:
|
|
||||||
hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
|
|
||||||
def_id: self.local_def_id(closure_node_id),
|
|
||||||
binder: hir::ClosureBinder::Default,
|
|
||||||
capture_clause,
|
|
||||||
bound_generic_params: &[],
|
|
||||||
fn_decl,
|
|
||||||
body,
|
|
||||||
fn_decl_span: self.lower_span(span),
|
|
||||||
fn_arg_span: None,
|
|
||||||
movability: Some(Movability::Movable),
|
|
||||||
constness: hir::Constness::NotConst,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Lower a `async gen` construct to a generator that implements `AsyncIterator`.
|
|
||||||
///
|
|
||||||
/// This results in:
|
|
||||||
///
|
|
||||||
/// ```text
|
|
||||||
/// static move? |_task_context| -> () {
|
|
||||||
/// <body>
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub(super) fn make_async_gen_expr(
|
|
||||||
&mut self,
|
|
||||||
capture_clause: CaptureBy,
|
|
||||||
closure_node_id: NodeId,
|
|
||||||
_yield_ty: Option<hir::FnRetTy<'hir>>,
|
|
||||||
span: Span,
|
|
||||||
async_coroutine_source: hir::CoroutineSource,
|
|
||||||
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
|
||||||
) -> hir::ExprKind<'hir> {
|
|
||||||
let output = hir::FnRetTy::DefaultReturn(self.lower_span(span));
|
|
||||||
|
|
||||||
// Resume argument type: `ResumeTy`
|
|
||||||
let unstable_span = self.mark_span_with_reason(
|
|
||||||
DesugaringKind::Async,
|
|
||||||
self.lower_span(span),
|
|
||||||
Some(self.allow_gen_future.clone()),
|
|
||||||
);
|
|
||||||
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span);
|
|
||||||
let input_ty = hir::Ty {
|
|
||||||
hir_id: self.next_id(),
|
|
||||||
kind: hir::TyKind::Path(resume_ty),
|
|
||||||
span: unstable_span,
|
|
||||||
};
|
|
||||||
|
|
||||||
// The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`.
|
|
||||||
let fn_decl = self.arena.alloc(hir::FnDecl {
|
|
||||||
inputs: arena_vec![self; input_ty],
|
|
||||||
output,
|
|
||||||
c_variadic: false,
|
|
||||||
implicit_self: hir::ImplicitSelfKind::None,
|
|
||||||
lifetime_elision_allowed: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
|
|
||||||
let (pat, task_context_hid) = self.pat_ident_binding_mode(
|
|
||||||
span,
|
|
||||||
Ident::with_dummy_span(sym::_task_context),
|
|
||||||
hir::BindingAnnotation::MUT,
|
|
||||||
);
|
|
||||||
let param = hir::Param {
|
|
||||||
hir_id: self.next_id(),
|
|
||||||
pat,
|
|
||||||
ty_span: self.lower_span(span),
|
|
||||||
span: self.lower_span(span),
|
|
||||||
};
|
|
||||||
let params = arena_vec![self; param];
|
|
||||||
|
|
||||||
let body = self.lower_body(move |this| {
|
|
||||||
this.coroutine_kind = Some(hir::CoroutineKind::AsyncGen(async_coroutine_source));
|
|
||||||
|
|
||||||
let old_ctx = this.task_context;
|
let old_ctx = this.task_context;
|
||||||
this.task_context = Some(task_context_hid);
|
if task_context.is_some() {
|
||||||
|
this.task_context = task_context;
|
||||||
|
}
|
||||||
let res = body(this);
|
let res = body(this);
|
||||||
this.task_context = old_ctx;
|
this.task_context = old_ctx;
|
||||||
|
|
||||||
(params, res)
|
(params, res)
|
||||||
});
|
});
|
||||||
|
|
||||||
// `static |_task_context| -> <ret_ty> { body }`:
|
// `static |<_task_context?>| -> <return_ty> { <body> }`:
|
||||||
hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
|
hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
|
||||||
def_id: self.local_def_id(closure_node_id),
|
def_id: self.local_def_id(closure_node_id),
|
||||||
binder: hir::ClosureBinder::Default,
|
binder: hir::ClosureBinder::Default,
|
||||||
@ -821,7 +680,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
body,
|
body,
|
||||||
fn_decl_span: self.lower_span(span),
|
fn_decl_span: self.lower_span(span),
|
||||||
fn_arg_span: None,
|
fn_arg_span: None,
|
||||||
movability: Some(hir::Movability::Static),
|
kind: hir::ClosureKind::Coroutine(coroutine_kind),
|
||||||
constness: hir::Constness::NotConst,
|
constness: hir::Constness::NotConst,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -874,26 +733,42 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
|
fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
|
||||||
|
let expr = self.arena.alloc(self.lower_expr_mut(expr));
|
||||||
|
self.make_lowered_await(await_kw_span, expr, FutureKind::Future)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes an expr that has already been lowered and generates a desugared await loop around it
|
||||||
|
fn make_lowered_await(
|
||||||
|
&mut self,
|
||||||
|
await_kw_span: Span,
|
||||||
|
expr: &'hir hir::Expr<'hir>,
|
||||||
|
await_kind: FutureKind,
|
||||||
|
) -> hir::ExprKind<'hir> {
|
||||||
let full_span = expr.span.to(await_kw_span);
|
let full_span = expr.span.to(await_kw_span);
|
||||||
|
|
||||||
let is_async_gen = match self.coroutine_kind {
|
let is_async_gen = match self.coroutine_kind {
|
||||||
Some(hir::CoroutineKind::Async(_)) => false,
|
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => false,
|
||||||
Some(hir::CoroutineKind::AsyncGen(_)) => true,
|
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
|
||||||
Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => {
|
Some(hir::CoroutineKind::Coroutine(_))
|
||||||
return hir::ExprKind::Err(self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
|
| Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
|
||||||
|
| None => {
|
||||||
|
return hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
|
||||||
await_kw_span,
|
await_kw_span,
|
||||||
item_span: self.current_item,
|
item_span: self.current_item,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None);
|
let features = match await_kind {
|
||||||
|
FutureKind::Future => None,
|
||||||
|
FutureKind::AsyncIterator => Some(self.allow_for_await.clone()),
|
||||||
|
};
|
||||||
|
let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features);
|
||||||
let gen_future_span = self.mark_span_with_reason(
|
let gen_future_span = self.mark_span_with_reason(
|
||||||
DesugaringKind::Await,
|
DesugaringKind::Await,
|
||||||
full_span,
|
full_span,
|
||||||
Some(self.allow_gen_future.clone()),
|
Some(self.allow_gen_future.clone()),
|
||||||
);
|
);
|
||||||
let expr = self.lower_expr_mut(expr);
|
|
||||||
let expr_hir_id = expr.hir_id;
|
let expr_hir_id = expr.hir_id;
|
||||||
|
|
||||||
// Note that the name of this binding must not be changed to something else because
|
// Note that the name of this binding must not be changed to something else because
|
||||||
@ -934,11 +809,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
hir::LangItem::GetContext,
|
hir::LangItem::GetContext,
|
||||||
arena_vec![self; task_context],
|
arena_vec![self; task_context],
|
||||||
);
|
);
|
||||||
let call = self.expr_call_lang_item_fn(
|
let call = match await_kind {
|
||||||
span,
|
FutureKind::Future => self.expr_call_lang_item_fn(
|
||||||
hir::LangItem::FuturePoll,
|
span,
|
||||||
arena_vec![self; new_unchecked, get_context],
|
hir::LangItem::FuturePoll,
|
||||||
);
|
arena_vec![self; new_unchecked, get_context],
|
||||||
|
),
|
||||||
|
FutureKind::AsyncIterator => self.expr_call_lang_item_fn(
|
||||||
|
span,
|
||||||
|
hir::LangItem::AsyncIteratorPollNext,
|
||||||
|
arena_vec![self; new_unchecked, get_context],
|
||||||
|
),
|
||||||
|
};
|
||||||
self.arena.alloc(self.expr_unsafe(call))
|
self.arena.alloc(self.expr_unsafe(call))
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1020,11 +902,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let awaitee_arm = self.arm(awaitee_pat, loop_expr);
|
let awaitee_arm = self.arm(awaitee_pat, loop_expr);
|
||||||
|
|
||||||
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
|
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
|
||||||
let into_future_expr = self.expr_call_lang_item_fn(
|
let into_future_expr = match await_kind {
|
||||||
span,
|
FutureKind::Future => self.expr_call_lang_item_fn(
|
||||||
hir::LangItem::IntoFutureIntoFuture,
|
span,
|
||||||
arena_vec![self; expr],
|
hir::LangItem::IntoFutureIntoFuture,
|
||||||
);
|
arena_vec![self; *expr],
|
||||||
|
),
|
||||||
|
// Not needed for `for await` because we expect to have already called
|
||||||
|
// `IntoAsyncIterator::into_async_iter` on it.
|
||||||
|
FutureKind::AsyncIterator => expr,
|
||||||
|
};
|
||||||
|
|
||||||
// match <into_future_expr> {
|
// match <into_future_expr> {
|
||||||
// mut __awaitee => loop { .. }
|
// mut __awaitee => loop { .. }
|
||||||
@ -1050,7 +937,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::ExprKind<'hir> {
|
||||||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||||
|
|
||||||
let (body_id, coroutine_option) = self.with_new_scopes(fn_decl_span, move |this| {
|
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
|
||||||
let mut coroutine_kind = None;
|
let mut coroutine_kind = None;
|
||||||
let body_id = this.lower_fn_body(decl, |this| {
|
let body_id = this.lower_fn_body(decl, |this| {
|
||||||
let e = this.lower_expr_mut(body);
|
let e = this.lower_expr_mut(body);
|
||||||
@ -1058,7 +945,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
e
|
e
|
||||||
});
|
});
|
||||||
let coroutine_option =
|
let coroutine_option =
|
||||||
this.coroutine_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
||||||
(body_id, coroutine_option)
|
(body_id, coroutine_option)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1075,39 +962,39 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
body: body_id,
|
body: body_id,
|
||||||
fn_decl_span: self.lower_span(fn_decl_span),
|
fn_decl_span: self.lower_span(fn_decl_span),
|
||||||
fn_arg_span: Some(self.lower_span(fn_arg_span)),
|
fn_arg_span: Some(self.lower_span(fn_arg_span)),
|
||||||
movability: coroutine_option,
|
kind: closure_kind,
|
||||||
constness: self.lower_constness(constness),
|
constness: self.lower_constness(constness),
|
||||||
});
|
});
|
||||||
|
|
||||||
hir::ExprKind::Closure(c)
|
hir::ExprKind::Closure(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coroutine_movability_for_fn(
|
fn closure_movability_for_fn(
|
||||||
&mut self,
|
&mut self,
|
||||||
decl: &FnDecl,
|
decl: &FnDecl,
|
||||||
fn_decl_span: Span,
|
fn_decl_span: Span,
|
||||||
coroutine_kind: Option<hir::CoroutineKind>,
|
coroutine_kind: Option<hir::CoroutineKind>,
|
||||||
movability: Movability,
|
movability: Movability,
|
||||||
) -> Option<hir::Movability> {
|
) -> hir::ClosureKind {
|
||||||
match coroutine_kind {
|
match coroutine_kind {
|
||||||
Some(hir::CoroutineKind::Coroutine) => {
|
Some(hir::CoroutineKind::Coroutine(_)) => {
|
||||||
if decl.inputs.len() > 1 {
|
if decl.inputs.len() > 1 {
|
||||||
self.tcx.sess.emit_err(CoroutineTooManyParameters { fn_decl_span });
|
self.dcx().emit_err(CoroutineTooManyParameters { fn_decl_span });
|
||||||
}
|
}
|
||||||
Some(movability)
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(movability))
|
||||||
}
|
}
|
||||||
Some(
|
Some(
|
||||||
hir::CoroutineKind::Gen(_)
|
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||||
| hir::CoroutineKind::Async(_)
|
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
|
||||||
| hir::CoroutineKind::AsyncGen(_),
|
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
|
||||||
) => {
|
) => {
|
||||||
panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering");
|
panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering");
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if movability == Movability::Static {
|
if movability == Movability::Static {
|
||||||
self.tcx.sess.emit_err(ClosureCannotBeStatic { fn_decl_span });
|
self.dcx().emit_err(ClosureCannotBeStatic { fn_decl_span });
|
||||||
}
|
}
|
||||||
None
|
hir::ClosureKind::Closure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1139,28 +1026,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
fn_decl_span: Span,
|
fn_decl_span: Span,
|
||||||
fn_arg_span: Span,
|
fn_arg_span: Span,
|
||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::ExprKind<'hir> {
|
||||||
let CoroutineKind::Async { closure_id: inner_closure_id, .. } = coroutine_kind else {
|
|
||||||
span_bug!(fn_decl_span, "`async gen` and `gen` closures are not supported, yet");
|
|
||||||
};
|
|
||||||
|
|
||||||
if let &ClosureBinder::For { span, .. } = binder {
|
if let &ClosureBinder::For { span, .. } = binder {
|
||||||
self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
|
self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
|
||||||
}
|
}
|
||||||
|
|
||||||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||||
|
|
||||||
let outer_decl =
|
|
||||||
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
|
||||||
|
|
||||||
let body = self.with_new_scopes(fn_decl_span, |this| {
|
let body = self.with_new_scopes(fn_decl_span, |this| {
|
||||||
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
|
|
||||||
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
|
|
||||||
this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform `async |x: u8| -> X { ... }` into
|
// Transform `async |x: u8| -> X { ... }` into
|
||||||
// `|x: u8| || -> X { ... }`.
|
// `|x: u8| || -> X { ... }`.
|
||||||
let body_id = this.lower_fn_body(&outer_decl, |this| {
|
let body_id = this.lower_body(|this| {
|
||||||
let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
|
let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
|
||||||
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
|
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
|
||||||
Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx)))
|
Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx)))
|
||||||
@ -1168,21 +1043,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let async_body = this.make_async_expr(
|
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||||
capture_clause,
|
decl,
|
||||||
inner_closure_id,
|
|
||||||
async_ret_ty,
|
|
||||||
body.span,
|
|
||||||
hir::CoroutineSource::Closure,
|
|
||||||
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
||||||
|
body.span,
|
||||||
|
coroutine_kind,
|
||||||
|
hir::CoroutineSource::Closure,
|
||||||
|
async_ret_ty,
|
||||||
);
|
);
|
||||||
let hir_id = this.lower_node_id(inner_closure_id);
|
|
||||||
|
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
|
||||||
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
|
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
|
||||||
hir::Expr { hir_id, kind: async_body, span: this.lower_span(body.span) }
|
|
||||||
|
(parameters, expr)
|
||||||
});
|
});
|
||||||
body_id
|
body_id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let outer_decl =
|
||||||
|
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
||||||
|
|
||||||
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
||||||
// We need to lower the declaration outside the new scope, because we
|
// We need to lower the declaration outside the new scope, because we
|
||||||
// have to conserve the state of being inside a loop condition for the
|
// have to conserve the state of being inside a loop condition for the
|
||||||
@ -1199,7 +1079,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
body,
|
body,
|
||||||
fn_decl_span: self.lower_span(fn_decl_span),
|
fn_decl_span: self.lower_span(fn_decl_span),
|
||||||
fn_arg_span: Some(self.lower_span(fn_arg_span)),
|
fn_arg_span: Some(self.lower_span(fn_arg_span)),
|
||||||
movability: None,
|
kind: hir::ClosureKind::Closure,
|
||||||
constness: hir::Constness::NotConst,
|
constness: hir::Constness::NotConst,
|
||||||
});
|
});
|
||||||
hir::ExprKind::Closure(c)
|
hir::ExprKind::Closure(c)
|
||||||
@ -1411,7 +1291,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
);
|
);
|
||||||
let fields_omitted = match &se.rest {
|
let fields_omitted = match &se.rest {
|
||||||
StructRest::Base(e) => {
|
StructRest::Base(e) => {
|
||||||
self.tcx.sess.emit_err(FunctionalRecordUpdateDestructuringAssignment {
|
self.dcx().emit_err(FunctionalRecordUpdateDestructuringAssignment {
|
||||||
span: e.span,
|
span: e.span,
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
@ -1507,7 +1387,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
|
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
|
||||||
(Some(..), Some(..), Closed) => unreachable!(),
|
(Some(..), Some(..), Closed) => unreachable!(),
|
||||||
(start, None, Closed) => {
|
(start, None, Closed) => {
|
||||||
self.tcx.sess.emit_err(InclusiveRangeWithNoEnd { span });
|
self.dcx().emit_err(InclusiveRangeWithNoEnd { span });
|
||||||
match start {
|
match start {
|
||||||
Some(..) => hir::LangItem::RangeFrom,
|
Some(..) => hir::LangItem::RangeFrom,
|
||||||
None => hir::LangItem::RangeFull,
|
None => hir::LangItem::RangeFull,
|
||||||
@ -1612,24 +1492,36 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
|
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
|
||||||
let is_async_gen = match self.coroutine_kind {
|
let is_async_gen = match self.coroutine_kind {
|
||||||
Some(hir::CoroutineKind::Gen(_)) => false,
|
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
|
||||||
Some(hir::CoroutineKind::AsyncGen(_)) => true,
|
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
|
||||||
Some(hir::CoroutineKind::Async(_)) => {
|
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
|
||||||
return hir::ExprKind::Err(
|
return hir::ExprKind::Err(
|
||||||
self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }),
|
self.dcx().emit_err(AsyncCoroutinesNotSupported { span }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some(hir::CoroutineKind::Coroutine) | None => {
|
Some(hir::CoroutineKind::Coroutine(_)) => {
|
||||||
if !self.tcx.features().coroutines {
|
if !self.tcx.features().coroutines {
|
||||||
rustc_session::parse::feature_err(
|
rustc_session::parse::feature_err(
|
||||||
&self.tcx.sess.parse_sess,
|
&self.tcx.sess,
|
||||||
sym::coroutines,
|
sym::coroutines,
|
||||||
span,
|
span,
|
||||||
"yield syntax is experimental",
|
"yield syntax is experimental",
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine);
|
false
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if !self.tcx.features().coroutines {
|
||||||
|
rustc_session::parse::feature_err(
|
||||||
|
&self.tcx.sess,
|
||||||
|
sym::coroutines,
|
||||||
|
span,
|
||||||
|
"yield syntax is experimental",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1685,6 +1577,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
head: &Expr,
|
head: &Expr,
|
||||||
body: &Block,
|
body: &Block,
|
||||||
opt_label: Option<Label>,
|
opt_label: Option<Label>,
|
||||||
|
loop_kind: ForLoopKind,
|
||||||
) -> hir::Expr<'hir> {
|
) -> hir::Expr<'hir> {
|
||||||
let head = self.lower_expr_mut(head);
|
let head = self.lower_expr_mut(head);
|
||||||
let pat = self.lower_pat(pat);
|
let pat = self.lower_pat(pat);
|
||||||
@ -1713,17 +1606,41 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let (iter_pat, iter_pat_nid) =
|
let (iter_pat, iter_pat_nid) =
|
||||||
self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT);
|
self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT);
|
||||||
|
|
||||||
// `match Iterator::next(&mut iter) { ... }`
|
|
||||||
let match_expr = {
|
let match_expr = {
|
||||||
let iter = self.expr_ident(head_span, iter, iter_pat_nid);
|
let iter = self.expr_ident(head_span, iter, iter_pat_nid);
|
||||||
let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
|
let next_expr = match loop_kind {
|
||||||
let next_expr = self.expr_call_lang_item_fn(
|
ForLoopKind::For => {
|
||||||
head_span,
|
// `Iterator::next(&mut iter)`
|
||||||
hir::LangItem::IteratorNext,
|
let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
|
||||||
arena_vec![self; ref_mut_iter],
|
self.expr_call_lang_item_fn(
|
||||||
);
|
head_span,
|
||||||
|
hir::LangItem::IteratorNext,
|
||||||
|
arena_vec![self; ref_mut_iter],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ForLoopKind::ForAwait => {
|
||||||
|
// we'll generate `unsafe { Pin::new_unchecked(&mut iter) })` and then pass this
|
||||||
|
// to make_lowered_await with `FutureKind::AsyncIterator` which will generator
|
||||||
|
// calls to `poll_next`. In user code, this would probably be a call to
|
||||||
|
// `Pin::as_mut` but here it's easy enough to do `new_unchecked`.
|
||||||
|
|
||||||
|
// `&mut iter`
|
||||||
|
let iter = self.expr_mut_addr_of(head_span, iter);
|
||||||
|
// `Pin::new_unchecked(...)`
|
||||||
|
let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
|
||||||
|
head_span,
|
||||||
|
hir::LangItem::PinNewUnchecked,
|
||||||
|
arena_vec![self; iter],
|
||||||
|
));
|
||||||
|
// `unsafe { ... }`
|
||||||
|
let iter = self.arena.alloc(self.expr_unsafe(iter));
|
||||||
|
let kind = self.make_lowered_await(head_span, iter, FutureKind::AsyncIterator);
|
||||||
|
self.arena.alloc(hir::Expr { hir_id: self.next_id(), kind, span: head_span })
|
||||||
|
}
|
||||||
|
};
|
||||||
let arms = arena_vec![self; none_arm, some_arm];
|
let arms = arena_vec![self; none_arm, some_arm];
|
||||||
|
|
||||||
|
// `match $next_expr { ... }`
|
||||||
self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
|
self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
|
||||||
};
|
};
|
||||||
let match_stmt = self.stmt_expr(for_span, match_expr);
|
let match_stmt = self.stmt_expr(for_span, match_expr);
|
||||||
@ -1743,13 +1660,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// `mut iter => { ... }`
|
// `mut iter => { ... }`
|
||||||
let iter_arm = self.arm(iter_pat, loop_expr);
|
let iter_arm = self.arm(iter_pat, loop_expr);
|
||||||
|
|
||||||
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
|
let into_iter_expr = match loop_kind {
|
||||||
let into_iter_expr = {
|
ForLoopKind::For => {
|
||||||
self.expr_call_lang_item_fn(
|
// `::std::iter::IntoIterator::into_iter(<head>)`
|
||||||
head_span,
|
self.expr_call_lang_item_fn(
|
||||||
hir::LangItem::IntoIterIntoIter,
|
head_span,
|
||||||
arena_vec![self; head],
|
hir::LangItem::IntoIterIntoIter,
|
||||||
)
|
arena_vec![self; head],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// ` unsafe { Pin::new_unchecked(&mut into_async_iter(<head>)) }`
|
||||||
|
ForLoopKind::ForAwait => {
|
||||||
|
// `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`
|
||||||
|
let iter = self.expr_call_lang_item_fn(
|
||||||
|
head_span,
|
||||||
|
hir::LangItem::IntoAsyncIterIntoIter,
|
||||||
|
arena_vec![self; head],
|
||||||
|
);
|
||||||
|
let iter = self.expr_mut_addr_of(head_span, iter);
|
||||||
|
// `Pin::new_unchecked(...)`
|
||||||
|
let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
|
||||||
|
head_span,
|
||||||
|
hir::LangItem::PinNewUnchecked,
|
||||||
|
arena_vec![self; iter],
|
||||||
|
));
|
||||||
|
// `unsafe { ... }`
|
||||||
|
let iter = self.arena.alloc(self.expr_unsafe(iter));
|
||||||
|
iter
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let match_expr = self.arena.alloc(self.expr_match(
|
let match_expr = self.arena.alloc(self.expr_match(
|
||||||
@ -1960,7 +1898,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
|
pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
|
||||||
let lit = self.arena.alloc(hir::Lit {
|
let lit = self.arena.alloc(hir::Lit {
|
||||||
span: sp,
|
span: sp,
|
||||||
node: ast::LitKind::Int(value as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
|
node: ast::LitKind::Int(
|
||||||
|
(value as u128).into(),
|
||||||
|
ast::LitIntType::Unsigned(ast::UintTy::Usize),
|
||||||
|
),
|
||||||
});
|
});
|
||||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||||
}
|
}
|
||||||
@ -1968,7 +1909,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
|
pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
|
||||||
let lit = self.arena.alloc(hir::Lit {
|
let lit = self.arena.alloc(hir::Lit {
|
||||||
span: sp,
|
span: sp,
|
||||||
node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)),
|
node: ast::LitKind::Int(
|
||||||
|
u128::from(value).into(),
|
||||||
|
ast::LitIntType::Unsigned(ast::UintTy::U32),
|
||||||
|
),
|
||||||
});
|
});
|
||||||
self.expr(sp, hir::ExprKind::Lit(lit))
|
self.expr(sp, hir::ExprKind::Lit(lit))
|
||||||
}
|
}
|
||||||
@ -2033,11 +1977,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
) -> hir::Expr<'hir> {
|
) -> hir::Expr<'hir> {
|
||||||
|
let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span));
|
||||||
let path = hir::ExprKind::Path(hir::QPath::TypeRelative(
|
let path = hir::ExprKind::Path(hir::QPath::TypeRelative(
|
||||||
self.arena.alloc(self.ty(
|
self.arena.alloc(self.ty(span, hir::TyKind::Path(qpath))),
|
||||||
span,
|
|
||||||
hir::TyKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))),
|
|
||||||
)),
|
|
||||||
self.arena.alloc(hir::PathSegment::new(
|
self.arena.alloc(hir::PathSegment::new(
|
||||||
Ident::new(name, span),
|
Ident::new(name, span),
|
||||||
self.next_id(),
|
self.next_id(),
|
||||||
@ -2152,3 +2094,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used by [`LoweringContext::make_lowered_await`] to customize the desugaring based on what kind
|
||||||
|
/// of future we are awaiting.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
enum FutureKind {
|
||||||
|
/// We are awaiting a normal future
|
||||||
|
Future,
|
||||||
|
/// We are awaiting something that's known to be an AsyncIterator (i.e. we are in the header of
|
||||||
|
/// a `for await` loop)
|
||||||
|
AsyncIterator,
|
||||||
|
}
|
||||||
|
|||||||
@ -267,7 +267,7 @@ fn make_count<'hir>(
|
|||||||
ctx.expr(
|
ctx.expr(
|
||||||
sp,
|
sp,
|
||||||
hir::ExprKind::Err(
|
hir::ExprKind::Err(
|
||||||
ctx.tcx.sess.span_delayed_bug(sp, "lowered bad format_args count"),
|
ctx.dcx().span_delayed_bug(sp, "lowered bad format_args count"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ fn make_format_spec<'hir>(
|
|||||||
}
|
}
|
||||||
Err(_) => ctx.expr(
|
Err(_) => ctx.expr(
|
||||||
sp,
|
sp,
|
||||||
hir::ExprKind::Err(ctx.tcx.sess.span_delayed_bug(sp, "lowered bad format_args count")),
|
hir::ExprKind::Err(ctx.dcx().span_delayed_bug(sp, "lowered bad format_args count")),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let &FormatOptions {
|
let &FormatOptions {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use rustc_hir::def::{DefKind, Res};
|
|||||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
|
||||||
use rustc_hir::PredicateOrigin;
|
use rustc_hir::PredicateOrigin;
|
||||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||||
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
||||||
use rustc_span::edit_distance::find_best_match_for_name;
|
use rustc_span::edit_distance::find_best_match_for_name;
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
@ -182,7 +183,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
|
self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
|
||||||
}
|
}
|
||||||
ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => {
|
ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => {
|
||||||
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
|
let (ty, body_id) =
|
||||||
|
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
|
||||||
hir::ItemKind::Static(ty, *m, body_id)
|
hir::ItemKind::Static(ty, *m, body_id)
|
||||||
}
|
}
|
||||||
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
||||||
@ -191,7 +193,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
Const::No,
|
Const::No,
|
||||||
id,
|
id,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| this.lower_const_item(ty, span, expr.as_deref()),
|
|this| {
|
||||||
|
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
|
||||||
|
},
|
||||||
);
|
);
|
||||||
hir::ItemKind::Const(ty, generics, body_id)
|
hir::ItemKind::Const(ty, generics, body_id)
|
||||||
}
|
}
|
||||||
@ -265,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| match ty {
|
|this| match ty {
|
||||||
None => {
|
None => {
|
||||||
let guar = this.tcx.sess.span_delayed_bug(
|
let guar = this.dcx().span_delayed_bug(
|
||||||
span,
|
span,
|
||||||
"expected to lower type alias type, but it was missing",
|
"expected to lower type alias type, but it was missing",
|
||||||
);
|
);
|
||||||
@ -339,9 +343,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, (trait_ref, lowered_ty)) =
|
let (generics, (trait_ref, lowered_ty)) =
|
||||||
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
|
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
|
||||||
|
let constness = match *constness {
|
||||||
|
Const::Yes(span) => BoundConstness::Maybe(span),
|
||||||
|
Const::No => BoundConstness::Never,
|
||||||
|
};
|
||||||
|
|
||||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||||
this.lower_trait_ref(
|
this.lower_trait_ref(
|
||||||
*constness,
|
constness,
|
||||||
trait_ref,
|
trait_ref,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||||
)
|
)
|
||||||
@ -432,6 +441,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
|
let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
|
||||||
hir::ItemKind::Macro(macro_def, macro_kind)
|
hir::ItemKind::Macro(macro_def, macro_kind)
|
||||||
}
|
}
|
||||||
|
ItemKind::Delegation(box delegation) => {
|
||||||
|
let delegation_results = self.lower_delegation(delegation, id);
|
||||||
|
hir::ItemKind::Fn(
|
||||||
|
delegation_results.sig,
|
||||||
|
delegation_results.generics,
|
||||||
|
delegation_results.body_id,
|
||||||
|
)
|
||||||
|
}
|
||||||
ItemKind::MacCall(..) => {
|
ItemKind::MacCall(..) => {
|
||||||
panic!("`TyMac` should have been expanded by now")
|
panic!("`TyMac` should have been expanded by now")
|
||||||
}
|
}
|
||||||
@ -443,8 +460,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
ty: &Ty,
|
ty: &Ty,
|
||||||
span: Span,
|
span: Span,
|
||||||
body: Option<&Expr>,
|
body: Option<&Expr>,
|
||||||
|
impl_trait_position: ImplTraitPosition,
|
||||||
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
|
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
|
||||||
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(impl_trait_position));
|
||||||
(ty, self.lower_const_body(span, body))
|
(ty, self.lower_const_body(span, body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,23 +585,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// This is used to track which lifetimes have already been defined,
|
// This is used to track which lifetimes have already been defined,
|
||||||
// and which need to be replicated when lowering an async fn.
|
// and which need to be replicated when lowering an async fn.
|
||||||
|
|
||||||
match parent_hir.node().expect_item().kind {
|
let generics = match parent_hir.node().expect_item().kind {
|
||||||
hir::ItemKind::Impl(impl_) => {
|
hir::ItemKind::Impl(impl_) => {
|
||||||
self.is_in_trait_impl = impl_.of_trait.is_some();
|
self.is_in_trait_impl = impl_.of_trait.is_some();
|
||||||
|
&impl_.generics
|
||||||
}
|
}
|
||||||
hir::ItemKind::Trait(_, _, generics, _, _) if self.tcx.features().effects => {
|
hir::ItemKind::Trait(_, _, generics, _, _) => generics,
|
||||||
self.host_param_id = generics
|
kind => {
|
||||||
.params
|
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
|
||||||
.iter()
|
|
||||||
.find(|param| {
|
|
||||||
matches!(
|
|
||||||
param.kind,
|
|
||||||
hir::GenericParamKind::Const { is_host_effect: true, .. }
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.map(|param| param.def_id);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
};
|
||||||
|
|
||||||
|
if self.tcx.features().effects {
|
||||||
|
self.host_param_id = generics
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.find(|param| {
|
||||||
|
matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })
|
||||||
|
})
|
||||||
|
.map(|param| param.def_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
match ctxt {
|
match ctxt {
|
||||||
@ -793,6 +813,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
);
|
);
|
||||||
(generics, kind, ty.is_some())
|
(generics, kind, ty.is_some())
|
||||||
}
|
}
|
||||||
|
AssocItemKind::Delegation(box delegation) => {
|
||||||
|
let delegation_results = self.lower_delegation(delegation, i.id);
|
||||||
|
let item_kind = hir::TraitItemKind::Fn(
|
||||||
|
delegation_results.sig,
|
||||||
|
hir::TraitFn::Provided(delegation_results.body_id),
|
||||||
|
);
|
||||||
|
(delegation_results.generics, item_kind, true)
|
||||||
|
}
|
||||||
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
|
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -814,6 +842,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
||||||
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
||||||
}
|
}
|
||||||
|
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
||||||
|
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
|
||||||
|
},
|
||||||
AssocItemKind::MacCall(..) => unimplemented!(),
|
AssocItemKind::MacCall(..) => unimplemented!(),
|
||||||
};
|
};
|
||||||
let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
|
let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
|
||||||
@ -879,7 +910,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| match ty {
|
|this| match ty {
|
||||||
None => {
|
None => {
|
||||||
let guar = this.tcx.sess.span_delayed_bug(
|
let guar = this.dcx().span_delayed_bug(
|
||||||
i.span,
|
i.span,
|
||||||
"expected to lower associated type, but it was missing",
|
"expected to lower associated type, but it was missing",
|
||||||
);
|
);
|
||||||
@ -896,6 +927,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
AssocItemKind::Delegation(box delegation) => {
|
||||||
|
let delegation_results = self.lower_delegation(delegation, i.id);
|
||||||
|
(
|
||||||
|
delegation_results.generics,
|
||||||
|
hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
|
||||||
|
)
|
||||||
|
}
|
||||||
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
|
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -912,6 +950,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
|
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
|
||||||
|
let trait_item_def_id = self
|
||||||
|
.resolver
|
||||||
|
.get_partial_res(i.id)
|
||||||
|
.map(|r| r.expect_full_res().opt_def_id())
|
||||||
|
.unwrap_or(None);
|
||||||
|
self.is_in_trait_impl = trait_item_def_id.is_some();
|
||||||
|
|
||||||
hir::ImplItemRef {
|
hir::ImplItemRef {
|
||||||
id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
|
id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
|
||||||
ident: self.lower_ident(i.ident),
|
ident: self.lower_ident(i.ident),
|
||||||
@ -922,12 +967,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
||||||
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
||||||
}
|
}
|
||||||
|
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
||||||
|
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
|
||||||
|
},
|
||||||
AssocItemKind::MacCall(..) => unimplemented!(),
|
AssocItemKind::MacCall(..) => unimplemented!(),
|
||||||
},
|
},
|
||||||
trait_item_def_id: self
|
trait_item_def_id,
|
||||||
.resolver
|
|
||||||
.get_partial_res(i.id)
|
|
||||||
.map(|r| r.expect_full_res().def_id()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,11 +997,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
params: &'hir [hir::Param<'hir>],
|
params: &'hir [hir::Param<'hir>],
|
||||||
value: hir::Expr<'hir>,
|
value: hir::Expr<'hir>,
|
||||||
) -> hir::BodyId {
|
) -> hir::BodyId {
|
||||||
let body = hir::Body {
|
let body = hir::Body { params, value: self.arena.alloc(value) };
|
||||||
coroutine_kind: self.coroutine_kind,
|
|
||||||
params,
|
|
||||||
value: self.arena.alloc(value),
|
|
||||||
};
|
|
||||||
let id = body.id();
|
let id = body.id();
|
||||||
debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
|
debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
|
||||||
self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
|
self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
|
||||||
@ -1012,7 +1053,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
|
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
|
||||||
match block {
|
match block {
|
||||||
Some(block) => self.lower_block_expr(block),
|
Some(block) => self.lower_block_expr(block),
|
||||||
None => self.expr_err(span, self.tcx.sess.span_delayed_bug(span, "no block")),
|
None => self.expr_err(span, self.dcx().span_delayed_bug(span, "no block")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1022,7 +1063,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
&[],
|
&[],
|
||||||
match expr {
|
match expr {
|
||||||
Some(expr) => this.lower_expr_mut(expr),
|
Some(expr) => this.lower_expr_mut(expr),
|
||||||
None => this.expr_err(span, this.tcx.sess.span_delayed_bug(span, "no block")),
|
None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -1041,207 +1082,224 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else {
|
let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else {
|
||||||
return self.lower_fn_body_block(span, decl, body);
|
return self.lower_fn_body_block(span, decl, body);
|
||||||
};
|
};
|
||||||
let closure_id = coroutine_kind.closure_id();
|
|
||||||
|
|
||||||
self.lower_body(|this| {
|
self.lower_body(|this| {
|
||||||
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
|
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||||
let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
|
decl,
|
||||||
|
|this| this.lower_block_expr(body),
|
||||||
|
body.span,
|
||||||
|
coroutine_kind,
|
||||||
|
hir::CoroutineSource::Fn,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
// Async function parameters are lowered into the closure body so that they are
|
// FIXME(async_fn_track_caller): Can this be moved above?
|
||||||
// captured and so that the drop order matches the equivalent non-async functions.
|
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
|
||||||
|
this.maybe_forward_track_caller(body.span, fn_id, hir_id);
|
||||||
|
|
||||||
|
(parameters, expr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lowers a desugared coroutine body after moving all of the arguments
|
||||||
|
/// into the body. This is to make sure that the future actually owns the
|
||||||
|
/// arguments that are passed to the function, and to ensure things like
|
||||||
|
/// drop order are stable.
|
||||||
|
pub fn lower_coroutine_body_with_moved_arguments(
|
||||||
|
&mut self,
|
||||||
|
decl: &FnDecl,
|
||||||
|
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
|
||||||
|
body_span: Span,
|
||||||
|
coroutine_kind: CoroutineKind,
|
||||||
|
coroutine_source: hir::CoroutineSource,
|
||||||
|
return_type_hint: Option<hir::FnRetTy<'hir>>,
|
||||||
|
) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
|
||||||
|
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
|
||||||
|
let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
|
||||||
|
|
||||||
|
// Async function parameters are lowered into the closure body so that they are
|
||||||
|
// captured and so that the drop order matches the equivalent non-async functions.
|
||||||
|
//
|
||||||
|
// from:
|
||||||
|
//
|
||||||
|
// async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
|
||||||
|
// <body>
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// into:
|
||||||
|
//
|
||||||
|
// fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
|
||||||
|
// async move {
|
||||||
|
// let __arg2 = __arg2;
|
||||||
|
// let <pattern> = __arg2;
|
||||||
|
// let __arg1 = __arg1;
|
||||||
|
// let <pattern> = __arg1;
|
||||||
|
// let __arg0 = __arg0;
|
||||||
|
// let <pattern> = __arg0;
|
||||||
|
// drop-temps { <body> } // see comments later in fn for details
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// If `<pattern>` is a simple ident, then it is lowered to a single
|
||||||
|
// `let <pattern> = <pattern>;` statement as an optimization.
|
||||||
|
//
|
||||||
|
// Note that the body is embedded in `drop-temps`; an
|
||||||
|
// equivalent desugaring would be `return { <body>
|
||||||
|
// };`. The key point is that we wish to drop all the
|
||||||
|
// let-bound variables and temporaries created in the body
|
||||||
|
// (and its tail expression!) before we drop the
|
||||||
|
// parameters (c.f. rust-lang/rust#64512).
|
||||||
|
for (index, parameter) in decl.inputs.iter().enumerate() {
|
||||||
|
let parameter = self.lower_param(parameter);
|
||||||
|
let span = parameter.pat.span;
|
||||||
|
|
||||||
|
// Check if this is a binding pattern, if so, we can optimize and avoid adding a
|
||||||
|
// `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
|
||||||
|
let (ident, is_simple_parameter) = match parameter.pat.kind {
|
||||||
|
hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
|
||||||
|
(ident, true)
|
||||||
|
}
|
||||||
|
// For `ref mut` or wildcard arguments, we can't reuse the binding, but
|
||||||
|
// we can keep the same name for the parameter.
|
||||||
|
// This lets rustdoc render it correctly in documentation.
|
||||||
|
hir::PatKind::Binding(_, _, ident, _) => (ident, false),
|
||||||
|
hir::PatKind::Wild => {
|
||||||
|
(Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Replace the ident for bindings that aren't simple.
|
||||||
|
let name = format!("__arg{index}");
|
||||||
|
let ident = Ident::from_str(&name);
|
||||||
|
|
||||||
|
(ident, false)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
|
||||||
|
|
||||||
|
// Construct a parameter representing `__argN: <ty>` to replace the parameter of the
|
||||||
|
// async function.
|
||||||
//
|
//
|
||||||
// from:
|
// If this is the simple case, this parameter will end up being the same as the
|
||||||
//
|
// original parameter, but with a different pattern id.
|
||||||
// async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
|
let stmt_attrs = self.attrs.get(¶meter.hir_id.local_id).copied();
|
||||||
// <body>
|
let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident);
|
||||||
// }
|
let new_parameter = hir::Param {
|
||||||
//
|
hir_id: parameter.hir_id,
|
||||||
// into:
|
pat: new_parameter_pat,
|
||||||
//
|
ty_span: self.lower_span(parameter.ty_span),
|
||||||
// fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
|
span: self.lower_span(parameter.span),
|
||||||
// async move {
|
};
|
||||||
// let __arg2 = __arg2;
|
|
||||||
// let <pattern> = __arg2;
|
|
||||||
// let __arg1 = __arg1;
|
|
||||||
// let <pattern> = __arg1;
|
|
||||||
// let __arg0 = __arg0;
|
|
||||||
// let <pattern> = __arg0;
|
|
||||||
// drop-temps { <body> } // see comments later in fn for details
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// If `<pattern>` is a simple ident, then it is lowered to a single
|
|
||||||
// `let <pattern> = <pattern>;` statement as an optimization.
|
|
||||||
//
|
|
||||||
// Note that the body is embedded in `drop-temps`; an
|
|
||||||
// equivalent desugaring would be `return { <body>
|
|
||||||
// };`. The key point is that we wish to drop all the
|
|
||||||
// let-bound variables and temporaries created in the body
|
|
||||||
// (and its tail expression!) before we drop the
|
|
||||||
// parameters (c.f. rust-lang/rust#64512).
|
|
||||||
for (index, parameter) in decl.inputs.iter().enumerate() {
|
|
||||||
let parameter = this.lower_param(parameter);
|
|
||||||
let span = parameter.pat.span;
|
|
||||||
|
|
||||||
// Check if this is a binding pattern, if so, we can optimize and avoid adding a
|
if is_simple_parameter {
|
||||||
// `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
|
// If this is the simple case, then we only insert one statement that is
|
||||||
let (ident, is_simple_parameter) = match parameter.pat.kind {
|
// `let <pat> = <pat>;`. We re-use the original argument's pattern so that
|
||||||
hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
|
// `HirId`s are densely assigned.
|
||||||
(ident, true)
|
let expr = self.expr_ident(desugared_span, ident, new_parameter_id);
|
||||||
}
|
let stmt = self.stmt_let_pat(
|
||||||
// For `ref mut` or wildcard arguments, we can't reuse the binding, but
|
stmt_attrs,
|
||||||
// we can keep the same name for the parameter.
|
|
||||||
// This lets rustdoc render it correctly in documentation.
|
|
||||||
hir::PatKind::Binding(_, _, ident, _) => (ident, false),
|
|
||||||
hir::PatKind::Wild => {
|
|
||||||
(Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Replace the ident for bindings that aren't simple.
|
|
||||||
let name = format!("__arg{index}");
|
|
||||||
let ident = Ident::from_str(&name);
|
|
||||||
|
|
||||||
(ident, false)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let desugared_span = this.mark_span_with_reason(DesugaringKind::Async, span, None);
|
|
||||||
|
|
||||||
// Construct a parameter representing `__argN: <ty>` to replace the parameter of the
|
|
||||||
// async function.
|
|
||||||
//
|
|
||||||
// If this is the simple case, this parameter will end up being the same as the
|
|
||||||
// original parameter, but with a different pattern id.
|
|
||||||
let stmt_attrs = this.attrs.get(¶meter.hir_id.local_id).copied();
|
|
||||||
let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident);
|
|
||||||
let new_parameter = hir::Param {
|
|
||||||
hir_id: parameter.hir_id,
|
|
||||||
pat: new_parameter_pat,
|
|
||||||
ty_span: this.lower_span(parameter.ty_span),
|
|
||||||
span: this.lower_span(parameter.span),
|
|
||||||
};
|
|
||||||
|
|
||||||
if is_simple_parameter {
|
|
||||||
// If this is the simple case, then we only insert one statement that is
|
|
||||||
// `let <pat> = <pat>;`. We re-use the original argument's pattern so that
|
|
||||||
// `HirId`s are densely assigned.
|
|
||||||
let expr = this.expr_ident(desugared_span, ident, new_parameter_id);
|
|
||||||
let stmt = this.stmt_let_pat(
|
|
||||||
stmt_attrs,
|
|
||||||
desugared_span,
|
|
||||||
Some(expr),
|
|
||||||
parameter.pat,
|
|
||||||
hir::LocalSource::AsyncFn,
|
|
||||||
);
|
|
||||||
statements.push(stmt);
|
|
||||||
} else {
|
|
||||||
// If this is not the simple case, then we construct two statements:
|
|
||||||
//
|
|
||||||
// ```
|
|
||||||
// let __argN = __argN;
|
|
||||||
// let <pat> = __argN;
|
|
||||||
// ```
|
|
||||||
//
|
|
||||||
// The first statement moves the parameter into the closure and thus ensures
|
|
||||||
// that the drop order is correct.
|
|
||||||
//
|
|
||||||
// The second statement creates the bindings that the user wrote.
|
|
||||||
|
|
||||||
// Construct the `let mut __argN = __argN;` statement. It must be a mut binding
|
|
||||||
// because the user may have specified a `ref mut` binding in the next
|
|
||||||
// statement.
|
|
||||||
let (move_pat, move_id) = this.pat_ident_binding_mode(
|
|
||||||
desugared_span,
|
|
||||||
ident,
|
|
||||||
hir::BindingAnnotation::MUT,
|
|
||||||
);
|
|
||||||
let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id);
|
|
||||||
let move_stmt = this.stmt_let_pat(
|
|
||||||
None,
|
|
||||||
desugared_span,
|
|
||||||
Some(move_expr),
|
|
||||||
move_pat,
|
|
||||||
hir::LocalSource::AsyncFn,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Construct the `let <pat> = __argN;` statement. We re-use the original
|
|
||||||
// parameter's pattern so that `HirId`s are densely assigned.
|
|
||||||
let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
|
|
||||||
let pattern_stmt = this.stmt_let_pat(
|
|
||||||
stmt_attrs,
|
|
||||||
desugared_span,
|
|
||||||
Some(pattern_expr),
|
|
||||||
parameter.pat,
|
|
||||||
hir::LocalSource::AsyncFn,
|
|
||||||
);
|
|
||||||
|
|
||||||
statements.push(move_stmt);
|
|
||||||
statements.push(pattern_stmt);
|
|
||||||
};
|
|
||||||
|
|
||||||
parameters.push(new_parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
|
|
||||||
// Create a block from the user's function body:
|
|
||||||
let user_body = this.lower_block_expr(body);
|
|
||||||
|
|
||||||
// Transform into `drop-temps { <user-body> }`, an expression:
|
|
||||||
let desugared_span =
|
|
||||||
this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
|
|
||||||
let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
|
|
||||||
|
|
||||||
// As noted above, create the final block like
|
|
||||||
//
|
|
||||||
// ```
|
|
||||||
// {
|
|
||||||
// let $param_pattern = $raw_param;
|
|
||||||
// ...
|
|
||||||
// drop-temps { <user-body> }
|
|
||||||
// }
|
|
||||||
// ```
|
|
||||||
let body = this.block_all(
|
|
||||||
desugared_span,
|
desugared_span,
|
||||||
this.arena.alloc_from_iter(statements),
|
Some(expr),
|
||||||
Some(user_body),
|
parameter.pat,
|
||||||
|
hir::LocalSource::AsyncFn,
|
||||||
|
);
|
||||||
|
statements.push(stmt);
|
||||||
|
} else {
|
||||||
|
// If this is not the simple case, then we construct two statements:
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// let __argN = __argN;
|
||||||
|
// let <pat> = __argN;
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// The first statement moves the parameter into the closure and thus ensures
|
||||||
|
// that the drop order is correct.
|
||||||
|
//
|
||||||
|
// The second statement creates the bindings that the user wrote.
|
||||||
|
|
||||||
|
// Construct the `let mut __argN = __argN;` statement. It must be a mut binding
|
||||||
|
// because the user may have specified a `ref mut` binding in the next
|
||||||
|
// statement.
|
||||||
|
let (move_pat, move_id) =
|
||||||
|
self.pat_ident_binding_mode(desugared_span, ident, hir::BindingAnnotation::MUT);
|
||||||
|
let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id);
|
||||||
|
let move_stmt = self.stmt_let_pat(
|
||||||
|
None,
|
||||||
|
desugared_span,
|
||||||
|
Some(move_expr),
|
||||||
|
move_pat,
|
||||||
|
hir::LocalSource::AsyncFn,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.expr_block(body)
|
// Construct the `let <pat> = __argN;` statement. We re-use the original
|
||||||
};
|
// parameter's pattern so that `HirId`s are densely assigned.
|
||||||
// FIXME(gen_blocks): Consider unifying the `make_*_expr` functions.
|
let pattern_expr = self.expr_ident(desugared_span, ident, move_id);
|
||||||
let coroutine_expr = match coroutine_kind {
|
let pattern_stmt = self.stmt_let_pat(
|
||||||
CoroutineKind::Async { .. } => this.make_async_expr(
|
stmt_attrs,
|
||||||
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
|
desugared_span,
|
||||||
closure_id,
|
Some(pattern_expr),
|
||||||
None,
|
parameter.pat,
|
||||||
body.span,
|
hir::LocalSource::AsyncFn,
|
||||||
hir::CoroutineSource::Fn,
|
);
|
||||||
mkbody,
|
|
||||||
),
|
statements.push(move_stmt);
|
||||||
CoroutineKind::Gen { .. } => this.make_gen_expr(
|
statements.push(pattern_stmt);
|
||||||
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
|
|
||||||
closure_id,
|
|
||||||
None,
|
|
||||||
body.span,
|
|
||||||
hir::CoroutineSource::Fn,
|
|
||||||
mkbody,
|
|
||||||
),
|
|
||||||
CoroutineKind::AsyncGen { .. } => this.make_async_gen_expr(
|
|
||||||
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
|
|
||||||
closure_id,
|
|
||||||
None,
|
|
||||||
body.span,
|
|
||||||
hir::CoroutineSource::Fn,
|
|
||||||
mkbody,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let hir_id = this.lower_node_id(closure_id);
|
parameters.push(new_parameter);
|
||||||
this.maybe_forward_track_caller(body.span, fn_id, hir_id);
|
}
|
||||||
let expr = hir::Expr { hir_id, kind: coroutine_expr, span: this.lower_span(body.span) };
|
|
||||||
|
|
||||||
(this.arena.alloc_from_iter(parameters), expr)
|
let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
|
||||||
})
|
// Create a block from the user's function body:
|
||||||
|
let user_body = lower_body(this);
|
||||||
|
|
||||||
|
// Transform into `drop-temps { <user-body> }`, an expression:
|
||||||
|
let desugared_span =
|
||||||
|
this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
|
||||||
|
let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
|
||||||
|
|
||||||
|
// As noted above, create the final block like
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// {
|
||||||
|
// let $param_pattern = $raw_param;
|
||||||
|
// ...
|
||||||
|
// drop-temps { <user-body> }
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
let body = this.block_all(
|
||||||
|
desugared_span,
|
||||||
|
this.arena.alloc_from_iter(statements),
|
||||||
|
Some(user_body),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.expr_block(body)
|
||||||
|
};
|
||||||
|
let desugaring_kind = match coroutine_kind {
|
||||||
|
CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
|
||||||
|
CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
|
||||||
|
CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen,
|
||||||
|
};
|
||||||
|
let closure_id = coroutine_kind.closure_id();
|
||||||
|
let coroutine_expr = self.make_desugared_coroutine_expr(
|
||||||
|
// FIXME(async_closures): This should only move locals,
|
||||||
|
// and not upvars. Capturing closure upvars by ref doesn't
|
||||||
|
// work right now anyways, so whatever.
|
||||||
|
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
|
||||||
|
closure_id,
|
||||||
|
return_type_hint,
|
||||||
|
body_span,
|
||||||
|
desugaring_kind,
|
||||||
|
coroutine_source,
|
||||||
|
mkbody,
|
||||||
|
);
|
||||||
|
|
||||||
|
let expr = hir::Expr {
|
||||||
|
hir_id: self.lower_node_id(closure_id),
|
||||||
|
kind: coroutine_expr,
|
||||||
|
span: self.lower_span(body_span),
|
||||||
|
};
|
||||||
|
|
||||||
|
(self.arena.alloc_from_iter(parameters), expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_method_sig(
|
fn lower_method_sig(
|
||||||
@ -1253,11 +1311,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
coroutine_kind: Option<CoroutineKind>,
|
coroutine_kind: Option<CoroutineKind>,
|
||||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||||
let header = self.lower_fn_header(sig.header);
|
let header = self.lower_fn_header(sig.header);
|
||||||
|
// Don't pass along the user-provided constness of trait associated functions; we don't want to
|
||||||
|
// synthesize a host effect param for them. We reject `const` on them during AST validation.
|
||||||
|
let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No };
|
||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, decl) =
|
let (generics, decl) = self.lower_generics(generics, constness, id, &itctx, |this| {
|
||||||
self.lower_generics(generics, sig.header.constness, id, &itctx, |this| {
|
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
||||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
});
|
||||||
});
|
|
||||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1296,7 +1356,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
.map(|s| Symbol::intern(s))
|
.map(|s| Symbol::intern(s))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
|
let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
|
||||||
self.tcx.sess.emit_err(InvalidAbi {
|
self.dcx().emit_err(InvalidAbi {
|
||||||
abi: abi.symbol_unescaped,
|
abi: abi.symbol_unescaped,
|
||||||
span: abi.span,
|
span: abi.span,
|
||||||
explain: match err {
|
explain: match err {
|
||||||
@ -1372,12 +1432,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// need to compute this at all unless there is a Maybe bound.
|
// need to compute this at all unless there is a Maybe bound.
|
||||||
let mut is_param: Option<bool> = None;
|
let mut is_param: Option<bool> = None;
|
||||||
for bound in &bound_pred.bounds {
|
for bound in &bound_pred.bounds {
|
||||||
if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) {
|
if !matches!(
|
||||||
|
*bound,
|
||||||
|
GenericBound::Trait(
|
||||||
|
_,
|
||||||
|
TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }
|
||||||
|
)
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
||||||
if !is_param {
|
if !is_param {
|
||||||
self.tcx.sess.emit_err(MisplacedRelaxTraitBound { span: bound.span() });
|
self.dcx().emit_err(MisplacedRelaxTraitBound { span: bound.span() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,6 @@
|
|||||||
#![doc(rust_logo)]
|
#![doc(rust_logo)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![recursion_limit = "256"]
|
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
|||||||
use rustc_data_structures::sorted_map::SortedMap;
|
use rustc_data_structures::sorted_map::SortedMap;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::{DiagnosticArgFromDisplay, StashKey};
|
use rustc_errors::{DiagCtxt, DiagnosticArgFromDisplay, StashKey};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||||
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
|
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
|
||||||
@ -76,6 +75,7 @@ macro_rules! arena_vec {
|
|||||||
|
|
||||||
mod asm;
|
mod asm;
|
||||||
mod block;
|
mod block;
|
||||||
|
mod delegation;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod expr;
|
mod expr;
|
||||||
mod format;
|
mod format;
|
||||||
@ -130,6 +130,7 @@ struct LoweringContext<'a, 'hir> {
|
|||||||
allow_try_trait: Lrc<[Symbol]>,
|
allow_try_trait: Lrc<[Symbol]>,
|
||||||
allow_gen_future: Lrc<[Symbol]>,
|
allow_gen_future: Lrc<[Symbol]>,
|
||||||
allow_async_iterator: Lrc<[Symbol]>,
|
allow_async_iterator: Lrc<[Symbol]>,
|
||||||
|
allow_for_await: Lrc<[Symbol]>,
|
||||||
|
|
||||||
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
|
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
|
||||||
/// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
|
/// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
|
||||||
@ -174,6 +175,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
} else {
|
} else {
|
||||||
[sym::gen_future].into()
|
[sym::gen_future].into()
|
||||||
},
|
},
|
||||||
|
allow_for_await: [sym::async_iterator].into(),
|
||||||
// FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`
|
// FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`
|
||||||
// interact with `gen`/`async gen` blocks
|
// interact with `gen`/`async gen` blocks
|
||||||
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
||||||
@ -181,6 +183,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
host_param_id: None,
|
host_param_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn dcx(&self) -> &'hir DiagCtxt {
|
||||||
|
self.tcx.dcx()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ResolverAstLoweringExt {
|
trait ResolverAstLoweringExt {
|
||||||
@ -297,8 +303,6 @@ enum ImplTraitPosition {
|
|||||||
ClosureParam,
|
ClosureParam,
|
||||||
PointerParam,
|
PointerParam,
|
||||||
FnTraitParam,
|
FnTraitParam,
|
||||||
TraitParam,
|
|
||||||
ImplParam,
|
|
||||||
ExternFnReturn,
|
ExternFnReturn,
|
||||||
ClosureReturn,
|
ClosureReturn,
|
||||||
PointerReturn,
|
PointerReturn,
|
||||||
@ -317,29 +321,27 @@ impl std::fmt::Display for ImplTraitPosition {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let name = match self {
|
let name = match self {
|
||||||
ImplTraitPosition::Path => "paths",
|
ImplTraitPosition::Path => "paths",
|
||||||
ImplTraitPosition::Variable => "variable bindings",
|
ImplTraitPosition::Variable => "the type of variable bindings",
|
||||||
ImplTraitPosition::Trait => "traits",
|
ImplTraitPosition::Trait => "traits",
|
||||||
ImplTraitPosition::AsyncBlock => "async blocks",
|
ImplTraitPosition::AsyncBlock => "async blocks",
|
||||||
ImplTraitPosition::Bound => "bounds",
|
ImplTraitPosition::Bound => "bounds",
|
||||||
ImplTraitPosition::Generic => "generics",
|
ImplTraitPosition::Generic => "generics",
|
||||||
ImplTraitPosition::ExternFnParam => "`extern fn` params",
|
ImplTraitPosition::ExternFnParam => "`extern fn` parameters",
|
||||||
ImplTraitPosition::ClosureParam => "closure params",
|
ImplTraitPosition::ClosureParam => "closure parameters",
|
||||||
ImplTraitPosition::PointerParam => "`fn` pointer params",
|
ImplTraitPosition::PointerParam => "`fn` pointer parameters",
|
||||||
ImplTraitPosition::FnTraitParam => "`Fn` trait params",
|
ImplTraitPosition::FnTraitParam => "the parameters of `Fn` trait bounds",
|
||||||
ImplTraitPosition::TraitParam => "trait method params",
|
|
||||||
ImplTraitPosition::ImplParam => "`impl` method params",
|
|
||||||
ImplTraitPosition::ExternFnReturn => "`extern fn` return types",
|
ImplTraitPosition::ExternFnReturn => "`extern fn` return types",
|
||||||
ImplTraitPosition::ClosureReturn => "closure return types",
|
ImplTraitPosition::ClosureReturn => "closure return types",
|
||||||
ImplTraitPosition::PointerReturn => "`fn` pointer return types",
|
ImplTraitPosition::PointerReturn => "`fn` pointer return types",
|
||||||
ImplTraitPosition::FnTraitReturn => "`Fn` trait return types",
|
ImplTraitPosition::FnTraitReturn => "the return type of `Fn` trait bounds",
|
||||||
ImplTraitPosition::GenericDefault => "generic parameter defaults",
|
ImplTraitPosition::GenericDefault => "generic parameter defaults",
|
||||||
ImplTraitPosition::ConstTy => "const types",
|
ImplTraitPosition::ConstTy => "const types",
|
||||||
ImplTraitPosition::StaticTy => "static types",
|
ImplTraitPosition::StaticTy => "static types",
|
||||||
ImplTraitPosition::AssocTy => "associated types",
|
ImplTraitPosition::AssocTy => "associated types",
|
||||||
ImplTraitPosition::FieldTy => "field types",
|
ImplTraitPosition::FieldTy => "field types",
|
||||||
ImplTraitPosition::Cast => "cast types",
|
ImplTraitPosition::Cast => "cast expression types",
|
||||||
ImplTraitPosition::ImplSelf => "impl headers",
|
ImplTraitPosition::ImplSelf => "impl headers",
|
||||||
ImplTraitPosition::OffsetOf => "`offset_of!` params",
|
ImplTraitPosition::OffsetOf => "`offset_of!` parameters",
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{name}")
|
write!(f, "{name}")
|
||||||
@ -357,19 +359,6 @@ enum FnDeclKind {
|
|||||||
Impl,
|
Impl,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnDeclKind {
|
|
||||||
fn param_impl_trait_allowed(&self) -> bool {
|
|
||||||
matches!(self, FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn return_impl_trait_allowed(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum AstOwner<'a> {
|
enum AstOwner<'a> {
|
||||||
NonOwner,
|
NonOwner,
|
||||||
@ -671,9 +660,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() {
|
let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() {
|
||||||
self.tcx.with_stable_hashing_context(|mut hcx| {
|
self.tcx.with_stable_hashing_context(|mut hcx| {
|
||||||
let mut stable_hasher = StableHasher::new();
|
let mut stable_hasher = StableHasher::new();
|
||||||
hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| {
|
node.hash_stable(&mut hcx, &mut stable_hasher);
|
||||||
node.hash_stable(hcx, &mut stable_hasher)
|
// Bodies are stored out of line, so we need to pull them explicitly in the hash.
|
||||||
});
|
bodies.hash_stable(&mut hcx, &mut stable_hasher);
|
||||||
let h1 = stable_hasher.finish();
|
let h1 = stable_hasher.finish();
|
||||||
|
|
||||||
let mut stable_hasher = StableHasher::new();
|
let mut stable_hasher = StableHasher::new();
|
||||||
@ -764,6 +753,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
self.resolver.get_import_res(id).present_items()
|
self.resolver.get_import_res(id).present_items()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_lang_item_qpath(&mut self, lang_item: hir::LangItem, span: Span) -> hir::QPath<'hir> {
|
||||||
|
hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, None))
|
||||||
|
}
|
||||||
|
|
||||||
fn make_lang_item_path(
|
fn make_lang_item_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
@ -781,7 +774,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
res,
|
res,
|
||||||
args,
|
args,
|
||||||
infer_args: false,
|
infer_args: args.is_none(),
|
||||||
}]),
|
}]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1033,11 +1026,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
&& first_char.is_ascii_lowercase()
|
&& first_char.is_ascii_lowercase()
|
||||||
{
|
{
|
||||||
let mut err = if !data.inputs.is_empty() {
|
let mut err = if !data.inputs.is_empty() {
|
||||||
self.tcx.sess.create_err(errors::BadReturnTypeNotation::Inputs {
|
self.dcx().create_err(errors::BadReturnTypeNotation::Inputs {
|
||||||
span: data.inputs_span,
|
span: data.inputs_span,
|
||||||
})
|
})
|
||||||
} else if let FnRetTy::Ty(ty) = &data.output {
|
} else if let FnRetTy::Ty(ty) = &data.output {
|
||||||
self.tcx.sess.create_err(errors::BadReturnTypeNotation::Output {
|
self.dcx().create_err(errors::BadReturnTypeNotation::Output {
|
||||||
span: data.inputs_span.shrink_to_hi().to(ty.span),
|
span: data.inputs_span.shrink_to_hi().to(ty.span),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -1048,7 +1041,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
{
|
{
|
||||||
add_feature_diagnostics(
|
add_feature_diagnostics(
|
||||||
&mut err,
|
&mut err,
|
||||||
&self.tcx.sess.parse_sess,
|
&self.tcx.sess,
|
||||||
sym::return_type_notation,
|
sym::return_type_notation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1161,7 +1154,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
hir::TypeBindingKind::Constraint { bounds }
|
hir::TypeBindingKind::Constraint { bounds }
|
||||||
}
|
}
|
||||||
DesugarKind::Error(position) => {
|
DesugarKind::Error(position) => {
|
||||||
let guar = self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding {
|
let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding {
|
||||||
span: constraint.span,
|
span: constraint.span,
|
||||||
position: DiagnosticArgFromDisplay(position),
|
position: DiagnosticArgFromDisplay(position),
|
||||||
});
|
});
|
||||||
@ -1203,7 +1196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi());
|
data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi());
|
||||||
AssocTyParenthesesSub::NotEmpty { open_param, close_param }
|
AssocTyParenthesesSub::NotEmpty { open_param, close_param }
|
||||||
};
|
};
|
||||||
self.tcx.sess.emit_err(AssocTyParentheses { span: data.span, sub });
|
self.dcx().emit_err(AssocTyParentheses { span: data.span, sub });
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
@ -1318,7 +1311,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
span: t.span,
|
span: t.span,
|
||||||
},
|
},
|
||||||
itctx,
|
itctx,
|
||||||
ast::Const::No,
|
ast::BoundConstness::Never,
|
||||||
);
|
);
|
||||||
let bounds = this.arena.alloc_from_iter([bound]);
|
let bounds = this.arena.alloc_from_iter([bound]);
|
||||||
let lifetime_bound = this.elided_dyn_bound(t.span);
|
let lifetime_bound = this.elided_dyn_bound(t.span);
|
||||||
@ -1345,20 +1338,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
let kind = match &t.kind {
|
let kind = match &t.kind {
|
||||||
TyKind::Infer => hir::TyKind::Infer,
|
TyKind::Infer => hir::TyKind::Infer,
|
||||||
TyKind::Err => {
|
TyKind::Err => {
|
||||||
hir::TyKind::Err(self.tcx.sess.span_delayed_bug(t.span, "TyKind::Err lowered"))
|
hir::TyKind::Err(self.dcx().span_delayed_bug(t.span, "TyKind::Err lowered"))
|
||||||
}
|
}
|
||||||
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
|
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||||
TyKind::AnonStruct(ref _fields) => hir::TyKind::Err(
|
TyKind::AnonStruct(ref _fields) => {
|
||||||
self.tcx.sess.span_err(t.span, "anonymous structs are unimplemented"),
|
hir::TyKind::Err(self.dcx().span_err(t.span, "anonymous structs are unimplemented"))
|
||||||
),
|
}
|
||||||
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
|
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||||
TyKind::AnonUnion(ref _fields) => hir::TyKind::Err(
|
TyKind::AnonUnion(ref _fields) => {
|
||||||
self.tcx.sess.span_err(t.span, "anonymous unions are unimplemented"),
|
hir::TyKind::Err(self.dcx().span_err(t.span, "anonymous unions are unimplemented"))
|
||||||
),
|
}
|
||||||
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
|
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
|
||||||
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
|
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
|
||||||
TyKind::Ref(region, mt) => {
|
TyKind::Ref(region, mt) => {
|
||||||
@ -1423,22 +1416,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
|
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
|
||||||
let bounds =
|
let bounds =
|
||||||
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
|
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
|
||||||
GenericBound::Trait(
|
// We can safely ignore constness here since AST validation
|
||||||
ty,
|
// takes care of rejecting invalid modifier combinations and
|
||||||
modifier @ (TraitBoundModifier::None
|
// const trait bounds in trait object types.
|
||||||
| TraitBoundModifier::MaybeConst(_)
|
GenericBound::Trait(ty, modifiers) => match modifiers.polarity {
|
||||||
| TraitBoundModifier::Negative),
|
BoundPolarity::Positive | BoundPolarity::Negative(_) => {
|
||||||
) => {
|
Some(this.lower_poly_trait_ref(
|
||||||
Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
|
ty,
|
||||||
}
|
itctx,
|
||||||
// `~const ?Bound` will cause an error during AST validation
|
// Still, don't pass along the constness here; we don't want to
|
||||||
// anyways, so treat it like `?Bound` as compilation proceeds.
|
// synthesize any host effect args, it'd only cause problems.
|
||||||
GenericBound::Trait(
|
ast::BoundConstness::Never,
|
||||||
_,
|
))
|
||||||
TraitBoundModifier::Maybe
|
}
|
||||||
| TraitBoundModifier::MaybeConstMaybe
|
BoundPolarity::Maybe(_) => None,
|
||||||
| TraitBoundModifier::MaybeConstNegative,
|
},
|
||||||
) => None,
|
|
||||||
GenericBound::Outlives(lifetime) => {
|
GenericBound::Outlives(lifetime) => {
|
||||||
if lifetime_bound.is_none() {
|
if lifetime_bound.is_none() {
|
||||||
lifetime_bound = Some(this.lower_lifetime(lifetime));
|
lifetime_bound = Some(this.lower_lifetime(lifetime));
|
||||||
@ -1519,7 +1511,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
hir::TyKind::Err(guar)
|
hir::TyKind::Err(guar)
|
||||||
}
|
}
|
||||||
ImplTraitContext::Disallowed(position) => {
|
ImplTraitContext::Disallowed(position) => {
|
||||||
let guar = self.tcx.sess.emit_err(MisplacedImplTrait {
|
let guar = self.dcx().emit_err(MisplacedImplTrait {
|
||||||
span: t.span,
|
span: t.span,
|
||||||
position: DiagnosticArgFromDisplay(position),
|
position: DiagnosticArgFromDisplay(position),
|
||||||
});
|
});
|
||||||
@ -1529,7 +1521,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
|
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
|
||||||
TyKind::CVarArgs => {
|
TyKind::CVarArgs => {
|
||||||
let guar = self.tcx.sess.span_delayed_bug(
|
let guar = self.dcx().span_delayed_bug(
|
||||||
t.span,
|
t.span,
|
||||||
"`TyKind::CVarArgs` should have been handled elsewhere",
|
"`TyKind::CVarArgs` should have been handled elsewhere",
|
||||||
);
|
);
|
||||||
@ -1673,8 +1665,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
if let Some(old_def_id) = self.orig_opt_local_def_id(param) {
|
if let Some(old_def_id) = self.orig_opt_local_def_id(param) {
|
||||||
old_def_id
|
old_def_id
|
||||||
} else {
|
} else {
|
||||||
self.tcx
|
self.dcx()
|
||||||
.sess
|
|
||||||
.span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime");
|
.span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1833,19 +1824,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
inputs = &inputs[..inputs.len() - 1];
|
inputs = &inputs[..inputs.len() - 1];
|
||||||
}
|
}
|
||||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
|
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
|
||||||
let itctx = if kind.param_impl_trait_allowed() {
|
let itctx = match kind {
|
||||||
ImplTraitContext::Universal
|
FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => {
|
||||||
} else {
|
ImplTraitContext::Universal
|
||||||
ImplTraitContext::Disallowed(match kind {
|
}
|
||||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
FnDeclKind::ExternFn => {
|
||||||
unreachable!("fn should allow APIT")
|
ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnParam)
|
||||||
}
|
}
|
||||||
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
|
FnDeclKind::Closure => {
|
||||||
FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
|
ImplTraitContext::Disallowed(ImplTraitPosition::ClosureParam)
|
||||||
FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
|
}
|
||||||
FnDeclKind::Trait => ImplTraitPosition::TraitParam,
|
FnDeclKind::Pointer => {
|
||||||
FnDeclKind::Impl => ImplTraitPosition::ImplParam,
|
ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam)
|
||||||
})
|
}
|
||||||
};
|
};
|
||||||
self.lower_ty_direct(¶m.ty, &itctx)
|
self.lower_ty_direct(¶m.ty, &itctx)
|
||||||
}));
|
}));
|
||||||
@ -1857,26 +1848,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
None => match &decl.output {
|
None => match &decl.output {
|
||||||
FnRetTy::Ty(ty) => {
|
FnRetTy::Ty(ty) => {
|
||||||
let context = if kind.return_impl_trait_allowed() {
|
let itctx = match kind {
|
||||||
let fn_def_id = self.local_def_id(fn_node_id);
|
FnDeclKind::Fn
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
| FnDeclKind::Inherent
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
| FnDeclKind::Trait
|
||||||
|
| FnDeclKind::Impl => ImplTraitContext::ReturnPositionOpaqueTy {
|
||||||
|
origin: hir::OpaqueTyOrigin::FnReturn(self.local_def_id(fn_node_id)),
|
||||||
fn_kind: kind,
|
fn_kind: kind,
|
||||||
|
},
|
||||||
|
FnDeclKind::ExternFn => {
|
||||||
|
ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn)
|
||||||
|
}
|
||||||
|
FnDeclKind::Closure => {
|
||||||
|
ImplTraitContext::Disallowed(ImplTraitPosition::ClosureReturn)
|
||||||
|
}
|
||||||
|
FnDeclKind::Pointer => {
|
||||||
|
ImplTraitContext::Disallowed(ImplTraitPosition::PointerReturn)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ImplTraitContext::Disallowed(match kind {
|
|
||||||
FnDeclKind::Fn
|
|
||||||
| FnDeclKind::Inherent
|
|
||||||
| FnDeclKind::Trait
|
|
||||||
| FnDeclKind::Impl => {
|
|
||||||
unreachable!("fn should allow return-position impl trait in traits")
|
|
||||||
}
|
|
||||||
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnReturn,
|
|
||||||
FnDeclKind::Closure => ImplTraitPosition::ClosureReturn,
|
|
||||||
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
hir::FnRetTy::Return(self.lower_ty(ty, &context))
|
hir::FnRetTy::Return(self.lower_ty(ty, &itctx))
|
||||||
}
|
}
|
||||||
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
|
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
|
||||||
},
|
},
|
||||||
@ -2028,9 +2018,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
) -> hir::GenericBound<'hir> {
|
) -> hir::GenericBound<'hir> {
|
||||||
match tpb {
|
match tpb {
|
||||||
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
|
GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait(
|
||||||
self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
|
self.lower_poly_trait_ref(p, itctx, modifiers.constness.into()),
|
||||||
self.lower_trait_bound_modifier(*modifier),
|
self.lower_trait_bound_modifiers(*modifiers),
|
||||||
),
|
),
|
||||||
GenericBound::Outlives(lifetime) => {
|
GenericBound::Outlives(lifetime) => {
|
||||||
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
|
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
|
||||||
@ -2109,7 +2099,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
param: &GenericParam,
|
param: &GenericParam,
|
||||||
source: hir::GenericParamSource,
|
source: hir::GenericParamSource,
|
||||||
) -> hir::GenericParam<'hir> {
|
) -> hir::GenericParam<'hir> {
|
||||||
let (name, kind) = self.lower_generic_param_kind(param);
|
let (name, kind) = self.lower_generic_param_kind(param, source);
|
||||||
|
|
||||||
let hir_id = self.lower_node_id(param.id);
|
let hir_id = self.lower_node_id(param.id);
|
||||||
self.lower_attrs(hir_id, ¶m.attrs);
|
self.lower_attrs(hir_id, ¶m.attrs);
|
||||||
@ -2128,6 +2118,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
fn lower_generic_param_kind(
|
fn lower_generic_param_kind(
|
||||||
&mut self,
|
&mut self,
|
||||||
param: &GenericParam,
|
param: &GenericParam,
|
||||||
|
source: hir::GenericParamSource,
|
||||||
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
|
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
|
||||||
match ¶m.kind {
|
match ¶m.kind {
|
||||||
GenericParamKind::Lifetime => {
|
GenericParamKind::Lifetime => {
|
||||||
@ -2146,22 +2137,51 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
(param_name, kind)
|
(param_name, kind)
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { default, .. } => {
|
GenericParamKind::Type { default, .. } => {
|
||||||
let kind = hir::GenericParamKind::Type {
|
// Not only do we deny type param defaults in binders but we also map them to `None`
|
||||||
default: default.as_ref().map(|x| {
|
// since later compiler stages cannot handle them (and shouldn't need to be able to).
|
||||||
|
let default = default
|
||||||
|
.as_ref()
|
||||||
|
.filter(|_| match source {
|
||||||
|
hir::GenericParamSource::Generics => true,
|
||||||
|
hir::GenericParamSource::Binder => {
|
||||||
|
self.dcx().emit_err(errors::GenericParamDefaultInBinder {
|
||||||
|
span: param.span(),
|
||||||
|
});
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(|def| {
|
||||||
self.lower_ty(
|
self.lower_ty(
|
||||||
x,
|
def,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
|
||||||
)
|
)
|
||||||
}),
|
});
|
||||||
synthetic: false,
|
|
||||||
};
|
let kind = hir::GenericParamKind::Type { default, synthetic: false };
|
||||||
|
|
||||||
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
|
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
|
||||||
}
|
}
|
||||||
GenericParamKind::Const { ty, kw_span: _, default } => {
|
GenericParamKind::Const { ty, kw_span: _, default } => {
|
||||||
let ty = self
|
let ty = self
|
||||||
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault));
|
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault));
|
||||||
let default = default.as_ref().map(|def| self.lower_anon_const(def));
|
|
||||||
|
// Not only do we deny const param defaults in binders but we also map them to `None`
|
||||||
|
// since later compiler stages cannot handle them (and shouldn't need to be able to).
|
||||||
|
let default = default
|
||||||
|
.as_ref()
|
||||||
|
.filter(|_| match source {
|
||||||
|
hir::GenericParamSource::Generics => true,
|
||||||
|
hir::GenericParamSource::Binder => {
|
||||||
|
self.dcx().emit_err(errors::GenericParamDefaultInBinder {
|
||||||
|
span: param.span(),
|
||||||
|
});
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(|def| self.lower_anon_const(def));
|
||||||
|
|
||||||
(
|
(
|
||||||
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
||||||
hir::GenericParamKind::Const { ty, default, is_host_effect: false },
|
hir::GenericParamKind::Const { ty, default, is_host_effect: false },
|
||||||
@ -2172,7 +2192,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
fn lower_trait_ref(
|
fn lower_trait_ref(
|
||||||
&mut self,
|
&mut self,
|
||||||
constness: ast::Const,
|
constness: ast::BoundConstness,
|
||||||
p: &TraitRef,
|
p: &TraitRef,
|
||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
) -> hir::TraitRef<'hir> {
|
) -> hir::TraitRef<'hir> {
|
||||||
@ -2195,7 +2215,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
p: &PolyTraitRef,
|
p: &PolyTraitRef,
|
||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
constness: ast::Const,
|
constness: ast::BoundConstness,
|
||||||
) -> hir::PolyTraitRef<'hir> {
|
) -> hir::PolyTraitRef<'hir> {
|
||||||
let bound_generic_params =
|
let bound_generic_params =
|
||||||
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
|
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
|
||||||
@ -2285,10 +2305,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
match c.value.kind {
|
match c.value.kind {
|
||||||
ExprKind::Underscore => {
|
ExprKind::Underscore => {
|
||||||
if self.tcx.features().generic_arg_infer {
|
if self.tcx.features().generic_arg_infer {
|
||||||
hir::ArrayLen::Infer(self.lower_node_id(c.id), self.lower_span(c.value.span))
|
hir::ArrayLen::Infer(hir::InferArg {
|
||||||
|
hir_id: self.lower_node_id(c.id),
|
||||||
|
span: self.lower_span(c.value.span),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess.parse_sess,
|
&self.tcx.sess,
|
||||||
sym::generic_arg_infer,
|
sym::generic_arg_infer,
|
||||||
c.value.span,
|
c.value.span,
|
||||||
"using `_` for array lengths is unstable",
|
"using `_` for array lengths is unstable",
|
||||||
@ -2316,25 +2339,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
|
fn lower_trait_bound_modifiers(
|
||||||
match f {
|
&mut self,
|
||||||
TraitBoundModifier::None => hir::TraitBoundModifier::None,
|
modifiers: TraitBoundModifiers,
|
||||||
TraitBoundModifier::MaybeConst(_) => hir::TraitBoundModifier::MaybeConst,
|
) -> hir::TraitBoundModifier {
|
||||||
|
// Invalid modifier combinations will cause an error during AST validation.
|
||||||
TraitBoundModifier::Negative => {
|
// Arbitrarily pick a placeholder for them to make compilation proceed.
|
||||||
|
match (modifiers.constness, modifiers.polarity) {
|
||||||
|
(BoundConstness::Never, BoundPolarity::Positive) => hir::TraitBoundModifier::None,
|
||||||
|
(_, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
|
||||||
|
(BoundConstness::Never, BoundPolarity::Negative(_)) => {
|
||||||
if self.tcx.features().negative_bounds {
|
if self.tcx.features().negative_bounds {
|
||||||
hir::TraitBoundModifier::Negative
|
hir::TraitBoundModifier::Negative
|
||||||
} else {
|
} else {
|
||||||
hir::TraitBoundModifier::None
|
hir::TraitBoundModifier::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(BoundConstness::Always(_), _) => hir::TraitBoundModifier::Const,
|
||||||
// `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a
|
(BoundConstness::Maybe(_), _) => hir::TraitBoundModifier::MaybeConst,
|
||||||
// placeholder for compilation to proceed.
|
|
||||||
TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => {
|
|
||||||
hir::TraitBoundModifier::Maybe
|
|
||||||
}
|
|
||||||
TraitBoundModifier::MaybeConstNegative => hir::TraitBoundModifier::MaybeConst,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2552,45 +2574,62 @@ struct GenericArgsCtor<'hir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> GenericArgsCtor<'hir> {
|
impl<'hir> GenericArgsCtor<'hir> {
|
||||||
fn push_constness(&mut self, lcx: &mut LoweringContext<'_, 'hir>, constness: ast::Const) {
|
fn push_constness(
|
||||||
|
&mut self,
|
||||||
|
lcx: &mut LoweringContext<'_, 'hir>,
|
||||||
|
constness: ast::BoundConstness,
|
||||||
|
) {
|
||||||
if !lcx.tcx.features().effects {
|
if !lcx.tcx.features().effects {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if bound is non-const, don't add host effect param
|
let (span, body) = match constness {
|
||||||
let ast::Const::Yes(span) = constness else { return };
|
BoundConstness::Never => return,
|
||||||
|
BoundConstness::Always(span) => {
|
||||||
|
let span = lcx.lower_span(span);
|
||||||
|
|
||||||
let span = lcx.lower_span(span);
|
let body = hir::ExprKind::Lit(
|
||||||
|
lcx.arena.alloc(hir::Lit { node: LitKind::Bool(false), span }),
|
||||||
|
);
|
||||||
|
|
||||||
let id = lcx.next_node_id();
|
(span, body)
|
||||||
let hir_id = lcx.next_id();
|
}
|
||||||
|
BoundConstness::Maybe(span) => {
|
||||||
|
let span = lcx.lower_span(span);
|
||||||
|
|
||||||
let Some(host_param_id) = lcx.host_param_id else {
|
let Some(host_param_id) = lcx.host_param_id else {
|
||||||
lcx.tcx.sess.span_delayed_bug(
|
lcx.dcx().span_delayed_bug(
|
||||||
span,
|
span,
|
||||||
"no host param id for call in const yet no errors reported",
|
"no host param id for call in const yet no errors reported",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = lcx.lower_body(|lcx| {
|
|
||||||
(&[], {
|
|
||||||
let hir_id = lcx.next_id();
|
let hir_id = lcx.next_id();
|
||||||
let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id());
|
let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id());
|
||||||
let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved(
|
let body = hir::ExprKind::Path(hir::QPath::Resolved(
|
||||||
None,
|
None,
|
||||||
lcx.arena.alloc(hir::Path {
|
lcx.arena.alloc(hir::Path {
|
||||||
span,
|
span,
|
||||||
res,
|
res,
|
||||||
segments: arena_vec![lcx; hir::PathSegment::new(Ident {
|
segments: arena_vec![
|
||||||
name: sym::host,
|
lcx;
|
||||||
span,
|
hir::PathSegment::new(
|
||||||
}, hir_id, res)],
|
Ident { name: sym::host, span },
|
||||||
|
hir_id,
|
||||||
|
res
|
||||||
|
)
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
lcx.expr(span, expr_kind)
|
|
||||||
})
|
(span, body)
|
||||||
});
|
}
|
||||||
|
};
|
||||||
|
let body = lcx.lower_body(|lcx| (&[], lcx.expr(span, body)));
|
||||||
|
|
||||||
|
let id = lcx.next_node_id();
|
||||||
|
let hir_id = lcx.next_id();
|
||||||
|
|
||||||
let def_id = lcx.create_def(
|
let def_id = lcx.create_def(
|
||||||
lcx.current_hir_id_owner.def_id,
|
lcx.current_hir_id_owner.def_id,
|
||||||
|
|||||||
@ -82,7 +82,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
span: self.lower_span(f.span),
|
span: self.lower_span(f.span),
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
break hir::PatKind::Struct(qpath, fs, *etc);
|
break hir::PatKind::Struct(qpath, fs, *etc == ast::PatFieldsRest::Rest);
|
||||||
}
|
}
|
||||||
PatKind::Tuple(pats) => {
|
PatKind::Tuple(pats) => {
|
||||||
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
|
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
|
||||||
@ -109,6 +109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// return inner to be processed in next loop
|
// return inner to be processed in next loop
|
||||||
PatKind::Paren(inner) => pattern = inner,
|
PatKind::Paren(inner) => pattern = inner,
|
||||||
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
|
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
|
||||||
|
PatKind::Err(guar) => break hir::PatKind::Err(*guar),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -140,7 +141,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// This is not allowed as a sub-tuple pattern
|
// This is not allowed as a sub-tuple pattern
|
||||||
PatKind::Ident(_, ident, Some(sub)) if sub.is_rest() => {
|
PatKind::Ident(_, ident, Some(sub)) if sub.is_rest() => {
|
||||||
let sp = pat.span;
|
let sp = pat.span;
|
||||||
self.tcx.sess.emit_err(SubTupleBinding {
|
self.dcx().emit_err(SubTupleBinding {
|
||||||
span: sp,
|
span: sp,
|
||||||
ident_name: ident.name,
|
ident_name: ident.name,
|
||||||
ident: *ident,
|
ident: *ident,
|
||||||
@ -289,12 +290,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
|
/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
|
||||||
pub(crate) fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
|
pub(crate) fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
|
||||||
self.tcx.sess.emit_err(ExtraDoubleDot { span: sp, prev_span: prev_sp, ctx });
|
self.dcx().emit_err(ExtraDoubleDot { span: sp, prev_span: prev_sp, ctx });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to ban the `..` pattern in places it shouldn't be semantically.
|
/// Used to ban the `..` pattern in places it shouldn't be semantically.
|
||||||
fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
|
fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> {
|
||||||
self.tcx.sess.emit_err(MisplacedDoubleDot { span: sp });
|
self.dcx().emit_err(MisplacedDoubleDot { span: sp });
|
||||||
|
|
||||||
// We're not in a list context so `..` can be reasonably treated
|
// We're not in a list context so `..` can be reasonably treated
|
||||||
// as `_` because it should always be valid and roughly matches the
|
// as `_` because it should always be valid and roughly matches the
|
||||||
@ -334,7 +335,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
ExprKind::Path(..) if allow_paths => {}
|
ExprKind::Path(..) if allow_paths => {}
|
||||||
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
|
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
|
||||||
_ => {
|
_ => {
|
||||||
let guar = self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
|
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern { span: expr.span });
|
||||||
return self.arena.alloc(self.expr_err(expr.span, guar));
|
return self.arena.alloc(self.expr_err(expr.span, guar));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
param_mode: ParamMode,
|
param_mode: ParamMode,
|
||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
// constness of the impl/bound if this is a trait path
|
// constness of the impl/bound if this is a trait path
|
||||||
constness: Option<ast::Const>,
|
constness: Option<ast::BoundConstness>,
|
||||||
) -> hir::QPath<'hir> {
|
) -> hir::QPath<'hir> {
|
||||||
let qself_position = qself.as_ref().map(|q| q.position);
|
let qself_position = qself.as_ref().map(|q| q.position);
|
||||||
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
|
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
|
||||||
@ -140,7 +140,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
// We should've returned in the for loop above.
|
// We should've returned in the for loop above.
|
||||||
|
|
||||||
self.tcx.sess.dcx().span_bug(
|
self.dcx().span_bug(
|
||||||
p.span,
|
p.span,
|
||||||
format!(
|
format!(
|
||||||
"lower_qpath: no final extension segment in {}..{}",
|
"lower_qpath: no final extension segment in {}..{}",
|
||||||
@ -179,7 +179,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
param_mode: ParamMode,
|
param_mode: ParamMode,
|
||||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
constness: Option<ast::Const>,
|
constness: Option<ast::BoundConstness>,
|
||||||
) -> hir::PathSegment<'hir> {
|
) -> hir::PathSegment<'hir> {
|
||||||
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
|
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
|
||||||
let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
|
let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
|
||||||
@ -214,7 +214,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
self.tcx.sess.emit_err(GenericTypeWithParentheses { span: data.span, sub });
|
self.dcx().emit_err(GenericTypeWithParentheses { span: data.span, sub });
|
||||||
(
|
(
|
||||||
self.lower_angle_bracketed_parameter_data(
|
self.lower_angle_bracketed_parameter_data(
|
||||||
&data.as_angle_bracketed_args(),
|
&data.as_angle_bracketed_args(),
|
||||||
|
|||||||
@ -46,6 +46,8 @@ ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadi
|
|||||||
.const = `const` because of this
|
.const = `const` because of this
|
||||||
.variadic = C-variadic because of this
|
.variadic = C-variadic because of this
|
||||||
|
|
||||||
|
ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types
|
||||||
|
|
||||||
ast_passes_const_without_body =
|
ast_passes_const_without_body =
|
||||||
free constant item without body
|
free constant item without body
|
||||||
.suggestion = provide a definition for the constant
|
.suggestion = provide a definition for the constant
|
||||||
@ -117,13 +119,13 @@ ast_passes_fn_without_body =
|
|||||||
free function without a body
|
free function without a body
|
||||||
.suggestion = provide a definition for the function
|
.suggestion = provide a definition for the function
|
||||||
|
|
||||||
|
ast_passes_forbidden_bound =
|
||||||
|
bounds cannot be used in this context
|
||||||
|
|
||||||
ast_passes_forbidden_default =
|
ast_passes_forbidden_default =
|
||||||
`default` is only allowed on items in trait impls
|
`default` is only allowed on items in trait impls
|
||||||
.label = `default` because of this
|
.label = `default` because of this
|
||||||
|
|
||||||
ast_passes_forbidden_lifetime_bound =
|
|
||||||
lifetime bounds cannot be used in this context
|
|
||||||
|
|
||||||
ast_passes_forbidden_non_lifetime_param =
|
ast_passes_forbidden_non_lifetime_param =
|
||||||
only lifetime parameters can be used in this context
|
only lifetime parameters can be used in this context
|
||||||
|
|
||||||
@ -152,6 +154,8 @@ ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
|
|||||||
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
|
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
|
||||||
.help = remove one of these features
|
.help = remove one of these features
|
||||||
|
|
||||||
|
ast_passes_incompatible_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive
|
||||||
|
|
||||||
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
|
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
|
||||||
.because = {$annotation} because of this
|
.because = {$annotation} because of this
|
||||||
.type = inherent impl for this type
|
.type = inherent impl for this type
|
||||||
@ -184,6 +188,9 @@ ast_passes_module_nonascii = trying to load file for module `{$name}` with non-a
|
|||||||
ast_passes_negative_bound_not_supported =
|
ast_passes_negative_bound_not_supported =
|
||||||
negative bounds are not supported
|
negative bounds are not supported
|
||||||
|
|
||||||
|
ast_passes_negative_bound_with_parenthetical_notation =
|
||||||
|
parenthetical notation may not be used for negative bounds
|
||||||
|
|
||||||
ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
|
ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
|
||||||
.outer = outer `impl Trait`
|
.outer = outer `impl Trait`
|
||||||
.inner = nested `impl Trait` here
|
.inner = nested `impl Trait` here
|
||||||
@ -195,8 +202,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
|
|||||||
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
|
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
|
||||||
.help = use `auto trait Trait {"{}"}` instead
|
.help = use `auto trait Trait {"{}"}` instead
|
||||||
|
|
||||||
ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
|
|
||||||
|
|
||||||
ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
|
ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
|
||||||
|
|
||||||
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
|
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
|
||||||
@ -227,12 +232,28 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here
|
|||||||
.trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
|
.trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
|
||||||
.trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds
|
.trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds
|
||||||
.impl = inherent impls cannot have `~const` trait bounds
|
.impl = inherent impls cannot have `~const` trait bounds
|
||||||
|
.trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
|
||||||
|
.trait_impl_assoc_ty = associated types in non-const impls cannot have `~const` trait bounds
|
||||||
|
.inherent_assoc_ty = inherent associated types cannot have `~const` trait bounds
|
||||||
.object = trait objects cannot have `~const` trait bounds
|
.object = trait objects cannot have `~const` trait bounds
|
||||||
.item = this item cannot have `~const` trait bounds
|
.item = this item cannot have `~const` trait bounds
|
||||||
|
|
||||||
ast_passes_trait_fn_const =
|
ast_passes_trait_fn_const =
|
||||||
functions in traits cannot be declared const
|
functions in {$in_impl ->
|
||||||
.label = functions in traits cannot be const
|
[true] trait impls
|
||||||
|
*[false] traits
|
||||||
|
} cannot be declared const
|
||||||
|
.label = functions in {$in_impl ->
|
||||||
|
[true] trait impls
|
||||||
|
*[false] traits
|
||||||
|
} cannot be const
|
||||||
|
.const_context_label = this declares all associated functions implicitly const
|
||||||
|
.remove_const_sugg = remove the `const`{$requires_multiple_changes ->
|
||||||
|
[true] {" ..."}
|
||||||
|
*[false] {""}
|
||||||
|
}
|
||||||
|
.make_impl_const_sugg = ... and declare the impl to be const instead
|
||||||
|
.make_trait_const_sugg = ... and declare the trait to be a `#[const_trait]` instead
|
||||||
|
|
||||||
ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
|
ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
|
||||||
|
|
||||||
|
|||||||
@ -37,15 +37,35 @@ enum SelfSemantic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// What is the context that prevents using `~const`?
|
/// What is the context that prevents using `~const`?
|
||||||
|
// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
|
||||||
|
// almost identical. This gets rid of an abstraction layer which might be considered bad.
|
||||||
enum DisallowTildeConstContext<'a> {
|
enum DisallowTildeConstContext<'a> {
|
||||||
TraitObject,
|
TraitObject,
|
||||||
Fn(FnKind<'a>),
|
Fn(FnKind<'a>),
|
||||||
Trait(Span),
|
Trait(Span),
|
||||||
TraitImpl(Span),
|
TraitImpl(Span),
|
||||||
Impl(Span),
|
Impl(Span),
|
||||||
|
TraitAssocTy(Span),
|
||||||
|
TraitImplAssocTy(Span),
|
||||||
|
InherentAssocTy(Span),
|
||||||
Item,
|
Item,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TraitOrTraitImpl<'a> {
|
||||||
|
Trait { span: Span, constness: Option<Span> },
|
||||||
|
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: &'a TraitRef },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TraitOrTraitImpl<'a> {
|
||||||
|
fn constness(&self) -> Option<Span> {
|
||||||
|
match self {
|
||||||
|
Self::Trait { constness: Some(span), .. }
|
||||||
|
| Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AstValidator<'a> {
|
struct AstValidator<'a> {
|
||||||
session: &'a Session,
|
session: &'a Session,
|
||||||
features: &'a Features,
|
features: &'a Features,
|
||||||
@ -53,11 +73,7 @@ struct AstValidator<'a> {
|
|||||||
/// The span of the `extern` in an `extern { ... }` block, if any.
|
/// The span of the `extern` in an `extern { ... }` block, if any.
|
||||||
extern_mod: Option<&'a Item>,
|
extern_mod: Option<&'a Item>,
|
||||||
|
|
||||||
/// Are we inside a trait impl?
|
outer_trait_or_trait_impl: Option<TraitOrTraitImpl<'a>>,
|
||||||
in_trait_impl: bool,
|
|
||||||
|
|
||||||
/// Are we inside a const trait defn or impl?
|
|
||||||
in_const_trait_or_impl: bool,
|
|
||||||
|
|
||||||
has_proc_macro_decls: bool,
|
has_proc_macro_decls: bool,
|
||||||
|
|
||||||
@ -78,24 +94,28 @@ struct AstValidator<'a> {
|
|||||||
impl<'a> AstValidator<'a> {
|
impl<'a> AstValidator<'a> {
|
||||||
fn with_in_trait_impl(
|
fn with_in_trait_impl(
|
||||||
&mut self,
|
&mut self,
|
||||||
is_in: bool,
|
trait_: Option<(Const, ImplPolarity, &'a TraitRef)>,
|
||||||
constness: Option<Const>,
|
|
||||||
f: impl FnOnce(&mut Self),
|
f: impl FnOnce(&mut Self),
|
||||||
) {
|
) {
|
||||||
let old = mem::replace(&mut self.in_trait_impl, is_in);
|
let old = mem::replace(
|
||||||
let old_const = mem::replace(
|
&mut self.outer_trait_or_trait_impl,
|
||||||
&mut self.in_const_trait_or_impl,
|
trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl {
|
||||||
matches!(constness, Some(Const::Yes(_))),
|
constness,
|
||||||
|
polarity,
|
||||||
|
trait_ref,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
f(self);
|
f(self);
|
||||||
self.in_trait_impl = old;
|
self.outer_trait_or_trait_impl = old;
|
||||||
self.in_const_trait_or_impl = old_const;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_in_trait(&mut self, is_const: bool, f: impl FnOnce(&mut Self)) {
|
fn with_in_trait(&mut self, span: Span, constness: Option<Span>, f: impl FnOnce(&mut Self)) {
|
||||||
let old = mem::replace(&mut self.in_const_trait_or_impl, is_const);
|
let old = mem::replace(
|
||||||
|
&mut self.outer_trait_or_trait_impl,
|
||||||
|
Some(TraitOrTraitImpl::Trait { span, constness }),
|
||||||
|
);
|
||||||
f(self);
|
f(self);
|
||||||
self.in_const_trait_or_impl = old;
|
self.outer_trait_or_trait_impl = old;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
|
fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
|
||||||
@ -228,13 +248,13 @@ impl<'a> AstValidator<'a> {
|
|||||||
fn check_lifetime(&self, ident: Ident) {
|
fn check_lifetime(&self, ident: Ident) {
|
||||||
let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
|
let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
|
||||||
if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
|
if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
|
||||||
self.session.emit_err(errors::KeywordLifetime { span: ident.span });
|
self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_label(&self, ident: Ident) {
|
fn check_label(&self, ident: Ident) {
|
||||||
if ident.without_first_quote().is_reserved() {
|
if ident.without_first_quote().is_reserved() {
|
||||||
self.session.emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
|
self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +263,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.session.emit_err(errors::VisibilityNotPermitted { span: vis.span, note });
|
self.dcx().emit_err(errors::VisibilityNotPermitted { span: vis.span, note });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
|
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
|
||||||
@ -291,10 +311,49 @@ impl<'a> AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_fn_not_const(&self, constness: Const) {
|
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'a>) {
|
||||||
if let Const::Yes(span) = constness {
|
let Const::Yes(span) = constness else {
|
||||||
self.session.emit_err(errors::TraitFnConst { span });
|
return;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let make_impl_const_sugg = if self.features.const_trait_impl
|
||||||
|
&& let TraitOrTraitImpl::TraitImpl {
|
||||||
|
constness: Const::No,
|
||||||
|
polarity: ImplPolarity::Positive,
|
||||||
|
trait_ref,
|
||||||
|
..
|
||||||
|
} = parent
|
||||||
|
{
|
||||||
|
Some(trait_ref.path.span.shrink_to_lo())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let make_trait_const_sugg = if self.features.const_trait_impl
|
||||||
|
&& let TraitOrTraitImpl::Trait { span, constness: None } = parent
|
||||||
|
{
|
||||||
|
Some(span.shrink_to_lo())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let parent_constness = parent.constness();
|
||||||
|
self.dcx().emit_err(errors::TraitFnConst {
|
||||||
|
span,
|
||||||
|
in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }),
|
||||||
|
const_context_label: parent_constness,
|
||||||
|
remove_const_sugg: (
|
||||||
|
self.session.source_map().span_extend_while(span, |c| c == ' ').unwrap_or(span),
|
||||||
|
match parent_constness {
|
||||||
|
Some(_) => rustc_errors::Applicability::MachineApplicable,
|
||||||
|
None => rustc_errors::Applicability::MaybeIncorrect,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
requires_multiple_changes: make_impl_const_sugg.is_some()
|
||||||
|
|| make_trait_const_sugg.is_some(),
|
||||||
|
make_impl_const_sugg,
|
||||||
|
make_trait_const_sugg,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
|
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
|
||||||
@ -310,7 +369,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
let max_num_args: usize = u16::MAX.into();
|
let max_num_args: usize = u16::MAX.into();
|
||||||
if fn_decl.inputs.len() > max_num_args {
|
if fn_decl.inputs.len() > max_num_args {
|
||||||
let Param { span, .. } = fn_decl.inputs[0];
|
let Param { span, .. } = fn_decl.inputs[0];
|
||||||
self.session.emit_fatal(errors::FnParamTooMany { span, max_num_args });
|
self.dcx().emit_fatal(errors::FnParamTooMany { span, max_num_args });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,13 +377,13 @@ impl<'a> AstValidator<'a> {
|
|||||||
match &*fn_decl.inputs {
|
match &*fn_decl.inputs {
|
||||||
[Param { ty, span, .. }] => {
|
[Param { ty, span, .. }] => {
|
||||||
if let TyKind::CVarArgs = ty.kind {
|
if let TyKind::CVarArgs = ty.kind {
|
||||||
self.session.emit_err(errors::FnParamCVarArgsOnly { span: *span });
|
self.dcx().emit_err(errors::FnParamCVarArgsOnly { span: *span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[ps @ .., _] => {
|
[ps @ .., _] => {
|
||||||
for Param { ty, span, .. } in ps {
|
for Param { ty, span, .. } in ps {
|
||||||
if let TyKind::CVarArgs = ty.kind {
|
if let TyKind::CVarArgs = ty.kind {
|
||||||
self.session.emit_err(errors::FnParamCVarArgsNotLast { span: *span });
|
self.dcx().emit_err(errors::FnParamCVarArgsNotLast { span: *span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,9 +410,9 @@ impl<'a> AstValidator<'a> {
|
|||||||
})
|
})
|
||||||
.for_each(|attr| {
|
.for_each(|attr| {
|
||||||
if attr.is_doc_comment() {
|
if attr.is_doc_comment() {
|
||||||
self.session.emit_err(errors::FnParamDocComment { span: attr.span });
|
self.dcx().emit_err(errors::FnParamDocComment { span: attr.span });
|
||||||
} else {
|
} else {
|
||||||
self.session.emit_err(errors::FnParamForbiddenAttr { span: attr.span });
|
self.dcx().emit_err(errors::FnParamForbiddenAttr { span: attr.span });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -361,7 +420,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
|
fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
|
||||||
if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
|
if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
|
||||||
if param.is_self() {
|
if param.is_self() {
|
||||||
self.session.emit_err(errors::FnParamForbiddenSelf { span: param.span });
|
self.dcx().emit_err(errors::FnParamForbiddenSelf { span: param.span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,7 +428,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
|
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
|
||||||
if let Defaultness::Default(def_span) = defaultness {
|
if let Defaultness::Default(def_span) = defaultness {
|
||||||
let span = self.session.source_map().guess_head_span(span);
|
let span = self.session.source_map().guess_head_span(span);
|
||||||
self.session.emit_err(errors::ForbiddenDefault { span, def_span });
|
self.dcx().emit_err(errors::ForbiddenDefault { span, def_span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,24 +591,24 @@ impl<'a> AstValidator<'a> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let span = self.session.source_map().guess_head_span(item_span);
|
let span = self.session.source_map().guess_head_span(item_span);
|
||||||
self.session.emit_err(errors::NoMangleAscii { span });
|
self.dcx().emit_err(errors::NoMangleAscii { span });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_mod_file_item_asciionly(&self, ident: Ident) {
|
fn check_mod_file_item_asciionly(&self, ident: Ident) {
|
||||||
if ident.name.as_str().is_ascii() {
|
if ident.name.as_str().is_ascii() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.session.emit_err(errors::ModuleNonAscii { span: ident.span, name: ident.name });
|
self.dcx().emit_err(errors::ModuleNonAscii { span: ident.span, name: ident.name });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deny_generic_params(&self, generics: &Generics, ident: Span) {
|
fn deny_generic_params(&self, generics: &Generics, ident: Span) {
|
||||||
if !generics.params.is_empty() {
|
if !generics.params.is_empty() {
|
||||||
self.session.emit_err(errors::AutoTraitGeneric { span: generics.span, ident });
|
self.dcx().emit_err(errors::AutoTraitGeneric { span: generics.span, ident });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_e0568(&self, span: Span, ident: Span) {
|
fn emit_e0568(&self, span: Span, ident: Span) {
|
||||||
self.session.emit_err(errors::AutoTraitBounds { span, ident });
|
self.dcx().emit_err(errors::AutoTraitBounds { span, ident });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
|
fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
|
||||||
@ -569,7 +628,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
if !trait_items.is_empty() {
|
if !trait_items.is_empty() {
|
||||||
let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
|
let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
|
||||||
let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
|
let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
|
||||||
self.session.emit_err(errors::AutoTraitItems { spans, total, ident });
|
self.dcx().emit_err(errors::AutoTraitItems { spans, total, ident });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,7 +692,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
TyKind::BareFn(bfty) => {
|
TyKind::BareFn(bfty) => {
|
||||||
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
|
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
|
||||||
Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
|
Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
|
||||||
self.session.emit_err(errors::PatternFnPointer { span });
|
self.dcx().emit_err(errors::PatternFnPointer { span });
|
||||||
});
|
});
|
||||||
if let Extern::Implicit(_) = bfty.ext {
|
if let Extern::Implicit(_) = bfty.ext {
|
||||||
let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
|
let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
|
||||||
@ -645,7 +704,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
for bound in bounds {
|
for bound in bounds {
|
||||||
if let GenericBound::Outlives(lifetime) = bound {
|
if let GenericBound::Outlives(lifetime) = bound {
|
||||||
if any_lifetime_bounds {
|
if any_lifetime_bounds {
|
||||||
self.session
|
self.dcx()
|
||||||
.emit_err(errors::TraitObjectBound { span: lifetime.ident.span });
|
.emit_err(errors::TraitObjectBound { span: lifetime.ident.span });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -655,11 +714,11 @@ impl<'a> AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
TyKind::ImplTrait(_, bounds) => {
|
TyKind::ImplTrait(_, bounds) => {
|
||||||
if self.is_impl_trait_banned {
|
if self.is_impl_trait_banned {
|
||||||
self.session.emit_err(errors::ImplTraitPath { span: ty.span });
|
self.dcx().emit_err(errors::ImplTraitPath { span: ty.span });
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
|
if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
|
||||||
self.session.emit_err(errors::NestedImplTrait {
|
self.dcx().emit_err(errors::NestedImplTrait {
|
||||||
span: ty.span,
|
span: ty.span,
|
||||||
outer: outer_impl_trait_sp,
|
outer: outer_impl_trait_sp,
|
||||||
inner: ty.span,
|
inner: ty.span,
|
||||||
@ -817,7 +876,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
self_ty,
|
self_ty,
|
||||||
items,
|
items,
|
||||||
}) => {
|
}) => {
|
||||||
self.with_in_trait_impl(true, Some(*constness), |this| {
|
self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| {
|
||||||
this.visibility_not_permitted(
|
this.visibility_not_permitted(
|
||||||
&item.vis,
|
&item.vis,
|
||||||
errors::VisibilityNotPermittedNote::TraitImpl,
|
errors::VisibilityNotPermittedNote::TraitImpl,
|
||||||
@ -827,7 +886,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity)
|
if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity)
|
||||||
{
|
{
|
||||||
this.session.emit_err(errors::UnsafeNegativeImpl {
|
this.dcx().emit_err(errors::UnsafeNegativeImpl {
|
||||||
span: sp.to(t.path.span),
|
span: sp.to(t.path.span),
|
||||||
negative: sp,
|
negative: sp,
|
||||||
r#unsafe: span,
|
r#unsafe: span,
|
||||||
@ -866,35 +925,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
only_trait: only_trait.then_some(()),
|
only_trait: only_trait.then_some(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.visibility_not_permitted(
|
self.with_in_trait_impl(None, |this| {
|
||||||
&item.vis,
|
this.visibility_not_permitted(
|
||||||
errors::VisibilityNotPermittedNote::IndividualImplItems,
|
&item.vis,
|
||||||
);
|
errors::VisibilityNotPermittedNote::IndividualImplItems,
|
||||||
if let &Unsafe::Yes(span) = unsafety {
|
);
|
||||||
self.dcx().emit_err(errors::InherentImplCannotUnsafe {
|
if let &Unsafe::Yes(span) = unsafety {
|
||||||
span: self_ty.span,
|
this.dcx().emit_err(errors::InherentImplCannotUnsafe {
|
||||||
annotation_span: span,
|
span: self_ty.span,
|
||||||
annotation: "unsafe",
|
annotation_span: span,
|
||||||
self_ty: self_ty.span,
|
annotation: "unsafe",
|
||||||
});
|
self_ty: self_ty.span,
|
||||||
}
|
});
|
||||||
if let &ImplPolarity::Negative(span) = polarity {
|
}
|
||||||
self.dcx().emit_err(error(span, "negative", false));
|
if let &ImplPolarity::Negative(span) = polarity {
|
||||||
}
|
this.dcx().emit_err(error(span, "negative", false));
|
||||||
if let &Defaultness::Default(def_span) = defaultness {
|
}
|
||||||
self.dcx().emit_err(error(def_span, "`default`", true));
|
if let &Defaultness::Default(def_span) = defaultness {
|
||||||
}
|
this.dcx().emit_err(error(def_span, "`default`", true));
|
||||||
if let &Const::Yes(span) = constness {
|
}
|
||||||
self.dcx().emit_err(error(span, "`const`", true));
|
if let &Const::Yes(span) = constness {
|
||||||
}
|
this.dcx().emit_err(error(span, "`const`", true));
|
||||||
|
}
|
||||||
|
|
||||||
self.visit_vis(&item.vis);
|
this.visit_vis(&item.vis);
|
||||||
self.visit_ident(item.ident);
|
this.visit_ident(item.ident);
|
||||||
self.with_tilde_const(Some(DisallowTildeConstContext::Impl(item.span)), |this| {
|
this.with_tilde_const(
|
||||||
this.visit_generics(generics)
|
Some(DisallowTildeConstContext::Impl(item.span)),
|
||||||
|
|this| this.visit_generics(generics),
|
||||||
|
);
|
||||||
|
this.visit_ty(self_ty);
|
||||||
|
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
|
||||||
});
|
});
|
||||||
self.visit_ty(self_ty);
|
|
||||||
walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl);
|
|
||||||
walk_list!(self, visit_attribute, &item.attrs);
|
walk_list!(self, visit_attribute, &item.attrs);
|
||||||
return; // Avoid visiting again.
|
return; // Avoid visiting again.
|
||||||
}
|
}
|
||||||
@ -902,7 +964,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
self.check_defaultness(item.span, *defaultness);
|
self.check_defaultness(item.span, *defaultness);
|
||||||
|
|
||||||
if body.is_none() {
|
if body.is_none() {
|
||||||
self.session.emit_err(errors::FnWithoutBody {
|
self.dcx().emit_err(errors::FnWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
extern_block_suggestion: match sig.header.ext {
|
extern_block_suggestion: match sig.header.ext {
|
||||||
@ -963,8 +1025,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
|
ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
|
||||||
let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait);
|
let is_const_trait =
|
||||||
self.with_in_trait(is_const_trait, |this| {
|
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
|
||||||
|
self.with_in_trait(item.span, is_const_trait, |this| {
|
||||||
if *is_auto == IsAuto::Yes {
|
if *is_auto == IsAuto::Yes {
|
||||||
// Auto traits cannot have generics, super traits nor contain items.
|
// Auto traits cannot have generics, super traits nor contain items.
|
||||||
this.deny_generic_params(generics, item.ident.span);
|
this.deny_generic_params(generics, item.ident.span);
|
||||||
@ -977,8 +1040,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
// context for the supertraits.
|
// context for the supertraits.
|
||||||
this.visit_vis(&item.vis);
|
this.visit_vis(&item.vis);
|
||||||
this.visit_ident(item.ident);
|
this.visit_ident(item.ident);
|
||||||
let disallowed =
|
let disallowed = is_const_trait
|
||||||
(!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span));
|
.is_none()
|
||||||
|
.then(|| DisallowTildeConstContext::Trait(item.span));
|
||||||
this.with_tilde_const(disallowed, |this| {
|
this.with_tilde_const(disallowed, |this| {
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
|
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
|
||||||
@ -1031,14 +1095,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
|
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
|
||||||
self.check_defaultness(item.span, *defaultness);
|
self.check_defaultness(item.span, *defaultness);
|
||||||
if expr.is_none() {
|
if expr.is_none() {
|
||||||
self.session.emit_err(errors::ConstWithoutBody {
|
self.dcx().emit_err(errors::ConstWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Static(box StaticItem { expr: None, .. }) => {
|
ItemKind::Static(box StaticItem { expr: None, .. }) => {
|
||||||
self.session.emit_err(errors::StaticWithoutBody {
|
self.dcx().emit_err(errors::StaticWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
});
|
});
|
||||||
@ -1048,7 +1112,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
) => {
|
) => {
|
||||||
self.check_defaultness(item.span, *defaultness);
|
self.check_defaultness(item.span, *defaultness);
|
||||||
if ty.is_none() {
|
if ty.is_none() {
|
||||||
self.session.emit_err(errors::TyAliasWithoutBody {
|
self.dcx().emit_err(errors::TyAliasWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
});
|
});
|
||||||
@ -1196,18 +1260,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
|
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
|
||||||
if let GenericBound::Trait(poly, modify) = bound {
|
if let GenericBound::Trait(poly, modifiers) = bound {
|
||||||
match (ctxt, modify) {
|
match (ctxt, modifiers.constness, modifiers.polarity) {
|
||||||
(BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
|
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||||
self.dcx().emit_err(errors::OptionalTraitSupertrait {
|
self.dcx().emit_err(errors::OptionalTraitSupertrait {
|
||||||
span: poly.span,
|
span: poly.span,
|
||||||
path_str: pprust::path_to_string(&poly.trait_ref.path),
|
path_str: pprust::path_to_string(&poly.trait_ref.path),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
(BoundKind::TraitObject, TraitBoundModifier::Maybe) => {
|
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||||
self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span });
|
self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span });
|
||||||
}
|
}
|
||||||
(_, &TraitBoundModifier::MaybeConst(span))
|
(BoundKind::TraitObject, BoundConstness::Always(_), BoundPolarity::Positive) => {
|
||||||
|
self.dcx().emit_err(errors::ConstBoundTraitObject { span: poly.span });
|
||||||
|
}
|
||||||
|
(_, BoundConstness::Maybe(span), BoundPolarity::Positive)
|
||||||
if let Some(reason) = &self.disallow_tilde_const =>
|
if let Some(reason) = &self.disallow_tilde_const =>
|
||||||
{
|
{
|
||||||
let reason = match reason {
|
let reason = match reason {
|
||||||
@ -1228,6 +1295,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
// suggestion for moving such bounds to the assoc const fns if available.
|
// suggestion for moving such bounds to the assoc const fns if available.
|
||||||
errors::TildeConstReason::Impl { span }
|
errors::TildeConstReason::Impl { span }
|
||||||
}
|
}
|
||||||
|
&DisallowTildeConstContext::TraitAssocTy(span) => {
|
||||||
|
errors::TildeConstReason::TraitAssocTy { span }
|
||||||
|
}
|
||||||
|
&DisallowTildeConstContext::TraitImplAssocTy(span) => {
|
||||||
|
errors::TildeConstReason::TraitImplAssocTy { span }
|
||||||
|
}
|
||||||
|
&DisallowTildeConstContext::InherentAssocTy(span) => {
|
||||||
|
errors::TildeConstReason::InherentAssocTy { span }
|
||||||
|
}
|
||||||
DisallowTildeConstContext::TraitObject => {
|
DisallowTildeConstContext::TraitObject => {
|
||||||
errors::TildeConstReason::TraitObject
|
errors::TildeConstReason::TraitObject
|
||||||
}
|
}
|
||||||
@ -1235,16 +1311,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
};
|
};
|
||||||
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
|
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
|
||||||
}
|
}
|
||||||
(_, TraitBoundModifier::MaybeConstMaybe) => {
|
(
|
||||||
self.dcx().emit_err(errors::OptionalConstExclusive {
|
_,
|
||||||
|
BoundConstness::Always(_) | BoundConstness::Maybe(_),
|
||||||
|
BoundPolarity::Negative(_) | BoundPolarity::Maybe(_),
|
||||||
|
) => {
|
||||||
|
self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers {
|
||||||
span: bound.span(),
|
span: bound.span(),
|
||||||
modifier: "?",
|
left: modifiers.constness.as_str(),
|
||||||
});
|
right: modifiers.polarity.as_str(),
|
||||||
}
|
|
||||||
(_, TraitBoundModifier::MaybeConstNegative) => {
|
|
||||||
self.dcx().emit_err(errors::OptionalConstExclusive {
|
|
||||||
span: bound.span(),
|
|
||||||
modifier: "!",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -1252,15 +1327,27 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Negative trait bounds are not allowed to have associated constraints
|
// Negative trait bounds are not allowed to have associated constraints
|
||||||
if let GenericBound::Trait(trait_ref, TraitBoundModifier::Negative) = bound
|
if let GenericBound::Trait(trait_ref, modifiers) = bound
|
||||||
|
&& let BoundPolarity::Negative(_) = modifiers.polarity
|
||||||
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
|
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
|
||||||
&& let Some(ast::GenericArgs::AngleBracketed(args)) = segment.args.as_deref()
|
|
||||||
{
|
{
|
||||||
for arg in &args.args {
|
match segment.args.as_deref() {
|
||||||
if let ast::AngleBracketedArg::Constraint(constraint) = arg {
|
Some(ast::GenericArgs::AngleBracketed(args)) => {
|
||||||
self.dcx()
|
for arg in &args.args {
|
||||||
.emit_err(errors::ConstraintOnNegativeBound { span: constraint.span });
|
if let ast::AngleBracketedArg::Constraint(constraint) = arg {
|
||||||
|
self.dcx().emit_err(errors::ConstraintOnNegativeBound {
|
||||||
|
span: constraint.span,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// The lowered form of parenthesized generic args contains a type binding.
|
||||||
|
Some(ast::GenericArgs::Parenthesized(args)) => {
|
||||||
|
self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation {
|
||||||
|
span: args.span,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,7 +1426,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
|
|
||||||
let tilde_const_allowed =
|
let tilde_const_allowed =
|
||||||
matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
|
matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
|
||||||
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl);
|
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)))
|
||||||
|
&& self
|
||||||
|
.outer_trait_or_trait_impl
|
||||||
|
.as_ref()
|
||||||
|
.and_then(TraitOrTraitImpl::constness)
|
||||||
|
.is_some();
|
||||||
|
|
||||||
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
|
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
|
||||||
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
|
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
|
||||||
@ -1350,21 +1442,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
self.check_nomangle_item_asciionly(item.ident, item.span);
|
self.check_nomangle_item_asciionly(item.ident, item.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
|
if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() {
|
||||||
self.check_defaultness(item.span, item.kind.defaultness());
|
self.check_defaultness(item.span, item.kind.defaultness());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt == AssocCtxt::Impl {
|
if ctxt == AssocCtxt::Impl {
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Const(box ConstItem { expr: None, .. }) => {
|
AssocItemKind::Const(box ConstItem { expr: None, .. }) => {
|
||||||
self.session.emit_err(errors::AssocConstWithoutBody {
|
self.dcx().emit_err(errors::AssocConstWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { body, .. }) => {
|
AssocItemKind::Fn(box Fn { body, .. }) => {
|
||||||
if body.is_none() {
|
if body.is_none() {
|
||||||
self.session.emit_err(errors::AssocFnWithoutBody {
|
self.dcx().emit_err(errors::AssocFnWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
});
|
});
|
||||||
@ -1372,7 +1464,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
AssocItemKind::Type(box TyAlias { bounds, ty, .. }) => {
|
AssocItemKind::Type(box TyAlias { bounds, ty, .. }) => {
|
||||||
if ty.is_none() {
|
if ty.is_none() {
|
||||||
self.session.emit_err(errors::AssocTypeWithoutBody {
|
self.dcx().emit_err(errors::AssocTypeWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
});
|
});
|
||||||
@ -1398,10 +1490,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt == AssocCtxt::Trait || self.in_trait_impl {
|
if let Some(parent) = &self.outer_trait_or_trait_impl {
|
||||||
self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
|
self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
|
||||||
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
|
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
|
||||||
self.check_trait_fn_not_const(sig.header.constness);
|
self.check_trait_fn_not_const(sig.header.constness, parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1409,9 +1501,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
self.check_item_named(item.ident, "const");
|
self.check_item_named(item.ident, "const");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let parent_is_const =
|
||||||
|
self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some();
|
||||||
|
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
|
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
|
||||||
if self.in_const_trait_or_impl
|
if parent_is_const
|
||||||
|| ctxt == AssocCtxt::Trait
|
|| ctxt == AssocCtxt::Trait
|
||||||
|| matches!(sig.header.constness, Const::Yes(_)) =>
|
|| matches!(sig.header.constness, Const::Yes(_)) =>
|
||||||
{
|
{
|
||||||
@ -1427,8 +1522,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
);
|
);
|
||||||
self.visit_fn(kind, item.span, item.id);
|
self.visit_fn(kind, item.span, item.id);
|
||||||
}
|
}
|
||||||
_ => self
|
AssocItemKind::Type(_) => {
|
||||||
.with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)),
|
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
|
||||||
|
Some(TraitOrTraitImpl::Trait { .. }) => {
|
||||||
|
DisallowTildeConstContext::TraitAssocTy(item.span)
|
||||||
|
}
|
||||||
|
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
|
||||||
|
DisallowTildeConstContext::TraitImplAssocTy(item.span)
|
||||||
|
}
|
||||||
|
None => DisallowTildeConstContext::InherentAssocTy(item.span),
|
||||||
|
});
|
||||||
|
self.with_tilde_const(disallowed, |this| {
|
||||||
|
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1494,7 +1602,8 @@ fn deny_equality_constraints(
|
|||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
if param.ident == potential_param.ident {
|
if param.ident == potential_param.ident {
|
||||||
for bound in ¶m.bounds {
|
for bound in ¶m.bounds {
|
||||||
if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
|
if let ast::GenericBound::Trait(trait_ref, TraitBoundModifiers::NONE) =
|
||||||
|
bound
|
||||||
{
|
{
|
||||||
if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
|
if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
|
||||||
let assoc = pprust::path_to_string(&ast::Path::from_ident(
|
let assoc = pprust::path_to_string(&ast::Path::from_ident(
|
||||||
@ -1543,8 +1652,7 @@ pub fn check_crate(
|
|||||||
session,
|
session,
|
||||||
features,
|
features,
|
||||||
extern_mod: None,
|
extern_mod: None,
|
||||||
in_trait_impl: false,
|
outer_trait_or_trait_impl: None,
|
||||||
in_const_trait_or_impl: false,
|
|
||||||
has_proc_macro_decls: false,
|
has_proc_macro_decls: false,
|
||||||
outer_impl_trait: None,
|
outer_impl_trait: None,
|
||||||
disallow_tilde_const: Some(DisallowTildeConstContext::Item),
|
disallow_tilde_const: Some(DisallowTildeConstContext::Item),
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
//! Errors emitted by ast_passes.
|
//! Errors emitted by ast_passes.
|
||||||
|
|
||||||
use rustc_ast::ParamKindOrd;
|
use rustc_ast::ParamKindOrd;
|
||||||
use rustc_errors::AddToDiagnostic;
|
use rustc_errors::{codes::*, AddToDiagnostic, Applicability};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ pub struct InvalidLabel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_visibility_not_permitted, code = "E0449")]
|
#[diag(ast_passes_visibility_not_permitted, code = E0449)]
|
||||||
pub struct VisibilityNotPermitted {
|
pub struct VisibilityNotPermitted {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -44,16 +44,34 @@ pub enum VisibilityNotPermittedNote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_trait_fn_const, code = "E0379")]
|
#[diag(ast_passes_trait_fn_const, code = E0379)]
|
||||||
pub struct TraitFnConst {
|
pub struct TraitFnConst {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
pub in_impl: bool,
|
||||||
|
#[label(ast_passes_const_context_label)]
|
||||||
|
pub const_context_label: Option<Span>,
|
||||||
|
#[suggestion(ast_passes_remove_const_sugg, code = "")]
|
||||||
|
pub remove_const_sugg: (Span, Applicability),
|
||||||
|
pub requires_multiple_changes: bool,
|
||||||
|
#[suggestion(
|
||||||
|
ast_passes_make_impl_const_sugg,
|
||||||
|
code = "const ",
|
||||||
|
applicability = "maybe-incorrect"
|
||||||
|
)]
|
||||||
|
pub make_impl_const_sugg: Option<Span>,
|
||||||
|
#[suggestion(
|
||||||
|
ast_passes_make_trait_const_sugg,
|
||||||
|
code = "#[const_trait]\n",
|
||||||
|
applicability = "maybe-incorrect"
|
||||||
|
)]
|
||||||
|
pub make_trait_const_sugg: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_forbidden_lifetime_bound)]
|
#[diag(ast_passes_forbidden_bound)]
|
||||||
pub struct ForbiddenLifetimeBound {
|
pub struct ForbiddenBound {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub spans: Vec<Span>,
|
pub spans: Vec<Span>,
|
||||||
}
|
}
|
||||||
@ -284,14 +302,14 @@ pub struct ItemUnderscore<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_nomangle_ascii, code = "E0754")]
|
#[diag(ast_passes_nomangle_ascii, code = E0754)]
|
||||||
pub struct NoMangleAscii {
|
pub struct NoMangleAscii {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_module_nonascii, code = "E0754")]
|
#[diag(ast_passes_module_nonascii, code = E0754)]
|
||||||
#[help]
|
#[help]
|
||||||
pub struct ModuleNonAscii {
|
pub struct ModuleNonAscii {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
@ -300,7 +318,7 @@ pub struct ModuleNonAscii {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_auto_generic, code = "E0567")]
|
#[diag(ast_passes_auto_generic, code = E0567)]
|
||||||
pub struct AutoTraitGeneric {
|
pub struct AutoTraitGeneric {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[suggestion(code = "", applicability = "machine-applicable")]
|
#[suggestion(code = "", applicability = "machine-applicable")]
|
||||||
@ -310,7 +328,7 @@ pub struct AutoTraitGeneric {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_auto_super_lifetime, code = "E0568")]
|
#[diag(ast_passes_auto_super_lifetime, code = E0568)]
|
||||||
pub struct AutoTraitBounds {
|
pub struct AutoTraitBounds {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[suggestion(code = "", applicability = "machine-applicable")]
|
#[suggestion(code = "", applicability = "machine-applicable")]
|
||||||
@ -320,7 +338,7 @@ pub struct AutoTraitBounds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_auto_items, code = "E0380")]
|
#[diag(ast_passes_auto_items, code = E0380)]
|
||||||
pub struct AutoTraitItems {
|
pub struct AutoTraitItems {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub spans: Vec<Span>,
|
pub spans: Vec<Span>,
|
||||||
@ -366,28 +384,28 @@ impl AddToDiagnostic for EmptyLabelManySpans {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_pattern_in_fn_pointer, code = "E0561")]
|
#[diag(ast_passes_pattern_in_fn_pointer, code = E0561)]
|
||||||
pub struct PatternFnPointer {
|
pub struct PatternFnPointer {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_trait_object_single_bound, code = "E0226")]
|
#[diag(ast_passes_trait_object_single_bound, code = E0226)]
|
||||||
pub struct TraitObjectBound {
|
pub struct TraitObjectBound {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_impl_trait_path, code = "E0667")]
|
#[diag(ast_passes_impl_trait_path, code = E0667)]
|
||||||
pub struct ImplTraitPath {
|
pub struct ImplTraitPath {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_nested_impl_trait, code = "E0666")]
|
#[diag(ast_passes_nested_impl_trait, code = E0666)]
|
||||||
pub struct NestedImplTrait {
|
pub struct NestedImplTrait {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -425,7 +443,7 @@ pub struct ObsoleteAuto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_unsafe_negative_impl, code = "E0198")]
|
#[diag(ast_passes_unsafe_negative_impl, code = E0198)]
|
||||||
pub struct UnsafeNegativeImpl {
|
pub struct UnsafeNegativeImpl {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -450,7 +468,7 @@ pub struct InherentImplCannot<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_inherent_cannot_be, code = "E0197")]
|
#[diag(ast_passes_inherent_cannot_be, code = E0197)]
|
||||||
pub struct InherentImplCannotUnsafe<'a> {
|
pub struct InherentImplCannotUnsafe<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -518,7 +536,7 @@ pub struct GenericDefaultTrailing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_nested_lifetimes, code = "E0316")]
|
#[diag(ast_passes_nested_lifetimes, code = E0316)]
|
||||||
pub struct NestedLifetimes {
|
pub struct NestedLifetimes {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -540,6 +558,15 @@ pub struct OptionalTraitObject {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_const_bound_trait_object)]
|
||||||
|
pub struct ConstBoundTraitObject {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(effects): Consider making the note/reason the message of the diagnostic.
|
||||||
|
// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_tilde_const_disallowed)]
|
#[diag(ast_passes_tilde_const_disallowed)]
|
||||||
pub struct TildeConstDisallowed {
|
pub struct TildeConstDisallowed {
|
||||||
@ -573,6 +600,21 @@ pub enum TildeConstReason {
|
|||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
|
#[note(ast_passes_trait_assoc_ty)]
|
||||||
|
TraitAssocTy {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
#[note(ast_passes_trait_impl_assoc_ty)]
|
||||||
|
TraitImplAssocTy {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
#[note(ast_passes_inherent_assoc_ty)]
|
||||||
|
InherentAssocTy {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
#[note(ast_passes_object)]
|
#[note(ast_passes_object)]
|
||||||
TraitObject,
|
TraitObject,
|
||||||
#[note(ast_passes_item)]
|
#[note(ast_passes_item)]
|
||||||
@ -580,11 +622,12 @@ pub enum TildeConstReason {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_optional_const_exclusive)]
|
#[diag(ast_passes_incompatible_trait_bound_modifiers)]
|
||||||
pub struct OptionalConstExclusive {
|
pub struct IncompatibleTraitBoundModifiers {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub modifier: &'static str,
|
pub left: &'static str,
|
||||||
|
pub right: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
@ -612,7 +655,7 @@ pub struct ConstAndCVariadic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_pattern_in_foreign, code = "E0130")]
|
#[diag(ast_passes_pattern_in_foreign, code = E0130)]
|
||||||
pub struct PatternInForeign {
|
pub struct PatternInForeign {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
@ -620,7 +663,7 @@ pub struct PatternInForeign {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_pattern_in_bodiless, code = "E0642")]
|
#[diag(ast_passes_pattern_in_bodiless, code = E0642)]
|
||||||
pub struct PatternInBodiless {
|
pub struct PatternInBodiless {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
@ -668,14 +711,14 @@ pub struct AssociatedSuggestion2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_stability_outside_std, code = "E0734")]
|
#[diag(ast_passes_stability_outside_std, code = E0734)]
|
||||||
pub struct StabilityOutsideStd {
|
pub struct StabilityOutsideStd {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_feature_on_non_nightly, code = "E0554")]
|
#[diag(ast_passes_feature_on_non_nightly, code = E0554)]
|
||||||
pub struct FeatureOnNonNightly {
|
pub struct FeatureOnNonNightly {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -699,8 +742,8 @@ impl AddToDiagnostic for StableFeature {
|
|||||||
rustc_errors::SubdiagnosticMessage,
|
rustc_errors::SubdiagnosticMessage,
|
||||||
) -> rustc_errors::SubdiagnosticMessage,
|
) -> rustc_errors::SubdiagnosticMessage,
|
||||||
{
|
{
|
||||||
diag.set_arg("name", self.name);
|
diag.arg("name", self.name);
|
||||||
diag.set_arg("since", self.since);
|
diag.arg("since", self.since);
|
||||||
diag.help(fluent::ast_passes_stable_since);
|
diag.help(fluent::ast_passes_stable_since);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -737,6 +780,13 @@ pub struct ConstraintOnNegativeBound {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_negative_bound_with_parenthetical_notation)]
|
||||||
|
pub struct NegativeBoundWithParentheticalNotation {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_invalid_unnamed_field_ty)]
|
#[diag(ast_passes_invalid_unnamed_field_ty)]
|
||||||
pub struct InvalidUnnamedFieldTy {
|
pub struct InvalidUnnamedFieldTy {
|
||||||
|
|||||||
@ -17,14 +17,12 @@ use crate::errors;
|
|||||||
macro_rules! gate {
|
macro_rules! gate {
|
||||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain).emit();
|
feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
|
feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit();
|
||||||
.help($help)
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -33,7 +31,7 @@ macro_rules! gate {
|
|||||||
macro_rules! gate_alt {
|
macro_rules! gate_alt {
|
||||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
|
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
|
||||||
if !$has_feature && !$span.allows_unstable($name) {
|
if !$has_feature && !$span.allows_unstable($name) {
|
||||||
feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit();
|
feature_err(&$visitor.sess, $name, $span, $explain).emit();
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -45,7 +43,7 @@ macro_rules! gate_multi {
|
|||||||
let spans: Vec<_> =
|
let spans: Vec<_> =
|
||||||
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
|
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
|
||||||
if !spans.is_empty() {
|
if !spans.is_empty() {
|
||||||
feature_err(&$visitor.sess.parse_sess, sym::$feature, spans, $explain).emit();
|
feature_err(&$visitor.sess, sym::$feature, spans, $explain).emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
@ -55,7 +53,7 @@ macro_rules! gate_multi {
|
|||||||
macro_rules! gate_legacy {
|
macro_rules! gate_legacy {
|
||||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||||
feature_warn(&$visitor.sess.parse_sess, sym::$feature, $span, $explain);
|
feature_warn(&$visitor.sess, sym::$feature, $span, $explain);
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -91,14 +89,7 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||||||
match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) {
|
match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(abi::AbiDisabled::Unstable { feature, explain }) => {
|
Err(abi::AbiDisabled::Unstable { feature, explain }) => {
|
||||||
feature_err_issue(
|
feature_err_issue(&self.sess, feature, span, GateIssue::Language, explain).emit();
|
||||||
&self.sess.parse_sess,
|
|
||||||
feature,
|
|
||||||
span,
|
|
||||||
GateIssue::Language,
|
|
||||||
explain,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
Err(abi::AbiDisabled::Unrecognized) => {
|
Err(abi::AbiDisabled::Unrecognized) => {
|
||||||
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
|
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
|
||||||
@ -152,8 +143,8 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
|
fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
|
||||||
// Check only lifetime parameters are present and that the lifetime
|
// Check only lifetime parameters are present and that the
|
||||||
// parameters that are present have no bounds.
|
// generic parameters that are present have no bounds.
|
||||||
let non_lt_param_spans = params.iter().filter_map(|param| match param.kind {
|
let non_lt_param_spans = params.iter().filter_map(|param| match param.kind {
|
||||||
ast::GenericParamKind::Lifetime { .. } => None,
|
ast::GenericParamKind::Lifetime { .. } => None,
|
||||||
_ => Some(param.ident.span),
|
_ => Some(param.ident.span),
|
||||||
@ -164,10 +155,11 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||||||
non_lt_param_spans,
|
non_lt_param_spans,
|
||||||
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param
|
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param
|
||||||
);
|
);
|
||||||
|
|
||||||
for param in params {
|
for param in params {
|
||||||
if !param.bounds.is_empty() {
|
if !param.bounds.is_empty() {
|
||||||
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
|
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
|
||||||
self.sess.emit_err(errors::ForbiddenLifetimeBound { spans });
|
self.sess.dcx().emit_err(errors::ForbiddenBound { spans });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,7 +217,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
|| attr.has_name(sym::rustc_const_stable)
|
|| attr.has_name(sym::rustc_const_stable)
|
||||||
|| attr.has_name(sym::rustc_default_body_unstable)
|
|| attr.has_name(sym::rustc_default_body_unstable)
|
||||||
{
|
{
|
||||||
self.sess.emit_err(errors::StabilityOutsideStd { span: attr.span });
|
self.sess.dcx().emit_err(errors::StabilityOutsideStd { span: attr.span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,6 +362,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_generic_args(&mut self, args: &'a ast::GenericArgs) {
|
||||||
|
// This check needs to happen here because the never type can be returned from a function,
|
||||||
|
// but cannot be used in any other context. If this check was in `visit_fn_ret_ty`, it
|
||||||
|
// include both functions and generics like `impl Fn() -> !`.
|
||||||
|
if let ast::GenericArgs::Parenthesized(generic_args) = args
|
||||||
|
&& let ast::FnRetTy::Ty(ref ty) = generic_args.output
|
||||||
|
&& matches!(ty.kind, ast::TyKind::Never)
|
||||||
|
{
|
||||||
|
gate!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||||
|
}
|
||||||
|
visit::walk_generic_args(self, args);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
ast::ExprKind::TryBlock(_) => {
|
ast::ExprKind::TryBlock(_) => {
|
||||||
@ -406,7 +411,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
&self,
|
&self,
|
||||||
exclusive_range_pattern,
|
exclusive_range_pattern,
|
||||||
pattern.span,
|
pattern.span,
|
||||||
"exclusive range pattern syntax is experimental"
|
"exclusive range pattern syntax is experimental",
|
||||||
|
"use an inclusive range pattern, like N..=M"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -515,7 +521,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
gate_all!(c_str_literals, "`c\"..\"` literals are experimental");
|
|
||||||
gate_all!(
|
gate_all!(
|
||||||
if_let_guard,
|
if_let_guard,
|
||||||
"`if let` guards are experimental",
|
"`if let` guards are experimental",
|
||||||
@ -527,6 +532,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||||||
"async closures are unstable",
|
"async closures are unstable",
|
||||||
"to use an async block, remove the `||`: `async {`"
|
"to use an async block, remove the `||`: `async {`"
|
||||||
);
|
);
|
||||||
|
gate_all!(async_for_loop, "`for await` loops are experimental");
|
||||||
gate_all!(
|
gate_all!(
|
||||||
closure_lifetime_binder,
|
closure_lifetime_binder,
|
||||||
"`for<...>` binders for closures are experimental",
|
"`for<...>` binders for closures are experimental",
|
||||||
@ -555,6 +561,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||||||
gate_all!(explicit_tail_calls, "`become` expression is experimental");
|
gate_all!(explicit_tail_calls, "`become` expression is experimental");
|
||||||
gate_all!(generic_const_items, "generic const items are experimental");
|
gate_all!(generic_const_items, "generic const items are experimental");
|
||||||
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
|
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
|
||||||
|
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
|
||||||
|
|
||||||
if !visitor.features.never_patterns {
|
if !visitor.features.never_patterns {
|
||||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||||
@ -569,16 +576,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||||||
if let Ok(snippet) = sm.span_to_snippet(span)
|
if let Ok(snippet) = sm.span_to_snippet(span)
|
||||||
&& snippet == "!"
|
&& snippet == "!"
|
||||||
{
|
{
|
||||||
feature_err(
|
feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
|
||||||
&sess.parse_sess,
|
.emit();
|
||||||
sym::never_patterns,
|
|
||||||
span,
|
|
||||||
"`!` patterns are experimental",
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
} else {
|
} else {
|
||||||
let suggestion = span.shrink_to_hi();
|
let suggestion = span.shrink_to_hi();
|
||||||
sess.emit_err(errors::MatchArmWithNoBody { span, suggestion });
|
sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,7 +588,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||||||
|
|
||||||
if !visitor.features.negative_bounds {
|
if !visitor.features.negative_bounds {
|
||||||
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
|
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
|
||||||
sess.emit_err(errors::NegativeBoundUnsupported { span });
|
sess.dcx().emit_err(errors::NegativeBoundUnsupported { span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,7 +678,11 @@ fn check_incompatible_features(sess: &Session, features: &Features) {
|
|||||||
if let Some((f2_name, f2_span)) = declared_features.clone().find(|(name, _)| name == f2)
|
if let Some((f2_name, f2_span)) = declared_features.clone().find(|(name, _)| name == f2)
|
||||||
{
|
{
|
||||||
let spans = vec![f1_span, f2_span];
|
let spans = vec![f1_span, f2_span];
|
||||||
sess.emit_err(errors::IncompatibleFeatures { spans, f1: f1_name, f2: f2_name });
|
sess.dcx().emit_err(errors::IncompatibleFeatures {
|
||||||
|
spans,
|
||||||
|
f1: f1_name,
|
||||||
|
f2: f2_name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(iter_is_partitioned)]
|
#![feature(iter_is_partitioned)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![recursion_limit = "256"]
|
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
|
||||||
|
|||||||
@ -38,21 +38,21 @@ struct ShowSpanVisitor<'a> {
|
|||||||
impl<'a> Visitor<'a> for ShowSpanVisitor<'a> {
|
impl<'a> Visitor<'a> for ShowSpanVisitor<'a> {
|
||||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||||
if let Mode::Expression = self.mode {
|
if let Mode::Expression = self.mode {
|
||||||
self.dcx.emit_warning(errors::ShowSpan { span: e.span, msg: "expression" });
|
self.dcx.emit_warn(errors::ShowSpan { span: e.span, msg: "expression" });
|
||||||
}
|
}
|
||||||
visit::walk_expr(self, e);
|
visit::walk_expr(self, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_pat(&mut self, p: &'a ast::Pat) {
|
fn visit_pat(&mut self, p: &'a ast::Pat) {
|
||||||
if let Mode::Pattern = self.mode {
|
if let Mode::Pattern = self.mode {
|
||||||
self.dcx.emit_warning(errors::ShowSpan { span: p.span, msg: "pattern" });
|
self.dcx.emit_warn(errors::ShowSpan { span: p.span, msg: "pattern" });
|
||||||
}
|
}
|
||||||
visit::walk_pat(self, p);
|
visit::walk_pat(self, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: &'a ast::Ty) {
|
fn visit_ty(&mut self, t: &'a ast::Ty) {
|
||||||
if let Mode::Type = self.mode {
|
if let Mode::Type = self.mode {
|
||||||
self.dcx.emit_warning(errors::ShowSpan { span: t.span, msg: "type" });
|
self.dcx.emit_warn(errors::ShowSpan { span: t.span, msg: "type" });
|
||||||
}
|
}
|
||||||
visit::walk_ty(self, t);
|
visit::walk_ty(self, t);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![recursion_limit = "256"]
|
|
||||||
|
|
||||||
mod helpers;
|
mod helpers;
|
||||||
pub mod pp;
|
pub mod pp;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
|
|||||||
use rustc_ast::util::parser;
|
use rustc_ast::util::parser;
|
||||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
|
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
|
||||||
use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
|
use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
|
||||||
use rustc_ast::{GenericArg, GenericBound, SelfKind, TraitBoundModifier};
|
use rustc_ast::{GenericArg, GenericBound, SelfKind};
|
||||||
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
@ -160,6 +160,10 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
|
|||||||
use TokenTree::Delimited as Del;
|
use TokenTree::Delimited as Del;
|
||||||
use TokenTree::Token as Tok;
|
use TokenTree::Token as Tok;
|
||||||
|
|
||||||
|
fn is_punct(tt: &TokenTree) -> bool {
|
||||||
|
matches!(tt, TokenTree::Token(tok, _) if tok.is_punct())
|
||||||
|
}
|
||||||
|
|
||||||
// Each match arm has one or more examples in comments. The default is to
|
// Each match arm has one or more examples in comments. The default is to
|
||||||
// insert space between adjacent tokens, except for the cases listed in
|
// insert space between adjacent tokens, except for the cases listed in
|
||||||
// this match.
|
// this match.
|
||||||
@ -167,24 +171,35 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
|
|||||||
// No space after line doc comments.
|
// No space after line doc comments.
|
||||||
(Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false,
|
(Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false,
|
||||||
|
|
||||||
// `.` + ANYTHING: `x.y`, `tup.0`
|
// `.` + NON-PUNCT: `x.y`, `tup.0`
|
||||||
// `$` + ANYTHING: `$e`
|
(Tok(Token { kind: Dot, .. }, _), tt2) if !is_punct(tt2) => false,
|
||||||
(Tok(Token { kind: Dot | Dollar, .. }, _), _) => false,
|
|
||||||
|
|
||||||
// ANYTHING + `,`: `foo,`
|
// `$` + IDENT: `$e`
|
||||||
// ANYTHING + `.`: `x.y`, `tup.0`
|
(Tok(Token { kind: Dollar, .. }, _), Tok(Token { kind: Ident(..), .. }, _)) => false,
|
||||||
// ANYTHING + `!`: `foo! { ... }`
|
|
||||||
//
|
|
||||||
// FIXME: Incorrect cases:
|
|
||||||
// - Logical not: `x =! y`, `if! x { f(); }`
|
|
||||||
// - Never type: `Fn() ->!`
|
|
||||||
(_, Tok(Token { kind: Comma | Dot | Not, .. }, _)) => false,
|
|
||||||
|
|
||||||
// IDENT + `(`: `f(3)`
|
// NON-PUNCT + `,`: `foo,`
|
||||||
//
|
// NON-PUNCT + `;`: `x = 3;`, `[T; 3]`
|
||||||
// FIXME: Incorrect cases:
|
// NON-PUNCT + `.`: `x.y`, `tup.0`
|
||||||
// - Let: `let(a, b) = (1, 2)`
|
(tt1, Tok(Token { kind: Comma | Semi | Dot, .. }, _)) if !is_punct(tt1) => false,
|
||||||
(Tok(Token { kind: Ident(..), .. }, _), Del(_, _, Parenthesis, _)) => false,
|
|
||||||
|
// IDENT + `!`: `println!()`, but `if !x { ... }` needs a space after the `if`
|
||||||
|
(Tok(Token { kind: Ident(sym, is_raw), span }, _), Tok(Token { kind: Not, .. }, _))
|
||||||
|
if !Ident::new(*sym, *span).is_reserved() || *is_raw =>
|
||||||
|
{
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDENT|`fn`|`Self`|`pub` + `(`: `f(3)`, `fn(x: u8)`, `Self()`, `pub(crate)`,
|
||||||
|
// but `let (a, b) = (1, 2)` needs a space after the `let`
|
||||||
|
(Tok(Token { kind: Ident(sym, is_raw), span }, _), Del(_, _, Parenthesis, _))
|
||||||
|
if !Ident::new(*sym, *span).is_reserved()
|
||||||
|
|| *sym == kw::Fn
|
||||||
|
|| *sym == kw::SelfUpper
|
||||||
|
|| *sym == kw::Pub
|
||||||
|
|| *is_raw =>
|
||||||
|
{
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
// `#` + `[`: `#[attr]`
|
// `#` + `[`: `#[attr]`
|
||||||
(Tok(Token { kind: Pound, .. }, _), Del(_, _, Bracket, _)) => false,
|
(Tok(Token { kind: Pound, .. }, _), Del(_, _, Bracket, _)) => false,
|
||||||
@ -1096,14 +1111,22 @@ impl<'a> State<'a> {
|
|||||||
ast::StmtKind::Item(item) => self.print_item(item),
|
ast::StmtKind::Item(item) => self.print_item(item),
|
||||||
ast::StmtKind::Expr(expr) => {
|
ast::StmtKind::Expr(expr) => {
|
||||||
self.space_if_not_bol();
|
self.space_if_not_bol();
|
||||||
self.print_expr_outer_attr_style(expr, false, FixupContext::default());
|
self.print_expr_outer_attr_style(
|
||||||
|
expr,
|
||||||
|
false,
|
||||||
|
FixupContext { stmt: true, ..FixupContext::default() },
|
||||||
|
);
|
||||||
if classify::expr_requires_semi_to_be_stmt(expr) {
|
if classify::expr_requires_semi_to_be_stmt(expr) {
|
||||||
self.word(";");
|
self.word(";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::StmtKind::Semi(expr) => {
|
ast::StmtKind::Semi(expr) => {
|
||||||
self.space_if_not_bol();
|
self.space_if_not_bol();
|
||||||
self.print_expr_outer_attr_style(expr, false, FixupContext::default());
|
self.print_expr_outer_attr_style(
|
||||||
|
expr,
|
||||||
|
false,
|
||||||
|
FixupContext { stmt: true, ..FixupContext::default() },
|
||||||
|
);
|
||||||
self.word(";");
|
self.word(";");
|
||||||
}
|
}
|
||||||
ast::StmtKind::Empty => {
|
ast::StmtKind::Empty => {
|
||||||
@ -1155,7 +1178,11 @@ impl<'a> State<'a> {
|
|||||||
ast::StmtKind::Expr(expr) if i == blk.stmts.len() - 1 => {
|
ast::StmtKind::Expr(expr) if i == blk.stmts.len() - 1 => {
|
||||||
self.maybe_print_comment(st.span.lo());
|
self.maybe_print_comment(st.span.lo());
|
||||||
self.space_if_not_bol();
|
self.space_if_not_bol();
|
||||||
self.print_expr_outer_attr_style(expr, false, FixupContext::default());
|
self.print_expr_outer_attr_style(
|
||||||
|
expr,
|
||||||
|
false,
|
||||||
|
FixupContext { stmt: true, ..FixupContext::default() },
|
||||||
|
);
|
||||||
self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
|
self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
|
||||||
}
|
}
|
||||||
_ => self.print_stmt(st),
|
_ => self.print_stmt(st),
|
||||||
@ -1427,7 +1454,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
self.nbsp();
|
self.nbsp();
|
||||||
self.word("{");
|
self.word("{");
|
||||||
let empty = fields.is_empty() && !etc;
|
let empty = fields.is_empty() && *etc == ast::PatFieldsRest::None;
|
||||||
if !empty {
|
if !empty {
|
||||||
self.space();
|
self.space();
|
||||||
}
|
}
|
||||||
@ -1445,7 +1472,7 @@ impl<'a> State<'a> {
|
|||||||
},
|
},
|
||||||
|f| f.pat.span,
|
|f| f.pat.span,
|
||||||
);
|
);
|
||||||
if *etc {
|
if *etc == ast::PatFieldsRest::Rest {
|
||||||
if !fields.is_empty() {
|
if !fields.is_empty() {
|
||||||
self.word_space(",");
|
self.word_space(",");
|
||||||
}
|
}
|
||||||
@ -1507,6 +1534,11 @@ impl<'a> State<'a> {
|
|||||||
self.pclose();
|
self.pclose();
|
||||||
}
|
}
|
||||||
PatKind::MacCall(m) => self.print_mac(m),
|
PatKind::MacCall(m) => self.print_mac(m),
|
||||||
|
PatKind::Err(_) => {
|
||||||
|
self.popen();
|
||||||
|
self.word("/*ERROR*/");
|
||||||
|
self.pclose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.ann.post(self, AnnNode::Pat(pat))
|
self.ann.post(self, AnnNode::Pat(pat))
|
||||||
}
|
}
|
||||||
@ -1559,26 +1591,20 @@ impl<'a> State<'a> {
|
|||||||
|
|
||||||
match bound {
|
match bound {
|
||||||
GenericBound::Trait(tref, modifier) => {
|
GenericBound::Trait(tref, modifier) => {
|
||||||
match modifier {
|
match modifier.constness {
|
||||||
TraitBoundModifier::None => {}
|
ast::BoundConstness::Never => {}
|
||||||
TraitBoundModifier::Negative => {
|
ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => {
|
||||||
self.word("!");
|
self.word_space(modifier.constness.as_str());
|
||||||
}
|
|
||||||
TraitBoundModifier::Maybe => {
|
|
||||||
self.word("?");
|
|
||||||
}
|
|
||||||
TraitBoundModifier::MaybeConst(_) => {
|
|
||||||
self.word_space("~const");
|
|
||||||
}
|
|
||||||
TraitBoundModifier::MaybeConstNegative => {
|
|
||||||
self.word_space("~const");
|
|
||||||
self.word("!");
|
|
||||||
}
|
|
||||||
TraitBoundModifier::MaybeConstMaybe => {
|
|
||||||
self.word_space("~const");
|
|
||||||
self.word("?");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match modifier.polarity {
|
||||||
|
ast::BoundPolarity::Positive => {}
|
||||||
|
ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => {
|
||||||
|
self.word(modifier.polarity.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.print_poly_trait_ref(tref);
|
self.print_poly_trait_ref(tref);
|
||||||
}
|
}
|
||||||
GenericBound::Outlives(lt) => self.print_lifetime(*lt),
|
GenericBound::Outlives(lt) => self.print_lifetime(*lt),
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
use crate::pp::Breaks::Inconsistent;
|
use crate::pp::Breaks::Inconsistent;
|
||||||
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
||||||
|
use ast::ForLoopKind;
|
||||||
use itertools::{Itertools, Position};
|
use itertools::{Itertools, Position};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token;
|
use rustc_ast::token;
|
||||||
|
use rustc_ast::util::classify;
|
||||||
use rustc_ast::util::literal::escape_byte_str_symbol;
|
use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||||
use rustc_ast::util::parser::{self, AssocOp, Fixity};
|
use rustc_ast::util::parser::{self, AssocOp, Fixity};
|
||||||
use rustc_ast::{self as ast, BlockCheckMode};
|
use rustc_ast::{self as ast, BlockCheckMode};
|
||||||
@ -14,6 +16,61 @@ use std::fmt::Write;
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub(crate) struct FixupContext {
|
pub(crate) struct FixupContext {
|
||||||
|
/// Print expression such that it can be parsed back as a statement
|
||||||
|
/// consisting of the original expression.
|
||||||
|
///
|
||||||
|
/// The effect of this is for binary operators in statement position to set
|
||||||
|
/// `leftmost_subexpression_in_stmt` when printing their left-hand operand.
|
||||||
|
///
|
||||||
|
/// ```ignore (illustrative)
|
||||||
|
/// (match x {}) - 1; // match needs parens when LHS of binary operator
|
||||||
|
///
|
||||||
|
/// match x {}; // not when its own statement
|
||||||
|
/// ```
|
||||||
|
pub stmt: bool,
|
||||||
|
|
||||||
|
/// This is the difference between:
|
||||||
|
///
|
||||||
|
/// ```ignore (illustrative)
|
||||||
|
/// (match x {}) - 1; // subexpression needs parens
|
||||||
|
///
|
||||||
|
/// let _ = match x {} - 1; // no parens
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// There are 3 distinguishable contexts in which `print_expr` might be
|
||||||
|
/// called with the expression `$match` as its argument, where `$match`
|
||||||
|
/// represents an expression of kind `ExprKind::Match`:
|
||||||
|
///
|
||||||
|
/// - stmt=false leftmost_subexpression_in_stmt=false
|
||||||
|
///
|
||||||
|
/// Example: `let _ = $match - 1;`
|
||||||
|
///
|
||||||
|
/// No parentheses required.
|
||||||
|
///
|
||||||
|
/// - stmt=false leftmost_subexpression_in_stmt=true
|
||||||
|
///
|
||||||
|
/// Example: `$match - 1;`
|
||||||
|
///
|
||||||
|
/// Must parenthesize `($match)`, otherwise parsing back the output as a
|
||||||
|
/// statement would terminate the statement after the closing brace of
|
||||||
|
/// the match, parsing `-1;` as a separate statement.
|
||||||
|
///
|
||||||
|
/// - stmt=true leftmost_subexpression_in_stmt=false
|
||||||
|
///
|
||||||
|
/// Example: `$match;`
|
||||||
|
///
|
||||||
|
/// No parentheses required.
|
||||||
|
pub leftmost_subexpression_in_stmt: bool,
|
||||||
|
|
||||||
|
/// This is the difference between:
|
||||||
|
///
|
||||||
|
/// ```ignore (illustrative)
|
||||||
|
/// if let _ = (Struct {}) {} // needs parens
|
||||||
|
///
|
||||||
|
/// match () {
|
||||||
|
/// () if let _ = Struct {} => {} // no parens
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
pub parenthesize_exterior_struct_lit: bool,
|
pub parenthesize_exterior_struct_lit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +78,11 @@ pub(crate) struct FixupContext {
|
|||||||
/// in a targetted fashion where needed.
|
/// in a targetted fashion where needed.
|
||||||
impl Default for FixupContext {
|
impl Default for FixupContext {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
FixupContext { parenthesize_exterior_struct_lit: false }
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: false,
|
||||||
|
parenthesize_exterior_struct_lit: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +136,8 @@ impl<'a> State<'a> {
|
|||||||
/// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
|
/// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
|
||||||
/// `if cond { ... }`.
|
/// `if cond { ... }`.
|
||||||
fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
|
fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
|
||||||
let fixup = FixupContext { parenthesize_exterior_struct_lit: true };
|
let fixup =
|
||||||
|
FixupContext { parenthesize_exterior_struct_lit: true, ..FixupContext::default() };
|
||||||
self.print_expr_cond_paren(expr, Self::cond_needs_par(expr), fixup)
|
self.print_expr_cond_paren(expr, Self::cond_needs_par(expr), fixup)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,26 +160,25 @@ impl<'a> State<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
needs_par: bool,
|
needs_par: bool,
|
||||||
fixup: FixupContext,
|
mut fixup: FixupContext,
|
||||||
) {
|
) {
|
||||||
if needs_par {
|
if needs_par {
|
||||||
self.popen();
|
self.popen();
|
||||||
|
|
||||||
|
// If we are surrounding the whole cond in parentheses, such as:
|
||||||
|
//
|
||||||
|
// if (return Struct {}) {}
|
||||||
|
//
|
||||||
|
// then there is no need for parenthesizing the individual struct
|
||||||
|
// expressions within. On the other hand if the whole cond is not
|
||||||
|
// parenthesized, then print_expr must parenthesize exterior struct
|
||||||
|
// literals.
|
||||||
|
//
|
||||||
|
// if x == (Struct {}) {}
|
||||||
|
//
|
||||||
|
fixup = FixupContext::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are surrounding the whole cond in parentheses, such as:
|
|
||||||
//
|
|
||||||
// if (return Struct {}) {}
|
|
||||||
//
|
|
||||||
// then there is no need for parenthesizing the individual struct
|
|
||||||
// expressions within. On the other hand if the whole cond is not
|
|
||||||
// parenthesized, then print_expr must parenthesize exterior struct
|
|
||||||
// literals.
|
|
||||||
//
|
|
||||||
// if x == (Struct {}) {}
|
|
||||||
//
|
|
||||||
let fixup = FixupContext {
|
|
||||||
parenthesize_exterior_struct_lit: fixup.parenthesize_exterior_struct_lit && !needs_par,
|
|
||||||
};
|
|
||||||
self.print_expr(expr, fixup);
|
self.print_expr(expr, fixup);
|
||||||
|
|
||||||
if needs_par {
|
if needs_par {
|
||||||
@ -233,7 +294,32 @@ impl<'a> State<'a> {
|
|||||||
_ => parser::PREC_POSTFIX,
|
_ => parser::PREC_POSTFIX,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.print_expr_maybe_paren(func, prec, fixup);
|
// Independent of parenthesization related to precedence, we must
|
||||||
|
// parenthesize `func` if this is a statement context in which without
|
||||||
|
// parentheses, a statement boundary would occur inside `func` or
|
||||||
|
// immediately after `func`.
|
||||||
|
//
|
||||||
|
// Suppose `func` represents `match () { _ => f }`. We must produce:
|
||||||
|
//
|
||||||
|
// (match () { _ => f })();
|
||||||
|
//
|
||||||
|
// instead of:
|
||||||
|
//
|
||||||
|
// match () { _ => f } ();
|
||||||
|
//
|
||||||
|
// because the latter is valid syntax but with the incorrect meaning.
|
||||||
|
// It's a match-expression followed by tuple-expression, not a function
|
||||||
|
// call.
|
||||||
|
self.print_expr_maybe_paren(
|
||||||
|
func,
|
||||||
|
prec,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: fixup.stmt || fixup.leftmost_subexpression_in_stmt,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
self.print_call_post(args)
|
self.print_call_post(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +330,17 @@ impl<'a> State<'a> {
|
|||||||
base_args: &[P<ast::Expr>],
|
base_args: &[P<ast::Expr>],
|
||||||
fixup: FixupContext,
|
fixup: FixupContext,
|
||||||
) {
|
) {
|
||||||
|
// Unlike in `print_expr_call`, no change to fixup here because
|
||||||
|
// statement boundaries never occur in front of a `.` (or `?`) token.
|
||||||
|
//
|
||||||
|
// match () { _ => f }.method();
|
||||||
|
//
|
||||||
|
// Parenthesizing only for precedence and not with regard to statement
|
||||||
|
// boundaries, `$receiver.method()` can be parsed back as a statement
|
||||||
|
// containing an expression if and only if `$receiver` can be parsed as
|
||||||
|
// a statement containing an expression.
|
||||||
self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX, fixup);
|
||||||
|
|
||||||
self.word(".");
|
self.word(".");
|
||||||
self.print_ident(segment.ident);
|
self.print_ident(segment.ident);
|
||||||
if let Some(args) = &segment.args {
|
if let Some(args) = &segment.args {
|
||||||
@ -288,22 +384,36 @@ impl<'a> State<'a> {
|
|||||||
(&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => {
|
(&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => {
|
||||||
parser::PREC_FORCE_PAREN
|
parser::PREC_FORCE_PAREN
|
||||||
}
|
}
|
||||||
// For a binary expression like `(match () { _ => a }) OP b`, the parens are required
|
|
||||||
// otherwise the parser would interpret `match () { _ => a }` as a statement,
|
|
||||||
// with the remaining `OP b` not making sense. So we force parens.
|
|
||||||
(&ast::ExprKind::Match(..), _) => parser::PREC_FORCE_PAREN,
|
|
||||||
_ => left_prec,
|
_ => left_prec,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.print_expr_maybe_paren(lhs, left_prec, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
lhs,
|
||||||
|
left_prec,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: fixup.stmt || fixup.leftmost_subexpression_in_stmt,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space(op.node.as_str());
|
self.word_space(op.node.as_str());
|
||||||
self.print_expr_maybe_paren(rhs, right_prec, fixup)
|
|
||||||
|
self.print_expr_maybe_paren(
|
||||||
|
rhs,
|
||||||
|
right_prec,
|
||||||
|
FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, ..fixup },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) {
|
fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) {
|
||||||
self.word(op.as_str());
|
self.word(op.as_str());
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup)
|
self.print_expr_maybe_paren(
|
||||||
|
expr,
|
||||||
|
parser::PREC_PREFIX,
|
||||||
|
FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, ..fixup },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_addr_of(
|
fn print_expr_addr_of(
|
||||||
@ -321,7 +431,11 @@ impl<'a> State<'a> {
|
|||||||
self.print_mutability(mutability, true);
|
self.print_mutability(mutability, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup)
|
self.print_expr_maybe_paren(
|
||||||
|
expr,
|
||||||
|
parser::PREC_PREFIX,
|
||||||
|
FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, ..fixup },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn print_expr(&mut self, expr: &ast::Expr, fixup: FixupContext) {
|
pub(super) fn print_expr(&mut self, expr: &ast::Expr, fixup: FixupContext) {
|
||||||
@ -332,7 +446,7 @@ impl<'a> State<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
is_inline: bool,
|
is_inline: bool,
|
||||||
fixup: FixupContext,
|
mut fixup: FixupContext,
|
||||||
) {
|
) {
|
||||||
self.maybe_print_comment(expr.span.lo());
|
self.maybe_print_comment(expr.span.lo());
|
||||||
|
|
||||||
@ -344,7 +458,27 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.ibox(INDENT_UNIT);
|
self.ibox(INDENT_UNIT);
|
||||||
|
|
||||||
|
// The Match subexpression in `match x {} - 1` must be parenthesized if
|
||||||
|
// it is the leftmost subexpression in a statement:
|
||||||
|
//
|
||||||
|
// (match x {}) - 1;
|
||||||
|
//
|
||||||
|
// But not otherwise:
|
||||||
|
//
|
||||||
|
// let _ = match x {} - 1;
|
||||||
|
//
|
||||||
|
// Same applies to a small set of other expression kinds which eagerly
|
||||||
|
// terminate a statement which opens with them.
|
||||||
|
let needs_par =
|
||||||
|
fixup.leftmost_subexpression_in_stmt && !classify::expr_requires_semi_to_be_stmt(expr);
|
||||||
|
if needs_par {
|
||||||
|
self.popen();
|
||||||
|
fixup = FixupContext::default();
|
||||||
|
}
|
||||||
|
|
||||||
self.ann.pre(self, AnnNode::Expr(expr));
|
self.ann.pre(self, AnnNode::Expr(expr));
|
||||||
|
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
ast::ExprKind::Array(exprs) => {
|
ast::ExprKind::Array(exprs) => {
|
||||||
self.print_expr_vec(exprs);
|
self.print_expr_vec(exprs);
|
||||||
@ -385,7 +519,16 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
ast::ExprKind::Cast(expr, ty) => {
|
ast::ExprKind::Cast(expr, ty) => {
|
||||||
let prec = AssocOp::As.precedence() as i8;
|
let prec = AssocOp::As.precedence() as i8;
|
||||||
self.print_expr_maybe_paren(expr, prec, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
expr,
|
||||||
|
prec,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: fixup.stmt
|
||||||
|
|| fixup.leftmost_subexpression_in_stmt,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("as");
|
self.word_space("as");
|
||||||
self.print_type(ty);
|
self.print_type(ty);
|
||||||
@ -418,20 +561,23 @@ impl<'a> State<'a> {
|
|||||||
self.space();
|
self.space();
|
||||||
self.print_block_with_attrs(blk, attrs);
|
self.print_block_with_attrs(blk, attrs);
|
||||||
}
|
}
|
||||||
ast::ExprKind::ForLoop(pat, iter, blk, opt_label) => {
|
ast::ExprKind::ForLoop { pat, iter, body, label, kind } => {
|
||||||
if let Some(label) = opt_label {
|
if let Some(label) = label {
|
||||||
self.print_ident(label.ident);
|
self.print_ident(label.ident);
|
||||||
self.word_space(":");
|
self.word_space(":");
|
||||||
}
|
}
|
||||||
self.cbox(0);
|
self.cbox(0);
|
||||||
self.ibox(0);
|
self.ibox(0);
|
||||||
self.word_nbsp("for");
|
self.word_nbsp("for");
|
||||||
|
if kind == &ForLoopKind::ForAwait {
|
||||||
|
self.word_nbsp("await");
|
||||||
|
}
|
||||||
self.print_pat(pat);
|
self.print_pat(pat);
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("in");
|
self.word_space("in");
|
||||||
self.print_expr_as_cond(iter);
|
self.print_expr_as_cond(iter);
|
||||||
self.space();
|
self.space();
|
||||||
self.print_block_with_attrs(blk, attrs);
|
self.print_block_with_attrs(body, attrs);
|
||||||
}
|
}
|
||||||
ast::ExprKind::Loop(blk, opt_label, _) => {
|
ast::ExprKind::Loop(blk, opt_label, _) => {
|
||||||
if let Some(label) = opt_label {
|
if let Some(label) = opt_label {
|
||||||
@ -504,31 +650,71 @@ impl<'a> State<'a> {
|
|||||||
self.print_block_with_attrs(blk, attrs);
|
self.print_block_with_attrs(blk, attrs);
|
||||||
}
|
}
|
||||||
ast::ExprKind::Await(expr, _) => {
|
ast::ExprKind::Await(expr, _) => {
|
||||||
|
// Same fixups as ExprKind::MethodCall.
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
||||||
self.word(".await");
|
self.word(".await");
|
||||||
}
|
}
|
||||||
ast::ExprKind::Assign(lhs, rhs, _) => {
|
ast::ExprKind::Assign(lhs, rhs, _) => {
|
||||||
|
// Same fixups as ExprKind::Binary.
|
||||||
let prec = AssocOp::Assign.precedence() as i8;
|
let prec = AssocOp::Assign.precedence() as i8;
|
||||||
self.print_expr_maybe_paren(lhs, prec + 1, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
lhs,
|
||||||
|
prec + 1,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: fixup.stmt
|
||||||
|
|| fixup.leftmost_subexpression_in_stmt,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_expr_maybe_paren(rhs, prec, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
rhs,
|
||||||
|
prec,
|
||||||
|
FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, ..fixup },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ast::ExprKind::AssignOp(op, lhs, rhs) => {
|
ast::ExprKind::AssignOp(op, lhs, rhs) => {
|
||||||
|
// Same fixups as ExprKind::Binary.
|
||||||
let prec = AssocOp::Assign.precedence() as i8;
|
let prec = AssocOp::Assign.precedence() as i8;
|
||||||
self.print_expr_maybe_paren(lhs, prec + 1, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
lhs,
|
||||||
|
prec + 1,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: fixup.stmt
|
||||||
|
|| fixup.leftmost_subexpression_in_stmt,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
self.space();
|
self.space();
|
||||||
self.word(op.node.as_str());
|
self.word(op.node.as_str());
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_expr_maybe_paren(rhs, prec, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
rhs,
|
||||||
|
prec,
|
||||||
|
FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, ..fixup },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ast::ExprKind::Field(expr, ident) => {
|
ast::ExprKind::Field(expr, ident) => {
|
||||||
|
// Same fixups as ExprKind::MethodCall.
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
||||||
self.word(".");
|
self.word(".");
|
||||||
self.print_ident(*ident);
|
self.print_ident(*ident);
|
||||||
}
|
}
|
||||||
ast::ExprKind::Index(expr, index, _) => {
|
ast::ExprKind::Index(expr, index, _) => {
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
// Same fixups as ExprKind::Call.
|
||||||
|
self.print_expr_maybe_paren(
|
||||||
|
expr,
|
||||||
|
parser::PREC_POSTFIX,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: fixup.stmt
|
||||||
|
|| fixup.leftmost_subexpression_in_stmt,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
self.word("[");
|
self.word("[");
|
||||||
self.print_expr(index, FixupContext::default());
|
self.print_expr(index, FixupContext::default());
|
||||||
self.word("]");
|
self.word("]");
|
||||||
@ -540,14 +726,31 @@ impl<'a> State<'a> {
|
|||||||
// a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
|
// a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
|
||||||
let fake_prec = AssocOp::LOr.precedence() as i8;
|
let fake_prec = AssocOp::LOr.precedence() as i8;
|
||||||
if let Some(e) = start {
|
if let Some(e) = start {
|
||||||
self.print_expr_maybe_paren(e, fake_prec, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
e,
|
||||||
|
fake_prec,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: fixup.stmt
|
||||||
|
|| fixup.leftmost_subexpression_in_stmt,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
match limits {
|
match limits {
|
||||||
ast::RangeLimits::HalfOpen => self.word(".."),
|
ast::RangeLimits::HalfOpen => self.word(".."),
|
||||||
ast::RangeLimits::Closed => self.word("..="),
|
ast::RangeLimits::Closed => self.word("..="),
|
||||||
}
|
}
|
||||||
if let Some(e) = end {
|
if let Some(e) = end {
|
||||||
self.print_expr_maybe_paren(e, fake_prec, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
e,
|
||||||
|
fake_prec,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: false,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Underscore => self.word("_"),
|
ast::ExprKind::Underscore => self.word("_"),
|
||||||
@ -561,7 +764,15 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
if let Some(expr) = opt_expr {
|
if let Some(expr) = opt_expr {
|
||||||
self.space();
|
self.space();
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
expr,
|
||||||
|
parser::PREC_JUMP,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: false,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Continue(opt_label) => {
|
ast::ExprKind::Continue(opt_label) => {
|
||||||
@ -575,7 +786,15 @@ impl<'a> State<'a> {
|
|||||||
self.word("return");
|
self.word("return");
|
||||||
if let Some(expr) = result {
|
if let Some(expr) = result {
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
expr,
|
||||||
|
parser::PREC_JUMP,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: false,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Yeet(result) => {
|
ast::ExprKind::Yeet(result) => {
|
||||||
@ -584,13 +803,25 @@ impl<'a> State<'a> {
|
|||||||
self.word("yeet");
|
self.word("yeet");
|
||||||
if let Some(expr) = result {
|
if let Some(expr) = result {
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
expr,
|
||||||
|
parser::PREC_JUMP,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: false,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Become(result) => {
|
ast::ExprKind::Become(result) => {
|
||||||
self.word("become");
|
self.word("become");
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
self.print_expr_maybe_paren(result, parser::PREC_JUMP, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
result,
|
||||||
|
parser::PREC_JUMP,
|
||||||
|
FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, ..fixup },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ast::ExprKind::InlineAsm(a) => {
|
ast::ExprKind::InlineAsm(a) => {
|
||||||
// FIXME: This should have its own syntax, distinct from a macro invocation.
|
// FIXME: This should have its own syntax, distinct from a macro invocation.
|
||||||
@ -640,10 +871,19 @@ impl<'a> State<'a> {
|
|||||||
|
|
||||||
if let Some(expr) = e {
|
if let Some(expr) = e {
|
||||||
self.space();
|
self.space();
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup);
|
self.print_expr_maybe_paren(
|
||||||
|
expr,
|
||||||
|
parser::PREC_JUMP,
|
||||||
|
FixupContext {
|
||||||
|
stmt: false,
|
||||||
|
leftmost_subexpression_in_stmt: false,
|
||||||
|
..fixup
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Try(e) => {
|
ast::ExprKind::Try(e) => {
|
||||||
|
// Same fixups as ExprKind::MethodCall.
|
||||||
self.print_expr_maybe_paren(e, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(e, parser::PREC_POSTFIX, fixup);
|
||||||
self.word("?")
|
self.word("?")
|
||||||
}
|
}
|
||||||
@ -659,7 +899,13 @@ impl<'a> State<'a> {
|
|||||||
self.pclose()
|
self.pclose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ann.post(self, AnnNode::Expr(expr));
|
self.ann.post(self, AnnNode::Expr(expr));
|
||||||
|
|
||||||
|
if needs_par {
|
||||||
|
self.pclose();
|
||||||
|
}
|
||||||
|
|
||||||
self.end();
|
self.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,7 +946,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.end(); // Close the ibox for the pattern.
|
self.end(); // Close the ibox for the pattern.
|
||||||
self.print_expr(body, FixupContext::default());
|
self.print_expr(body, FixupContext { stmt: true, ..FixupContext::default() });
|
||||||
self.word(",");
|
self.word(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
|||||||
use ast::StaticItem;
|
use ast::StaticItem;
|
||||||
use itertools::{Itertools, Position};
|
use itertools::{Itertools, Position};
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::GenericBound;
|
|
||||||
use rustc_ast::ModKind;
|
use rustc_ast::ModKind;
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
|
|
||||||
@ -338,19 +337,9 @@ impl<'a> State<'a> {
|
|||||||
self.word_nbsp("trait");
|
self.word_nbsp("trait");
|
||||||
self.print_ident(item.ident);
|
self.print_ident(item.ident);
|
||||||
self.print_generic_params(&generics.params);
|
self.print_generic_params(&generics.params);
|
||||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
if !bounds.is_empty() {
|
||||||
for b in bounds.iter() {
|
|
||||||
if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
|
|
||||||
self.space();
|
|
||||||
self.word_space("for ?");
|
|
||||||
self.print_trait_ref(&ptr.trait_ref);
|
|
||||||
} else {
|
|
||||||
real_bounds.push(b.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !real_bounds.is_empty() {
|
|
||||||
self.word_nbsp(":");
|
self.word_nbsp(":");
|
||||||
self.print_type_bounds(&real_bounds);
|
self.print_type_bounds(bounds);
|
||||||
}
|
}
|
||||||
self.print_where_clause(&generics.where_clause);
|
self.print_where_clause(&generics.where_clause);
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
@ -387,6 +376,9 @@ impl<'a> State<'a> {
|
|||||||
state.print_visibility(&item.vis)
|
state.print_visibility(&item.vis)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
ast::ItemKind::Delegation(box delegation) => {
|
||||||
|
self.print_delegation(delegation, &item.vis, &item.attrs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.ann.post(self, AnnNode::Item(item))
|
self.ann.post(self, AnnNode::Item(item))
|
||||||
}
|
}
|
||||||
@ -565,10 +557,38 @@ impl<'a> State<'a> {
|
|||||||
self.word(";");
|
self.word(";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::AssocItemKind::Delegation(box delegation) => {
|
||||||
|
self.print_delegation(delegation, vis, &item.attrs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.ann.post(self, AnnNode::SubItem(id))
|
self.ann.post(self, AnnNode::SubItem(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn print_delegation(
|
||||||
|
&mut self,
|
||||||
|
delegation: &ast::Delegation,
|
||||||
|
vis: &ast::Visibility,
|
||||||
|
attrs: &[ast::Attribute],
|
||||||
|
) {
|
||||||
|
if delegation.body.is_some() {
|
||||||
|
self.head("");
|
||||||
|
}
|
||||||
|
self.print_visibility(vis);
|
||||||
|
self.word_space("reuse");
|
||||||
|
|
||||||
|
if let Some(qself) = &delegation.qself {
|
||||||
|
self.print_qpath(&delegation.path, qself, false);
|
||||||
|
} else {
|
||||||
|
self.print_path(&delegation.path, false, 0);
|
||||||
|
}
|
||||||
|
if let Some(body) = &delegation.body {
|
||||||
|
self.nbsp();
|
||||||
|
self.print_block_with_attrs(body, attrs);
|
||||||
|
} else {
|
||||||
|
self.word(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn print_fn_full(
|
fn print_fn_full(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig: &ast::FnSig,
|
sig: &ast::FnSig,
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use rustc_macros::HashStable_Generic;
|
|||||||
use rustc_session::config::ExpectedValues;
|
use rustc_session::config::ExpectedValues;
|
||||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||||
use rustc_session::parse::{feature_err, ParseSess};
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_session::{RustcVersion, Session};
|
use rustc_session::{RustcVersion, Session};
|
||||||
use rustc_span::hygiene::Transparency;
|
use rustc_span::hygiene::Transparency;
|
||||||
use rustc_span::{symbol::sym, symbol::Symbol, Span};
|
use rustc_span::{symbol::sym, symbol::Symbol, Span};
|
||||||
@ -207,7 +207,8 @@ pub fn find_stability(
|
|||||||
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
|
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
|
||||||
sym::unstable => {
|
sym::unstable => {
|
||||||
if stab.is_some() {
|
if stab.is_some() {
|
||||||
sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
sess.dcx()
|
||||||
|
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +218,8 @@ pub fn find_stability(
|
|||||||
}
|
}
|
||||||
sym::stable => {
|
sym::stable => {
|
||||||
if stab.is_some() {
|
if stab.is_some() {
|
||||||
sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
sess.dcx()
|
||||||
|
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||||
@ -238,7 +240,8 @@ pub fn find_stability(
|
|||||||
_,
|
_,
|
||||||
)) => *allowed_through_unstable_modules = true,
|
)) => *allowed_through_unstable_modules = true,
|
||||||
_ => {
|
_ => {
|
||||||
sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
|
sess.dcx()
|
||||||
|
.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +264,8 @@ pub fn find_const_stability(
|
|||||||
sym::rustc_promotable => promotable = true,
|
sym::rustc_promotable => promotable = true,
|
||||||
sym::rustc_const_unstable => {
|
sym::rustc_const_unstable => {
|
||||||
if const_stab.is_some() {
|
if const_stab.is_some() {
|
||||||
sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
sess.dcx()
|
||||||
|
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +276,8 @@ pub fn find_const_stability(
|
|||||||
}
|
}
|
||||||
sym::rustc_const_stable => {
|
sym::rustc_const_stable => {
|
||||||
if const_stab.is_some() {
|
if const_stab.is_some() {
|
||||||
sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
sess.dcx()
|
||||||
|
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||||
@ -288,7 +293,11 @@ pub fn find_const_stability(
|
|||||||
if promotable {
|
if promotable {
|
||||||
match &mut const_stab {
|
match &mut const_stab {
|
||||||
Some((stab, _)) => stab.promotable = promotable,
|
Some((stab, _)) => stab.promotable = promotable,
|
||||||
_ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
|
_ => {
|
||||||
|
_ = sess
|
||||||
|
.dcx()
|
||||||
|
.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +315,8 @@ pub fn find_body_stability(
|
|||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if attr.has_name(sym::rustc_default_body_unstable) {
|
if attr.has_name(sym::rustc_default_body_unstable) {
|
||||||
if body_stab.is_some() {
|
if body_stab.is_some() {
|
||||||
sess.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
sess.dcx()
|
||||||
|
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +331,7 @@ pub fn find_body_stability(
|
|||||||
|
|
||||||
fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -> Option<()> {
|
fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -> Option<()> {
|
||||||
if item.is_some() {
|
if item.is_some() {
|
||||||
sess.emit_err(session_diagnostics::MultipleItem {
|
sess.dcx().emit_err(session_diagnostics::MultipleItem {
|
||||||
span: meta.span,
|
span: meta.span,
|
||||||
item: pprust::path_to_string(&meta.path),
|
item: pprust::path_to_string(&meta.path),
|
||||||
});
|
});
|
||||||
@ -330,7 +340,7 @@ fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -
|
|||||||
*item = Some(v);
|
*item = Some(v);
|
||||||
Some(())
|
Some(())
|
||||||
} else {
|
} else {
|
||||||
sess.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
sess.dcx().emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,7 +355,7 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
|
|||||||
let mut since = None;
|
let mut since = None;
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
let Some(mi) = meta.meta_item() else {
|
let Some(mi) = meta.meta_item() else {
|
||||||
sess.emit_err(session_diagnostics::UnsupportedLiteral {
|
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
|
||||||
span: meta.span(),
|
span: meta.span(),
|
||||||
reason: UnsupportedLiteralReason::Generic,
|
reason: UnsupportedLiteralReason::Generic,
|
||||||
is_bytestr: false,
|
is_bytestr: false,
|
||||||
@ -358,7 +368,7 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
|
|||||||
sym::feature => insert_or_error(sess, mi, &mut feature)?,
|
sym::feature => insert_or_error(sess, mi, &mut feature)?,
|
||||||
sym::since => insert_or_error(sess, mi, &mut since)?,
|
sym::since => insert_or_error(sess, mi, &mut since)?,
|
||||||
_ => {
|
_ => {
|
||||||
sess.emit_err(session_diagnostics::UnknownMetaItem {
|
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
|
||||||
span: meta.span(),
|
span: meta.span(),
|
||||||
item: pprust::path_to_string(&mi.path),
|
item: pprust::path_to_string(&mi.path),
|
||||||
expected: &["feature", "since"],
|
expected: &["feature", "since"],
|
||||||
@ -371,9 +381,9 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
|
|||||||
let feature = match feature {
|
let feature = match feature {
|
||||||
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
||||||
Some(_bad_feature) => {
|
Some(_bad_feature) => {
|
||||||
Err(sess.emit_err(session_diagnostics::NonIdentFeature { span: attr.span }))
|
Err(sess.dcx().emit_err(session_diagnostics::NonIdentFeature { span: attr.span }))
|
||||||
}
|
}
|
||||||
None => Err(sess.emit_err(session_diagnostics::MissingFeature { span: attr.span })),
|
None => Err(sess.dcx().emit_err(session_diagnostics::MissingFeature { span: attr.span })),
|
||||||
};
|
};
|
||||||
|
|
||||||
let since = if let Some(since) = since {
|
let since = if let Some(since) = since {
|
||||||
@ -382,11 +392,11 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
|
|||||||
} else if let Some(version) = parse_version(since) {
|
} else if let Some(version) = parse_version(since) {
|
||||||
StableSince::Version(version)
|
StableSince::Version(version)
|
||||||
} else {
|
} else {
|
||||||
sess.emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
||||||
StableSince::Err
|
StableSince::Err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
|
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span });
|
||||||
StableSince::Err
|
StableSince::Err
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -413,7 +423,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
|
|||||||
let mut implied_by = None;
|
let mut implied_by = None;
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
let Some(mi) = meta.meta_item() else {
|
let Some(mi) = meta.meta_item() else {
|
||||||
sess.emit_err(session_diagnostics::UnsupportedLiteral {
|
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
|
||||||
span: meta.span(),
|
span: meta.span(),
|
||||||
reason: UnsupportedLiteralReason::Generic,
|
reason: UnsupportedLiteralReason::Generic,
|
||||||
is_bytestr: false,
|
is_bytestr: false,
|
||||||
@ -435,7 +445,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
|
|||||||
issue => match issue.parse::<NonZeroU32>() {
|
issue => match issue.parse::<NonZeroU32>() {
|
||||||
Ok(num) => Some(num),
|
Ok(num) => Some(num),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
sess.emit_err(
|
sess.dcx().emit_err(
|
||||||
session_diagnostics::InvalidIssueString {
|
session_diagnostics::InvalidIssueString {
|
||||||
span: mi.span,
|
span: mi.span,
|
||||||
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
||||||
@ -451,13 +461,13 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
|
|||||||
}
|
}
|
||||||
sym::soft => {
|
sym::soft => {
|
||||||
if !mi.is_word() {
|
if !mi.is_word() {
|
||||||
sess.emit_err(session_diagnostics::SoftNoArgs { span: mi.span });
|
sess.dcx().emit_err(session_diagnostics::SoftNoArgs { span: mi.span });
|
||||||
}
|
}
|
||||||
is_soft = true;
|
is_soft = true;
|
||||||
}
|
}
|
||||||
sym::implied_by => insert_or_error(sess, mi, &mut implied_by)?,
|
sym::implied_by => insert_or_error(sess, mi, &mut implied_by)?,
|
||||||
_ => {
|
_ => {
|
||||||
sess.emit_err(session_diagnostics::UnknownMetaItem {
|
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
|
||||||
span: meta.span(),
|
span: meta.span(),
|
||||||
item: pprust::path_to_string(&mi.path),
|
item: pprust::path_to_string(&mi.path),
|
||||||
expected: &["feature", "reason", "issue", "soft", "implied_by"],
|
expected: &["feature", "reason", "issue", "soft", "implied_by"],
|
||||||
@ -470,13 +480,13 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
|
|||||||
let feature = match feature {
|
let feature = match feature {
|
||||||
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
||||||
Some(_bad_feature) => {
|
Some(_bad_feature) => {
|
||||||
Err(sess.emit_err(session_diagnostics::NonIdentFeature { span: attr.span }))
|
Err(sess.dcx().emit_err(session_diagnostics::NonIdentFeature { span: attr.span }))
|
||||||
}
|
}
|
||||||
None => Err(sess.emit_err(session_diagnostics::MissingFeature { span: attr.span })),
|
None => Err(sess.dcx().emit_err(session_diagnostics::MissingFeature { span: attr.span })),
|
||||||
};
|
};
|
||||||
|
|
||||||
let issue =
|
let issue = issue
|
||||||
issue.ok_or_else(|| sess.emit_err(session_diagnostics::MissingIssue { span: attr.span }));
|
.ok_or_else(|| sess.dcx().emit_err(session_diagnostics::MissingIssue { span: attr.span }));
|
||||||
|
|
||||||
match (feature, issue) {
|
match (feature, issue) {
|
||||||
(Ok(feature), Ok(_)) => {
|
(Ok(feature), Ok(_)) => {
|
||||||
@ -508,15 +518,15 @@ pub struct Condition {
|
|||||||
/// Tests if a cfg-pattern matches the cfg set
|
/// Tests if a cfg-pattern matches the cfg set
|
||||||
pub fn cfg_matches(
|
pub fn cfg_matches(
|
||||||
cfg: &ast::MetaItem,
|
cfg: &ast::MetaItem,
|
||||||
sess: &ParseSess,
|
sess: &Session,
|
||||||
lint_node_id: NodeId,
|
lint_node_id: NodeId,
|
||||||
features: Option<&Features>,
|
features: Option<&Features>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
eval_condition(cfg, sess, features, &mut |cfg| {
|
eval_condition(cfg, sess, features, &mut |cfg| {
|
||||||
try_gate_cfg(cfg.name, cfg.span, sess, features);
|
try_gate_cfg(cfg.name, cfg.span, sess, features);
|
||||||
match sess.check_config.expecteds.get(&cfg.name) {
|
match sess.parse_sess.check_config.expecteds.get(&cfg.name) {
|
||||||
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
|
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
|
||||||
sess.buffer_lint_with_diagnostic(
|
sess.parse_sess.buffer_lint_with_diagnostic(
|
||||||
UNEXPECTED_CFGS,
|
UNEXPECTED_CFGS,
|
||||||
cfg.span,
|
cfg.span,
|
||||||
lint_node_id,
|
lint_node_id,
|
||||||
@ -531,8 +541,8 @@ pub fn cfg_matches(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
None if sess.check_config.exhaustive_names => {
|
None if sess.parse_sess.check_config.exhaustive_names => {
|
||||||
sess.buffer_lint_with_diagnostic(
|
sess.parse_sess.buffer_lint_with_diagnostic(
|
||||||
UNEXPECTED_CFGS,
|
UNEXPECTED_CFGS,
|
||||||
cfg.span,
|
cfg.span,
|
||||||
lint_node_id,
|
lint_node_id,
|
||||||
@ -545,18 +555,18 @@ pub fn cfg_matches(
|
|||||||
}
|
}
|
||||||
_ => { /* not unexpected */ }
|
_ => { /* not unexpected */ }
|
||||||
}
|
}
|
||||||
sess.config.contains(&(cfg.name, cfg.value))
|
sess.parse_sess.config.contains(&(cfg.name, cfg.value))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) {
|
fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
|
||||||
let gate = find_gated_cfg(|sym| sym == name);
|
let gate = find_gated_cfg(|sym| sym == name);
|
||||||
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
||||||
gate_cfg(gated_cfg, span, sess, feats);
|
gate_cfg(gated_cfg, span, sess, feats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) {
|
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
|
||||||
let (cfg, feature, has_feature) = gated_cfg;
|
let (cfg, feature, has_feature) = gated_cfg;
|
||||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||||
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
||||||
@ -584,10 +594,11 @@ fn parse_version(s: Symbol) -> Option<RustcVersion> {
|
|||||||
/// evaluate individual items.
|
/// evaluate individual items.
|
||||||
pub fn eval_condition(
|
pub fn eval_condition(
|
||||||
cfg: &ast::MetaItem,
|
cfg: &ast::MetaItem,
|
||||||
sess: &ParseSess,
|
sess: &Session,
|
||||||
features: Option<&Features>,
|
features: Option<&Features>,
|
||||||
eval: &mut impl FnMut(Condition) -> bool,
|
eval: &mut impl FnMut(Condition) -> bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let dcx = &sess.parse_sess.dcx;
|
||||||
match &cfg.kind {
|
match &cfg.kind {
|
||||||
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
||||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||||
@ -599,23 +610,23 @@ pub fn eval_condition(
|
|||||||
NestedMetaItem::Lit(MetaItemLit { span, .. })
|
NestedMetaItem::Lit(MetaItemLit { span, .. })
|
||||||
| NestedMetaItem::MetaItem(MetaItem { span, .. }),
|
| NestedMetaItem::MetaItem(MetaItem { span, .. }),
|
||||||
] => {
|
] => {
|
||||||
sess.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
|
dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
[..] => {
|
[..] => {
|
||||||
sess.emit_err(session_diagnostics::ExpectedSingleVersionLiteral {
|
dcx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral {
|
||||||
span: cfg.span,
|
span: cfg.span,
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let Some(min_version) = parse_version(*min_version) else {
|
let Some(min_version) = parse_version(*min_version) else {
|
||||||
sess.emit_warning(session_diagnostics::UnknownVersionLiteral { span: *span });
|
dcx.emit_warn(session_diagnostics::UnknownVersionLiteral { span: *span });
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||||
if sess.assume_incomplete_release {
|
if sess.parse_sess.assume_incomplete_release {
|
||||||
RustcVersion::CURRENT > min_version
|
RustcVersion::CURRENT > min_version
|
||||||
} else {
|
} else {
|
||||||
RustcVersion::CURRENT >= min_version
|
RustcVersion::CURRENT >= min_version
|
||||||
@ -624,7 +635,7 @@ pub fn eval_condition(
|
|||||||
ast::MetaItemKind::List(mis) => {
|
ast::MetaItemKind::List(mis) => {
|
||||||
for mi in mis.iter() {
|
for mi in mis.iter() {
|
||||||
if !mi.is_meta_item() {
|
if !mi.is_meta_item() {
|
||||||
sess.emit_err(session_diagnostics::UnsupportedLiteral {
|
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||||
span: mi.span(),
|
span: mi.span(),
|
||||||
reason: UnsupportedLiteralReason::Generic,
|
reason: UnsupportedLiteralReason::Generic,
|
||||||
is_bytestr: false,
|
is_bytestr: false,
|
||||||
@ -653,9 +664,7 @@ pub fn eval_condition(
|
|||||||
}),
|
}),
|
||||||
sym::not => {
|
sym::not => {
|
||||||
if mis.len() != 1 {
|
if mis.len() != 1 {
|
||||||
sess.emit_err(session_diagnostics::ExpectedOneCfgPattern {
|
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
||||||
span: cfg.span,
|
|
||||||
});
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,7 +693,7 @@ pub fn eval_condition(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
sess.emit_err(session_diagnostics::InvalidPredicate {
|
dcx.emit_err(session_diagnostics::InvalidPredicate {
|
||||||
span: cfg.span,
|
span: cfg.span,
|
||||||
predicate: pprust::path_to_string(&cfg.path),
|
predicate: pprust::path_to_string(&cfg.path),
|
||||||
});
|
});
|
||||||
@ -693,11 +702,11 @@ pub fn eval_condition(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
|
ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
|
||||||
sess.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
|
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
|
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
|
||||||
sess.emit_err(session_diagnostics::UnsupportedLiteral {
|
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||||
span: lit.span,
|
span: lit.span,
|
||||||
reason: UnsupportedLiteralReason::CfgString,
|
reason: UnsupportedLiteralReason::CfgString,
|
||||||
is_bytestr: lit.kind.is_bytestr(),
|
is_bytestr: lit.kind.is_bytestr(),
|
||||||
@ -791,7 +800,7 @@ pub fn find_deprecation(
|
|||||||
MetaItemKind::List(list) => {
|
MetaItemKind::List(list) => {
|
||||||
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||||
if item.is_some() {
|
if item.is_some() {
|
||||||
sess.emit_err(session_diagnostics::MultipleItem {
|
sess.dcx().emit_err(session_diagnostics::MultipleItem {
|
||||||
span: meta.span,
|
span: meta.span,
|
||||||
item: pprust::path_to_string(&meta.path),
|
item: pprust::path_to_string(&meta.path),
|
||||||
});
|
});
|
||||||
@ -802,14 +811,14 @@ pub fn find_deprecation(
|
|||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
if let Some(lit) = meta.name_value_literal() {
|
if let Some(lit) = meta.name_value_literal() {
|
||||||
sess.emit_err(session_diagnostics::UnsupportedLiteral {
|
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
|
||||||
span: lit.span,
|
span: lit.span,
|
||||||
reason: UnsupportedLiteralReason::DeprecatedString,
|
reason: UnsupportedLiteralReason::DeprecatedString,
|
||||||
is_bytestr: lit.kind.is_bytestr(),
|
is_bytestr: lit.kind.is_bytestr(),
|
||||||
start_point_span: sess.source_map().start_point(lit.span),
|
start_point_span: sess.source_map().start_point(lit.span),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
sess.emit_err(session_diagnostics::IncorrectMetaItem {
|
sess.dcx().emit_err(session_diagnostics::IncorrectMetaItem {
|
||||||
span: meta.span,
|
span: meta.span,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -833,11 +842,13 @@ pub fn find_deprecation(
|
|||||||
}
|
}
|
||||||
sym::suggestion => {
|
sym::suggestion => {
|
||||||
if !features.deprecated_suggestion {
|
if !features.deprecated_suggestion {
|
||||||
sess.emit_err(session_diagnostics::DeprecatedItemSuggestion {
|
sess.dcx().emit_err(
|
||||||
span: mi.span,
|
session_diagnostics::DeprecatedItemSuggestion {
|
||||||
is_nightly: sess.is_nightly_build().then_some(()),
|
span: mi.span,
|
||||||
details: (),
|
is_nightly: sess.is_nightly_build().then_some(()),
|
||||||
});
|
details: (),
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !get(mi, &mut suggestion) {
|
if !get(mi, &mut suggestion) {
|
||||||
@ -845,7 +856,7 @@ pub fn find_deprecation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
sess.emit_err(session_diagnostics::UnknownMetaItem {
|
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
|
||||||
span: meta.span(),
|
span: meta.span(),
|
||||||
item: pprust::path_to_string(&mi.path),
|
item: pprust::path_to_string(&mi.path),
|
||||||
expected: if features.deprecated_suggestion {
|
expected: if features.deprecated_suggestion {
|
||||||
@ -858,7 +869,7 @@ pub fn find_deprecation(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
NestedMetaItem::Lit(lit) => {
|
NestedMetaItem::Lit(lit) => {
|
||||||
sess.emit_err(session_diagnostics::UnsupportedLiteral {
|
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
|
||||||
span: lit.span,
|
span: lit.span,
|
||||||
reason: UnsupportedLiteralReason::DeprecatedKvPair,
|
reason: UnsupportedLiteralReason::DeprecatedKvPair,
|
||||||
is_bytestr: false,
|
is_bytestr: false,
|
||||||
@ -879,18 +890,18 @@ pub fn find_deprecation(
|
|||||||
} else if let Some(version) = parse_version(since) {
|
} else if let Some(version) = parse_version(since) {
|
||||||
DeprecatedSince::RustcVersion(version)
|
DeprecatedSince::RustcVersion(version)
|
||||||
} else {
|
} else {
|
||||||
sess.emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
||||||
DeprecatedSince::Err
|
DeprecatedSince::Err
|
||||||
}
|
}
|
||||||
} else if is_rustc {
|
} else if is_rustc {
|
||||||
sess.emit_err(session_diagnostics::MissingSince { span: attr.span });
|
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span });
|
||||||
DeprecatedSince::Err
|
DeprecatedSince::Err
|
||||||
} else {
|
} else {
|
||||||
DeprecatedSince::Unspecified
|
DeprecatedSince::Unspecified
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_rustc && note.is_none() {
|
if is_rustc && note.is_none() {
|
||||||
sess.emit_err(session_diagnostics::MissingNote { span: attr.span });
|
sess.dcx().emit_err(session_diagnostics::MissingNote { span: attr.span });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -945,7 +956,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||||||
assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}");
|
assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}");
|
||||||
use ReprAttr::*;
|
use ReprAttr::*;
|
||||||
let mut acc = Vec::new();
|
let mut acc = Vec::new();
|
||||||
let diagnostic = sess.dcx();
|
let dcx = sess.dcx();
|
||||||
|
|
||||||
if let Some(items) = attr.meta_item_list() {
|
if let Some(items) = attr.meta_item_list() {
|
||||||
for item in items {
|
for item in items {
|
||||||
@ -958,7 +969,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||||||
sym::simd => Some(ReprSimd),
|
sym::simd => Some(ReprSimd),
|
||||||
sym::transparent => Some(ReprTransparent),
|
sym::transparent => Some(ReprTransparent),
|
||||||
sym::align => {
|
sym::align => {
|
||||||
sess.emit_err(session_diagnostics::InvalidReprAlignNeedArg {
|
sess.dcx().emit_err(session_diagnostics::InvalidReprAlignNeedArg {
|
||||||
span: item.span(),
|
span: item.span(),
|
||||||
});
|
});
|
||||||
recognised = true;
|
recognised = true;
|
||||||
@ -989,13 +1000,13 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||||||
|| int_type_of_word(name).is_some()
|
|| int_type_of_word(name).is_some()
|
||||||
{
|
{
|
||||||
recognised = true;
|
recognised = true;
|
||||||
sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
|
sess.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen {
|
||||||
span: item.span(),
|
span: item.span(),
|
||||||
name: name.to_ident_string(),
|
name: name.to_ident_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(literal_error) = literal_error {
|
if let Some(literal_error) = literal_error {
|
||||||
sess.emit_err(session_diagnostics::InvalidReprGeneric {
|
sess.dcx().emit_err(session_diagnostics::InvalidReprGeneric {
|
||||||
span: item.span(),
|
span: item.span(),
|
||||||
repr_arg: name.to_ident_string(),
|
repr_arg: name.to_ident_string(),
|
||||||
error_part: literal_error,
|
error_part: literal_error,
|
||||||
@ -1007,7 +1018,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||||||
if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
|
if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
|
||||||
let name = meta_item.name_or_empty().to_ident_string();
|
let name = meta_item.name_or_empty().to_ident_string();
|
||||||
recognised = true;
|
recognised = true;
|
||||||
sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
|
sess.dcx().emit_err(session_diagnostics::IncorrectReprFormatGeneric {
|
||||||
span: item.span(),
|
span: item.span(),
|
||||||
repr_arg: &name,
|
repr_arg: &name,
|
||||||
cause: IncorrectReprFormatGenericCause::from_lit_kind(
|
cause: IncorrectReprFormatGenericCause::from_lit_kind(
|
||||||
@ -1022,7 +1033,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||||
{
|
{
|
||||||
recognised = true;
|
recognised = true;
|
||||||
sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
|
sess.dcx().emit_err(session_diagnostics::InvalidReprHintNoValue {
|
||||||
span: meta_item.span,
|
span: meta_item.span,
|
||||||
name: meta_item.name_or_empty().to_ident_string(),
|
name: meta_item.name_or_empty().to_ident_string(),
|
||||||
});
|
});
|
||||||
@ -1031,12 +1042,14 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||||||
MetaItemKind::List(_) => {
|
MetaItemKind::List(_) => {
|
||||||
if meta_item.has_name(sym::align) {
|
if meta_item.has_name(sym::align) {
|
||||||
recognised = true;
|
recognised = true;
|
||||||
sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
|
sess.dcx().emit_err(
|
||||||
span: meta_item.span,
|
session_diagnostics::IncorrectReprFormatAlignOneArg {
|
||||||
});
|
span: meta_item.span,
|
||||||
|
},
|
||||||
|
);
|
||||||
} else if meta_item.has_name(sym::packed) {
|
} else if meta_item.has_name(sym::packed) {
|
||||||
recognised = true;
|
recognised = true;
|
||||||
sess.emit_err(
|
sess.dcx().emit_err(
|
||||||
session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
|
session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
|
||||||
span: meta_item.span,
|
span: meta_item.span,
|
||||||
},
|
},
|
||||||
@ -1047,7 +1060,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||||
{
|
{
|
||||||
recognised = true;
|
recognised = true;
|
||||||
sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
|
sess.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen {
|
||||||
span: meta_item.span,
|
span: meta_item.span,
|
||||||
name: meta_item.name_or_empty().to_ident_string(),
|
name: meta_item.name_or_empty().to_ident_string(),
|
||||||
});
|
});
|
||||||
@ -1062,7 +1075,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||||||
// (e.g. if we only pretty-print the source), so we have to gate
|
// (e.g. if we only pretty-print the source), so we have to gate
|
||||||
// the `span_delayed_bug` call as follows:
|
// the `span_delayed_bug` call as follows:
|
||||||
if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
|
if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
|
||||||
diagnostic.span_delayed_bug(item.span(), "unrecognized representation hint");
|
dcx.span_delayed_bug(item.span(), "unrecognized representation hint");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1149,7 +1162,7 @@ fn allow_unstable<'a>(
|
|||||||
let list = attrs
|
let list = attrs
|
||||||
.filter_map(move |attr| {
|
.filter_map(move |attr| {
|
||||||
attr.meta_item_list().or_else(|| {
|
attr.meta_item_list().or_else(|| {
|
||||||
sess.emit_err(session_diagnostics::ExpectsFeatureList {
|
sess.dcx().emit_err(session_diagnostics::ExpectsFeatureList {
|
||||||
span: attr.span,
|
span: attr.span,
|
||||||
name: symbol.to_ident_string(),
|
name: symbol.to_ident_string(),
|
||||||
});
|
});
|
||||||
@ -1161,7 +1174,7 @@ fn allow_unstable<'a>(
|
|||||||
list.into_iter().filter_map(move |it| {
|
list.into_iter().filter_map(move |it| {
|
||||||
let name = it.ident().map(|ident| ident.name);
|
let name = it.ident().map(|ident| ident.name);
|
||||||
if name.is_none() {
|
if name.is_none() {
|
||||||
sess.emit_err(session_diagnostics::ExpectsFeatures {
|
sess.dcx().emit_err(session_diagnostics::ExpectsFeatures {
|
||||||
span: it.span(),
|
span: it.span(),
|
||||||
name: symbol.to_ident_string(),
|
name: symbol.to_ident_string(),
|
||||||
});
|
});
|
||||||
@ -1172,9 +1185,9 @@ fn allow_unstable<'a>(
|
|||||||
|
|
||||||
pub fn parse_alignment(node: &ast::LitKind) -> Result<u32, &'static str> {
|
pub fn parse_alignment(node: &ast::LitKind) -> Result<u32, &'static str> {
|
||||||
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
|
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
|
||||||
if literal.is_power_of_two() {
|
if literal.get().is_power_of_two() {
|
||||||
// rustc_middle::ty::layout::Align restricts align to <= 2^29
|
// rustc_middle::ty::layout::Align restricts align to <= 2^29
|
||||||
if *literal <= 1 << 29 { Ok(*literal as u32) } else { Err("larger than 2^29") }
|
if *literal <= 1 << 29 { Ok(literal.get() as u32) } else { Err("larger than 2^29") }
|
||||||
} else {
|
} else {
|
||||||
Err("not a power of two")
|
Err("not a power of two")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use std::num::IntErrorKind;
|
|||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
|
codes::*, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
|
||||||
};
|
};
|
||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::Diagnostic;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
@ -11,14 +11,14 @@ use crate::fluent_generated as fluent;
|
|||||||
use crate::UnsupportedLiteralReason;
|
use crate::UnsupportedLiteralReason;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_expected_one_cfg_pattern, code = "E0536")]
|
#[diag(attr_expected_one_cfg_pattern, code = E0536)]
|
||||||
pub(crate) struct ExpectedOneCfgPattern {
|
pub(crate) struct ExpectedOneCfgPattern {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_invalid_predicate, code = "E0537")]
|
#[diag(attr_invalid_predicate, code = E0537)]
|
||||||
pub(crate) struct InvalidPredicate {
|
pub(crate) struct InvalidPredicate {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -27,7 +27,7 @@ pub(crate) struct InvalidPredicate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_multiple_item, code = "E0538")]
|
#[diag(attr_multiple_item, code = E0538)]
|
||||||
pub(crate) struct MultipleItem {
|
pub(crate) struct MultipleItem {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -36,7 +36,7 @@ pub(crate) struct MultipleItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_incorrect_meta_item, code = "E0539")]
|
#[diag(attr_incorrect_meta_item, code = E0539)]
|
||||||
pub(crate) struct IncorrectMetaItem {
|
pub(crate) struct IncorrectMetaItem {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -50,44 +50,41 @@ pub(crate) struct UnknownMetaItem<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Manual implementation to be able to format `expected` items correctly.
|
// Manual implementation to be able to format `expected` items correctly.
|
||||||
impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
|
||||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||||
let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
|
let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
|
||||||
let mut diag = dcx.struct_span_err_with_code(
|
DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item)
|
||||||
self.span,
|
.with_span(self.span)
|
||||||
fluent::attr_unknown_meta_item,
|
.with_code(E0541)
|
||||||
error_code!(E0541),
|
.with_arg("item", self.item)
|
||||||
);
|
.with_arg("expected", expected.join(", "))
|
||||||
diag.set_arg("item", self.item);
|
.with_span_label(self.span, fluent::attr_label)
|
||||||
diag.set_arg("expected", expected.join(", "));
|
|
||||||
diag.span_label(self.span, fluent::attr_label);
|
|
||||||
diag
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_missing_since, code = "E0542")]
|
#[diag(attr_missing_since, code = E0542)]
|
||||||
pub(crate) struct MissingSince {
|
pub(crate) struct MissingSince {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_missing_note, code = "E0543")]
|
#[diag(attr_missing_note, code = E0543)]
|
||||||
pub(crate) struct MissingNote {
|
pub(crate) struct MissingNote {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_multiple_stability_levels, code = "E0544")]
|
#[diag(attr_multiple_stability_levels, code = E0544)]
|
||||||
pub(crate) struct MultipleStabilityLevels {
|
pub(crate) struct MultipleStabilityLevels {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_invalid_issue_string, code = "E0545")]
|
#[diag(attr_invalid_issue_string, code = E0545)]
|
||||||
pub(crate) struct InvalidIssueString {
|
pub(crate) struct InvalidIssueString {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -145,21 +142,21 @@ impl InvalidIssueStringCause {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_missing_feature, code = "E0546")]
|
#[diag(attr_missing_feature, code = E0546)]
|
||||||
pub(crate) struct MissingFeature {
|
pub(crate) struct MissingFeature {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_non_ident_feature, code = "E0546")]
|
#[diag(attr_non_ident_feature, code = E0546)]
|
||||||
pub(crate) struct NonIdentFeature {
|
pub(crate) struct NonIdentFeature {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_missing_issue, code = "E0547")]
|
#[diag(attr_missing_issue, code = E0547)]
|
||||||
pub(crate) struct MissingIssue {
|
pub(crate) struct MissingIssue {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -168,14 +165,14 @@ pub(crate) struct MissingIssue {
|
|||||||
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
|
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
|
||||||
// It is more similar to `IncorrectReprFormatGeneric`.
|
// It is more similar to `IncorrectReprFormatGeneric`.
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
|
#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)]
|
||||||
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
|
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_invalid_repr_hint_no_paren, code = "E0552")]
|
#[diag(attr_invalid_repr_hint_no_paren, code = E0552)]
|
||||||
pub(crate) struct InvalidReprHintNoParen {
|
pub(crate) struct InvalidReprHintNoParen {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -184,7 +181,7 @@ pub(crate) struct InvalidReprHintNoParen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_invalid_repr_hint_no_value, code = "E0552")]
|
#[diag(attr_invalid_repr_hint_no_value, code = E0552)]
|
||||||
pub(crate) struct InvalidReprHintNoValue {
|
pub(crate) struct InvalidReprHintNoValue {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -200,10 +197,11 @@ pub(crate) struct UnsupportedLiteral {
|
|||||||
pub start_point_span: Span,
|
pub start_point_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral {
|
||||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||||
let mut diag = dcx.struct_span_err_with_code(
|
let mut diag = DiagnosticBuilder::new(
|
||||||
self.span,
|
dcx,
|
||||||
|
level,
|
||||||
match self.reason {
|
match self.reason {
|
||||||
UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
|
UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
|
||||||
UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
|
UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
|
||||||
@ -214,8 +212,9 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
|||||||
fluent::attr_unsupported_literal_deprecated_kv_pair
|
fluent::attr_unsupported_literal_deprecated_kv_pair
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error_code!(E0565),
|
|
||||||
);
|
);
|
||||||
|
diag.span(self.span);
|
||||||
|
diag.code(E0565);
|
||||||
if self.is_bytestr {
|
if self.is_bytestr {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
self.start_point_span,
|
self.start_point_span,
|
||||||
@ -229,7 +228,7 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_invalid_repr_align_need_arg, code = "E0589")]
|
#[diag(attr_invalid_repr_align_need_arg, code = E0589)]
|
||||||
pub(crate) struct InvalidReprAlignNeedArg {
|
pub(crate) struct InvalidReprAlignNeedArg {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[suggestion(code = "align(...)", applicability = "has-placeholders")]
|
#[suggestion(code = "align(...)", applicability = "has-placeholders")]
|
||||||
@ -237,7 +236,7 @@ pub(crate) struct InvalidReprAlignNeedArg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_invalid_repr_generic, code = "E0589")]
|
#[diag(attr_invalid_repr_generic, code = E0589)]
|
||||||
pub(crate) struct InvalidReprGeneric<'a> {
|
pub(crate) struct InvalidReprGeneric<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -247,14 +246,14 @@ pub(crate) struct InvalidReprGeneric<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_incorrect_repr_format_align_one_arg, code = "E0693")]
|
#[diag(attr_incorrect_repr_format_align_one_arg, code = E0693)]
|
||||||
pub(crate) struct IncorrectReprFormatAlignOneArg {
|
pub(crate) struct IncorrectReprFormatAlignOneArg {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_incorrect_repr_format_generic, code = "E0693")]
|
#[diag(attr_incorrect_repr_format_generic, code = E0693)]
|
||||||
pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -296,7 +295,7 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
|
|||||||
pub fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> {
|
pub fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> {
|
||||||
match kind {
|
match kind {
|
||||||
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
|
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
|
||||||
Some(Self::Int { span, name, int: *int })
|
Some(Self::Int { span, name, int: int.get() })
|
||||||
}
|
}
|
||||||
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
|
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -305,14 +304,14 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_rustc_promotable_pairing, code = "E0717")]
|
#[diag(attr_rustc_promotable_pairing, code = E0717)]
|
||||||
pub(crate) struct RustcPromotablePairing {
|
pub(crate) struct RustcPromotablePairing {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_rustc_allowed_unstable_pairing, code = "E0789")]
|
#[diag(attr_rustc_allowed_unstable_pairing, code = E0789)]
|
||||||
pub(crate) struct RustcAllowedUnstablePairing {
|
pub(crate) struct RustcAllowedUnstablePairing {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
use rustc_errors::{
|
use rustc_errors::{codes::*, struct_span_code_err, DiagCtxt, DiagnosticBuilder};
|
||||||
struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
|
||||||
};
|
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
|
pub fn dcx(&self) -> &'tcx DiagCtxt {
|
||||||
|
self.infcx.dcx()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_move_when_borrowed(
|
pub(crate) fn cannot_move_when_borrowed(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -12,8 +14,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
place: &str,
|
place: &str,
|
||||||
borrow_place: &str,
|
borrow_place: &str,
|
||||||
value_place: &str,
|
value_place: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow {
|
self.dcx().create_err(crate::session_diagnostics::MoveBorrow {
|
||||||
place,
|
place,
|
||||||
span,
|
span,
|
||||||
borrow_place,
|
borrow_place,
|
||||||
@ -28,18 +30,16 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
desc: &str,
|
desc: &str,
|
||||||
borrow_span: Span,
|
borrow_span: Span,
|
||||||
borrow_desc: &str,
|
borrow_desc: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let mut err = struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0503,
|
E0503,
|
||||||
"cannot use {} because it was mutably borrowed",
|
"cannot use {} because it was mutably borrowed",
|
||||||
desc,
|
desc,
|
||||||
);
|
)
|
||||||
|
.with_span_label(borrow_span, format!("{borrow_desc} is borrowed here"))
|
||||||
err.span_label(borrow_span, format!("{borrow_desc} is borrowed here"));
|
.with_span_label(span, format!("use of borrowed {borrow_desc}"))
|
||||||
err.span_label(span, format!("use of borrowed {borrow_desc}"));
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_mutably_borrow_multiply(
|
pub(crate) fn cannot_mutably_borrow_multiply(
|
||||||
@ -50,10 +50,10 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
old_loan_span: Span,
|
old_loan_span: Span,
|
||||||
old_opt_via: &str,
|
old_opt_via: &str,
|
||||||
old_load_end_span: Option<Span>,
|
old_load_end_span: Option<Span>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
new_loan_span,
|
new_loan_span,
|
||||||
E0499,
|
E0499,
|
||||||
"cannot borrow {}{} as mutable more than once at a time",
|
"cannot borrow {}{} as mutable more than once at a time",
|
||||||
@ -97,9 +97,9 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
desc: &str,
|
desc: &str,
|
||||||
old_loan_span: Span,
|
old_loan_span: Span,
|
||||||
old_load_end_span: Option<Span>,
|
old_load_end_span: Option<Span>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
new_loan_span,
|
new_loan_span,
|
||||||
E0524,
|
E0524,
|
||||||
"two closures require unique access to {} at the same time",
|
"two closures require unique access to {} at the same time",
|
||||||
@ -130,9 +130,9 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
noun_old: &str,
|
noun_old: &str,
|
||||||
old_opt_via: &str,
|
old_opt_via: &str,
|
||||||
previous_end_span: Option<Span>,
|
previous_end_span: Option<Span>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
new_loan_span,
|
new_loan_span,
|
||||||
E0500,
|
E0500,
|
||||||
"closure requires unique access to {} but {} is already borrowed{}",
|
"closure requires unique access to {} but {} is already borrowed{}",
|
||||||
@ -162,9 +162,9 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
old_opt_via: &str,
|
old_opt_via: &str,
|
||||||
previous_end_span: Option<Span>,
|
previous_end_span: Option<Span>,
|
||||||
second_borrow_desc: &str,
|
second_borrow_desc: &str,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
new_loan_span,
|
new_loan_span,
|
||||||
E0501,
|
E0501,
|
||||||
"cannot borrow {}{} as {} because previous closure requires unique access",
|
"cannot borrow {}{} as {} because previous closure requires unique access",
|
||||||
@ -194,10 +194,10 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
kind_old: &str,
|
kind_old: &str,
|
||||||
msg_old: &str,
|
msg_old: &str,
|
||||||
old_load_end_span: Option<Span>,
|
old_load_end_span: Option<Span>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0502,
|
E0502,
|
||||||
"cannot borrow {}{} as {} because {} is also borrowed as {}{}",
|
"cannot borrow {}{} as {} because {} is also borrowed as {}{}",
|
||||||
@ -235,18 +235,16 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
borrow_span: Span,
|
borrow_span: Span,
|
||||||
desc: &str,
|
desc: &str,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let mut err = struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0506,
|
E0506,
|
||||||
"cannot assign to {} because it is borrowed",
|
"cannot assign to {} because it is borrowed",
|
||||||
desc,
|
desc,
|
||||||
);
|
)
|
||||||
|
.with_span_label(borrow_span, format!("{desc} is borrowed here"))
|
||||||
err.span_label(borrow_span, format!("{desc} is borrowed here"));
|
.with_span_label(span, format!("{desc} is assigned to here but it was already borrowed"))
|
||||||
err.span_label(span, format!("{desc} is assigned to here but it was already borrowed"));
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_reassign_immutable(
|
pub(crate) fn cannot_reassign_immutable(
|
||||||
@ -254,25 +252,27 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
desc: &str,
|
desc: &str,
|
||||||
is_arg: bool,
|
is_arg: bool,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
|
let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
|
||||||
struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc)
|
struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_assign(
|
pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'tcx> {
|
||||||
&self,
|
struct_span_code_err!(self.dcx(), span, E0594, "cannot assign to {}", desc)
|
||||||
span: Span,
|
|
||||||
desc: &str,
|
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
|
||||||
struct_span_err!(self, span, E0594, "cannot assign to {}", desc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_move_out_of(
|
pub(crate) fn cannot_move_out_of(
|
||||||
&self,
|
&self,
|
||||||
move_from_span: Span,
|
move_from_span: Span,
|
||||||
move_from_desc: &str,
|
move_from_desc: &str,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc)
|
struct_span_code_err!(
|
||||||
|
self.dcx(),
|
||||||
|
move_from_span,
|
||||||
|
E0507,
|
||||||
|
"cannot move out of {}",
|
||||||
|
move_from_desc
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signal an error due to an attempt to move out of the interior
|
/// Signal an error due to an attempt to move out of the interior
|
||||||
@ -283,38 +283,36 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
move_from_span: Span,
|
move_from_span: Span,
|
||||||
ty: Ty<'_>,
|
ty: Ty<'_>,
|
||||||
is_index: Option<bool>,
|
is_index: Option<bool>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let type_name = match (&ty.kind(), is_index) {
|
let type_name = match (&ty.kind(), is_index) {
|
||||||
(&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
|
(&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
|
||||||
(&ty::Slice(_), _) => "slice",
|
(&ty::Slice(_), _) => "slice",
|
||||||
_ => span_bug!(move_from_span, "this path should not cause illegal move"),
|
_ => span_bug!(move_from_span, "this path should not cause illegal move"),
|
||||||
};
|
};
|
||||||
let mut err = struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
move_from_span,
|
move_from_span,
|
||||||
E0508,
|
E0508,
|
||||||
"cannot move out of type `{}`, a non-copy {}",
|
"cannot move out of type `{}`, a non-copy {}",
|
||||||
ty,
|
ty,
|
||||||
type_name,
|
type_name,
|
||||||
);
|
)
|
||||||
err.span_label(move_from_span, "cannot move out of here");
|
.with_span_label(move_from_span, "cannot move out of here")
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_move_out_of_interior_of_drop(
|
pub(crate) fn cannot_move_out_of_interior_of_drop(
|
||||||
&self,
|
&self,
|
||||||
move_from_span: Span,
|
move_from_span: Span,
|
||||||
container_ty: Ty<'_>,
|
container_ty: Ty<'_>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let mut err = struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
move_from_span,
|
move_from_span,
|
||||||
E0509,
|
E0509,
|
||||||
"cannot move out of type `{}`, which implements the `Drop` trait",
|
"cannot move out of type `{}`, which implements the `Drop` trait",
|
||||||
container_ty,
|
container_ty,
|
||||||
);
|
)
|
||||||
err.span_label(move_from_span, "cannot move out of here");
|
.with_span_label(move_from_span, "cannot move out of here")
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_act_on_moved_value(
|
pub(crate) fn cannot_act_on_moved_value(
|
||||||
@ -323,11 +321,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
verb: &str,
|
verb: &str,
|
||||||
optional_adverb_for_moved: &str,
|
optional_adverb_for_moved: &str,
|
||||||
moved_path: Option<String>,
|
moved_path: Option<String>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default();
|
let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default();
|
||||||
|
|
||||||
struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
use_span,
|
use_span,
|
||||||
E0382,
|
E0382,
|
||||||
"{} of {}moved value{}",
|
"{} of {}moved value{}",
|
||||||
@ -342,8 +340,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
path: &str,
|
path: &str,
|
||||||
reason: &str,
|
reason: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,)
|
struct_span_code_err!(
|
||||||
|
self.dcx(),
|
||||||
|
span,
|
||||||
|
E0596,
|
||||||
|
"cannot borrow {} as mutable{}",
|
||||||
|
path,
|
||||||
|
reason
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_mutate_in_immutable_section(
|
pub(crate) fn cannot_mutate_in_immutable_section(
|
||||||
@ -353,43 +358,41 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
immutable_place: &str,
|
immutable_place: &str,
|
||||||
immutable_section: &str,
|
immutable_section: &str,
|
||||||
action: &str,
|
action: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let mut err = struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
mutate_span,
|
mutate_span,
|
||||||
E0510,
|
E0510,
|
||||||
"cannot {} {} in {}",
|
"cannot {} {} in {}",
|
||||||
action,
|
action,
|
||||||
immutable_place,
|
immutable_place,
|
||||||
immutable_section,
|
immutable_section,
|
||||||
);
|
)
|
||||||
err.span_label(mutate_span, format!("cannot {action}"));
|
.with_span_label(mutate_span, format!("cannot {action}"))
|
||||||
err.span_label(immutable_span, format!("value is immutable in {immutable_section}"));
|
.with_span_label(immutable_span, format!("value is immutable in {immutable_section}"))
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_borrow_across_coroutine_yield(
|
pub(crate) fn cannot_borrow_across_coroutine_yield(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
yield_span: Span,
|
yield_span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||||
let mut err = struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0626,
|
E0626,
|
||||||
"borrow may still be in use when {coroutine_kind:#} yields",
|
"borrow may still be in use when {coroutine_kind:#} yields",
|
||||||
);
|
)
|
||||||
err.span_label(yield_span, "possible yield occurs here");
|
.with_span_label(yield_span, "possible yield occurs here")
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_borrow_across_destructor(
|
pub(crate) fn cannot_borrow_across_destructor(
|
||||||
&self,
|
&self,
|
||||||
borrow_span: Span,
|
borrow_span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
borrow_span,
|
borrow_span,
|
||||||
E0713,
|
E0713,
|
||||||
"borrow may still be in use when destructor runs",
|
"borrow may still be in use when destructor runs",
|
||||||
@ -400,8 +403,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
struct_span_err!(self, span, E0597, "{} does not live long enough", path,)
|
struct_span_code_err!(self.dcx(), span, E0597, "{} does not live long enough", path,)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_return_reference_to_local(
|
pub(crate) fn cannot_return_reference_to_local(
|
||||||
@ -410,23 +413,20 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
return_kind: &str,
|
return_kind: &str,
|
||||||
reference_desc: &str,
|
reference_desc: &str,
|
||||||
path_desc: &str,
|
path_desc: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let mut err = struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0515,
|
E0515,
|
||||||
"cannot {RETURN} {REFERENCE} {LOCAL}",
|
"cannot {RETURN} {REFERENCE} {LOCAL}",
|
||||||
RETURN = return_kind,
|
RETURN = return_kind,
|
||||||
REFERENCE = reference_desc,
|
REFERENCE = reference_desc,
|
||||||
LOCAL = path_desc,
|
LOCAL = path_desc,
|
||||||
);
|
)
|
||||||
|
.with_span_label(
|
||||||
err.span_label(
|
|
||||||
span,
|
span,
|
||||||
format!("{return_kind}s a {reference_desc} data owned by the current function"),
|
format!("{return_kind}s a {reference_desc} data owned by the current function"),
|
||||||
);
|
)
|
||||||
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cannot_capture_in_long_lived_closure(
|
pub(crate) fn cannot_capture_in_long_lived_closure(
|
||||||
@ -436,42 +436,35 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
borrowed_path: &str,
|
borrowed_path: &str,
|
||||||
capture_span: Span,
|
capture_span: Span,
|
||||||
scope: &str,
|
scope: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let mut err = struct_span_err!(
|
struct_span_code_err!(
|
||||||
self,
|
self.dcx(),
|
||||||
closure_span,
|
closure_span,
|
||||||
E0373,
|
E0373,
|
||||||
"{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
|
"{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
|
||||||
which is owned by the current {scope}",
|
which is owned by the current {scope}",
|
||||||
);
|
)
|
||||||
err.span_label(capture_span, format!("{borrowed_path} is borrowed here"))
|
.with_span_label(capture_span, format!("{borrowed_path} is borrowed here"))
|
||||||
.span_label(closure_span, format!("may outlive borrowed value {borrowed_path}"));
|
.with_span_label(closure_span, format!("may outlive borrowed value {borrowed_path}"))
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn thread_local_value_does_not_live_long_enough(
|
pub(crate) fn thread_local_value_does_not_live_long_enough(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",)
|
struct_span_code_err!(
|
||||||
|
self.dcx(),
|
||||||
|
span,
|
||||||
|
E0712,
|
||||||
|
"thread-local variable borrowed past end of function",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn temporary_value_borrowed_for_too_long(
|
pub(crate) fn temporary_value_borrowed_for_too_long(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
|
struct_span_code_err!(self.dcx(), span, E0716, "temporary value dropped while borrowed",)
|
||||||
}
|
|
||||||
|
|
||||||
#[rustc_lint_diagnostics]
|
|
||||||
#[track_caller]
|
|
||||||
pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>(
|
|
||||||
&self,
|
|
||||||
sp: S,
|
|
||||||
msg: impl Into<DiagnosticMessage>,
|
|
||||||
code: DiagnosticId,
|
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
|
||||||
self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,9 +472,9 @@ pub(crate) fn borrowed_data_escapes_closure<'tcx>(
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
escape_span: Span,
|
escape_span: Span,
|
||||||
escapes_from: &str,
|
escapes_from: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
struct_span_err!(
|
struct_span_code_err!(
|
||||||
tcx.sess,
|
tcx.dcx(),
|
||||||
escape_span,
|
escape_span,
|
||||||
E0521,
|
E0521,
|
||||||
"borrowed data escapes outside of {}",
|
"borrowed data escapes outside of {}",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
|
||||||
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::DiagnosticBuilder;
|
||||||
use rustc_infer::infer::canonical::Canonical;
|
use rustc_infer::infer::canonical::Canonical;
|
||||||
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
|
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use rustc_infer::infer::region_constraints::Constraint;
|
use rustc_infer::infer::region_constraints::Constraint;
|
||||||
@ -77,7 +77,7 @@ impl<'tcx> UniverseInfo<'tcx> {
|
|||||||
// up in the existing UI tests. Consider investigating this
|
// up in the existing UI tests. Consider investigating this
|
||||||
// some more.
|
// some more.
|
||||||
mbcx.buffer_error(
|
mbcx.buffer_error(
|
||||||
mbcx.infcx.tcx.sess.create_err(HigherRankedSubtypeError { span: cause.span }),
|
mbcx.dcx().create_err(HigherRankedSubtypeError { span: cause.span }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,11 +147,7 @@ impl<'tcx> ToUniverseInfo<'tcx> for ! {
|
|||||||
trait TypeOpInfo<'tcx> {
|
trait TypeOpInfo<'tcx> {
|
||||||
/// Returns an error to be reported if rerunning the type op fails to
|
/// Returns an error to be reported if rerunning the type op fails to
|
||||||
/// recover the error's cause.
|
/// recover the error's cause.
|
||||||
fn fallback_error(
|
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
|
||||||
&self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
span: Span,
|
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
|
||||||
|
|
||||||
fn base_universe(&self) -> ty::UniverseIndex;
|
fn base_universe(&self) -> ty::UniverseIndex;
|
||||||
|
|
||||||
@ -161,7 +157,7 @@ trait TypeOpInfo<'tcx> {
|
|||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
placeholder_region: ty::Region<'tcx>,
|
placeholder_region: ty::Region<'tcx>,
|
||||||
error_region: Option<ty::Region<'tcx>>,
|
error_region: Option<ty::Region<'tcx>>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
|
) -> Option<DiagnosticBuilder<'tcx>>;
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, mbcx))]
|
#[instrument(level = "debug", skip(self, mbcx))]
|
||||||
fn report_error(
|
fn report_error(
|
||||||
@ -224,12 +220,8 @@ struct PredicateQuery<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
||||||
fn fallback_error(
|
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||||
&self,
|
tcx.dcx().create_err(HigherRankedLifetimeError {
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
span: Span,
|
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
|
||||||
tcx.sess.create_err(HigherRankedLifetimeError {
|
|
||||||
cause: Some(HigherRankedErrorCause::CouldNotProve {
|
cause: Some(HigherRankedErrorCause::CouldNotProve {
|
||||||
predicate: self.canonical_query.value.value.predicate.to_string(),
|
predicate: self.canonical_query.value.value.predicate.to_string(),
|
||||||
}),
|
}),
|
||||||
@ -247,7 +239,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
|||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
placeholder_region: ty::Region<'tcx>,
|
placeholder_region: ty::Region<'tcx>,
|
||||||
error_region: Option<ty::Region<'tcx>>,
|
error_region: Option<ty::Region<'tcx>>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||||
let (infcx, key, _) =
|
let (infcx, key, _) =
|
||||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
@ -265,12 +257,8 @@ impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
|
|||||||
where
|
where
|
||||||
T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx,
|
T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx,
|
||||||
{
|
{
|
||||||
fn fallback_error(
|
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||||
&self,
|
tcx.dcx().create_err(HigherRankedLifetimeError {
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
span: Span,
|
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
|
||||||
tcx.sess.create_err(HigherRankedLifetimeError {
|
|
||||||
cause: Some(HigherRankedErrorCause::CouldNotNormalize {
|
cause: Some(HigherRankedErrorCause::CouldNotNormalize {
|
||||||
value: self.canonical_query.value.value.value.to_string(),
|
value: self.canonical_query.value.value.value.to_string(),
|
||||||
}),
|
}),
|
||||||
@ -288,7 +276,7 @@ where
|
|||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
placeholder_region: ty::Region<'tcx>,
|
placeholder_region: ty::Region<'tcx>,
|
||||||
error_region: Option<ty::Region<'tcx>>,
|
error_region: Option<ty::Region<'tcx>>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||||
let (infcx, key, _) =
|
let (infcx, key, _) =
|
||||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
@ -312,14 +300,10 @@ struct AscribeUserTypeQuery<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
||||||
fn fallback_error(
|
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||||
&self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
span: Span,
|
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
|
||||||
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
|
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
|
||||||
// and is only the fallback when the nice error fails. Consider improving this some more.
|
// and is only the fallback when the nice error fails. Consider improving this some more.
|
||||||
tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span })
|
tcx.dcx().create_err(HigherRankedLifetimeError { cause: None, span })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_universe(&self) -> ty::UniverseIndex {
|
fn base_universe(&self) -> ty::UniverseIndex {
|
||||||
@ -332,7 +316,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
|||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
placeholder_region: ty::Region<'tcx>,
|
placeholder_region: ty::Region<'tcx>,
|
||||||
error_region: Option<ty::Region<'tcx>>,
|
error_region: Option<ty::Region<'tcx>>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||||
let (infcx, key, _) =
|
let (infcx, key, _) =
|
||||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
@ -342,14 +326,10 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
||||||
fn fallback_error(
|
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
|
||||||
&self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
span: Span,
|
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
|
||||||
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
|
// FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
|
||||||
// and is only the fallback when the nice error fails. Consider improving this some more.
|
// and is only the fallback when the nice error fails. Consider improving this some more.
|
||||||
tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span })
|
tcx.dcx().create_err(HigherRankedLifetimeError { cause: None, span })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_universe(&self) -> ty::UniverseIndex {
|
fn base_universe(&self) -> ty::UniverseIndex {
|
||||||
@ -362,7 +342,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
|||||||
_cause: ObligationCause<'tcx>,
|
_cause: ObligationCause<'tcx>,
|
||||||
placeholder_region: ty::Region<'tcx>,
|
placeholder_region: ty::Region<'tcx>,
|
||||||
error_region: Option<ty::Region<'tcx>>,
|
error_region: Option<ty::Region<'tcx>>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||||
try_extract_error_from_region_constraints(
|
try_extract_error_from_region_constraints(
|
||||||
mbcx.infcx,
|
mbcx.infcx,
|
||||||
placeholder_region,
|
placeholder_region,
|
||||||
@ -383,7 +363,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
|||||||
ocx: &ObligationCtxt<'_, 'tcx>,
|
ocx: &ObligationCtxt<'_, 'tcx>,
|
||||||
placeholder_region: ty::Region<'tcx>,
|
placeholder_region: ty::Region<'tcx>,
|
||||||
error_region: Option<ty::Region<'tcx>>,
|
error_region: Option<ty::Region<'tcx>>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||||
// We generally shouldn't have errors here because the query was
|
// We generally shouldn't have errors here because the query was
|
||||||
// already run, but there's no point using `span_delayed_bug`
|
// already run, but there's no point using `span_delayed_bug`
|
||||||
// when we're going to emit an error here anyway.
|
// when we're going to emit an error here anyway.
|
||||||
@ -407,14 +387,19 @@ fn try_extract_error_from_region_constraints<'tcx>(
|
|||||||
region_constraints: &RegionConstraintData<'tcx>,
|
region_constraints: &RegionConstraintData<'tcx>,
|
||||||
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
|
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
|
||||||
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
|
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||||
|
let placeholder_universe = match placeholder_region.kind() {
|
||||||
|
ty::RePlaceholder(p) => p.universe,
|
||||||
|
ty::ReVar(vid) => universe_of_region(vid),
|
||||||
|
_ => ty::UniverseIndex::ROOT,
|
||||||
|
};
|
||||||
let matches =
|
let matches =
|
||||||
|a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) {
|
|a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) {
|
||||||
(RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
|
(RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
|
||||||
_ => a_region == b_region,
|
_ => a_region == b_region,
|
||||||
};
|
};
|
||||||
let check = |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| {
|
let mut check =
|
||||||
match *constraint {
|
|constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match *constraint {
|
||||||
Constraint::RegSubReg(sub, sup)
|
Constraint::RegSubReg(sub, sup)
|
||||||
if ((exact && sup == placeholder_region)
|
if ((exact && sup == placeholder_region)
|
||||||
|| (!exact && matches(sup, placeholder_region)))
|
|| (!exact && matches(sup, placeholder_region)))
|
||||||
@ -422,16 +407,16 @@ fn try_extract_error_from_region_constraints<'tcx>(
|
|||||||
{
|
{
|
||||||
Some((sub, cause.clone()))
|
Some((sub, cause.clone()))
|
||||||
}
|
}
|
||||||
// FIXME: Should this check the universe of the var?
|
|
||||||
Constraint::VarSubReg(vid, sup)
|
Constraint::VarSubReg(vid, sup)
|
||||||
if ((exact && sup == placeholder_region)
|
if (exact
|
||||||
|| (!exact && matches(sup, placeholder_region))) =>
|
&& sup == placeholder_region
|
||||||
|
&& !universe_of_region(vid).can_name(placeholder_universe))
|
||||||
|
|| (!exact && matches(sup, placeholder_region)) =>
|
||||||
{
|
{
|
||||||
Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
|
Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
};
|
||||||
};
|
|
||||||
let mut info = region_constraints
|
let mut info = region_constraints
|
||||||
.constraints
|
.constraints
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
|
// ignore-tidy-filelength
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::PatField;
|
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
|
codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
|
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
|
||||||
|
use rustc_hir::{CoroutineDesugaring, PatField};
|
||||||
use rustc_hir::{CoroutineKind, CoroutineSource, LangItem};
|
use rustc_hir::{CoroutineKind, CoroutineSource, LangItem};
|
||||||
use rustc_infer::traits::ObligationCause;
|
use rustc_infer::traits::ObligationCause;
|
||||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||||
@ -26,6 +28,7 @@ use rustc_span::hygiene::DesugaringKind;
|
|||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{BytePos, Span, Symbol};
|
use rustc_span::{BytePos, Span, Symbol};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
|
use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
@ -324,7 +327,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
mpi: MovePathIndex,
|
mpi: MovePathIndex,
|
||||||
move_span: Span,
|
move_span: Span,
|
||||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
in_pattern: &mut bool,
|
in_pattern: &mut bool,
|
||||||
move_spans: UseSpans<'_>,
|
move_spans: UseSpans<'_>,
|
||||||
) {
|
) {
|
||||||
@ -483,8 +486,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
desired_action: InitializationRequiringAction,
|
desired_action: InitializationRequiringAction,
|
||||||
span: Span,
|
span: Span,
|
||||||
use_spans: UseSpans<'tcx>,
|
use_spans: UseSpans<'tcx>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
// We need all statements in the body where the binding was assigned to to later find all
|
// We need all statements in the body where the binding was assigned to later find all
|
||||||
// the branching code paths where the binding *wasn't* assigned to.
|
// the branching code paths where the binding *wasn't* assigned to.
|
||||||
let inits = &self.move_data.init_path_map[mpi];
|
let inits = &self.move_data.init_path_map[mpi];
|
||||||
let move_path = &self.move_data.move_paths[mpi];
|
let move_path = &self.move_data.move_paths[mpi];
|
||||||
@ -552,8 +555,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let used = desired_action.as_general_verb_in_past_tense();
|
let used = desired_action.as_general_verb_in_past_tense();
|
||||||
let mut err =
|
let mut err = struct_span_code_err!(
|
||||||
struct_span_err!(self, span, E0381, "{used} binding {desc}{isnt_initialized}");
|
self.dcx(),
|
||||||
|
span,
|
||||||
|
E0381,
|
||||||
|
"{used} binding {desc}{isnt_initialized}"
|
||||||
|
);
|
||||||
use_spans.var_path_only_subdiag(&mut err, desired_action);
|
use_spans.var_path_only_subdiag(&mut err, desired_action);
|
||||||
|
|
||||||
if let InitializationRequiringAction::PartialAssignment
|
if let InitializationRequiringAction::PartialAssignment
|
||||||
@ -850,8 +857,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
|
move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
|
||||||
use crate::session_diagnostics::CaptureVarCause::*;
|
use crate::session_diagnostics::CaptureVarCause::*;
|
||||||
match kind {
|
match kind {
|
||||||
Some(_) => MoveUseInCoroutine { var_span },
|
hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span },
|
||||||
None => MoveUseInClosure { var_span },
|
hir::ClosureKind::Closure => MoveUseInClosure { var_span },
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -873,7 +880,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
location: Location,
|
location: Location,
|
||||||
(place, _span): (Place<'tcx>, Span),
|
(place, _span): (Place<'tcx>, Span),
|
||||||
borrow: &BorrowData<'tcx>,
|
borrow: &BorrowData<'tcx>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let borrow_spans = self.retrieve_borrow_spans(borrow);
|
let borrow_spans = self.retrieve_borrow_spans(borrow);
|
||||||
let borrow_span = borrow_spans.args_or_use();
|
let borrow_span = borrow_spans.args_or_use();
|
||||||
|
|
||||||
@ -895,10 +902,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let place = &borrow.borrowed_place;
|
let place = &borrow.borrowed_place;
|
||||||
let desc_place = self.describe_any_place(place.as_ref());
|
let desc_place = self.describe_any_place(place.as_ref());
|
||||||
match kind {
|
match kind {
|
||||||
Some(_) => {
|
hir::ClosureKind::Coroutine(_) => {
|
||||||
BorrowUsePlaceCoroutine { place: desc_place, var_span, is_single_var: true }
|
BorrowUsePlaceCoroutine { place: desc_place, var_span, is_single_var: true }
|
||||||
}
|
}
|
||||||
None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true },
|
hir::ClosureKind::Closure => {
|
||||||
|
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -921,7 +930,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
(place, span): (Place<'tcx>, Span),
|
(place, span): (Place<'tcx>, Span),
|
||||||
gen_borrow_kind: BorrowKind,
|
gen_borrow_kind: BorrowKind,
|
||||||
issued_borrow: &BorrowData<'tcx>,
|
issued_borrow: &BorrowData<'tcx>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let issued_spans = self.retrieve_borrow_spans(issued_borrow);
|
let issued_spans = self.retrieve_borrow_spans(issued_borrow);
|
||||||
let issued_span = issued_spans.args_or_use();
|
let issued_span = issued_spans.args_or_use();
|
||||||
|
|
||||||
@ -1042,12 +1051,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
|kind, var_span| {
|
|kind, var_span| {
|
||||||
use crate::session_diagnostics::CaptureVarCause::*;
|
use crate::session_diagnostics::CaptureVarCause::*;
|
||||||
match kind {
|
match kind {
|
||||||
Some(_) => BorrowUsePlaceCoroutine {
|
hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
|
||||||
place: desc_place,
|
place: desc_place,
|
||||||
var_span,
|
var_span,
|
||||||
is_single_var: true,
|
is_single_var: true,
|
||||||
},
|
},
|
||||||
None => BorrowUsePlaceClosure {
|
hir::ClosureKind::Closure => BorrowUsePlaceClosure {
|
||||||
place: desc_place,
|
place: desc_place,
|
||||||
var_span,
|
var_span,
|
||||||
is_single_var: true,
|
is_single_var: true,
|
||||||
@ -1126,19 +1135,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
|
borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
|
||||||
use crate::session_diagnostics::CaptureVarCause::*;
|
use crate::session_diagnostics::CaptureVarCause::*;
|
||||||
match kind {
|
match kind {
|
||||||
Some(_) => BorrowUsePlaceCoroutine {
|
hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
|
||||||
place: desc_place,
|
place: desc_place,
|
||||||
var_span,
|
var_span,
|
||||||
is_single_var: false,
|
is_single_var: false,
|
||||||
},
|
},
|
||||||
None => {
|
hir::ClosureKind::Closure => {
|
||||||
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
|
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
issued_spans.var_subdiag(
|
issued_spans.var_subdiag(
|
||||||
Some(self.infcx.tcx.sess.dcx()),
|
Some(self.dcx()),
|
||||||
&mut err,
|
&mut err,
|
||||||
Some(issued_borrow.kind),
|
Some(issued_borrow.kind),
|
||||||
|kind, var_span| {
|
|kind, var_span| {
|
||||||
@ -1146,23 +1155,29 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let borrow_place = &issued_borrow.borrowed_place;
|
let borrow_place = &issued_borrow.borrowed_place;
|
||||||
let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
|
let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
|
||||||
match kind {
|
match kind {
|
||||||
Some(_) => {
|
hir::ClosureKind::Coroutine(_) => {
|
||||||
FirstBorrowUsePlaceCoroutine { place: borrow_place_desc, var_span }
|
FirstBorrowUsePlaceCoroutine { place: borrow_place_desc, var_span }
|
||||||
}
|
}
|
||||||
None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span },
|
hir::ClosureKind::Closure => {
|
||||||
|
FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
borrow_spans.var_subdiag(
|
borrow_spans.var_subdiag(
|
||||||
Some(self.infcx.tcx.sess.dcx()),
|
Some(self.dcx()),
|
||||||
&mut err,
|
&mut err,
|
||||||
Some(gen_borrow_kind),
|
Some(gen_borrow_kind),
|
||||||
|kind, var_span| {
|
|kind, var_span| {
|
||||||
use crate::session_diagnostics::CaptureVarCause::*;
|
use crate::session_diagnostics::CaptureVarCause::*;
|
||||||
match kind {
|
match kind {
|
||||||
Some(_) => SecondBorrowUsePlaceCoroutine { place: desc_place, var_span },
|
hir::ClosureKind::Coroutine(_) => {
|
||||||
None => SecondBorrowUsePlaceClosure { place: desc_place, var_span },
|
SecondBorrowUsePlaceCoroutine { place: desc_place, var_span }
|
||||||
|
}
|
||||||
|
hir::ClosureKind::Closure => {
|
||||||
|
SecondBorrowUsePlaceClosure { place: desc_place, var_span }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -1245,7 +1260,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
debug!("checking call args for uses of inner_param: {:?}", args);
|
debug!("checking call args for uses of inner_param: {:?}", args);
|
||||||
args.contains(&Operand::Move(inner_param)).then_some((loc, term))
|
args.iter()
|
||||||
|
.map(|a| &a.node)
|
||||||
|
.any(|a| a == &Operand::Move(inner_param))
|
||||||
|
.then_some((loc, term))
|
||||||
})
|
})
|
||||||
else {
|
else {
|
||||||
debug!("no uses of inner_param found as a by-move call arg");
|
debug!("no uses of inner_param found as a by-move call arg");
|
||||||
@ -1289,14 +1307,96 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
place: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
borrowed_place: Place<'tcx>,
|
borrowed_place: Place<'tcx>,
|
||||||
) {
|
) {
|
||||||
if let ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) =
|
let tcx = self.infcx.tcx;
|
||||||
(&place.projection[..], &borrowed_place.projection[..])
|
let hir = tcx.hir();
|
||||||
|
|
||||||
|
if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)])
|
||||||
|
| (
|
||||||
|
[ProjectionElem::Deref, ProjectionElem::Index(index1)],
|
||||||
|
[ProjectionElem::Deref, ProjectionElem::Index(index2)],
|
||||||
|
) = (&place.projection[..], &borrowed_place.projection[..])
|
||||||
{
|
{
|
||||||
err.help(
|
let mut note_default_suggestion = || {
|
||||||
"consider using `.split_at_mut(position)` or similar method to obtain \
|
err.help(
|
||||||
two mutable non-overlapping sub-slices",
|
"consider using `.split_at_mut(position)` or similar method to obtain \
|
||||||
)
|
two mutable non-overlapping sub-slices",
|
||||||
.help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
|
)
|
||||||
|
.help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut expr_finder =
|
||||||
|
FindExprBySpan::new(self.body.local_decls[*index1].source_info.span);
|
||||||
|
expr_finder.visit_expr(hir.body(body_id).value);
|
||||||
|
let Some(index1) = expr_finder.result else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span);
|
||||||
|
expr_finder.visit_expr(hir.body(body_id).value);
|
||||||
|
let Some(index2) = expr_finder.result else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let sm = tcx.sess.source_map();
|
||||||
|
|
||||||
|
let Ok(index1_str) = sm.span_to_snippet(index1.span) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(index2_str) = sm.span_to_snippet(index2.span) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(object) = hir.parent_id_iter(index1.hir_id).find_map(|id| {
|
||||||
|
if let hir::Node::Expr(expr) = tcx.hir_node(id)
|
||||||
|
&& let hir::ExprKind::Index(obj, ..) = expr.kind
|
||||||
|
{
|
||||||
|
Some(obj)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(obj_str) = sm.span_to_snippet(object.span) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(swap_call) = hir.parent_id_iter(object.hir_id).find_map(|id| {
|
||||||
|
if let hir::Node::Expr(call) = tcx.hir_node(id)
|
||||||
|
&& let hir::ExprKind::Call(callee, ..) = call.kind
|
||||||
|
&& let hir::ExprKind::Path(qpath) = callee.kind
|
||||||
|
&& let hir::QPath::Resolved(None, res) = qpath
|
||||||
|
&& let hir::def::Res::Def(_, did) = res.res
|
||||||
|
&& tcx.is_diagnostic_item(sym::mem_swap, did)
|
||||||
|
{
|
||||||
|
Some(call)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}) else {
|
||||||
|
note_default_suggestion();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
err.span_suggestion(
|
||||||
|
swap_call.span,
|
||||||
|
"use `.swap()` to swap elements at the specified indices instead",
|
||||||
|
format!("{obj_str}.swap({index1_str}, {index2_str})"),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1653,7 +1753,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
||||||
if e.span.contains(self.capture_span) {
|
if e.span.contains(self.capture_span) {
|
||||||
if let hir::ExprKind::Closure(&hir::Closure {
|
if let hir::ExprKind::Closure(&hir::Closure {
|
||||||
movability: None,
|
kind: hir::ClosureKind::Closure,
|
||||||
body,
|
body,
|
||||||
fn_arg_span,
|
fn_arg_span,
|
||||||
fn_decl: hir::FnDecl { inputs, .. },
|
fn_decl: hir::FnDecl { inputs, .. },
|
||||||
@ -1688,7 +1788,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
&& let Some(init) = local.init
|
&& let Some(init) = local.init
|
||||||
{
|
{
|
||||||
if let hir::Expr {
|
if let hir::Expr {
|
||||||
kind: hir::ExprKind::Closure(&hir::Closure { movability: None, .. }),
|
kind:
|
||||||
|
hir::ExprKind::Closure(&hir::Closure {
|
||||||
|
kind: hir::ClosureKind::Closure,
|
||||||
|
..
|
||||||
|
}),
|
||||||
..
|
..
|
||||||
} = init
|
} = init
|
||||||
&& init.span.contains(self.capture_span)
|
&& init.span.contains(self.capture_span)
|
||||||
@ -2025,7 +2129,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
drop_span: Span,
|
drop_span: Span,
|
||||||
borrow_spans: UseSpans<'tcx>,
|
borrow_spans: UseSpans<'tcx>,
|
||||||
explanation: BorrowExplanation<'tcx>,
|
explanation: BorrowExplanation<'tcx>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
debug!(
|
debug!(
|
||||||
"report_local_value_does_not_live_long_enough(\
|
"report_local_value_does_not_live_long_enough(\
|
||||||
{:?}, {:?}, {:?}, {:?}, {:?}\
|
{:?}, {:?}, {:?}, {:?}, {:?}\
|
||||||
@ -2200,7 +2304,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
drop_span: Span,
|
drop_span: Span,
|
||||||
borrow_span: Span,
|
borrow_span: Span,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
debug!(
|
debug!(
|
||||||
"report_thread_local_value_does_not_live_long_enough(\
|
"report_thread_local_value_does_not_live_long_enough(\
|
||||||
{:?}, {:?}\
|
{:?}, {:?}\
|
||||||
@ -2208,15 +2312,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
drop_span, borrow_span
|
drop_span, borrow_span
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut err = self.thread_local_value_does_not_live_long_enough(borrow_span);
|
self.thread_local_value_does_not_live_long_enough(borrow_span)
|
||||||
|
.with_span_label(
|
||||||
err.span_label(
|
borrow_span,
|
||||||
borrow_span,
|
"thread-local variables cannot be borrowed beyond the end of the function",
|
||||||
"thread-local variables cannot be borrowed beyond the end of the function",
|
)
|
||||||
);
|
.with_span_label(drop_span, "end of enclosing function is here")
|
||||||
err.span_label(drop_span, "end of enclosing function is here");
|
|
||||||
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
@ -2228,7 +2329,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
borrow_spans: UseSpans<'tcx>,
|
borrow_spans: UseSpans<'tcx>,
|
||||||
proper_span: Span,
|
proper_span: Span,
|
||||||
explanation: BorrowExplanation<'tcx>,
|
explanation: BorrowExplanation<'tcx>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
|
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
|
||||||
explanation
|
explanation
|
||||||
{
|
{
|
||||||
@ -2395,7 +2496,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
return_span: Span,
|
return_span: Span,
|
||||||
category: ConstraintCategory<'tcx>,
|
category: ConstraintCategory<'tcx>,
|
||||||
opt_place_desc: Option<&String>,
|
opt_place_desc: Option<&String>,
|
||||||
) -> Option<DiagnosticBuilder<'cx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'cx>> {
|
||||||
let return_kind = match category {
|
let return_kind = match category {
|
||||||
ConstraintCategory::Return(_) => "return",
|
ConstraintCategory::Return(_) => "return",
|
||||||
ConstraintCategory::Yield => "yield",
|
ConstraintCategory::Yield => "yield",
|
||||||
@ -2490,7 +2591,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
constraint_span: Span,
|
constraint_span: Span,
|
||||||
captured_var: &str,
|
captured_var: &str,
|
||||||
scope: &str,
|
scope: &str,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
let args_span = use_span.args_or_use();
|
let args_span = use_span.args_or_use();
|
||||||
|
|
||||||
@ -2516,28 +2617,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
};
|
};
|
||||||
let kind = match use_span.coroutine_kind() {
|
let kind = match use_span.coroutine_kind() {
|
||||||
Some(coroutine_kind) => match coroutine_kind {
|
Some(coroutine_kind) => match coroutine_kind {
|
||||||
CoroutineKind::Gen(kind) => match kind {
|
CoroutineKind::Desugared(CoroutineDesugaring::Gen, kind) => match kind {
|
||||||
CoroutineSource::Block => "gen block",
|
CoroutineSource::Block => "gen block",
|
||||||
CoroutineSource::Closure => "gen closure",
|
CoroutineSource::Closure => "gen closure",
|
||||||
CoroutineSource::Fn => {
|
CoroutineSource::Fn => {
|
||||||
bug!("gen block/closure expected, but gen function found.")
|
bug!("gen block/closure expected, but gen function found.")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CoroutineKind::AsyncGen(kind) => match kind {
|
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, kind) => match kind {
|
||||||
CoroutineSource::Block => "async gen block",
|
CoroutineSource::Block => "async gen block",
|
||||||
CoroutineSource::Closure => "async gen closure",
|
CoroutineSource::Closure => "async gen closure",
|
||||||
CoroutineSource::Fn => {
|
CoroutineSource::Fn => {
|
||||||
bug!("gen block/closure expected, but gen function found.")
|
bug!("gen block/closure expected, but gen function found.")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CoroutineKind::Async(async_kind) => match async_kind {
|
CoroutineKind::Desugared(CoroutineDesugaring::Async, async_kind) => {
|
||||||
CoroutineSource::Block => "async block",
|
match async_kind {
|
||||||
CoroutineSource::Closure => "async closure",
|
CoroutineSource::Block => "async block",
|
||||||
CoroutineSource::Fn => {
|
CoroutineSource::Closure => "async closure",
|
||||||
bug!("async block/closure expected, but async function found.")
|
CoroutineSource::Fn => {
|
||||||
|
bug!("async block/closure expected, but async function found.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
CoroutineKind::Coroutine => "coroutine",
|
CoroutineKind::Coroutine(_) => "coroutine",
|
||||||
},
|
},
|
||||||
None => "closure",
|
None => "closure",
|
||||||
};
|
};
|
||||||
@ -2566,7 +2669,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
ConstraintCategory::CallArgument(_) => {
|
ConstraintCategory::CallArgument(_) => {
|
||||||
fr_name.highlight_region_name(&mut err);
|
fr_name.highlight_region_name(&mut err);
|
||||||
if matches!(use_span.coroutine_kind(), Some(CoroutineKind::Async(_))) {
|
if matches!(
|
||||||
|
use_span.coroutine_kind(),
|
||||||
|
Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, _))
|
||||||
|
) {
|
||||||
err.note(
|
err.note(
|
||||||
"async blocks are not executed immediately and must either take a \
|
"async blocks are not executed immediately and must either take a \
|
||||||
reference or ownership of outside variables they use",
|
reference or ownership of outside variables they use",
|
||||||
@ -2593,7 +2699,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
upvar_span: Span,
|
upvar_span: Span,
|
||||||
upvar_name: Symbol,
|
upvar_name: Symbol,
|
||||||
escape_span: Span,
|
escape_span: Span,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
|
|
||||||
let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());
|
let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());
|
||||||
@ -2835,8 +2941,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
||||||
use crate::session_diagnostics::CaptureVarCause::*;
|
use crate::session_diagnostics::CaptureVarCause::*;
|
||||||
match kind {
|
match kind {
|
||||||
Some(_) => BorrowUseInCoroutine { var_span },
|
hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
|
||||||
None => BorrowUseInClosure { var_span },
|
hir::ClosureKind::Closure => BorrowUseInClosure { var_span },
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2851,8 +2957,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
||||||
use crate::session_diagnostics::CaptureVarCause::*;
|
use crate::session_diagnostics::CaptureVarCause::*;
|
||||||
match kind {
|
match kind {
|
||||||
Some(_) => BorrowUseInCoroutine { var_span },
|
hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
|
||||||
None => BorrowUseInClosure { var_span },
|
hir::ClosureKind::Closure => BorrowUseInClosure { var_span },
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3052,7 +3158,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
|
) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
|
||||||
// Define a fallback for when we can't match a closure.
|
// Define a fallback for when we can't match a closure.
|
||||||
let fallback = || {
|
let fallback = || {
|
||||||
let is_closure = self.infcx.tcx.is_closure(self.mir_def_id().to_def_id());
|
let is_closure = self.infcx.tcx.is_closure_or_coroutine(self.mir_def_id().to_def_id());
|
||||||
if is_closure {
|
if is_closure {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -3224,7 +3330,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
assigned_to, args
|
assigned_to, args
|
||||||
);
|
);
|
||||||
for operand in args {
|
for operand in args {
|
||||||
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand
|
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
|
||||||
|
&operand.node
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
@ -3262,7 +3369,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
sig: ty::PolyFnSig<'tcx>,
|
sig: ty::PolyFnSig<'tcx>,
|
||||||
) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
|
) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
|
||||||
debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
|
debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
|
||||||
let is_closure = self.infcx.tcx.is_closure(did.to_def_id());
|
let is_closure = self.infcx.tcx.is_closure_or_coroutine(did.to_def_id());
|
||||||
let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did);
|
let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did);
|
||||||
let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;
|
let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;
|
||||||
|
|
||||||
@ -3575,7 +3682,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
|
|||||||
));
|
));
|
||||||
} else if let Some(guard) = &arm.guard {
|
} else if let Some(guard) = &arm.guard {
|
||||||
self.errors.push((
|
self.errors.push((
|
||||||
arm.pat.span.to(guard.body().span),
|
arm.pat.span.to(guard.span),
|
||||||
format!(
|
format!(
|
||||||
"if this pattern and condition are matched, {} is not \
|
"if this pattern and condition are matched, {} is not \
|
||||||
initialized",
|
initialized",
|
||||||
|
|||||||
@ -315,7 +315,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||||||
let mut failed = false;
|
let mut failed = false;
|
||||||
|
|
||||||
let elaborated_args = std::iter::zip(*args, &generics.params).map(|(arg, param)| {
|
let elaborated_args = std::iter::zip(*args, &generics.params).map(|(arg, param)| {
|
||||||
if let Some(ty::Dynamic(obj, _, ty::DynKind::Dyn)) = arg.as_type().map(Ty::kind) {
|
if let Some(ty::Dynamic(obj, _, ty::Dyn)) = arg.as_type().map(Ty::kind) {
|
||||||
let default = tcx.object_lifetime_default(param.def_id);
|
let default = tcx.object_lifetime_default(param.def_id);
|
||||||
|
|
||||||
let re_static = tcx.lifetimes.re_static;
|
let re_static = tcx.lifetimes.re_static;
|
||||||
@ -339,7 +339,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||||||
|
|
||||||
has_dyn = true;
|
has_dyn = true;
|
||||||
|
|
||||||
Ty::new_dynamic(tcx, obj, implied_region, ty::DynKind::Dyn).into()
|
Ty::new_dynamic(tcx, obj, implied_region, ty::Dyn).into()
|
||||||
} else {
|
} else {
|
||||||
arg
|
arg
|
||||||
}
|
}
|
||||||
@ -691,7 +691,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
);
|
);
|
||||||
// Check if one of the arguments to this function is the target place.
|
// Check if one of the arguments to this function is the target place.
|
||||||
let found_target = args.iter().any(|arg| {
|
let found_target = args.iter().any(|arg| {
|
||||||
if let Operand::Move(place) = arg {
|
if let Operand::Move(place) = arg.node {
|
||||||
if let Some(potential) = place.as_local() {
|
if let Some(potential) = place.as_local() {
|
||||||
potential == target
|
potential == target
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -23,6 +23,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
|||||||
use rustc_middle::util::{call_kind, CallDesugaringKind};
|
use rustc_middle::util::{call_kind, CallDesugaringKind};
|
||||||
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
|
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
||||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
@ -111,9 +112,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
|
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 Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
|
||||||
let closure = match args.first() {
|
let closure = match args.first() {
|
||||||
Some(Operand::Copy(place) | Operand::Move(place))
|
Some(Spanned {
|
||||||
if target == place.local_or_deref_local() =>
|
node: Operand::Copy(place) | Operand::Move(place), ..
|
||||||
{
|
}) if target == place.local_or_deref_local() => {
|
||||||
place.local_or_deref_local().unwrap()
|
place.local_or_deref_local().unwrap()
|
||||||
}
|
}
|
||||||
_ => return false,
|
_ => return false,
|
||||||
@ -124,7 +125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let did = did.expect_local();
|
let did = did.expect_local();
|
||||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||||
diag.eager_subdiagnostic(
|
diag.eager_subdiagnostic(
|
||||||
self.infcx.tcx.sess.dcx(),
|
self.dcx(),
|
||||||
OnClosureNote::InvokedTwice {
|
OnClosureNote::InvokedTwice {
|
||||||
place_name: &ty::place_to_string_for_capture(
|
place_name: &ty::place_to_string_for_capture(
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
@ -146,7 +147,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let did = did.expect_local();
|
let did = did.expect_local();
|
||||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||||
diag.eager_subdiagnostic(
|
diag.eager_subdiagnostic(
|
||||||
self.infcx.tcx.sess.dcx(),
|
self.dcx(),
|
||||||
OnClosureNote::MovedTwice {
|
OnClosureNote::MovedTwice {
|
||||||
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
|
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
|
||||||
span: *span,
|
span: *span,
|
||||||
@ -370,7 +371,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
ty::Array(ty, _) | ty::Slice(ty) => {
|
ty::Array(ty, _) | ty::Slice(ty) => {
|
||||||
self.describe_field_from_ty(ty, field, variant_index, including_tuple_field)
|
self.describe_field_from_ty(ty, field, variant_index, including_tuple_field)
|
||||||
}
|
}
|
||||||
ty::Closure(def_id, _) | ty::Coroutine(def_id, _, _) => {
|
ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => {
|
||||||
// We won't be borrowck'ing here if the closure came from another crate,
|
// We won't be borrowck'ing here if the closure came from another crate,
|
||||||
// so it's safe to call `expect_local`.
|
// so it's safe to call `expect_local`.
|
||||||
//
|
//
|
||||||
@ -505,7 +506,7 @@ pub(super) enum UseSpans<'tcx> {
|
|||||||
/// The access is caused by capturing a variable for a closure.
|
/// The access is caused by capturing a variable for a closure.
|
||||||
ClosureUse {
|
ClosureUse {
|
||||||
/// This is true if the captured variable was from a coroutine.
|
/// This is true if the captured variable was from a coroutine.
|
||||||
coroutine_kind: Option<CoroutineKind>,
|
closure_kind: hir::ClosureKind,
|
||||||
/// The span of the args of the closure, including the `move` keyword if
|
/// The span of the args of the closure, including the `move` keyword if
|
||||||
/// it's present.
|
/// it's present.
|
||||||
args_span: Span,
|
args_span: Span,
|
||||||
@ -572,9 +573,13 @@ impl UseSpans<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(coroutines): Make this just return the `ClosureKind` directly?
|
||||||
pub(super) fn coroutine_kind(self) -> Option<CoroutineKind> {
|
pub(super) fn coroutine_kind(self) -> Option<CoroutineKind> {
|
||||||
match self {
|
match self {
|
||||||
UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind,
|
UseSpans::ClosureUse {
|
||||||
|
closure_kind: hir::ClosureKind::Coroutine(coroutine_kind),
|
||||||
|
..
|
||||||
|
} => Some(coroutine_kind),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -599,9 +604,9 @@ impl UseSpans<'_> {
|
|||||||
) {
|
) {
|
||||||
use crate::InitializationRequiringAction::*;
|
use crate::InitializationRequiringAction::*;
|
||||||
use CaptureVarPathUseCause::*;
|
use CaptureVarPathUseCause::*;
|
||||||
if let UseSpans::ClosureUse { coroutine_kind, path_span, .. } = self {
|
if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self {
|
||||||
match coroutine_kind {
|
match closure_kind {
|
||||||
Some(_) => {
|
hir::ClosureKind::Coroutine(_) => {
|
||||||
err.subdiagnostic(match action {
|
err.subdiagnostic(match action {
|
||||||
Borrow => BorrowInCoroutine { path_span },
|
Borrow => BorrowInCoroutine { path_span },
|
||||||
MatchOn | Use => UseInCoroutine { path_span },
|
MatchOn | Use => UseInCoroutine { path_span },
|
||||||
@ -609,7 +614,7 @@ impl UseSpans<'_> {
|
|||||||
PartialAssignment => AssignPartInCoroutine { path_span },
|
PartialAssignment => AssignPartInCoroutine { path_span },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None => {
|
hir::ClosureKind::Closure => {
|
||||||
err.subdiagnostic(match action {
|
err.subdiagnostic(match action {
|
||||||
Borrow => BorrowInClosure { path_span },
|
Borrow => BorrowInClosure { path_span },
|
||||||
MatchOn | Use => UseInClosure { path_span },
|
MatchOn | Use => UseInClosure { path_span },
|
||||||
@ -627,9 +632,9 @@ impl UseSpans<'_> {
|
|||||||
dcx: Option<&rustc_errors::DiagCtxt>,
|
dcx: Option<&rustc_errors::DiagCtxt>,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
kind: Option<rustc_middle::mir::BorrowKind>,
|
kind: Option<rustc_middle::mir::BorrowKind>,
|
||||||
f: impl FnOnce(Option<CoroutineKind>, Span) -> CaptureVarCause,
|
f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause,
|
||||||
) {
|
) {
|
||||||
if let UseSpans::ClosureUse { coroutine_kind, capture_kind_span, path_span, .. } = self {
|
if let UseSpans::ClosureUse { closure_kind, capture_kind_span, path_span, .. } = self {
|
||||||
if capture_kind_span != path_span {
|
if capture_kind_span != path_span {
|
||||||
err.subdiagnostic(match kind {
|
err.subdiagnostic(match kind {
|
||||||
Some(kd) => match kd {
|
Some(kd) => match kd {
|
||||||
@ -645,7 +650,7 @@ impl UseSpans<'_> {
|
|||||||
None => CaptureVarKind::Move { kind_span: capture_kind_span },
|
None => CaptureVarKind::Move { kind_span: capture_kind_span },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
let diag = f(coroutine_kind, path_span);
|
let diag = f(closure_kind, path_span);
|
||||||
match dcx {
|
match dcx {
|
||||||
Some(hd) => err.eager_subdiagnostic(hd, diag),
|
Some(hd) => err.eager_subdiagnostic(hd, diag),
|
||||||
None => err.subdiagnostic(diag),
|
None => err.subdiagnostic(diag),
|
||||||
@ -656,7 +661,9 @@ impl UseSpans<'_> {
|
|||||||
/// Returns `false` if this place is not used in a closure.
|
/// Returns `false` if this place is not used in a closure.
|
||||||
pub(super) fn for_closure(&self) -> bool {
|
pub(super) fn for_closure(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind.is_none(),
|
UseSpans::ClosureUse { closure_kind, .. } => {
|
||||||
|
matches!(closure_kind, hir::ClosureKind::Closure)
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -664,7 +671,10 @@ impl UseSpans<'_> {
|
|||||||
/// Returns `false` if this place is not used in a coroutine.
|
/// Returns `false` if this place is not used in a coroutine.
|
||||||
pub(super) fn for_coroutine(&self) -> bool {
|
pub(super) fn for_coroutine(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind.is_some(),
|
// FIXME(coroutines): Do we want this to apply to synthetic coroutines?
|
||||||
|
UseSpans::ClosureUse { closure_kind, .. } => {
|
||||||
|
matches!(closure_kind, hir::ClosureKind::Coroutine(..))
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -783,15 +793,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
|
|
||||||
debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
|
debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
|
||||||
if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind
|
if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind
|
||||||
&& let AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _, _) =
|
&& let AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) = **kind
|
||||||
**kind
|
|
||||||
{
|
{
|
||||||
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
|
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
|
||||||
let def_id = def_id.expect_local();
|
let def_id = def_id.expect_local();
|
||||||
if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
|
if let Some((args_span, closure_kind, capture_kind_span, path_span)) =
|
||||||
self.closure_span(def_id, moved_place, places)
|
self.closure_span(def_id, moved_place, places)
|
||||||
{
|
{
|
||||||
return ClosureUse { coroutine_kind, args_span, capture_kind_span, path_span };
|
return ClosureUse { closure_kind, args_span, capture_kind_span, path_span };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,11 +812,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
| FakeReadCause::ForLet(Some(closure_def_id)) => {
|
| FakeReadCause::ForLet(Some(closure_def_id)) => {
|
||||||
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
|
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
|
||||||
let places = &[Operand::Move(place)];
|
let places = &[Operand::Move(place)];
|
||||||
if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
|
if let Some((args_span, closure_kind, capture_kind_span, path_span)) =
|
||||||
self.closure_span(closure_def_id, moved_place, IndexSlice::from_raw(places))
|
self.closure_span(closure_def_id, moved_place, IndexSlice::from_raw(places))
|
||||||
{
|
{
|
||||||
return ClosureUse {
|
return ClosureUse {
|
||||||
coroutine_kind,
|
closure_kind,
|
||||||
args_span,
|
args_span,
|
||||||
capture_kind_span,
|
capture_kind_span,
|
||||||
path_span,
|
path_span,
|
||||||
@ -919,7 +928,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
|
if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
|
||||||
let (&def_id, is_coroutine) = match kind {
|
let (&def_id, is_coroutine) = match kind {
|
||||||
box AggregateKind::Closure(def_id, _) => (def_id, false),
|
box AggregateKind::Closure(def_id, _) => (def_id, false),
|
||||||
box AggregateKind::Coroutine(def_id, _, _) => (def_id, true),
|
box AggregateKind::Coroutine(def_id, _) => (def_id, true),
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
let def_id = def_id.expect_local();
|
let def_id = def_id.expect_local();
|
||||||
@ -928,10 +937,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
"borrow_spans: def_id={:?} is_coroutine={:?} places={:?}",
|
"borrow_spans: def_id={:?} is_coroutine={:?} places={:?}",
|
||||||
def_id, is_coroutine, places
|
def_id, is_coroutine, places
|
||||||
);
|
);
|
||||||
if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
|
if let Some((args_span, closure_kind, capture_kind_span, path_span)) =
|
||||||
self.closure_span(def_id, Place::from(target).as_ref(), places)
|
self.closure_span(def_id, Place::from(target).as_ref(), places)
|
||||||
{
|
{
|
||||||
return ClosureUse { coroutine_kind, args_span, capture_kind_span, path_span };
|
return ClosureUse { closure_kind, args_span, capture_kind_span, path_span };
|
||||||
} else {
|
} else {
|
||||||
return OtherUse(use_span);
|
return OtherUse(use_span);
|
||||||
}
|
}
|
||||||
@ -953,7 +962,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
target_place: PlaceRef<'tcx>,
|
target_place: PlaceRef<'tcx>,
|
||||||
places: &IndexSlice<FieldIdx, Operand<'tcx>>,
|
places: &IndexSlice<FieldIdx, Operand<'tcx>>,
|
||||||
) -> Option<(Span, Option<CoroutineKind>, Span, Span)> {
|
) -> Option<(Span, hir::ClosureKind, Span, Span)> {
|
||||||
debug!(
|
debug!(
|
||||||
"closure_span: def_id={:?} target_place={:?} places={:?}",
|
"closure_span: def_id={:?} target_place={:?} places={:?}",
|
||||||
def_id, target_place, places
|
def_id, target_place, places
|
||||||
@ -961,7 +970,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let hir_id = self.infcx.tcx.local_def_id_to_hir_id(def_id);
|
let hir_id = self.infcx.tcx.local_def_id_to_hir_id(def_id);
|
||||||
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
|
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
|
||||||
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
|
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
|
||||||
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
|
if let hir::ExprKind::Closure(&hir::Closure { kind, fn_decl_span, .. }) = expr {
|
||||||
for (captured_place, place) in
|
for (captured_place, place) in
|
||||||
self.infcx.tcx.closure_captures(def_id).iter().zip(places)
|
self.infcx.tcx.closure_captures(def_id).iter().zip(places)
|
||||||
{
|
{
|
||||||
@ -970,12 +979,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
if target_place == place.as_ref() =>
|
if target_place == place.as_ref() =>
|
||||||
{
|
{
|
||||||
debug!("closure_span: found captured local {:?}", place);
|
debug!("closure_span: found captured local {:?}", place);
|
||||||
let body = self.infcx.tcx.hir().body(body);
|
|
||||||
let coroutine_kind = body.coroutine_kind();
|
|
||||||
|
|
||||||
return Some((
|
return Some((
|
||||||
fn_decl_span,
|
fn_decl_span,
|
||||||
coroutine_kind,
|
kind,
|
||||||
captured_place.get_capture_kind_span(self.infcx.tcx),
|
captured_place.get_capture_kind_span(self.infcx.tcx),
|
||||||
captured_place.get_path_span(self.infcx.tcx),
|
captured_place.get_path_span(self.infcx.tcx),
|
||||||
));
|
));
|
||||||
@ -1150,7 +1156,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
&& self.infcx.can_eq(self.param_env, ty, self_ty)
|
&& self.infcx.can_eq(self.param_env, ty, self_ty)
|
||||||
{
|
{
|
||||||
err.eager_subdiagnostic(
|
err.eager_subdiagnostic(
|
||||||
self.infcx.tcx.sess.dcx(),
|
self.dcx(),
|
||||||
CaptureReasonSuggest::FreshReborrow {
|
CaptureReasonSuggest::FreshReborrow {
|
||||||
span: move_span.shrink_to_hi(),
|
span: move_span.shrink_to_hi(),
|
||||||
},
|
},
|
||||||
@ -1173,9 +1179,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
vec![(move_span.shrink_to_hi(), ".clone()".to_string())]
|
vec![(move_span.shrink_to_hi(), ".clone()".to_string())]
|
||||||
};
|
};
|
||||||
if let Some(errors) =
|
if let Some(errors) = self.infcx.type_implements_trait_shallow(
|
||||||
self.infcx.could_impl_trait(clone_trait, ty, self.param_env)
|
clone_trait,
|
||||||
&& !has_sugg
|
ty,
|
||||||
|
self.param_env,
|
||||||
|
) && !has_sugg
|
||||||
{
|
{
|
||||||
let msg = match &errors[..] {
|
let msg = match &errors[..] {
|
||||||
[] => "you can `clone` the value and consume it, but this \
|
[] => "you can `clone` the value and consume it, but this \
|
||||||
@ -1208,7 +1216,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
for error in errors {
|
for error in errors {
|
||||||
if let FulfillmentErrorCode::CodeSelectionError(
|
if let FulfillmentErrorCode::SelectionError(
|
||||||
SelectionError::Unimplemented,
|
SelectionError::Unimplemented,
|
||||||
) = error.code
|
) = error.code
|
||||||
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
||||||
@ -1242,8 +1250,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
// another message for the same span
|
// another message for the same span
|
||||||
if !is_loop_message {
|
if !is_loop_message {
|
||||||
move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
|
move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
|
||||||
Some(_) => CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial },
|
hir::ClosureKind::Coroutine(_) => {
|
||||||
None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial },
|
CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial }
|
||||||
|
}
|
||||||
|
hir::ClosureKind::Closure => {
|
||||||
|
CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial }
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||||
@ -288,7 +288,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
place: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'a> {
|
||||||
let description = if place.projection.len() == 1 {
|
let description = if place.projection.len() == 1 {
|
||||||
format!("static item {}", self.describe_any_place(place.as_ref()))
|
format!("static item {}", self.describe_any_place(place.as_ref()))
|
||||||
} else {
|
} else {
|
||||||
@ -310,7 +310,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
deref_target_place: Place<'tcx>,
|
deref_target_place: Place<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
use_spans: Option<UseSpans<'tcx>>,
|
use_spans: Option<UseSpans<'tcx>>,
|
||||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'a> {
|
||||||
// Inspect the type of the content behind the
|
// Inspect the type of the content behind the
|
||||||
// borrow to provide feedback about why this
|
// borrow to provide feedback about why this
|
||||||
// was a move rather than a copy.
|
// was a move rather than a copy.
|
||||||
@ -329,15 +329,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
if let PlaceRef { local, projection: [] } = deref_base {
|
if let PlaceRef { local, projection: [] } = deref_base {
|
||||||
let decl = &self.body.local_decls[local];
|
let decl = &self.body.local_decls[local];
|
||||||
if decl.is_ref_for_guard() {
|
if decl.is_ref_for_guard() {
|
||||||
let mut err = self.cannot_move_out_of(
|
return self
|
||||||
span,
|
.cannot_move_out_of(
|
||||||
&format!("`{}` in pattern guard", self.local_names[local].unwrap()),
|
span,
|
||||||
);
|
&format!("`{}` in pattern guard", self.local_names[local].unwrap()),
|
||||||
err.note(
|
)
|
||||||
"variables bound in patterns cannot be moved from \
|
.with_note(
|
||||||
until after the end of the pattern guard",
|
"variables bound in patterns cannot be moved from \
|
||||||
);
|
until after the end of the pattern guard",
|
||||||
return err;
|
);
|
||||||
} else if decl.is_ref_to_static() {
|
} else if decl.is_ref_to_static() {
|
||||||
return self.report_cannot_move_from_static(move_place, span);
|
return self.report_cannot_move_from_static(move_place, span);
|
||||||
}
|
}
|
||||||
@ -381,15 +381,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
closure_kind_ty, closure_kind, place_description,
|
closure_kind_ty, closure_kind, place_description,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut diag = self.cannot_move_out_of(span, &place_description);
|
self.cannot_move_out_of(span, &place_description)
|
||||||
|
.with_span_label(upvar_span, "captured outer variable")
|
||||||
diag.span_label(upvar_span, "captured outer variable");
|
.with_span_label(
|
||||||
diag.span_label(
|
self.infcx.tcx.def_span(def_id),
|
||||||
self.infcx.tcx.def_span(def_id),
|
format!("captured by this `{closure_kind}` closure"),
|
||||||
format!("captured by this `{closure_kind}` closure"),
|
)
|
||||||
);
|
|
||||||
|
|
||||||
diag
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let source = self.borrowed_content_source(deref_base);
|
let source = self.borrowed_content_source(deref_base);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use hir::ExprKind;
|
use hir::ExprKind;
|
||||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
@ -711,7 +711,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
fn construct_mut_suggestion_for_local_binding_patterns(
|
fn construct_mut_suggestion_for_local_binding_patterns(
|
||||||
&self,
|
&self,
|
||||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
local: Local,
|
local: Local,
|
||||||
) {
|
) {
|
||||||
let local_decl = &self.body.local_decls[local];
|
let local_decl = &self.body.local_decls[local];
|
||||||
@ -1025,13 +1025,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_>) {
|
||||||
let source = self.body.source;
|
let source = self.body.source;
|
||||||
let hir = self.infcx.tcx.hir();
|
let hir = self.infcx.tcx.hir();
|
||||||
if let InstanceDef::Item(def_id) = source.instance
|
if let InstanceDef::Item(def_id) = source.instance
|
||||||
&& let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) = hir.get_if_local(def_id)
|
&& let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) = hir.get_if_local(def_id)
|
||||||
&& let ExprKind::Closure(closure) = kind
|
&& let ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Closure, .. }) = kind
|
||||||
&& closure.movability == None
|
|
||||||
&& let Some(Node::Expr(expr)) = hir.find_parent(*hir_id)
|
&& let Some(Node::Expr(expr)) = hir.find_parent(*hir_id)
|
||||||
{
|
{
|
||||||
let mut cur_expr = expr;
|
let mut cur_expr = expr;
|
||||||
@ -1067,12 +1066,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_make_local_mut(
|
fn suggest_make_local_mut(&self, err: &mut DiagnosticBuilder<'_>, local: Local, name: Symbol) {
|
||||||
&self,
|
|
||||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
|
||||||
local: Local,
|
|
||||||
name: Symbol,
|
|
||||||
) {
|
|
||||||
let local_decl = &self.body.local_decls[local];
|
let local_decl = &self.body.local_decls[local];
|
||||||
|
|
||||||
let (pointer_sigil, pointer_desc) =
|
let (pointer_sigil, pointer_desc) =
|
||||||
@ -1223,19 +1217,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
{
|
{
|
||||||
match self
|
match self
|
||||||
.infcx
|
.infcx
|
||||||
.could_impl_trait(clone_trait, ty.peel_refs(), self.param_env)
|
.type_implements_trait_shallow(
|
||||||
|
clone_trait,
|
||||||
|
ty.peel_refs(),
|
||||||
|
self.param_env,
|
||||||
|
)
|
||||||
.as_deref()
|
.as_deref()
|
||||||
{
|
{
|
||||||
Some([]) => {
|
Some([]) => {
|
||||||
// The type implements Clone.
|
// FIXME: This error message isn't useful, since we're just
|
||||||
err.span_help(
|
// vaguely suggesting to clone a value that already
|
||||||
expr.span,
|
// implements `Clone`.
|
||||||
format!(
|
//
|
||||||
"you can `clone` the `{}` value and consume it, but this \
|
// A correct suggestion here would take into account the fact
|
||||||
might not be your desired behavior",
|
// that inference may be affected by missing types on bindings,
|
||||||
ty.peel_refs(),
|
// etc., to improve "tests/ui/borrowck/issue-91206.stderr", for
|
||||||
),
|
// example.
|
||||||
);
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) =
|
if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) =
|
||||||
@ -1294,7 +1291,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
// The type doesn't implement Clone because of unmet obligations.
|
// The type doesn't implement Clone because of unmet obligations.
|
||||||
for error in errors {
|
for error in errors {
|
||||||
if let traits::FulfillmentErrorCode::CodeSelectionError(
|
if let traits::FulfillmentErrorCode::SelectionError(
|
||||||
traits::SelectionError::Unimplemented,
|
traits::SelectionError::Unimplemented,
|
||||||
) = error.code
|
) = error.code
|
||||||
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
||||||
|
|||||||
@ -206,7 +206,7 @@ impl OutlivesSuggestionBuilder {
|
|||||||
// If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
|
// If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
|
||||||
// list of diagnostics.
|
// list of diagnostics.
|
||||||
let mut diag = if suggested.len() == 1 {
|
let mut diag = if suggested.len() == 1 {
|
||||||
mbcx.infcx.tcx.sess.dcx().struct_help(match suggested.last().unwrap() {
|
mbcx.dcx().struct_help(match suggested.last().unwrap() {
|
||||||
SuggestedConstraint::Outlives(a, bs) => {
|
SuggestedConstraint::Outlives(a, bs) => {
|
||||||
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect();
|
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect();
|
||||||
format!("add bound `{a}: {}`", bs.join(" + "))
|
format!("add bound `{a}: {}`", bs.join(" + "))
|
||||||
@ -222,7 +222,6 @@ impl OutlivesSuggestionBuilder {
|
|||||||
let mut diag = mbcx
|
let mut diag = mbcx
|
||||||
.infcx
|
.infcx
|
||||||
.tcx
|
.tcx
|
||||||
.sess
|
|
||||||
.dcx()
|
.dcx()
|
||||||
.struct_help("the following changes may resolve your lifetime errors");
|
.struct_help("the following changes may resolve your lifetime errors");
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
//! Error reporting machinery for lifetime errors.
|
//! Error reporting machinery for lifetime errors.
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::Res::Def;
|
use rustc_hir::def::Res::Def;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
@ -27,7 +27,7 @@ use rustc_middle::ty::TypeVisitor;
|
|||||||
use rustc_middle::ty::{self, RegionVid, Ty};
|
use rustc_middle::ty::{self, RegionVid, Ty};
|
||||||
use rustc_middle::ty::{Region, TyCtxt};
|
use rustc_middle::ty::{Region, TyCtxt};
|
||||||
use rustc_span::symbol::{kw, Ident};
|
use rustc_span::symbol::{kw, Ident};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::borrowck_errors;
|
use crate::borrowck_errors;
|
||||||
use crate::session_diagnostics::{
|
use crate::session_diagnostics::{
|
||||||
@ -84,7 +84,7 @@ impl<'tcx> RegionErrors<'tcx> {
|
|||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) {
|
pub fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) {
|
||||||
let val = val.into();
|
let val = val.into();
|
||||||
self.1.sess.span_delayed_bug(DUMMY_SP, format!("{val:?}"));
|
self.1.sess.dcx().delayed_bug(format!("{val:?}"));
|
||||||
self.0.push(val);
|
self.0.push(val);
|
||||||
}
|
}
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
@ -202,7 +202,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
// and the span which bounded to the trait for adding 'static lifetime suggestion
|
// and the span which bounded to the trait for adding 'static lifetime suggestion
|
||||||
fn suggest_static_lifetime_for_gat_from_hrtb(
|
fn suggest_static_lifetime_for_gat_from_hrtb(
|
||||||
&self,
|
&self,
|
||||||
diag: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
diag: &mut DiagnosticBuilder<'_>,
|
||||||
lower_bound: RegionVid,
|
lower_bound: RegionVid,
|
||||||
) {
|
) {
|
||||||
let mut suggestions = vec![];
|
let mut suggestions = vec![];
|
||||||
@ -327,11 +327,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
// to report it; we could probably handle it by
|
// to report it; we could probably handle it by
|
||||||
// iterating over the universal regions and reporting
|
// iterating over the universal regions and reporting
|
||||||
// an error that multiple bounds are required.
|
// an error that multiple bounds are required.
|
||||||
let mut diag =
|
let mut diag = self.dcx().create_err(GenericDoesNotLiveLongEnough {
|
||||||
self.infcx.tcx.sess.create_err(GenericDoesNotLiveLongEnough {
|
kind: type_test.generic_kind.to_string(),
|
||||||
kind: type_test.generic_kind.to_string(),
|
span: type_test_span,
|
||||||
span: type_test_span,
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Add notes and suggestions for the case of 'static lifetime
|
// Add notes and suggestions for the case of 'static lifetime
|
||||||
// implied but not specified when a generic associated types
|
// implied but not specified when a generic associated types
|
||||||
@ -349,7 +348,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
|
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
|
||||||
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
|
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
|
||||||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||||
let mut diag = unexpected_hidden_region_diagnostic(
|
let diag = unexpected_hidden_region_diagnostic(
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
span,
|
span,
|
||||||
named_ty,
|
named_ty,
|
||||||
@ -573,7 +572,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
errci: &ErrorConstraintInfo<'tcx>,
|
errci: &ErrorConstraintInfo<'tcx>,
|
||||||
kind: ReturnConstraint,
|
kind: ReturnConstraint,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
||||||
|
|
||||||
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
||||||
@ -596,7 +595,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut diag = self.infcx.tcx.sess.create_err(err);
|
let mut diag = self.dcx().create_err(err);
|
||||||
|
|
||||||
if let ReturnConstraint::ClosureUpvar(upvar_field) = kind {
|
if let ReturnConstraint::ClosureUpvar(upvar_field) = kind {
|
||||||
let def_id = match self.regioncx.universal_regions().defining_ty {
|
let def_id = match self.regioncx.universal_regions().defining_ty {
|
||||||
@ -645,7 +644,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
fn report_escaping_data_error(
|
fn report_escaping_data_error(
|
||||||
&self,
|
&self,
|
||||||
errci: &ErrorConstraintInfo<'tcx>,
|
errci: &ErrorConstraintInfo<'tcx>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let ErrorConstraintInfo { span, category, .. } = errci;
|
let ErrorConstraintInfo { span, category, .. } = errci;
|
||||||
|
|
||||||
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
|
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
|
||||||
@ -744,10 +743,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
/// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
|
/// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
|
||||||
/// | is returning data with lifetime `'b`
|
/// | is returning data with lifetime `'b`
|
||||||
/// ```
|
/// ```
|
||||||
fn report_general_error(
|
fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> DiagnosticBuilder<'tcx> {
|
||||||
&self,
|
|
||||||
errci: &ErrorConstraintInfo<'tcx>,
|
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
|
||||||
let ErrorConstraintInfo {
|
let ErrorConstraintInfo {
|
||||||
fr,
|
fr,
|
||||||
fr_is_local,
|
fr_is_local,
|
||||||
@ -761,7 +757,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
let mir_def_name = self.infcx.tcx.def_descr(self.mir_def_id().to_def_id());
|
let mir_def_name = self.infcx.tcx.def_descr(self.mir_def_id().to_def_id());
|
||||||
|
|
||||||
let err = LifetimeOutliveErr { span: *span };
|
let err = LifetimeOutliveErr { span: *span };
|
||||||
let mut diag = self.infcx.tcx.sess.create_err(err);
|
let mut diag = self.dcx().create_err(err);
|
||||||
|
|
||||||
// In certain scenarios, such as the one described in issue #118021,
|
// In certain scenarios, such as the one described in issue #118021,
|
||||||
// we might encounter a lifetime that cannot be named.
|
// we might encounter a lifetime that cannot be named.
|
||||||
@ -1045,11 +1041,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
hir::ExprKind::Closure(hir::Closure {
|
hir::ExprKind::Closure(hir::Closure {
|
||||||
capture_clause: hir::CaptureBy::Ref,
|
capture_clause: hir::CaptureBy::Ref,
|
||||||
body,
|
kind,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let body = map.body(*body);
|
if !matches!(
|
||||||
if !matches!(body.coroutine_kind, Some(hir::CoroutineKind::Async(..))) {
|
kind,
|
||||||
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
|
hir::CoroutineDesugaring::Async,
|
||||||
|
_
|
||||||
|
),)
|
||||||
|
) {
|
||||||
closure_span = Some(expr.span.shrink_to_lo());
|
closure_span = Some(expr.span.shrink_to_lo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -188,7 +188,7 @@ impl Display for RegionName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl rustc_errors::IntoDiagnosticArg for RegionName {
|
impl rustc_errors::IntoDiagnosticArg for RegionName {
|
||||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue {
|
||||||
self.to_string().into_diagnostic_arg()
|
self.to_string().into_diagnostic_arg()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,7 +620,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
) => {
|
) => {
|
||||||
// HIR lowering sometimes doesn't catch this in erroneous
|
// HIR lowering sometimes doesn't catch this in erroneous
|
||||||
// programs, so we need to use span_delayed_bug here. See #82126.
|
// programs, so we need to use span_delayed_bug here. See #82126.
|
||||||
self.infcx.tcx.sess.span_delayed_bug(
|
self.dcx().span_delayed_bug(
|
||||||
hir_arg.span(),
|
hir_arg.span(),
|
||||||
format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
|
format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
|
||||||
);
|
);
|
||||||
@ -674,7 +674,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
|
|
||||||
let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) {
|
let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) {
|
||||||
hir::Node::Expr(hir::Expr {
|
hir::Node::Expr(hir::Expr {
|
||||||
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, body, fn_decl_span, .. }),
|
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, kind, fn_decl_span, .. }),
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let (mut span, mut hir_ty) = match fn_decl.output {
|
let (mut span, mut hir_ty) = match fn_decl.output {
|
||||||
@ -683,55 +683,86 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
|
hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
|
||||||
};
|
};
|
||||||
let mir_description = match hir.body(body).coroutine_kind {
|
let mir_description = match kind {
|
||||||
Some(hir::CoroutineKind::Async(src)) => match src {
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
hir::CoroutineSource::Block => " of async block",
|
hir::CoroutineDesugaring::Async,
|
||||||
hir::CoroutineSource::Closure => " of async closure",
|
hir::CoroutineSource::Block,
|
||||||
hir::CoroutineSource::Fn => {
|
)) => " of async block",
|
||||||
let parent_item =
|
|
||||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
|
||||||
let output = &parent_item
|
|
||||||
.fn_decl()
|
|
||||||
.expect("coroutine lowered from async fn should be in fn")
|
|
||||||
.output;
|
|
||||||
span = output.span();
|
|
||||||
if let hir::FnRetTy::Return(ret) = output {
|
|
||||||
hir_ty = Some(self.get_future_inner_return_ty(*ret));
|
|
||||||
}
|
|
||||||
" of async function"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(hir::CoroutineKind::Gen(src)) => match src {
|
|
||||||
hir::CoroutineSource::Block => " of gen block",
|
|
||||||
hir::CoroutineSource::Closure => " of gen closure",
|
|
||||||
hir::CoroutineSource::Fn => {
|
|
||||||
let parent_item =
|
|
||||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
|
||||||
let output = &parent_item
|
|
||||||
.fn_decl()
|
|
||||||
.expect("coroutine lowered from gen fn should be in fn")
|
|
||||||
.output;
|
|
||||||
span = output.span();
|
|
||||||
" of gen function"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Some(hir::CoroutineKind::AsyncGen(src)) => match src {
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
hir::CoroutineSource::Block => " of async gen block",
|
hir::CoroutineDesugaring::Async,
|
||||||
hir::CoroutineSource::Closure => " of async gen closure",
|
hir::CoroutineSource::Closure,
|
||||||
hir::CoroutineSource::Fn => {
|
)) => " of async closure",
|
||||||
let parent_item =
|
|
||||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
let output = &parent_item
|
hir::CoroutineDesugaring::Async,
|
||||||
.fn_decl()
|
hir::CoroutineSource::Fn,
|
||||||
.expect("coroutine lowered from async gen fn should be in fn")
|
)) => {
|
||||||
.output;
|
let parent_item =
|
||||||
span = output.span();
|
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||||
" of async gen function"
|
let output = &parent_item
|
||||||
|
.fn_decl()
|
||||||
|
.expect("coroutine lowered from async fn should be in fn")
|
||||||
|
.output;
|
||||||
|
span = output.span();
|
||||||
|
if let hir::FnRetTy::Return(ret) = output {
|
||||||
|
hir_ty = Some(self.get_future_inner_return_ty(*ret));
|
||||||
}
|
}
|
||||||
},
|
" of async function"
|
||||||
Some(hir::CoroutineKind::Coroutine) => " of coroutine",
|
}
|
||||||
None => " of closure",
|
|
||||||
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
|
hir::CoroutineDesugaring::Gen,
|
||||||
|
hir::CoroutineSource::Block,
|
||||||
|
)) => " of gen block",
|
||||||
|
|
||||||
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
|
hir::CoroutineDesugaring::Gen,
|
||||||
|
hir::CoroutineSource::Closure,
|
||||||
|
)) => " of gen closure",
|
||||||
|
|
||||||
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
|
hir::CoroutineDesugaring::Gen,
|
||||||
|
hir::CoroutineSource::Fn,
|
||||||
|
)) => {
|
||||||
|
let parent_item =
|
||||||
|
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||||
|
let output = &parent_item
|
||||||
|
.fn_decl()
|
||||||
|
.expect("coroutine lowered from gen fn should be in fn")
|
||||||
|
.output;
|
||||||
|
span = output.span();
|
||||||
|
" of gen function"
|
||||||
|
}
|
||||||
|
|
||||||
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
|
hir::CoroutineDesugaring::AsyncGen,
|
||||||
|
hir::CoroutineSource::Block,
|
||||||
|
)) => " of async gen block",
|
||||||
|
|
||||||
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
|
hir::CoroutineDesugaring::AsyncGen,
|
||||||
|
hir::CoroutineSource::Closure,
|
||||||
|
)) => " of async gen closure",
|
||||||
|
|
||||||
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
|
hir::CoroutineDesugaring::AsyncGen,
|
||||||
|
hir::CoroutineSource::Fn,
|
||||||
|
)) => {
|
||||||
|
let parent_item =
|
||||||
|
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||||
|
let output = &parent_item
|
||||||
|
.fn_decl()
|
||||||
|
.expect("coroutine lowered from async gen fn should be in fn")
|
||||||
|
.output;
|
||||||
|
span = output.span();
|
||||||
|
" of async gen function"
|
||||||
|
}
|
||||||
|
|
||||||
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => {
|
||||||
|
" of coroutine"
|
||||||
|
}
|
||||||
|
hir::ClosureKind::Closure => " of closure",
|
||||||
};
|
};
|
||||||
(span, mir_description, hir_ty)
|
(span, mir_description, hir_ty)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,9 @@
|
|||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(lazy_cell)]
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
#![feature(trusted_step)]
|
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![recursion_limit = "256"]
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
@ -274,11 +271,12 @@ fn do_mir_borrowck<'tcx>(
|
|||||||
// The first argument is the coroutine type passed by value
|
// The first argument is the coroutine type passed by value
|
||||||
if let Some(local) = body.local_decls.raw.get(1)
|
if let Some(local) = body.local_decls.raw.get(1)
|
||||||
// Get the interior types and args which typeck computed
|
// Get the interior types and args which typeck computed
|
||||||
&& let ty::Coroutine(_, _, hir::Movability::Static) = local.ty.kind()
|
&& let ty::Coroutine(def_id, _) = *local.ty.kind()
|
||||||
|
&& tcx.coroutine_movability(def_id) == hir::Movability::Movable
|
||||||
{
|
{
|
||||||
false
|
|
||||||
} else {
|
|
||||||
true
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
for (idx, move_data) in promoted_move_data {
|
for (idx, move_data) in promoted_move_data {
|
||||||
@ -414,7 +412,7 @@ fn do_mir_borrowck<'tcx>(
|
|||||||
|
|
||||||
let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
|
let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
|
||||||
|
|
||||||
tcx.emit_spanned_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span })
|
tcx.emit_node_span_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span })
|
||||||
}
|
}
|
||||||
|
|
||||||
let tainted_by_errors = mbcx.emit_errors();
|
let tainted_by_errors = mbcx.emit_errors();
|
||||||
@ -702,7 +700,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
|
|||||||
} => {
|
} => {
|
||||||
self.consume_operand(loc, (func, span), flow_state);
|
self.consume_operand(loc, (func, span), flow_state);
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.consume_operand(loc, (arg, span), flow_state);
|
self.consume_operand(loc, (&arg.node, arg.span), flow_state);
|
||||||
}
|
}
|
||||||
self.mutate_place(loc, (*destination, span), Deep, flow_state);
|
self.mutate_place(loc, (*destination, span), Deep, flow_state);
|
||||||
}
|
}
|
||||||
@ -1306,7 +1304,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
// moved into the closure and subsequently used by the closure,
|
// moved into the closure and subsequently used by the closure,
|
||||||
// in order to populate our used_mut set.
|
// in order to populate our used_mut set.
|
||||||
match **aggregate_kind {
|
match **aggregate_kind {
|
||||||
AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _, _) => {
|
AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) => {
|
||||||
let def_id = def_id.expect_local();
|
let def_id = def_id.expect_local();
|
||||||
let BorrowCheckResult { used_mut_upvars, .. } =
|
let BorrowCheckResult { used_mut_upvars, .. } =
|
||||||
self.infcx.tcx.mir_borrowck(def_id);
|
self.infcx.tcx.mir_borrowck(def_id);
|
||||||
@ -1612,7 +1610,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
| ty::FnPtr(_)
|
| ty::FnPtr(_)
|
||||||
| ty::Dynamic(_, _, _)
|
| ty::Dynamic(_, _, _)
|
||||||
| ty::Closure(_, _)
|
| ty::Closure(_, _)
|
||||||
| ty::Coroutine(_, _, _)
|
| ty::Coroutine(_, _)
|
||||||
| ty::CoroutineWitness(..)
|
| ty::CoroutineWitness(..)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Tuple(_)
|
| ty::Tuple(_)
|
||||||
@ -1636,7 +1634,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Closure(_, _) | ty::Coroutine(_, _, _) | ty::Tuple(_) => (),
|
ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (),
|
||||||
ty::Bool
|
ty::Bool
|
||||||
| ty::Char
|
| ty::Char
|
||||||
| ty::Int(_)
|
| ty::Int(_)
|
||||||
@ -2134,7 +2132,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
// dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug`
|
// dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug`
|
||||||
// enabled. We don't want to ICE for that case, as other errors will have
|
// enabled. We don't want to ICE for that case, as other errors will have
|
||||||
// been emitted (#52262).
|
// been emitted (#52262).
|
||||||
self.infcx.tcx.sess.span_delayed_bug(
|
self.dcx().span_delayed_bug(
|
||||||
span,
|
span,
|
||||||
format!(
|
format!(
|
||||||
"Accessing `{place:?}` with the kind `{kind:?}` shouldn't be possible",
|
"Accessing `{place:?}` with the kind `{kind:?}` shouldn't be possible",
|
||||||
@ -2398,18 +2396,19 @@ mod error {
|
|||||||
/// and we want only the best of those errors.
|
/// and we want only the best of those errors.
|
||||||
///
|
///
|
||||||
/// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
|
/// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
|
||||||
/// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the
|
/// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of
|
||||||
/// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once
|
/// the `Place` of the previous most diagnostic. This happens instead of buffering the
|
||||||
/// all move errors have been reported, any diagnostics in this map are added to the buffer
|
/// error. Once all move errors have been reported, any diagnostics in this map are added
|
||||||
/// to be emitted.
|
/// to the buffer to be emitted.
|
||||||
///
|
///
|
||||||
/// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
|
/// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
|
||||||
/// when errors in the map are being re-added to the error buffer so that errors with the
|
/// when errors in the map are being re-added to the error buffer so that errors with the
|
||||||
/// same primary span come out in a consistent order.
|
/// same primary span come out in a consistent order.
|
||||||
buffered_move_errors:
|
buffered_move_errors:
|
||||||
BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>,
|
BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>,
|
||||||
buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>,
|
buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx>, usize)>,
|
||||||
/// Diagnostics to be reported buffer.
|
/// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder`
|
||||||
|
/// because it has a mixture of error diagnostics and non-error diagnostics.
|
||||||
buffered: Vec<Diagnostic>,
|
buffered: Vec<Diagnostic>,
|
||||||
/// Set to Some if we emit an error during borrowck
|
/// Set to Some if we emit an error during borrowck
|
||||||
tainted_by_errors: Option<ErrorGuaranteed>,
|
tainted_by_errors: Option<ErrorGuaranteed>,
|
||||||
@ -2426,18 +2425,18 @@ mod error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
|
||||||
if let None = self.tainted_by_errors {
|
if let None = self.tainted_by_errors {
|
||||||
self.tainted_by_errors = Some(self.tcx.sess.span_delayed_bug(
|
self.tainted_by_errors = Some(self.tcx.dcx().span_delayed_bug(
|
||||||
t.span.clone_ignoring_labels(),
|
t.span.clone_ignoring_labels(),
|
||||||
"diagnostic buffered but not emitted",
|
"diagnostic buffered but not emitted",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
t.buffer(&mut self.buffered);
|
self.buffered.push(t.into_diagnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) {
|
pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) {
|
||||||
t.buffer(&mut self.buffered);
|
self.buffered.push(t.into_diagnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) {
|
pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) {
|
||||||
@ -2446,7 +2445,7 @@ mod error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
|
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
|
||||||
self.errors.buffer_error(t);
|
self.errors.buffer_error(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2457,7 +2456,7 @@ mod error {
|
|||||||
pub fn buffer_move_error(
|
pub fn buffer_move_error(
|
||||||
&mut self,
|
&mut self,
|
||||||
move_out_indices: Vec<MoveOutIndex>,
|
move_out_indices: Vec<MoveOutIndex>,
|
||||||
place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>),
|
place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>),
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Some((_, diag)) =
|
if let Some((_, diag)) =
|
||||||
self.errors.buffered_move_errors.insert(move_out_indices, place_and_err)
|
self.errors.buffered_move_errors.insert(move_out_indices, place_and_err)
|
||||||
@ -2473,16 +2472,11 @@ mod error {
|
|||||||
pub fn get_buffered_mut_error(
|
pub fn get_buffered_mut_error(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Option<(DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)> {
|
) -> Option<(DiagnosticBuilder<'tcx>, usize)> {
|
||||||
self.errors.buffered_mut_errors.remove(&span)
|
self.errors.buffered_mut_errors.remove(&span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_mut_error(
|
pub fn buffer_mut_error(&mut self, span: Span, t: DiagnosticBuilder<'tcx>, count: usize) {
|
||||||
&mut self,
|
|
||||||
span: Span,
|
|
||||||
t: DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
|
||||||
count: usize,
|
|
||||||
) {
|
|
||||||
self.errors.buffered_mut_errors.insert(span, (t, count));
|
self.errors.buffered_mut_errors.insert(span, (t, count));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2490,20 +2484,21 @@ mod error {
|
|||||||
// Buffer any move errors that we collected and de-duplicated.
|
// Buffer any move errors that we collected and de-duplicated.
|
||||||
for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) {
|
for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) {
|
||||||
// We have already set tainted for this error, so just buffer it.
|
// We have already set tainted for this error, so just buffer it.
|
||||||
diag.buffer(&mut self.errors.buffered);
|
self.errors.buffered.push(diag.into_diagnostic());
|
||||||
}
|
}
|
||||||
for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) {
|
for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) {
|
||||||
if count > 10 {
|
if count > 10 {
|
||||||
diag.note(format!("...and {} other attempted mutable borrows", count - 10));
|
diag.note(format!("...and {} other attempted mutable borrows", count - 10));
|
||||||
}
|
}
|
||||||
diag.buffer(&mut self.errors.buffered);
|
self.errors.buffered.push(diag.into_diagnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.errors.buffered.is_empty() {
|
if !self.errors.buffered.is_empty() {
|
||||||
self.errors.buffered.sort_by_key(|diag| diag.sort_span);
|
self.errors.buffered.sort_by_key(|diag| diag.sort_span);
|
||||||
|
|
||||||
|
let dcx = self.dcx();
|
||||||
for diag in self.errors.buffered.drain(..) {
|
for diag in self.errors.buffered.drain(..) {
|
||||||
self.infcx.tcx.sess.dcx().emit_diagnostic(diag);
|
dcx.emit_diagnostic(diag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2517,7 +2512,7 @@ mod error {
|
|||||||
pub fn has_move_error(
|
pub fn has_move_error(
|
||||||
&self,
|
&self,
|
||||||
move_out_indices: &[MoveOutIndex],
|
move_out_indices: &[MoveOutIndex],
|
||||||
) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx, ErrorGuaranteed>)> {
|
) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> {
|
||||||
self.errors.buffered_move_errors.get(move_out_indices)
|
self.errors.buffered_move_errors.get(move_out_indices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
|||||||
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
|
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
|
||||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||||
use rustc_mir_dataflow::move_paths::MoveData;
|
use rustc_mir_dataflow::move_paths::MoveData;
|
||||||
|
use rustc_mir_dataflow::points::DenseLocationMap;
|
||||||
use rustc_mir_dataflow::ResultsCursor;
|
use rustc_mir_dataflow::ResultsCursor;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::env;
|
use std::env;
|
||||||
@ -27,7 +28,7 @@ use crate::{
|
|||||||
facts::{AllFacts, AllFactsExt, RustcFacts},
|
facts::{AllFacts, AllFactsExt, RustcFacts},
|
||||||
location::LocationTable,
|
location::LocationTable,
|
||||||
polonius,
|
polonius,
|
||||||
region_infer::{values::RegionValueElements, RegionInferenceContext},
|
region_infer::RegionInferenceContext,
|
||||||
renumber,
|
renumber,
|
||||||
type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
|
type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
|
||||||
universal_regions::UniversalRegions,
|
universal_regions::UniversalRegions,
|
||||||
@ -98,7 +99,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||||||
|
|
||||||
let universal_regions = Rc::new(universal_regions);
|
let universal_regions = Rc::new(universal_regions);
|
||||||
|
|
||||||
let elements = &Rc::new(RegionValueElements::new(body));
|
let elements = &Rc::new(DenseLocationMap::new(body));
|
||||||
|
|
||||||
// Run the MIR type-checker.
|
// Run the MIR type-checker.
|
||||||
let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
|
let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
|
||||||
@ -187,7 +188,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
|||||||
|
|
||||||
if !nll_errors.is_empty() {
|
if !nll_errors.is_empty() {
|
||||||
// Suppress unhelpful extra errors in `infer_opaque_types`.
|
// Suppress unhelpful extra errors in `infer_opaque_types`.
|
||||||
infcx.set_tainted_by_errors(infcx.tcx.sess.span_delayed_bug(
|
infcx.set_tainted_by_errors(infcx.dcx().span_delayed_bug(
|
||||||
body.span,
|
body.span,
|
||||||
"`compute_regions` tainted `infcx` with errors but did not emit any errors",
|
"`compute_regions` tainted `infcx` with errors but did not emit any errors",
|
||||||
));
|
));
|
||||||
@ -280,7 +281,7 @@ pub(super) fn dump_annotation<'tcx>(
|
|||||||
|
|
||||||
let def_span = tcx.def_span(body.source.def_id());
|
let def_span = tcx.def_span(body.source.def_id());
|
||||||
let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
|
let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
|
||||||
let mut err = tcx.sess.dcx().struct_span_note(def_span, "external requirements");
|
let mut err = tcx.dcx().struct_span_note(def_span, "external requirements");
|
||||||
|
|
||||||
regioncx.annotate(tcx, &mut err);
|
regioncx.annotate(tcx, &mut err);
|
||||||
|
|
||||||
@ -299,7 +300,7 @@ pub(super) fn dump_annotation<'tcx>(
|
|||||||
|
|
||||||
err
|
err
|
||||||
} else {
|
} else {
|
||||||
let mut err = tcx.sess.dcx().struct_span_note(def_span, "no external requirements");
|
let mut err = tcx.dcx().struct_span_note(def_span, "no external requirements");
|
||||||
regioncx.annotate(tcx, &mut err);
|
regioncx.annotate(tcx, &mut err);
|
||||||
|
|
||||||
err
|
err
|
||||||
|
|||||||
@ -120,7 +120,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
|
|||||||
} => {
|
} => {
|
||||||
self.consume_operand(location, func);
|
self.consume_operand(location, func);
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.consume_operand(location, arg);
|
self.consume_operand(location, &arg.node);
|
||||||
}
|
}
|
||||||
self.mutate_place(location, *destination, Deep);
|
self.mutate_place(location, *destination, Deep);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,8 @@ use rustc_middle::mir::{
|
|||||||
};
|
};
|
||||||
use rustc_middle::traits::ObligationCause;
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::traits::ObligationCauseCode;
|
use rustc_middle::traits::ObligationCauseCode;
|
||||||
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
|
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
|
||||||
|
use rustc_mir_dataflow::points::DenseLocationMap;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph};
|
use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph};
|
||||||
@ -30,8 +31,7 @@ use crate::{
|
|||||||
nll::PoloniusOutput,
|
nll::PoloniusOutput,
|
||||||
region_infer::reverse_sccs::ReverseSccGraph,
|
region_infer::reverse_sccs::ReverseSccGraph,
|
||||||
region_infer::values::{
|
region_infer::values::{
|
||||||
LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
|
LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex,
|
||||||
ToElementIndex,
|
|
||||||
},
|
},
|
||||||
type_check::{free_region_relations::UniversalRegionRelations, Locations},
|
type_check::{free_region_relations::UniversalRegionRelations, Locations},
|
||||||
universal_regions::UniversalRegions,
|
universal_regions::UniversalRegions,
|
||||||
@ -330,7 +330,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||||||
universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||||
type_tests: Vec<TypeTest<'tcx>>,
|
type_tests: Vec<TypeTest<'tcx>>,
|
||||||
liveness_constraints: LivenessValues,
|
liveness_constraints: LivenessValues,
|
||||||
elements: &Rc<RegionValueElements>,
|
elements: &Rc<DenseLocationMap>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
debug!("universal_regions: {:#?}", universal_regions);
|
debug!("universal_regions: {:#?}", universal_regions);
|
||||||
debug!("outlives constraints: {:#?}", outlives_constraints);
|
debug!("outlives constraints: {:#?}", outlives_constraints);
|
||||||
@ -1145,6 +1145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let ty = ty.fold_with(&mut OpaqueFolder { tcx });
|
let ty = ty.fold_with(&mut OpaqueFolder { tcx });
|
||||||
|
let mut failed = false;
|
||||||
|
|
||||||
let ty = tcx.fold_regions(ty, |r, _depth| {
|
let ty = tcx.fold_regions(ty, |r, _depth| {
|
||||||
let r_vid = self.to_region_vid(r);
|
let r_vid = self.to_region_vid(r);
|
||||||
@ -1160,15 +1161,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||||||
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
|
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
|
||||||
.find(|&u_r| self.eval_equal(u_r, r_vid))
|
.find(|&u_r| self.eval_equal(u_r, r_vid))
|
||||||
.map(|u_r| ty::Region::new_var(tcx, u_r))
|
.map(|u_r| ty::Region::new_var(tcx, u_r))
|
||||||
// In the case of a failure, use `ReErased`. We will eventually
|
// In case we could not find a named region to map to,
|
||||||
// return `None` in this case.
|
// we will return `None` below.
|
||||||
.unwrap_or(tcx.lifetimes.re_erased)
|
.unwrap_or_else(|| {
|
||||||
|
failed = true;
|
||||||
|
r
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
|
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
|
||||||
|
|
||||||
// This will be true if we failed to promote some region.
|
// This will be true if we failed to promote some region.
|
||||||
if ty.has_erased_regions() {
|
if failed {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -402,7 +402,7 @@ fn check_opaque_type_parameter_valid(
|
|||||||
let opaque_param = opaque_generics.param_at(i, tcx);
|
let opaque_param = opaque_generics.param_at(i, tcx);
|
||||||
let kind = opaque_param.kind.descr();
|
let kind = opaque_param.kind.descr();
|
||||||
|
|
||||||
return Err(tcx.sess.emit_err(NonGenericOpaqueTypeParam {
|
return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
|
||||||
ty: arg,
|
ty: arg,
|
||||||
kind,
|
kind,
|
||||||
span,
|
span,
|
||||||
@ -419,9 +419,9 @@ fn check_opaque_type_parameter_valid(
|
|||||||
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
|
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
|
||||||
.collect();
|
.collect();
|
||||||
return Err(tcx
|
return Err(tcx
|
||||||
.sess
|
.dcx()
|
||||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||||
.span_note(spans, format!("{descr} used multiple times"))
|
.with_span_note(spans, format!("{descr} used multiple times"))
|
||||||
.emit());
|
.emit());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,101 +1,18 @@
|
|||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_index::bit_set::SparseBitMatrix;
|
use rustc_index::bit_set::SparseBitMatrix;
|
||||||
use rustc_index::interval::IntervalSet;
|
use rustc_index::interval::IntervalSet;
|
||||||
use rustc_index::interval::SparseIntervalMatrix;
|
use rustc_index::interval::SparseIntervalMatrix;
|
||||||
use rustc_index::Idx;
|
use rustc_index::Idx;
|
||||||
use rustc_index::IndexVec;
|
use rustc_middle::mir::{BasicBlock, Location};
|
||||||
use rustc_middle::mir::{BasicBlock, Body, Location};
|
|
||||||
use rustc_middle::ty::{self, RegionVid};
|
use rustc_middle::ty::{self, RegionVid};
|
||||||
|
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::dataflow::BorrowIndex;
|
use crate::BorrowIndex;
|
||||||
|
|
||||||
/// Maps between a `Location` and a `PointIndex` (and vice versa).
|
|
||||||
pub(crate) struct RegionValueElements {
|
|
||||||
/// For each basic block, how many points are contained within?
|
|
||||||
statements_before_block: IndexVec<BasicBlock, usize>,
|
|
||||||
|
|
||||||
/// Map backward from each point to the basic block that it
|
|
||||||
/// belongs to.
|
|
||||||
basic_blocks: IndexVec<PointIndex, BasicBlock>,
|
|
||||||
|
|
||||||
num_points: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RegionValueElements {
|
|
||||||
pub(crate) fn new(body: &Body<'_>) -> Self {
|
|
||||||
let mut num_points = 0;
|
|
||||||
let statements_before_block: IndexVec<BasicBlock, usize> = body
|
|
||||||
.basic_blocks
|
|
||||||
.iter()
|
|
||||||
.map(|block_data| {
|
|
||||||
let v = num_points;
|
|
||||||
num_points += block_data.statements.len() + 1;
|
|
||||||
v
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
debug!("RegionValueElements: statements_before_block={:#?}", statements_before_block);
|
|
||||||
debug!("RegionValueElements: num_points={:#?}", num_points);
|
|
||||||
|
|
||||||
let mut basic_blocks = IndexVec::with_capacity(num_points);
|
|
||||||
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
|
|
||||||
basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb));
|
|
||||||
}
|
|
||||||
|
|
||||||
Self { statements_before_block, basic_blocks, num_points }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Total number of point indices
|
|
||||||
pub(crate) fn num_points(&self) -> usize {
|
|
||||||
self.num_points
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a `Location` into a `PointIndex`. O(1).
|
|
||||||
pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
|
|
||||||
let Location { block, statement_index } = location;
|
|
||||||
let start_index = self.statements_before_block[block];
|
|
||||||
PointIndex::new(start_index + statement_index)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a `Location` into a `PointIndex`. O(1).
|
|
||||||
pub(crate) fn entry_point(&self, block: BasicBlock) -> PointIndex {
|
|
||||||
let start_index = self.statements_before_block[block];
|
|
||||||
PointIndex::new(start_index)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the PointIndex for the block start of this index.
|
|
||||||
pub(crate) fn to_block_start(&self, index: PointIndex) -> PointIndex {
|
|
||||||
PointIndex::new(self.statements_before_block[self.basic_blocks[index]])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a `PointIndex` back to a location. O(1).
|
|
||||||
pub(crate) fn to_location(&self, index: PointIndex) -> Location {
|
|
||||||
assert!(index.index() < self.num_points);
|
|
||||||
let block = self.basic_blocks[index];
|
|
||||||
let start_index = self.statements_before_block[block];
|
|
||||||
let statement_index = index.index() - start_index;
|
|
||||||
Location { block, statement_index }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sometimes we get point-indices back from bitsets that may be
|
|
||||||
/// out of range (because they round up to the nearest 2^N number
|
|
||||||
/// of bits). Use this function to filter such points out if you
|
|
||||||
/// like.
|
|
||||||
pub(crate) fn point_in_range(&self, index: PointIndex) -> bool {
|
|
||||||
index.index() < self.num_points
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
|
||||||
/// A single integer representing a `Location` in the MIR control-flow
|
|
||||||
/// graph. Constructed efficiently from `RegionValueElements`.
|
|
||||||
#[orderable]
|
|
||||||
#[debug_format = "PointIndex({})"]
|
|
||||||
pub struct PointIndex {}
|
|
||||||
}
|
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
rustc_index::newtype_index! {
|
||||||
/// A single integer representing a `ty::Placeholder`.
|
/// A single integer representing a `ty::Placeholder`.
|
||||||
@ -123,10 +40,17 @@ pub(crate) enum RegionElement {
|
|||||||
/// an interval matrix storing liveness ranges for each region-vid.
|
/// an interval matrix storing liveness ranges for each region-vid.
|
||||||
pub(crate) struct LivenessValues {
|
pub(crate) struct LivenessValues {
|
||||||
/// The map from locations to points.
|
/// The map from locations to points.
|
||||||
elements: Rc<RegionValueElements>,
|
elements: Rc<DenseLocationMap>,
|
||||||
|
|
||||||
|
/// Which regions are live. This is exclusive with the fine-grained tracking in `points`, and
|
||||||
|
/// currently only used for validating promoteds (which don't care about more precise tracking).
|
||||||
|
live_regions: Option<FxHashSet<RegionVid>>,
|
||||||
|
|
||||||
/// For each region: the points where it is live.
|
/// For each region: the points where it is live.
|
||||||
points: SparseIntervalMatrix<RegionVid, PointIndex>,
|
///
|
||||||
|
/// This is not initialized for promoteds, because we don't care *where* within a promoted a
|
||||||
|
/// region is live, only that it is.
|
||||||
|
points: Option<SparseIntervalMatrix<RegionVid, PointIndex>>,
|
||||||
|
|
||||||
/// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at
|
/// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at
|
||||||
/// that point.
|
/// that point.
|
||||||
@ -155,24 +79,52 @@ impl LiveLoans {
|
|||||||
|
|
||||||
impl LivenessValues {
|
impl LivenessValues {
|
||||||
/// Create an empty map of regions to locations where they're live.
|
/// Create an empty map of regions to locations where they're live.
|
||||||
pub(crate) fn new(elements: Rc<RegionValueElements>) -> Self {
|
pub(crate) fn with_specific_points(elements: Rc<DenseLocationMap>) -> Self {
|
||||||
LivenessValues {
|
LivenessValues {
|
||||||
points: SparseIntervalMatrix::new(elements.num_points),
|
live_regions: None,
|
||||||
|
points: Some(SparseIntervalMatrix::new(elements.num_points())),
|
||||||
|
elements,
|
||||||
|
loans: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an empty map of regions to locations where they're live.
|
||||||
|
///
|
||||||
|
/// Unlike `with_specific_points`, does not track exact locations where something is live, only
|
||||||
|
/// which regions are live.
|
||||||
|
pub(crate) fn without_specific_points(elements: Rc<DenseLocationMap>) -> Self {
|
||||||
|
LivenessValues {
|
||||||
|
live_regions: Some(Default::default()),
|
||||||
|
points: None,
|
||||||
elements,
|
elements,
|
||||||
loans: None,
|
loans: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate through each region that has a value in this set.
|
/// Iterate through each region that has a value in this set.
|
||||||
pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> {
|
pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> + '_ {
|
||||||
self.points.rows()
|
self.points.as_ref().expect("use with_specific_points").rows()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate through each region that has a value in this set.
|
||||||
|
// We are passing query instability implications to the caller.
|
||||||
|
#[rustc_lint_query_instability]
|
||||||
|
#[allow(rustc::potential_query_instability)]
|
||||||
|
pub(crate) fn live_regions_unordered(&self) -> impl Iterator<Item = RegionVid> + '_ {
|
||||||
|
self.live_regions.as_ref().unwrap().iter().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Records `region` as being live at the given `location`.
|
/// Records `region` as being live at the given `location`.
|
||||||
pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) {
|
pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) {
|
||||||
debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
|
|
||||||
let point = self.elements.point_from_location(location);
|
let point = self.elements.point_from_location(location);
|
||||||
self.points.insert(region, point);
|
debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
|
||||||
|
if let Some(points) = &mut self.points {
|
||||||
|
points.insert(region, point);
|
||||||
|
} else {
|
||||||
|
if self.elements.point_in_range(point) {
|
||||||
|
self.live_regions.as_mut().unwrap().insert(region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When available, record the loans flowing into this region as live at the given point.
|
// When available, record the loans flowing into this region as live at the given point.
|
||||||
if let Some(loans) = self.loans.as_mut() {
|
if let Some(loans) = self.loans.as_mut() {
|
||||||
@ -185,7 +137,13 @@ impl LivenessValues {
|
|||||||
/// Records `region` as being live at all the given `points`.
|
/// Records `region` as being live at all the given `points`.
|
||||||
pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet<PointIndex>) {
|
pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet<PointIndex>) {
|
||||||
debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
|
debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
|
||||||
self.points.union_row(region, points);
|
if let Some(this) = &mut self.points {
|
||||||
|
this.union_row(region, points);
|
||||||
|
} else {
|
||||||
|
if points.iter().any(|point| self.elements.point_in_range(point)) {
|
||||||
|
self.live_regions.as_mut().unwrap().insert(region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When available, record the loans flowing into this region as live at the given points.
|
// When available, record the loans flowing into this region as live at the given points.
|
||||||
if let Some(loans) = self.loans.as_mut() {
|
if let Some(loans) = self.loans.as_mut() {
|
||||||
@ -201,23 +159,33 @@ impl LivenessValues {
|
|||||||
|
|
||||||
/// Records `region` as being live at all the control-flow points.
|
/// Records `region` as being live at all the control-flow points.
|
||||||
pub(crate) fn add_all_points(&mut self, region: RegionVid) {
|
pub(crate) fn add_all_points(&mut self, region: RegionVid) {
|
||||||
self.points.insert_all_into_row(region);
|
if let Some(points) = &mut self.points {
|
||||||
|
points.insert_all_into_row(region);
|
||||||
|
} else {
|
||||||
|
self.live_regions.as_mut().unwrap().insert(region);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether `region` is marked live at the given `location`.
|
/// Returns whether `region` is marked live at the given `location`.
|
||||||
pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
|
pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
|
||||||
let point = self.elements.point_from_location(location);
|
let point = self.elements.point_from_location(location);
|
||||||
self.points.row(region).is_some_and(|r| r.contains(point))
|
if let Some(points) = &self.points {
|
||||||
}
|
points.row(region).is_some_and(|r| r.contains(point))
|
||||||
|
} else {
|
||||||
/// Returns whether `region` is marked live at any location.
|
unreachable!(
|
||||||
pub(crate) fn is_live_anywhere(&self, region: RegionVid) -> bool {
|
"Should be using LivenessValues::with_specific_points to ask whether live at a location"
|
||||||
self.live_points(region).next().is_some()
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator of all the points where `region` is live.
|
/// Returns an iterator of all the points where `region` is live.
|
||||||
fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> + '_ {
|
fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> + '_ {
|
||||||
self.points
|
let Some(points) = &self.points else {
|
||||||
|
unreachable!(
|
||||||
|
"Should be using LivenessValues::with_specific_points to ask whether live at a location"
|
||||||
|
)
|
||||||
|
};
|
||||||
|
points
|
||||||
.row(region)
|
.row(region)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|set| set.iter())
|
.flat_map(|set| set.iter())
|
||||||
@ -298,7 +266,7 @@ impl PlaceholderIndices {
|
|||||||
/// it would also contain various points from within the function.
|
/// it would also contain various points from within the function.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct RegionValues<N: Idx> {
|
pub(crate) struct RegionValues<N: Idx> {
|
||||||
elements: Rc<RegionValueElements>,
|
elements: Rc<DenseLocationMap>,
|
||||||
placeholder_indices: Rc<PlaceholderIndices>,
|
placeholder_indices: Rc<PlaceholderIndices>,
|
||||||
points: SparseIntervalMatrix<N, PointIndex>,
|
points: SparseIntervalMatrix<N, PointIndex>,
|
||||||
free_regions: SparseBitMatrix<N, RegionVid>,
|
free_regions: SparseBitMatrix<N, RegionVid>,
|
||||||
@ -313,14 +281,14 @@ impl<N: Idx> RegionValues<N> {
|
|||||||
/// Each of the regions in num_region_variables will be initialized with an
|
/// Each of the regions in num_region_variables will be initialized with an
|
||||||
/// empty set of points and no causal information.
|
/// empty set of points and no causal information.
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
elements: &Rc<RegionValueElements>,
|
elements: &Rc<DenseLocationMap>,
|
||||||
num_universal_regions: usize,
|
num_universal_regions: usize,
|
||||||
placeholder_indices: &Rc<PlaceholderIndices>,
|
placeholder_indices: &Rc<PlaceholderIndices>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let num_placeholders = placeholder_indices.len();
|
let num_placeholders = placeholder_indices.len();
|
||||||
Self {
|
Self {
|
||||||
elements: elements.clone(),
|
elements: elements.clone(),
|
||||||
points: SparseIntervalMatrix::new(elements.num_points),
|
points: SparseIntervalMatrix::new(elements.num_points()),
|
||||||
placeholder_indices: placeholder_indices.clone(),
|
placeholder_indices: placeholder_indices.clone(),
|
||||||
free_regions: SparseBitMatrix::new(num_universal_regions),
|
free_regions: SparseBitMatrix::new(num_universal_regions),
|
||||||
placeholders: SparseBitMatrix::new(num_placeholders),
|
placeholders: SparseBitMatrix::new(num_placeholders),
|
||||||
@ -372,7 +340,10 @@ impl<N: Idx> RegionValues<N> {
|
|||||||
/// elements for the region `from` from `values` and add them to
|
/// elements for the region `from` from `values` and add them to
|
||||||
/// the region `to` in `self`.
|
/// the region `to` in `self`.
|
||||||
pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) {
|
pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) {
|
||||||
if let Some(set) = values.points.row(from) {
|
let Some(value_points) = &values.points else {
|
||||||
|
panic!("LivenessValues must track specific points for use in merge_liveness");
|
||||||
|
};
|
||||||
|
if let Some(set) = value_points.row(from) {
|
||||||
self.points.union_row(to, set);
|
self.points.union_row(to, set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -486,7 +457,7 @@ impl ToElementIndex for ty::PlaceholderRegion {
|
|||||||
|
|
||||||
/// For debugging purposes, returns a pretty-printed string of the given points.
|
/// For debugging purposes, returns a pretty-printed string of the given points.
|
||||||
pub(crate) fn pretty_print_points(
|
pub(crate) fn pretty_print_points(
|
||||||
elements: &RegionValueElements,
|
elements: &DenseLocationMap,
|
||||||
points: impl IntoIterator<Item = PointIndex>,
|
points: impl IntoIterator<Item = PointIndex>,
|
||||||
) -> String {
|
) -> String {
|
||||||
pretty_print_region_elements(
|
pretty_print_region_elements(
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use rustc_errors::MultiSpan;
|
use rustc_errors::{codes::*, MultiSpan};
|
||||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||||
use rustc_middle::ty::{GenericArg, Ty};
|
use rustc_middle::ty::{GenericArg, Ty};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -6,7 +6,7 @@ use rustc_span::Span;
|
|||||||
use crate::diagnostics::RegionName;
|
use crate::diagnostics::RegionName;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(borrowck_move_unsized, code = "E0161")]
|
#[diag(borrowck_move_unsized, code = E0161)]
|
||||||
pub(crate) struct MoveUnsized<'tcx> {
|
pub(crate) struct MoveUnsized<'tcx> {
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
@ -281,7 +281,7 @@ pub(crate) enum CaptureVarCause {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(borrowck_cannot_move_when_borrowed, code = "E0505")]
|
#[diag(borrowck_cannot_move_when_borrowed, code = E0505)]
|
||||||
pub(crate) struct MoveBorrow<'a> {
|
pub(crate) struct MoveBorrow<'a> {
|
||||||
pub place: &'a str,
|
pub place: &'a str,
|
||||||
pub borrow_place: &'a str,
|
pub borrow_place: &'a str,
|
||||||
@ -294,7 +294,7 @@ pub(crate) struct MoveBorrow<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(borrowck_opaque_type_non_generic_param, code = "E0792")]
|
#[diag(borrowck_opaque_type_non_generic_param, code = E0792)]
|
||||||
pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
|
pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
|
||||||
pub ty: GenericArg<'tcx>,
|
pub ty: GenericArg<'tcx>,
|
||||||
pub kind: &'a str,
|
pub kind: &'a str,
|
||||||
|
|||||||
@ -33,7 +33,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
|
|||||||
/// our special inference variable there, we would mess that up.
|
/// our special inference variable there, we would mess that up.
|
||||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||||
implicit_region_bound: ty::Region<'tcx>,
|
implicit_region_bound: ty::Region<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
span: Span,
|
span: Span,
|
||||||
category: ConstraintCategory<'tcx>,
|
category: ConstraintCategory<'tcx>,
|
||||||
@ -47,7 +47,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||||||
universal_regions: &'a UniversalRegions<'tcx>,
|
universal_regions: &'a UniversalRegions<'tcx>,
|
||||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||||
implicit_region_bound: ty::Region<'tcx>,
|
implicit_region_bound: ty::Region<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
span: Span,
|
span: Span,
|
||||||
category: ConstraintCategory<'tcx>,
|
category: ConstraintCategory<'tcx>,
|
||||||
@ -59,7 +59,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||||||
universal_regions,
|
universal_regions,
|
||||||
region_bound_pairs,
|
region_bound_pairs,
|
||||||
implicit_region_bound,
|
implicit_region_bound,
|
||||||
param_env,
|
known_type_outlives_obligations,
|
||||||
locations,
|
locations,
|
||||||
span,
|
span,
|
||||||
category,
|
category,
|
||||||
@ -136,7 +136,11 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||||||
|
|
||||||
// Extract out various useful fields we'll need below.
|
// Extract out various useful fields we'll need below.
|
||||||
let ConstraintConversion {
|
let ConstraintConversion {
|
||||||
tcx, region_bound_pairs, implicit_region_bound, param_env, ..
|
tcx,
|
||||||
|
region_bound_pairs,
|
||||||
|
implicit_region_bound,
|
||||||
|
known_type_outlives_obligations,
|
||||||
|
..
|
||||||
} = *self;
|
} = *self;
|
||||||
|
|
||||||
let ty::OutlivesPredicate(k1, r2) = predicate;
|
let ty::OutlivesPredicate(k1, r2) = predicate;
|
||||||
@ -157,7 +161,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||||||
tcx,
|
tcx,
|
||||||
region_bound_pairs,
|
region_bound_pairs,
|
||||||
Some(implicit_region_bound),
|
Some(implicit_region_bound),
|
||||||
param_env,
|
known_type_outlives_obligations,
|
||||||
)
|
)
|
||||||
.type_must_outlive(origin, t1, r2, constraint_category);
|
.type_must_outlive(origin, t1, r2, constraint_category);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use rustc_data_structures::frozen::Frozen;
|
use rustc_data_structures::frozen::Frozen;
|
||||||
use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
|
use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||||
use rustc_infer::infer::outlives;
|
use rustc_infer::infer::outlives;
|
||||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||||
@ -44,12 +45,14 @@ type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
|
|||||||
pub(crate) struct CreateResult<'tcx> {
|
pub(crate) struct CreateResult<'tcx> {
|
||||||
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||||
pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>,
|
pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>,
|
||||||
|
pub(crate) known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||||
pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
|
pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create<'tcx>(
|
pub(crate) fn create<'tcx>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||||
implicit_region_bound: ty::Region<'tcx>,
|
implicit_region_bound: ty::Region<'tcx>,
|
||||||
universal_regions: &Rc<UniversalRegions<'tcx>>,
|
universal_regions: &Rc<UniversalRegions<'tcx>>,
|
||||||
constraints: &mut MirTypeckRegionConstraints<'tcx>,
|
constraints: &mut MirTypeckRegionConstraints<'tcx>,
|
||||||
@ -57,6 +60,7 @@ pub(crate) fn create<'tcx>(
|
|||||||
UniversalRegionRelationsBuilder {
|
UniversalRegionRelationsBuilder {
|
||||||
infcx,
|
infcx,
|
||||||
param_env,
|
param_env,
|
||||||
|
known_type_outlives_obligations,
|
||||||
implicit_region_bound,
|
implicit_region_bound,
|
||||||
constraints,
|
constraints,
|
||||||
universal_regions: universal_regions.clone(),
|
universal_regions: universal_regions.clone(),
|
||||||
@ -174,6 +178,7 @@ impl UniversalRegionRelations<'_> {
|
|||||||
struct UniversalRegionRelationsBuilder<'this, 'tcx> {
|
struct UniversalRegionRelationsBuilder<'this, 'tcx> {
|
||||||
infcx: &'this InferCtxt<'tcx>,
|
infcx: &'this InferCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||||
implicit_region_bound: ty::Region<'tcx>,
|
implicit_region_bound: ty::Region<'tcx>,
|
||||||
constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
|
constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
|
||||||
@ -195,9 +200,12 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
|
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
|
||||||
let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
|
let tcx = self.infcx.tcx;
|
||||||
|
let defining_ty_def_id = self.universal_regions.defining_ty.def_id().expect_local();
|
||||||
|
let span = tcx.def_span(defining_ty_def_id);
|
||||||
|
|
||||||
// Insert the facts we know from the predicates. Why? Why not.
|
// Insert the `'a: 'b` we know from the predicates.
|
||||||
|
// This does not consider the type-outlives.
|
||||||
let param_env = self.param_env;
|
let param_env = self.param_env;
|
||||||
self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
|
self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
|
||||||
|
|
||||||
@ -275,6 +283,26 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||||||
normalized_inputs_and_output.push(norm_ty);
|
normalized_inputs_and_output.push(norm_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add implied bounds from impl header.
|
||||||
|
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
|
||||||
|
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
|
||||||
|
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = self
|
||||||
|
.param_env
|
||||||
|
.and(type_op::normalize::Normalize::new(ty))
|
||||||
|
.fully_perform(self.infcx, span)
|
||||||
|
else {
|
||||||
|
tcx.dcx().span_delayed_bug(span, format!("failed to normalize {ty:?}"));
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
constraints.extend(c);
|
||||||
|
|
||||||
|
// We currently add implied bounds from the normalized ty only.
|
||||||
|
// This is more conservative and matches wfcheck behavior.
|
||||||
|
let c = self.add_implied_bounds(norm_ty);
|
||||||
|
constraints.extend(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for c in constraints {
|
for c in constraints {
|
||||||
self.push_region_constraints(c, span);
|
self.push_region_constraints(c, span);
|
||||||
}
|
}
|
||||||
@ -285,6 +313,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||||||
outlives: self.outlives.freeze(),
|
outlives: self.outlives.freeze(),
|
||||||
inverse_outlives: self.inverse_outlives.freeze(),
|
inverse_outlives: self.inverse_outlives.freeze(),
|
||||||
}),
|
}),
|
||||||
|
known_type_outlives_obligations: self.known_type_outlives_obligations,
|
||||||
region_bound_pairs: self.region_bound_pairs,
|
region_bound_pairs: self.region_bound_pairs,
|
||||||
normalized_inputs_and_output,
|
normalized_inputs_and_output,
|
||||||
}
|
}
|
||||||
@ -299,7 +328,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||||||
&self.universal_regions,
|
&self.universal_regions,
|
||||||
&self.region_bound_pairs,
|
&self.region_bound_pairs,
|
||||||
self.implicit_region_bound,
|
self.implicit_region_bound,
|
||||||
self.param_env,
|
self.known_type_outlives_obligations,
|
||||||
Locations::All(span),
|
Locations::All(span),
|
||||||
span,
|
span,
|
||||||
ConstraintCategory::Internal,
|
ConstraintCategory::Internal,
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
|
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
|
||||||
//! contain revealed `impl Trait` values).
|
//! contain revealed `impl Trait` values).
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
use rustc_infer::infer::BoundRegionConversionTime;
|
use rustc_infer::infer::BoundRegionConversionTime;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
@ -22,7 +23,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
#[instrument(skip(self, body), level = "debug")]
|
#[instrument(skip(self, body), level = "debug")]
|
||||||
pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) {
|
pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) {
|
||||||
let mir_def_id = body.source.def_id().expect_local();
|
let mir_def_id = body.source.def_id().expect_local();
|
||||||
if !self.tcx().is_closure(mir_def_id.to_def_id()) {
|
if !self.tcx().is_closure_or_coroutine(mir_def_id.to_def_id()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
|
let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
|
||||||
@ -39,9 +40,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
user_provided_sig,
|
user_provided_sig,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip(
|
let is_coroutine_with_implicit_resume_ty = self.tcx().is_coroutine(mir_def_id.to_def_id())
|
||||||
// In MIR, closure args begin with an implicit `self`. Skip it!
|
&& user_provided_sig.inputs().is_empty();
|
||||||
body.args_iter().skip(1).map(|local| &body.local_decls[local]),
|
|
||||||
|
for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq(
|
||||||
|
// In MIR, closure args begin with an implicit `self`.
|
||||||
|
// Also, coroutines have a resume type which may be implicitly `()`.
|
||||||
|
body.args_iter()
|
||||||
|
.skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 })
|
||||||
|
.map(|local| &body.local_decls[local]),
|
||||||
) {
|
) {
|
||||||
self.ascribe_user_type_skip_wf(
|
self.ascribe_user_type_skip_wf(
|
||||||
arg_decl.ty,
|
arg_decl.ty,
|
||||||
@ -76,7 +83,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
|
for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
|
||||||
if argument_index + 1 >= body.local_decls.len() {
|
if argument_index + 1 >= body.local_decls.len() {
|
||||||
self.tcx()
|
self.tcx()
|
||||||
.sess
|
.dcx()
|
||||||
.span_delayed_bug(body.span, "found more normalized_input_ty than local_decls");
|
.span_delayed_bug(body.span, "found more normalized_input_ty than local_decls");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -94,31 +101,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(
|
if let Some(mir_yield_ty) = body.yield_ty() {
|
||||||
"equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
|
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
|
||||||
body.yield_ty(),
|
self.equate_normalized_input_or_output(
|
||||||
universal_regions.yield_ty
|
universal_regions.yield_ty.unwrap(),
|
||||||
);
|
mir_yield_ty,
|
||||||
|
yield_span,
|
||||||
// We will not have a universal_regions.yield_ty if we yield (by accident)
|
|
||||||
// outside of a coroutine and return an `impl Trait`, so emit a span_delayed_bug
|
|
||||||
// because we don't want to panic in an assert here if we've already got errors.
|
|
||||||
if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
|
|
||||||
self.tcx().sess.span_delayed_bug(
|
|
||||||
body.span,
|
|
||||||
format!(
|
|
||||||
"Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
|
|
||||||
body.yield_ty(),
|
|
||||||
universal_regions.yield_ty,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (Some(mir_yield_ty), Some(ur_yield_ty)) =
|
if let Some(mir_resume_ty) = body.resume_ty() {
|
||||||
(body.yield_ty(), universal_regions.yield_ty)
|
|
||||||
{
|
|
||||||
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
|
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
|
||||||
self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
|
self.equate_normalized_input_or_output(
|
||||||
|
universal_regions.resume_ty.unwrap(),
|
||||||
|
mir_resume_ty,
|
||||||
|
yield_span,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return types are a bit more complex. They may contain opaque `impl Trait` types.
|
// Return types are a bit more complex. They may contain opaque `impl Trait` types.
|
||||||
|
|||||||
@ -2,9 +2,9 @@ use rustc_data_structures::vec_linked_list as vll;
|
|||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::{Body, Local, Location};
|
use rustc_middle::mir::{Body, Local, Location};
|
||||||
|
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
|
||||||
|
|
||||||
use crate::def_use::{self, DefUse};
|
use crate::def_use::{self, DefUse};
|
||||||
use crate::region_infer::values::{PointIndex, RegionValueElements};
|
|
||||||
|
|
||||||
/// A map that cross references each local with the locations where it
|
/// A map that cross references each local with the locations where it
|
||||||
/// is defined (assigned), used, or dropped. Used during liveness
|
/// is defined (assigned), used, or dropped. Used during liveness
|
||||||
@ -60,7 +60,7 @@ impl vll::LinkElem for Appearance {
|
|||||||
impl LocalUseMap {
|
impl LocalUseMap {
|
||||||
pub(crate) fn build(
|
pub(crate) fn build(
|
||||||
live_locals: &[Local],
|
live_locals: &[Local],
|
||||||
elements: &RegionValueElements,
|
elements: &DenseLocationMap,
|
||||||
body: &Body<'_>,
|
body: &Body<'_>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let nones = IndexVec::from_elem(None, &body.local_decls);
|
let nones = IndexVec::from_elem(None, &body.local_decls);
|
||||||
@ -103,7 +103,7 @@ impl LocalUseMap {
|
|||||||
|
|
||||||
struct LocalUseMapBuild<'me> {
|
struct LocalUseMapBuild<'me> {
|
||||||
local_use_map: &'me mut LocalUseMap,
|
local_use_map: &'me mut LocalUseMap,
|
||||||
elements: &'me RegionValueElements,
|
elements: &'me DenseLocationMap,
|
||||||
|
|
||||||
// Vector used in `visit_local` to signal which `Local`s do we need
|
// Vector used in `visit_local` to signal which `Local`s do we need
|
||||||
// def/use/drop information on, constructed from `live_locals` (that
|
// def/use/drop information on, constructed from `live_locals` (that
|
||||||
@ -144,7 +144,7 @@ impl LocalUseMapBuild<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn insert(
|
fn insert(
|
||||||
elements: &RegionValueElements,
|
elements: &DenseLocationMap,
|
||||||
first_appearance: &mut Option<AppearanceIndex>,
|
first_appearance: &mut Option<AppearanceIndex>,
|
||||||
appearances: &mut IndexVec<AppearanceIndex, Appearance>,
|
appearances: &mut IndexVec<AppearanceIndex, Appearance>,
|
||||||
location: Location,
|
location: Location,
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use rustc_middle::ty::visit::TypeVisitable;
|
|||||||
use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt};
|
use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt};
|
||||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||||
use rustc_mir_dataflow::move_paths::MoveData;
|
use rustc_mir_dataflow::move_paths::MoveData;
|
||||||
|
use rustc_mir_dataflow::points::DenseLocationMap;
|
||||||
use rustc_mir_dataflow::ResultsCursor;
|
use rustc_mir_dataflow::ResultsCursor;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ use crate::{
|
|||||||
constraints::OutlivesConstraintSet,
|
constraints::OutlivesConstraintSet,
|
||||||
facts::{AllFacts, AllFactsExt},
|
facts::{AllFacts, AllFactsExt},
|
||||||
location::LocationTable,
|
location::LocationTable,
|
||||||
region_infer::values::{LivenessValues, RegionValueElements},
|
region_infer::values::LivenessValues,
|
||||||
universal_regions::UniversalRegions,
|
universal_regions::UniversalRegions,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ mod trace;
|
|||||||
pub(super) fn generate<'mir, 'tcx>(
|
pub(super) fn generate<'mir, 'tcx>(
|
||||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
elements: &Rc<RegionValueElements>,
|
elements: &Rc<DenseLocationMap>,
|
||||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||||
move_data: &MoveData<'tcx>,
|
move_data: &MoveData<'tcx>,
|
||||||
location_table: &LocationTable,
|
location_table: &LocationTable,
|
||||||
@ -183,6 +184,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> {
|
|||||||
match ty_context {
|
match ty_context {
|
||||||
TyContext::ReturnTy(SourceInfo { span, .. })
|
TyContext::ReturnTy(SourceInfo { span, .. })
|
||||||
| TyContext::YieldTy(SourceInfo { span, .. })
|
| TyContext::YieldTy(SourceInfo { span, .. })
|
||||||
|
| TyContext::ResumeTy(SourceInfo { span, .. })
|
||||||
| TyContext::UserTy(span)
|
| TyContext::UserTy(span)
|
||||||
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
|
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
|
||||||
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);
|
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::graph::WithSuccessors;
|
use rustc_data_structures::graph::WithSuccessors;
|
||||||
use rustc_index::bit_set::HybridBitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::interval::IntervalSet;
|
use rustc_index::interval::IntervalSet;
|
||||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||||
use rustc_infer::infer::outlives::for_liveness;
|
use rustc_infer::infer::outlives::for_liveness;
|
||||||
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
|
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
|
||||||
use rustc_middle::traits::query::DropckOutlivesResult;
|
use rustc_middle::traits::query::DropckOutlivesResult;
|
||||||
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
|
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
|
||||||
|
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
|
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
|
||||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||||
@ -17,7 +18,7 @@ use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
|
|||||||
use rustc_mir_dataflow::ResultsCursor;
|
use rustc_mir_dataflow::ResultsCursor;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
region_infer::values::{self, LiveLoans, PointIndex, RegionValueElements},
|
region_infer::values::{self, LiveLoans},
|
||||||
type_check::liveness::local_use_map::LocalUseMap,
|
type_check::liveness::local_use_map::LocalUseMap,
|
||||||
type_check::liveness::polonius,
|
type_check::liveness::polonius,
|
||||||
type_check::NormalizeLocation,
|
type_check::NormalizeLocation,
|
||||||
@ -41,7 +42,7 @@ use crate::{
|
|||||||
pub(super) fn trace<'mir, 'tcx>(
|
pub(super) fn trace<'mir, 'tcx>(
|
||||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
elements: &Rc<RegionValueElements>,
|
elements: &Rc<DenseLocationMap>,
|
||||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||||
move_data: &MoveData<'tcx>,
|
move_data: &MoveData<'tcx>,
|
||||||
relevant_live_locals: Vec<Local>,
|
relevant_live_locals: Vec<Local>,
|
||||||
@ -105,7 +106,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
|
|||||||
typeck: &'me mut TypeChecker<'typeck, 'tcx>,
|
typeck: &'me mut TypeChecker<'typeck, 'tcx>,
|
||||||
|
|
||||||
/// Defines the `PointIndex` mapping
|
/// Defines the `PointIndex` mapping
|
||||||
elements: &'me RegionValueElements,
|
elements: &'me DenseLocationMap,
|
||||||
|
|
||||||
/// MIR we are analyzing.
|
/// MIR we are analyzing.
|
||||||
body: &'me Body<'tcx>,
|
body: &'me Body<'tcx>,
|
||||||
@ -134,7 +135,7 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
|||||||
cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>,
|
cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>,
|
||||||
|
|
||||||
/// Set of points that define the current local.
|
/// Set of points that define the current local.
|
||||||
defs: HybridBitSet<PointIndex>,
|
defs: BitSet<PointIndex>,
|
||||||
|
|
||||||
/// Points where the current variable is "use live" -- meaning
|
/// Points where the current variable is "use live" -- meaning
|
||||||
/// that there is a future "full use" that may use its value.
|
/// that there is a future "full use" that may use its value.
|
||||||
@ -157,7 +158,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
|||||||
let num_points = cx.elements.num_points();
|
let num_points = cx.elements.num_points();
|
||||||
LivenessResults {
|
LivenessResults {
|
||||||
cx,
|
cx,
|
||||||
defs: HybridBitSet::new_empty(num_points),
|
defs: BitSet::new_empty(num_points),
|
||||||
use_live_at: IntervalSet::new(num_points),
|
use_live_at: IntervalSet::new(num_points),
|
||||||
drop_live_at: IntervalSet::new(num_points),
|
drop_live_at: IntervalSet::new(num_points),
|
||||||
drop_locations: vec![],
|
drop_locations: vec![],
|
||||||
@ -570,7 +571,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_all_regions_live(
|
fn make_all_regions_live(
|
||||||
elements: &RegionValueElements,
|
elements: &DenseLocationMap,
|
||||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||||
value: impl TypeVisitable<TyCtxt<'tcx>>,
|
value: impl TypeVisitable<TyCtxt<'tcx>>,
|
||||||
live_at: &IntervalSet<PointIndex>,
|
live_at: &IntervalSet<PointIndex>,
|
||||||
|
|||||||
@ -35,7 +35,9 @@ use rustc_middle::ty::{
|
|||||||
OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
|
OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{GenericArgsRef, UserArgs};
|
use rustc_middle::ty::{GenericArgsRef, UserArgs};
|
||||||
|
use rustc_mir_dataflow::points::DenseLocationMap;
|
||||||
use rustc_span::def_id::CRATE_DEF_ID;
|
use rustc_span::def_id::CRATE_DEF_ID;
|
||||||
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
|
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
|
||||||
@ -58,9 +60,7 @@ use crate::{
|
|||||||
location::LocationTable,
|
location::LocationTable,
|
||||||
member_constraints::MemberConstraintSet,
|
member_constraints::MemberConstraintSet,
|
||||||
path_utils,
|
path_utils,
|
||||||
region_infer::values::{
|
region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices},
|
||||||
LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
|
|
||||||
},
|
|
||||||
region_infer::TypeTest,
|
region_infer::TypeTest,
|
||||||
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
|
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
|
||||||
universal_regions::{DefiningTy, UniversalRegions},
|
universal_regions::{DefiningTy, UniversalRegions},
|
||||||
@ -133,7 +133,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||||||
all_facts: &mut Option<AllFacts>,
|
all_facts: &mut Option<AllFacts>,
|
||||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||||
move_data: &MoveData<'tcx>,
|
move_data: &MoveData<'tcx>,
|
||||||
elements: &Rc<RegionValueElements>,
|
elements: &Rc<DenseLocationMap>,
|
||||||
upvars: &[&ty::CapturedPlace<'tcx>],
|
upvars: &[&ty::CapturedPlace<'tcx>],
|
||||||
use_polonius: bool,
|
use_polonius: bool,
|
||||||
) -> MirTypeckResults<'tcx> {
|
) -> MirTypeckResults<'tcx> {
|
||||||
@ -141,7 +141,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||||||
let mut constraints = MirTypeckRegionConstraints {
|
let mut constraints = MirTypeckRegionConstraints {
|
||||||
placeholder_indices: PlaceholderIndices::default(),
|
placeholder_indices: PlaceholderIndices::default(),
|
||||||
placeholder_index_to_region: IndexVec::default(),
|
placeholder_index_to_region: IndexVec::default(),
|
||||||
liveness_constraints: LivenessValues::new(elements.clone()),
|
liveness_constraints: LivenessValues::with_specific_points(elements.clone()),
|
||||||
outlives_constraints: OutlivesConstraintSet::default(),
|
outlives_constraints: OutlivesConstraintSet::default(),
|
||||||
member_constraints: MemberConstraintSet::default(),
|
member_constraints: MemberConstraintSet::default(),
|
||||||
type_tests: Vec::default(),
|
type_tests: Vec::default(),
|
||||||
@ -152,9 +152,14 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||||||
universal_region_relations,
|
universal_region_relations,
|
||||||
region_bound_pairs,
|
region_bound_pairs,
|
||||||
normalized_inputs_and_output,
|
normalized_inputs_and_output,
|
||||||
|
known_type_outlives_obligations,
|
||||||
} = free_region_relations::create(
|
} = free_region_relations::create(
|
||||||
infcx,
|
infcx,
|
||||||
param_env,
|
param_env,
|
||||||
|
// FIXME(-Znext-solver): These are unnormalized. Normalize them.
|
||||||
|
infcx.tcx.arena.alloc_from_iter(
|
||||||
|
param_env.caller_bounds().iter().filter_map(|clause| clause.as_type_outlives_clause()),
|
||||||
|
),
|
||||||
implicit_region_bound,
|
implicit_region_bound,
|
||||||
universal_regions,
|
universal_regions,
|
||||||
&mut constraints,
|
&mut constraints,
|
||||||
@ -176,6 +181,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||||||
body,
|
body,
|
||||||
param_env,
|
param_env,
|
||||||
®ion_bound_pairs,
|
®ion_bound_pairs,
|
||||||
|
known_type_outlives_obligations,
|
||||||
implicit_region_bound,
|
implicit_region_bound,
|
||||||
&mut borrowck_context,
|
&mut borrowck_context,
|
||||||
);
|
);
|
||||||
@ -224,7 +230,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||||||
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
|
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
|
||||||
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
|
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
|
||||||
if hidden_type.has_non_region_infer() {
|
if hidden_type.has_non_region_infer() {
|
||||||
let reported = infcx.tcx.sess.span_delayed_bug(
|
let reported = infcx.dcx().span_delayed_bug(
|
||||||
decl.hidden_type.span,
|
decl.hidden_type.span,
|
||||||
format!("could not resolve {:#?}", hidden_type.ty.kind()),
|
format!("could not resolve {:#?}", hidden_type.ty.kind()),
|
||||||
);
|
);
|
||||||
@ -268,7 +274,7 @@ fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
|
|||||||
// We sometimes see MIR failures (notably predicate failures) due to
|
// We sometimes see MIR failures (notably predicate failures) due to
|
||||||
// the fact that we check rvalue sized predicates here. So use `span_delayed_bug`
|
// the fact that we check rvalue sized predicates here. So use `span_delayed_bug`
|
||||||
// to avoid reporting bugs in those cases.
|
// to avoid reporting bugs in those cases.
|
||||||
tcx.sess.dcx().span_delayed_bug(span, msg);
|
tcx.dcx().span_delayed_bug(span, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FieldAccessError {
|
enum FieldAccessError {
|
||||||
@ -406,6 +412,16 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||||||
instantiated_predicates,
|
instantiated_predicates,
|
||||||
locations,
|
locations,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert!(!matches!(
|
||||||
|
tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
|
||||||
|
Some(DefKind::Impl { of_trait: true })
|
||||||
|
));
|
||||||
|
self.cx.prove_predicates(
|
||||||
|
args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
|
||||||
|
locations,
|
||||||
|
ConstraintCategory::Boring,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,7 +561,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||||||
let all_facts = &mut None;
|
let all_facts = &mut None;
|
||||||
let mut constraints = Default::default();
|
let mut constraints = Default::default();
|
||||||
let mut liveness_constraints =
|
let mut liveness_constraints =
|
||||||
LivenessValues::new(Rc::new(RegionValueElements::new(promoted_body)));
|
LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
|
||||||
// Don't try to add borrow_region facts for the promoted MIR
|
// Don't try to add borrow_region facts for the promoted MIR
|
||||||
|
|
||||||
let mut swap_constraints = |this: &mut Self| {
|
let mut swap_constraints = |this: &mut Self| {
|
||||||
@ -584,17 +600,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||||||
}
|
}
|
||||||
self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
|
self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
|
||||||
}
|
}
|
||||||
for region in liveness_constraints.regions() {
|
// If the region is live at at least one location in the promoted MIR,
|
||||||
// If the region is live at at least one location in the promoted MIR,
|
// then add a liveness constraint to the main MIR for this region
|
||||||
// then add a liveness constraint to the main MIR for this region
|
// at the location provided as an argument to this method
|
||||||
// at the location provided as an argument to this method
|
//
|
||||||
if liveness_constraints.is_live_anywhere(region) {
|
// add_location doesn't care about ordering so not a problem for the live regions to be
|
||||||
self.cx
|
// unordered.
|
||||||
.borrowck_context
|
#[allow(rustc::potential_query_instability)]
|
||||||
.constraints
|
for region in liveness_constraints.live_regions_unordered() {
|
||||||
.liveness_constraints
|
self.cx
|
||||||
.add_location(region, location);
|
.borrowck_context
|
||||||
}
|
.constraints
|
||||||
|
.liveness_constraints
|
||||||
|
.add_location(region, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,7 +780,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||||||
let (variant, args) = match base_ty {
|
let (variant, args) = match base_ty {
|
||||||
PlaceTy { ty, variant_index: Some(variant_index) } => match *ty.kind() {
|
PlaceTy { ty, variant_index: Some(variant_index) } => match *ty.kind() {
|
||||||
ty::Adt(adt_def, args) => (adt_def.variant(variant_index), args),
|
ty::Adt(adt_def, args) => (adt_def.variant(variant_index), args),
|
||||||
ty::Coroutine(def_id, args, _) => {
|
ty::Coroutine(def_id, args) => {
|
||||||
let mut variants = args.as_coroutine().state_tys(def_id, tcx);
|
let mut variants = args.as_coroutine().state_tys(def_id, tcx);
|
||||||
let Some(mut variant) = variants.nth(variant_index.into()) else {
|
let Some(mut variant) = variants.nth(variant_index.into()) else {
|
||||||
bug!(
|
bug!(
|
||||||
@ -790,7 +808,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
ty::Coroutine(_, args, _) => {
|
ty::Coroutine(_, args) => {
|
||||||
// Only prefix fields (upvars and current state) are
|
// Only prefix fields (upvars and current state) are
|
||||||
// accessible without a variant index.
|
// accessible without a variant index.
|
||||||
return match args.as_coroutine().prefix_tys().get(field.index()) {
|
return match args.as_coroutine().prefix_tys().get(field.index()) {
|
||||||
@ -838,6 +856,7 @@ struct TypeChecker<'a, 'tcx> {
|
|||||||
/// all of the promoted items.
|
/// all of the promoted items.
|
||||||
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
|
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
|
||||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||||
|
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||||
implicit_region_bound: ty::Region<'tcx>,
|
implicit_region_bound: ty::Region<'tcx>,
|
||||||
reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
|
reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
|
||||||
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
|
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
|
||||||
@ -988,6 +1007,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
body: &'a Body<'tcx>,
|
body: &'a Body<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||||
|
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||||
implicit_region_bound: ty::Region<'tcx>,
|
implicit_region_bound: ty::Region<'tcx>,
|
||||||
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
|
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -998,6 +1018,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
user_type_annotations: &body.user_type_annotations,
|
user_type_annotations: &body.user_type_annotations,
|
||||||
param_env,
|
param_env,
|
||||||
region_bound_pairs,
|
region_bound_pairs,
|
||||||
|
known_type_outlives_obligations,
|
||||||
implicit_region_bound,
|
implicit_region_bound,
|
||||||
borrowck_context,
|
borrowck_context,
|
||||||
reported_errors: Default::default(),
|
reported_errors: Default::default(),
|
||||||
@ -1067,7 +1088,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
self.infcx.tcx.sess.span_delayed_bug(
|
self.infcx.dcx().span_delayed_bug(
|
||||||
self.body.span,
|
self.body.span,
|
||||||
"failed re-defining predefined opaques in mir typeck",
|
"failed re-defining predefined opaques in mir typeck",
|
||||||
);
|
);
|
||||||
@ -1087,10 +1108,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn check_user_type_annotations(&mut self) {
|
fn check_user_type_annotations(&mut self) {
|
||||||
debug!(?self.user_type_annotations);
|
debug!(?self.user_type_annotations);
|
||||||
|
let tcx = self.tcx();
|
||||||
for user_annotation in self.user_type_annotations {
|
for user_annotation in self.user_type_annotations {
|
||||||
let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
|
let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
|
||||||
let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
|
let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
|
||||||
self.ascribe_user_type(inferred_ty, annotation, span);
|
if let ty::UserType::TypeOf(def, args) = annotation
|
||||||
|
&& let DefKind::InlineConst = tcx.def_kind(def)
|
||||||
|
{
|
||||||
|
self.check_inline_const(inferred_ty, def.expect_local(), args, span);
|
||||||
|
} else {
|
||||||
|
self.ascribe_user_type(inferred_ty, annotation, span);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1108,7 +1136,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
self.borrowck_context.universal_regions,
|
self.borrowck_context.universal_regions,
|
||||||
self.region_bound_pairs,
|
self.region_bound_pairs,
|
||||||
self.implicit_region_bound,
|
self.implicit_region_bound,
|
||||||
self.param_env,
|
self.known_type_outlives_obligations,
|
||||||
locations,
|
locations,
|
||||||
locations.span(self.body),
|
locations.span(self.body),
|
||||||
category,
|
category,
|
||||||
@ -1183,6 +1211,36 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_inline_const(
|
||||||
|
&mut self,
|
||||||
|
inferred_ty: Ty<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
args: UserArgs<'tcx>,
|
||||||
|
span: Span,
|
||||||
|
) {
|
||||||
|
assert!(args.user_self_ty.is_none());
|
||||||
|
let tcx = self.tcx();
|
||||||
|
let const_ty = tcx.type_of(def_id).instantiate(tcx, args.args);
|
||||||
|
if let Err(terr) =
|
||||||
|
self.eq_types(const_ty, inferred_ty, Locations::All(span), ConstraintCategory::Boring)
|
||||||
|
{
|
||||||
|
span_bug!(
|
||||||
|
span,
|
||||||
|
"bad inline const pattern: ({:?} = {:?}) {:?}",
|
||||||
|
const_ty,
|
||||||
|
inferred_ty,
|
||||||
|
terr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let args = self.infcx.resolve_vars_if_possible(args.args);
|
||||||
|
let predicates = self.prove_closure_bounds(tcx, def_id, args, Locations::All(span));
|
||||||
|
self.normalize_and_prove_instantiated_predicates(
|
||||||
|
def_id.to_def_id(),
|
||||||
|
predicates,
|
||||||
|
Locations::All(span),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
@ -1359,7 +1417,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
|
TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
|
||||||
self.check_operand(func, term_location);
|
self.check_operand(func, term_location);
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.check_operand(arg, term_location);
|
self.check_operand(&arg.node, term_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
let func_ty = func.ty(body, tcx);
|
let func_ty = func.ty(body, tcx);
|
||||||
@ -1450,13 +1508,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TerminatorKind::Yield { value, .. } => {
|
TerminatorKind::Yield { value, resume_arg, .. } => {
|
||||||
self.check_operand(value, term_location);
|
self.check_operand(value, term_location);
|
||||||
|
|
||||||
let value_ty = value.ty(body, tcx);
|
|
||||||
match body.yield_ty() {
|
match body.yield_ty() {
|
||||||
None => span_mirbug!(self, term, "yield in non-coroutine"),
|
None => span_mirbug!(self, term, "yield in non-coroutine"),
|
||||||
Some(ty) => {
|
Some(ty) => {
|
||||||
|
let value_ty = value.ty(body, tcx);
|
||||||
if let Err(terr) = self.sub_types(
|
if let Err(terr) = self.sub_types(
|
||||||
value_ty,
|
value_ty,
|
||||||
ty,
|
ty,
|
||||||
@ -1474,6 +1532,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match body.resume_ty() {
|
||||||
|
None => span_mirbug!(self, term, "yield in non-coroutine"),
|
||||||
|
Some(ty) => {
|
||||||
|
let resume_ty = resume_arg.ty(body, tcx);
|
||||||
|
if let Err(terr) = self.sub_types(
|
||||||
|
ty,
|
||||||
|
resume_ty.ty,
|
||||||
|
term_location.to_locations(),
|
||||||
|
ConstraintCategory::Yield,
|
||||||
|
) {
|
||||||
|
span_mirbug!(
|
||||||
|
self,
|
||||||
|
term,
|
||||||
|
"type of resume place is {:?}, but the resume type is {:?}: {:?}",
|
||||||
|
resume_ty,
|
||||||
|
ty,
|
||||||
|
terr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1558,7 +1638,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
term: &Terminator<'tcx>,
|
term: &Terminator<'tcx>,
|
||||||
func: &Operand<'tcx>,
|
func: &Operand<'tcx>,
|
||||||
sig: &ty::FnSig<'tcx>,
|
sig: &ty::FnSig<'tcx>,
|
||||||
args: &[Operand<'tcx>],
|
args: &[Spanned<Operand<'tcx>>],
|
||||||
term_location: Location,
|
term_location: Location,
|
||||||
call_source: CallSource,
|
call_source: CallSource,
|
||||||
) {
|
) {
|
||||||
@ -1571,9 +1651,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
if self.tcx().is_intrinsic(def_id) {
|
if self.tcx().is_intrinsic(def_id) {
|
||||||
match self.tcx().item_name(def_id) {
|
match self.tcx().item_name(def_id) {
|
||||||
sym::simd_shuffle => {
|
sym::simd_shuffle => {
|
||||||
if !matches!(args[2], Operand::Constant(_)) {
|
if !matches!(args[2], Spanned { node: Operand::Constant(_), .. }) {
|
||||||
self.tcx()
|
self.tcx()
|
||||||
.sess
|
.dcx()
|
||||||
.emit_err(SimdShuffleLastConst { span: term.source_info.span });
|
.emit_err(SimdShuffleLastConst { span: term.source_info.span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1584,7 +1664,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
debug!(?func_ty);
|
debug!(?func_ty);
|
||||||
|
|
||||||
for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
|
for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
|
||||||
let op_arg_ty = op_arg.ty(body, self.tcx());
|
let op_arg_ty = op_arg.node.ty(body, self.tcx());
|
||||||
|
|
||||||
let op_arg_ty = self.normalize(op_arg_ty, term_location);
|
let op_arg_ty = self.normalize(op_arg_ty, term_location);
|
||||||
let category = if call_source.from_hir_call() {
|
let category = if call_source.from_hir_call() {
|
||||||
@ -1752,7 +1832,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
// While this is located in `nll::typeck` this error is not
|
// While this is located in `nll::typeck` this error is not
|
||||||
// an NLL error, it's a required check to prevent creation
|
// an NLL error, it's a required check to prevent creation
|
||||||
// of unsized rvalues in a call expression.
|
// of unsized rvalues in a call expression.
|
||||||
self.tcx().sess.emit_err(MoveUnsized { ty, span });
|
self.tcx().dcx().emit_err(MoveUnsized { ty, span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1784,7 +1864,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AggregateKind::Coroutine(_, args, _) => {
|
AggregateKind::Coroutine(_, args) => {
|
||||||
// It doesn't make sense to look at a field beyond the prefix;
|
// It doesn't make sense to look at a field beyond the prefix;
|
||||||
// these require a variant index, and are not initialized in
|
// these require a variant index, and are not initialized in
|
||||||
// aggregate rvalues.
|
// aggregate rvalues.
|
||||||
@ -1817,7 +1897,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
let def_id = uv.def;
|
let def_id = uv.def;
|
||||||
if tcx.def_kind(def_id) == DefKind::InlineConst {
|
if tcx.def_kind(def_id) == DefKind::InlineConst {
|
||||||
let def_id = def_id.expect_local();
|
let def_id = def_id.expect_local();
|
||||||
let predicates = self.prove_closure_bounds(tcx, def_id, uv.args, location);
|
let predicates = self.prove_closure_bounds(
|
||||||
|
tcx,
|
||||||
|
def_id,
|
||||||
|
uv.args,
|
||||||
|
location.to_locations(),
|
||||||
|
);
|
||||||
self.normalize_and_prove_instantiated_predicates(
|
self.normalize_and_prove_instantiated_predicates(
|
||||||
def_id.to_def_id(),
|
def_id.to_def_id(),
|
||||||
predicates,
|
predicates,
|
||||||
@ -2392,7 +2477,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
AggregateKind::Array(_) => None,
|
AggregateKind::Array(_) => None,
|
||||||
AggregateKind::Tuple => None,
|
AggregateKind::Tuple => None,
|
||||||
AggregateKind::Closure(_, _) => None,
|
AggregateKind::Closure(_, _) => None,
|
||||||
AggregateKind::Coroutine(_, _, _) => None,
|
AggregateKind::Coroutine(_, _) => None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2620,9 +2705,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
// desugaring. A closure gets desugared to a struct, and
|
// desugaring. A closure gets desugared to a struct, and
|
||||||
// these extra requirements are basically like where
|
// these extra requirements are basically like where
|
||||||
// clauses on the struct.
|
// clauses on the struct.
|
||||||
AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args, _) => {
|
AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args) => (
|
||||||
(def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), args, location))
|
def_id,
|
||||||
}
|
self.prove_closure_bounds(
|
||||||
|
tcx,
|
||||||
|
def_id.expect_local(),
|
||||||
|
args,
|
||||||
|
location.to_locations(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
AggregateKind::Array(_) | AggregateKind::Tuple => {
|
AggregateKind::Array(_) | AggregateKind::Tuple => {
|
||||||
(CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
|
(CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
|
||||||
@ -2641,7 +2732,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
args: GenericArgsRef<'tcx>,
|
args: GenericArgsRef<'tcx>,
|
||||||
location: Location,
|
locations: Locations,
|
||||||
) -> ty::InstantiatedPredicates<'tcx> {
|
) -> ty::InstantiatedPredicates<'tcx> {
|
||||||
if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
|
if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
|
||||||
constraint_conversion::ConstraintConversion::new(
|
constraint_conversion::ConstraintConversion::new(
|
||||||
@ -2649,8 +2740,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
self.borrowck_context.universal_regions,
|
self.borrowck_context.universal_regions,
|
||||||
self.region_bound_pairs,
|
self.region_bound_pairs,
|
||||||
self.implicit_region_bound,
|
self.implicit_region_bound,
|
||||||
self.param_env,
|
self.known_type_outlives_obligations,
|
||||||
location.to_locations(),
|
locations,
|
||||||
DUMMY_SP, // irrelevant; will be overridden.
|
DUMMY_SP, // irrelevant; will be overridden.
|
||||||
ConstraintCategory::Boring, // same as above.
|
ConstraintCategory::Boring, // same as above.
|
||||||
self.borrowck_context.constraints,
|
self.borrowck_context.constraints,
|
||||||
@ -2676,7 +2767,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
if let Err(_) = self.eq_args(
|
if let Err(_) = self.eq_args(
|
||||||
typeck_root_args,
|
typeck_root_args,
|
||||||
parent_args,
|
parent_args,
|
||||||
location.to_locations(),
|
locations,
|
||||||
ConstraintCategory::BoringNoLocation,
|
ConstraintCategory::BoringNoLocation,
|
||||||
) {
|
) {
|
||||||
span_mirbug!(
|
span_mirbug!(
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::Diagnostic;
|
use rustc_errors::Diagnostic;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::BodyOwnerKind;
|
use rustc_hir::BodyOwnerKind;
|
||||||
@ -77,6 +76,8 @@ pub struct UniversalRegions<'tcx> {
|
|||||||
pub unnormalized_input_tys: &'tcx [Ty<'tcx>],
|
pub unnormalized_input_tys: &'tcx [Ty<'tcx>],
|
||||||
|
|
||||||
pub yield_ty: Option<Ty<'tcx>>,
|
pub yield_ty: Option<Ty<'tcx>>,
|
||||||
|
|
||||||
|
pub resume_ty: Option<Ty<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The "defining type" for this MIR. The key feature of the "defining
|
/// The "defining type" for this MIR. The key feature of the "defining
|
||||||
@ -94,7 +95,7 @@ pub enum DefiningTy<'tcx> {
|
|||||||
/// The MIR is a coroutine. The signature is that coroutines take
|
/// The MIR is a coroutine. The signature is that coroutines take
|
||||||
/// no parameters and return the result of
|
/// no parameters and return the result of
|
||||||
/// `ClosureArgs::coroutine_return_ty`.
|
/// `ClosureArgs::coroutine_return_ty`.
|
||||||
Coroutine(DefId, GenericArgsRef<'tcx>, hir::Movability),
|
Coroutine(DefId, GenericArgsRef<'tcx>),
|
||||||
|
|
||||||
/// The MIR is a fn item with the given `DefId` and args. The signature
|
/// The MIR is a fn item with the given `DefId` and args. The signature
|
||||||
/// of the function can be bound then with the `fn_sig` query.
|
/// of the function can be bound then with the `fn_sig` query.
|
||||||
@ -118,7 +119,7 @@ impl<'tcx> DefiningTy<'tcx> {
|
|||||||
pub fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> {
|
pub fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> {
|
||||||
match self {
|
match self {
|
||||||
DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
|
DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
|
||||||
DefiningTy::Coroutine(_, args, _) => args.as_coroutine().upvar_tys(),
|
DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(),
|
||||||
DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
|
DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
|
||||||
ty::List::empty()
|
ty::List::empty()
|
||||||
}
|
}
|
||||||
@ -354,7 +355,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
|||||||
err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
|
err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
DefiningTy::Coroutine(def_id, args, _) => {
|
DefiningTy::Coroutine(def_id, args) => {
|
||||||
let v = with_no_trimmed_paths!(
|
let v = with_no_trimmed_paths!(
|
||||||
args[tcx.generics_of(def_id).parent_count..]
|
args[tcx.generics_of(def_id).parent_count..]
|
||||||
.iter()
|
.iter()
|
||||||
@ -526,9 +527,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||||||
debug!("build: extern regions = {}..{}", first_extern_index, first_local_index);
|
debug!("build: extern regions = {}..{}", first_extern_index, first_local_index);
|
||||||
debug!("build: local regions = {}..{}", first_local_index, num_universals);
|
debug!("build: local regions = {}..{}", first_local_index, num_universals);
|
||||||
|
|
||||||
let yield_ty = match defining_ty {
|
let (resume_ty, yield_ty) = match defining_ty {
|
||||||
DefiningTy::Coroutine(_, args, _) => Some(args.as_coroutine().yield_ty()),
|
DefiningTy::Coroutine(_, args) => {
|
||||||
_ => None,
|
let tys = args.as_coroutine();
|
||||||
|
(Some(tys.resume_ty()), Some(tys.yield_ty()))
|
||||||
|
}
|
||||||
|
_ => (None, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
UniversalRegions {
|
UniversalRegions {
|
||||||
@ -542,6 +546,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||||||
unnormalized_output_ty: *unnormalized_output_ty,
|
unnormalized_output_ty: *unnormalized_output_ty,
|
||||||
unnormalized_input_tys,
|
unnormalized_input_tys,
|
||||||
yield_ty,
|
yield_ty,
|
||||||
|
resume_ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,9 +567,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||||||
|
|
||||||
match *defining_ty.kind() {
|
match *defining_ty.kind() {
|
||||||
ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args),
|
ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args),
|
||||||
ty::Coroutine(def_id, args, movability) => {
|
ty::Coroutine(def_id, args) => DefiningTy::Coroutine(def_id, args),
|
||||||
DefiningTy::Coroutine(def_id, args, movability)
|
|
||||||
}
|
|
||||||
ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args),
|
ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args),
|
||||||
_ => span_bug!(
|
_ => span_bug!(
|
||||||
tcx.def_span(self.mir_def),
|
tcx.def_span(self.mir_def),
|
||||||
@ -620,7 +623,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||||||
let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
|
let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
|
||||||
let fr_args = match defining_ty {
|
let fr_args = match defining_ty {
|
||||||
DefiningTy::Closure(_, args)
|
DefiningTy::Closure(_, args)
|
||||||
| DefiningTy::Coroutine(_, args, _)
|
| DefiningTy::Coroutine(_, args)
|
||||||
| DefiningTy::InlineConst(_, args) => {
|
| DefiningTy::InlineConst(_, args) => {
|
||||||
// In the case of closures, we rely on the fact that
|
// In the case of closures, we rely on the fact that
|
||||||
// the first N elements in the ClosureArgs are
|
// the first N elements in the ClosureArgs are
|
||||||
@ -665,7 +668,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||||||
kind: ty::BrEnv,
|
kind: ty::BrEnv,
|
||||||
};
|
};
|
||||||
let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
|
let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
|
||||||
let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap();
|
let closure_ty = tcx.closure_env_ty(
|
||||||
|
Ty::new_closure(tcx, def_id, args),
|
||||||
|
args.as_closure().kind(),
|
||||||
|
env_region,
|
||||||
|
);
|
||||||
|
|
||||||
// The "inputs" of the closure in the
|
// The "inputs" of the closure in the
|
||||||
// signature appear as a tuple. The MIR side
|
// signature appear as a tuple. The MIR side
|
||||||
@ -685,11 +692,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
DefiningTy::Coroutine(def_id, args, movability) => {
|
DefiningTy::Coroutine(def_id, args) => {
|
||||||
assert_eq!(self.mir_def.to_def_id(), def_id);
|
assert_eq!(self.mir_def.to_def_id(), def_id);
|
||||||
let resume_ty = args.as_coroutine().resume_ty();
|
let resume_ty = args.as_coroutine().resume_ty();
|
||||||
let output = args.as_coroutine().return_ty();
|
let output = args.as_coroutine().return_ty();
|
||||||
let coroutine_ty = Ty::new_coroutine(tcx, def_id, args, movability);
|
let coroutine_ty = Ty::new_coroutine(tcx, def_id, args);
|
||||||
let inputs_and_output =
|
let inputs_and_output =
|
||||||
self.infcx.tcx.mk_type_list(&[coroutine_ty, resume_ty, output]);
|
self.infcx.tcx.mk_type_list(&[coroutine_ty, resume_ty, output]);
|
||||||
ty::Binder::dummy(inputs_and_output)
|
ty::Binder::dummy(inputs_and_output)
|
||||||
|
|||||||
@ -31,7 +31,7 @@ pub fn expand(
|
|||||||
{
|
{
|
||||||
(item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
|
(item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
|
||||||
} else {
|
} else {
|
||||||
ecx.sess.dcx().emit_err(errors::AllocErrorMustBeFn { span: item.span() });
|
ecx.dcx().emit_err(errors::AllocErrorMustBeFn { span: item.span() });
|
||||||
return vec![orig_item];
|
return vec![orig_item];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -422,7 +422,7 @@ fn parse_reg<'a>(
|
|||||||
ast::InlineAsmRegOrRegClass::Reg(symbol)
|
ast::InlineAsmRegOrRegClass::Reg(symbol)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(p.sess.create_err(errors::ExpectedRegisterClassOrExplicitRegister {
|
return Err(p.dcx().create_err(errors::ExpectedRegisterClassOrExplicitRegister {
|
||||||
span: p.token.span,
|
span: p.token.span,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -458,7 +458,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||||||
match expr_to_spanned_string(ecx, template_expr, msg) {
|
match expr_to_spanned_string(ecx, template_expr, msg) {
|
||||||
Ok(template_part) => template_part,
|
Ok(template_part) => template_part,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let Some((mut err, _)) = err {
|
if let Some((err, _)) = err {
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
@ -541,7 +541,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||||||
let err = parser.errors.remove(0);
|
let err = parser.errors.remove(0);
|
||||||
let err_sp = template_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
|
let err_sp = template_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
|
||||||
let msg = format!("invalid asm template string: {}", err.description);
|
let msg = format!("invalid asm template string: {}", err.description);
|
||||||
let mut e = ecx.struct_span_err(err_sp, msg);
|
let mut e = ecx.dcx().struct_span_err(err_sp, msg);
|
||||||
e.span_label(err_sp, err.label + " in asm template string");
|
e.span_label(err_sp, err.label + " in asm template string");
|
||||||
if let Some(note) = err.note {
|
if let Some(note) = err.note {
|
||||||
e.note(note);
|
e.note(note);
|
||||||
@ -575,7 +575,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||||||
|| args.reg_args.contains(idx)
|
|| args.reg_args.contains(idx)
|
||||||
{
|
{
|
||||||
let msg = format!("invalid reference to argument at index {idx}");
|
let msg = format!("invalid reference to argument at index {idx}");
|
||||||
let mut err = ecx.struct_span_err(span, msg);
|
let mut err = ecx.dcx().struct_span_err(span, msg);
|
||||||
err.span_label(span, "from here");
|
err.span_label(span, "from here");
|
||||||
|
|
||||||
let positional_args = args.operands.len()
|
let positional_args = args.operands.len()
|
||||||
@ -625,12 +625,13 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||||||
None => {
|
None => {
|
||||||
let msg = format!("there is no argument named `{name}`");
|
let msg = format!("there is no argument named `{name}`");
|
||||||
let span = arg.position_span;
|
let span = arg.position_span;
|
||||||
ecx.struct_span_err(
|
ecx.dcx()
|
||||||
template_span
|
.struct_span_err(
|
||||||
.from_inner(InnerSpan::new(span.start, span.end)),
|
template_span
|
||||||
msg,
|
.from_inner(InnerSpan::new(span.start, span.end)),
|
||||||
)
|
msg,
|
||||||
.emit();
|
)
|
||||||
|
.emit();
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -645,7 +646,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||||||
.ty_span
|
.ty_span
|
||||||
.map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end)))
|
.map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end)))
|
||||||
.unwrap_or(template_sp);
|
.unwrap_or(template_sp);
|
||||||
ecx.emit_err(errors::AsmModifierInvalid { span });
|
ecx.dcx().emit_err(errors::AsmModifierInvalid { span });
|
||||||
modifier = None;
|
modifier = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,16 +693,17 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||||||
0 => {}
|
0 => {}
|
||||||
1 => {
|
1 => {
|
||||||
let (sp, msg) = unused_operands.into_iter().next().unwrap();
|
let (sp, msg) = unused_operands.into_iter().next().unwrap();
|
||||||
let mut err = ecx.struct_span_err(sp, msg);
|
ecx.dcx()
|
||||||
err.span_label(sp, msg);
|
.struct_span_err(sp, msg)
|
||||||
err.help(format!(
|
.with_span_label(sp, msg)
|
||||||
"if this argument is intentionally unused, \
|
.with_help(format!(
|
||||||
consider using it in an asm comment: `\"/*{help_str} */\"`"
|
"if this argument is intentionally unused, \
|
||||||
));
|
consider using it in an asm comment: `\"/*{help_str} */\"`"
|
||||||
err.emit();
|
))
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut err = ecx.struct_span_err(
|
let mut err = ecx.dcx().struct_span_err(
|
||||||
unused_operands.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
|
unused_operands.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
|
||||||
"multiple unused asm arguments",
|
"multiple unused asm arguments",
|
||||||
);
|
);
|
||||||
@ -746,7 +748,7 @@ pub(super) fn expand_asm<'cx>(
|
|||||||
};
|
};
|
||||||
MacEager::expr(expr)
|
MacEager::expr(expr)
|
||||||
}
|
}
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
@ -778,7 +780,7 @@ pub(super) fn expand_global_asm<'cx>(
|
|||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ pub fn expand_assert<'cx>(
|
|||||||
) -> Box<dyn MacResult + 'cx> {
|
) -> Box<dyn MacResult + 'cx> {
|
||||||
let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) {
|
let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) {
|
||||||
Ok(assert) => assert,
|
Ok(assert) => assert,
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
return DummyResult::any(span);
|
return DummyResult::any(span);
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
|
|||||||
let mut parser = cx.new_parser_from_tts(stream);
|
let mut parser = cx.new_parser_from_tts(stream);
|
||||||
|
|
||||||
if parser.token == token::Eof {
|
if parser.token == token::Eof {
|
||||||
return Err(cx.create_err(errors::AssertRequiresBoolean { span: sp }));
|
return Err(cx.dcx().create_err(errors::AssertRequiresBoolean { span: sp }));
|
||||||
}
|
}
|
||||||
|
|
||||||
let cond_expr = parser.parse_expr()?;
|
let cond_expr = parser.parse_expr()?;
|
||||||
@ -128,7 +128,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
|
|||||||
//
|
//
|
||||||
// Emit an error about semicolon and suggest removing it.
|
// Emit an error about semicolon and suggest removing it.
|
||||||
if parser.token == token::Semi {
|
if parser.token == token::Semi {
|
||||||
cx.emit_err(errors::AssertRequiresExpression { span: sp, token: parser.token.span });
|
cx.dcx().emit_err(errors::AssertRequiresExpression { span: sp, token: parser.token.span });
|
||||||
parser.bump();
|
parser.bump();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
|
|||||||
let custom_message =
|
let custom_message =
|
||||||
if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind {
|
if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind {
|
||||||
let comma = parser.prev_token.span.shrink_to_hi();
|
let comma = parser.prev_token.span.shrink_to_hi();
|
||||||
cx.emit_err(errors::AssertMissingComma { span: parser.token.span, comma });
|
cx.dcx().emit_err(errors::AssertMissingComma { span: parser.token.span, comma });
|
||||||
|
|
||||||
parse_custom_message(&mut parser)
|
parse_custom_message(&mut parser)
|
||||||
} else if parser.eat(&token::Comma) {
|
} else if parser.eat(&token::Comma) {
|
||||||
|
|||||||
@ -303,7 +303,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||||||
| ExprKind::Continue(_)
|
| ExprKind::Continue(_)
|
||||||
| ExprKind::Err
|
| ExprKind::Err
|
||||||
| ExprKind::Field(_, _)
|
| ExprKind::Field(_, _)
|
||||||
| ExprKind::ForLoop(_, _, _, _)
|
| ExprKind::ForLoop { .. }
|
||||||
| ExprKind::FormatArgs(_)
|
| ExprKind::FormatArgs(_)
|
||||||
| ExprKind::IncludedBytes(..)
|
| ExprKind::IncludedBytes(..)
|
||||||
| ExprKind::InlineAsm(_)
|
| ExprKind::InlineAsm(_)
|
||||||
|
|||||||
@ -22,13 +22,13 @@ pub fn expand_cfg(
|
|||||||
Ok(cfg) => {
|
Ok(cfg) => {
|
||||||
let matches_cfg = attr::cfg_matches(
|
let matches_cfg = attr::cfg_matches(
|
||||||
&cfg,
|
&cfg,
|
||||||
&cx.sess.parse_sess,
|
&cx.sess,
|
||||||
cx.current_expansion.lint_node_id,
|
cx.current_expansion.lint_node_id,
|
||||||
Some(cx.ecfg.features),
|
Some(cx.ecfg.features),
|
||||||
);
|
);
|
||||||
MacEager::expr(cx.expr_bool(sp, matches_cfg))
|
MacEager::expr(cx.expr_bool(sp, matches_cfg))
|
||||||
}
|
}
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@ fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<
|
|||||||
let mut p = cx.new_parser_from_tts(tts);
|
let mut p = cx.new_parser_from_tts(tts);
|
||||||
|
|
||||||
if p.token == token::Eof {
|
if p.token == token::Eof {
|
||||||
return Err(cx.create_err(errors::RequiresCfgPattern { span }));
|
return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));
|
||||||
}
|
}
|
||||||
|
|
||||||
let cfg = p.parse_meta_item()?;
|
let cfg = p.parse_meta_item()?;
|
||||||
@ -47,7 +47,7 @@ fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<
|
|||||||
let _ = p.eat(&token::Comma);
|
let _ = p.eat(&token::Comma);
|
||||||
|
|
||||||
if !p.eat(&token::Eof) {
|
if !p.eat(&token::Eof) {
|
||||||
return Err(cx.create_err(errors::OneCfgPattern { span }));
|
return Err(cx.dcx().create_err(errors::OneCfgPattern { span }));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(cfg)
|
Ok(cfg)
|
||||||
|
|||||||
@ -15,18 +15,18 @@ fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'
|
|||||||
match mi.meta_item_list() {
|
match mi.meta_item_list() {
|
||||||
None => {}
|
None => {}
|
||||||
Some([]) => {
|
Some([]) => {
|
||||||
ecx.emit_err(UnspecifiedPath(mi.span));
|
ecx.dcx().emit_err(UnspecifiedPath(mi.span));
|
||||||
}
|
}
|
||||||
Some([_, .., l]) => {
|
Some([_, .., l]) => {
|
||||||
ecx.emit_err(MultiplePaths(l.span()));
|
ecx.dcx().emit_err(MultiplePaths(l.span()));
|
||||||
}
|
}
|
||||||
Some([nmi]) => match nmi.meta_item() {
|
Some([nmi]) => match nmi.meta_item() {
|
||||||
None => {
|
None => {
|
||||||
ecx.emit_err(LiteralPath(nmi.span()));
|
ecx.dcx().emit_err(LiteralPath(nmi.span()));
|
||||||
}
|
}
|
||||||
Some(mi) => {
|
Some(mi) => {
|
||||||
if !mi.is_word() {
|
if !mi.is_word() {
|
||||||
ecx.emit_err(HasArguments(mi.span));
|
ecx.dcx().emit_err(HasArguments(mi.span));
|
||||||
}
|
}
|
||||||
return Some(&mi.path);
|
return Some(&mi.path);
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ impl MultiItemModifier for Expander {
|
|||||||
Ok(true) => ExpandResult::Ready(vec![item]),
|
Ok(true) => ExpandResult::Ready(vec![item]),
|
||||||
Ok(false) => ExpandResult::Ready(Vec::new()),
|
Ok(false) => ExpandResult::Ready(Vec::new()),
|
||||||
Err(Indeterminate) if ecx.force_mode => {
|
Err(Indeterminate) if ecx.force_mode => {
|
||||||
ecx.emit_err(errors::CfgAccessibleIndeterminate { span });
|
ecx.dcx().emit_err(errors::CfgAccessibleIndeterminate { span });
|
||||||
ExpandResult::Ready(vec![item])
|
ExpandResult::Ready(vec![item])
|
||||||
}
|
}
|
||||||
Err(Indeterminate) => ExpandResult::Retry(item),
|
Err(Indeterminate) => ExpandResult::Retry(item),
|
||||||
|
|||||||
@ -200,7 +200,7 @@ impl CfgEval<'_, '_> {
|
|||||||
parser.capture_cfg = true;
|
parser.capture_cfg = true;
|
||||||
match parse_annotatable_with(&mut parser) {
|
match parse_annotatable_with(&mut parser) {
|
||||||
Ok(a) => annotatable = a,
|
Ok(a) => annotatable = a,
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
return Some(annotatable);
|
return Some(annotatable);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String])
|
|||||||
let start_span = parser.token.span;
|
let start_span = parser.token.span;
|
||||||
let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
||||||
Ok(ai) => ai,
|
Ok(ai) => ai,
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ pub fn expand_compile_error<'cx>(
|
|||||||
reason = "diagnostic message is specified by user"
|
reason = "diagnostic message is specified by user"
|
||||||
)]
|
)]
|
||||||
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
|
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
|
||||||
cx.span_err(sp, var.to_string());
|
cx.dcx().span_err(sp, var.to_string());
|
||||||
|
|
||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,11 +33,11 @@ pub fn expand_concat(
|
|||||||
accumulator.push_str(&b.to_string());
|
accumulator.push_str(&b.to_string());
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::CStr(..)) => {
|
Ok(ast::LitKind::CStr(..)) => {
|
||||||
cx.emit_err(errors::ConcatCStrLit { span: e.span });
|
cx.dcx().emit_err(errors::ConcatCStrLit { span: e.span });
|
||||||
has_errors = true;
|
has_errors = true;
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
|
Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
|
||||||
cx.emit_err(errors::ConcatBytestr { span: e.span });
|
cx.dcx().emit_err(errors::ConcatBytestr { span: e.span });
|
||||||
has_errors = true;
|
has_errors = true;
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Err) => {
|
Ok(ast::LitKind::Err) => {
|
||||||
@ -63,7 +63,7 @@ pub fn expand_concat(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::IncludedBytes(..) => {
|
ast::ExprKind::IncludedBytes(..) => {
|
||||||
cx.emit_err(errors::ConcatBytestr { span: e.span });
|
cx.dcx().emit_err(errors::ConcatBytestr { span: e.span });
|
||||||
}
|
}
|
||||||
ast::ExprKind::Err => {
|
ast::ExprKind::Err => {
|
||||||
has_errors = true;
|
has_errors = true;
|
||||||
@ -75,7 +75,7 @@ pub fn expand_concat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !missing_literal.is_empty() {
|
if !missing_literal.is_empty() {
|
||||||
cx.emit_err(errors::ConcatMissingLiteral { spans: missing_literal });
|
cx.dcx().emit_err(errors::ConcatMissingLiteral { spans: missing_literal });
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
} else if has_errors {
|
} else if has_errors {
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
|
|||||||
@ -17,16 +17,17 @@ fn invalid_type_err(
|
|||||||
ConcatBytesInvalid, ConcatBytesInvalidSuggestion, ConcatBytesNonU8, ConcatBytesOob,
|
ConcatBytesInvalid, ConcatBytesInvalidSuggestion, ConcatBytesNonU8, ConcatBytesOob,
|
||||||
};
|
};
|
||||||
let snippet = cx.sess.source_map().span_to_snippet(span).ok();
|
let snippet = cx.sess.source_map().span_to_snippet(span).ok();
|
||||||
|
let dcx = cx.dcx();
|
||||||
match ast::LitKind::from_token_lit(token_lit) {
|
match ast::LitKind::from_token_lit(token_lit) {
|
||||||
Ok(ast::LitKind::CStr(_, _)) => {
|
Ok(ast::LitKind::CStr(_, _)) => {
|
||||||
// FIXME(c_str_literals): should concatenation of C string literals
|
// Avoid ambiguity in handling of terminal `NUL` by refusing to
|
||||||
// include the null bytes in the end?
|
// concatenate C string literals as bytes.
|
||||||
cx.emit_err(errors::ConcatCStrLit { span: span });
|
dcx.emit_err(errors::ConcatCStrLit { span: span });
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Char(_)) => {
|
Ok(ast::LitKind::Char(_)) => {
|
||||||
let sugg =
|
let sugg =
|
||||||
snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet });
|
snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet });
|
||||||
cx.sess.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg });
|
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg });
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Str(_, _)) => {
|
Ok(ast::LitKind::Str(_, _)) => {
|
||||||
// suggestion would be invalid if we are nested
|
// suggestion would be invalid if we are nested
|
||||||
@ -35,29 +36,29 @@ fn invalid_type_err(
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
cx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg });
|
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg });
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Float(_, _)) => {
|
Ok(ast::LitKind::Float(_, _)) => {
|
||||||
cx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None });
|
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None });
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Bool(_)) => {
|
Ok(ast::LitKind::Bool(_)) => {
|
||||||
cx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None });
|
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None });
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Err) => {}
|
Ok(ast::LitKind::Err) => {}
|
||||||
Ok(ast::LitKind::Int(_, _)) if !is_nested => {
|
Ok(ast::LitKind::Int(_, _)) if !is_nested => {
|
||||||
let sugg =
|
let sugg =
|
||||||
snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span: span, snippet });
|
snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span: span, snippet });
|
||||||
cx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg });
|
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg });
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Int(
|
Ok(ast::LitKind::Int(
|
||||||
val,
|
val,
|
||||||
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
||||||
)) => {
|
)) => {
|
||||||
assert!(val > u8::MAX.into()); // must be an error
|
assert!(val.get() > u8::MAX.into()); // must be an error
|
||||||
cx.emit_err(ConcatBytesOob { span });
|
dcx.emit_err(ConcatBytesOob { span });
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::Int(_, _)) => {
|
Ok(ast::LitKind::Int(_, _)) => {
|
||||||
cx.emit_err(ConcatBytesNonU8 { span });
|
dcx.emit_err(ConcatBytesNonU8 { span });
|
||||||
}
|
}
|
||||||
Ok(ast::LitKind::ByteStr(..) | ast::LitKind::Byte(_)) => unreachable!(),
|
Ok(ast::LitKind::ByteStr(..) | ast::LitKind::Byte(_)) => unreachable!(),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -72,10 +73,11 @@ fn handle_array_element(
|
|||||||
missing_literals: &mut Vec<rustc_span::Span>,
|
missing_literals: &mut Vec<rustc_span::Span>,
|
||||||
expr: &P<rustc_ast::Expr>,
|
expr: &P<rustc_ast::Expr>,
|
||||||
) -> Option<u8> {
|
) -> Option<u8> {
|
||||||
|
let dcx = cx.dcx();
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => {
|
ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => {
|
||||||
if !*has_errors {
|
if !*has_errors {
|
||||||
cx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false });
|
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false });
|
||||||
}
|
}
|
||||||
*has_errors = true;
|
*has_errors = true;
|
||||||
None
|
None
|
||||||
@ -84,12 +86,12 @@ fn handle_array_element(
|
|||||||
Ok(ast::LitKind::Int(
|
Ok(ast::LitKind::Int(
|
||||||
val,
|
val,
|
||||||
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
||||||
)) if val <= u8::MAX.into() => Some(val as u8),
|
)) if val.get() <= u8::MAX.into() => Some(val.get() as u8),
|
||||||
|
|
||||||
Ok(ast::LitKind::Byte(val)) => Some(val),
|
Ok(ast::LitKind::Byte(val)) => Some(val),
|
||||||
Ok(ast::LitKind::ByteStr(..)) => {
|
Ok(ast::LitKind::ByteStr(..)) => {
|
||||||
if !*has_errors {
|
if !*has_errors {
|
||||||
cx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: true });
|
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: true });
|
||||||
}
|
}
|
||||||
*has_errors = true;
|
*has_errors = true;
|
||||||
None
|
None
|
||||||
@ -104,7 +106,7 @@ fn handle_array_element(
|
|||||||
},
|
},
|
||||||
ast::ExprKind::IncludedBytes(..) => {
|
ast::ExprKind::IncludedBytes(..) => {
|
||||||
if !*has_errors {
|
if !*has_errors {
|
||||||
cx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false });
|
dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false });
|
||||||
}
|
}
|
||||||
*has_errors = true;
|
*has_errors = true;
|
||||||
None
|
None
|
||||||
@ -146,12 +148,12 @@ pub fn expand_concat_bytes(
|
|||||||
if let Some(elem) =
|
if let Some(elem) =
|
||||||
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
|
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
|
||||||
{
|
{
|
||||||
for _ in 0..count_val {
|
for _ in 0..count_val.get() {
|
||||||
accumulator.push(elem);
|
accumulator.push(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cx.emit_err(errors::ConcatBytesBadRepeat { span: count.value.span });
|
cx.dcx().emit_err(errors::ConcatBytesBadRepeat { span: count.value.span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
&ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||||
@ -180,7 +182,7 @@ pub fn expand_concat_bytes(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !missing_literals.is_empty() {
|
if !missing_literals.is_empty() {
|
||||||
cx.emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals });
|
cx.dcx().emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals });
|
||||||
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
|
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
|
||||||
} else if has_errors {
|
} else if has_errors {
|
||||||
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
|
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
|
||||||
|
|||||||
@ -14,7 +14,7 @@ pub fn expand_concat_idents<'cx>(
|
|||||||
tts: TokenStream,
|
tts: TokenStream,
|
||||||
) -> Box<dyn base::MacResult + 'cx> {
|
) -> Box<dyn base::MacResult + 'cx> {
|
||||||
if tts.is_empty() {
|
if tts.is_empty() {
|
||||||
cx.emit_err(errors::ConcatIdentsMissingArgs { span: sp });
|
cx.dcx().emit_err(errors::ConcatIdentsMissingArgs { span: sp });
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ pub fn expand_concat_idents<'cx>(
|
|||||||
match e {
|
match e {
|
||||||
TokenTree::Token(Token { kind: token::Comma, .. }, _) => {}
|
TokenTree::Token(Token { kind: token::Comma, .. }, _) => {}
|
||||||
_ => {
|
_ => {
|
||||||
cx.emit_err(errors::ConcatIdentsMissingComma { span: sp });
|
cx.dcx().emit_err(errors::ConcatIdentsMissingComma { span: sp });
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ pub fn expand_concat_idents<'cx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.emit_err(errors::ConcatIdentsIdentArgs { span: sp });
|
cx.dcx().emit_err(errors::ConcatIdentsIdentArgs { span: sp });
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -120,7 +120,7 @@ fn report_bad_target(
|
|||||||
let bad_target =
|
let bad_target =
|
||||||
!matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..)));
|
!matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..)));
|
||||||
if bad_target {
|
if bad_target {
|
||||||
return Err(sess.emit_err(errors::BadDeriveTarget { span, item: item.span() }));
|
return Err(sess.dcx().emit_err(errors::BadDeriveTarget { span, item: item.span() }));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
|
|||||||
}
|
}
|
||||||
_ => errors::BadDeriveLitHelp::Other,
|
_ => errors::BadDeriveLitHelp::Other,
|
||||||
};
|
};
|
||||||
sess.emit_err(errors::BadDeriveLit { span: lit.span, help });
|
sess.dcx().emit_err(errors::BadDeriveLit { span: lit.span, help });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
|
fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
|
||||||
@ -143,10 +143,10 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
|
|||||||
match meta.kind {
|
match meta.kind {
|
||||||
MetaItemKind::Word => {}
|
MetaItemKind::Word => {}
|
||||||
MetaItemKind::List(..) => {
|
MetaItemKind::List(..) => {
|
||||||
sess.emit_err(errors::DerivePathArgsList { span });
|
sess.dcx().emit_err(errors::DerivePathArgsList { span });
|
||||||
}
|
}
|
||||||
MetaItemKind::NameValue(..) => {
|
MetaItemKind::NameValue(..) => {
|
||||||
sess.emit_err(errors::DerivePathArgsValue { span });
|
sess.dcx().emit_err(errors::DerivePathArgsValue { span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,10 +62,10 @@ pub fn expand_deriving_clone(
|
|||||||
cs_clone_simple("Clone", c, s, sub, true)
|
cs_clone_simple("Clone", c, s, sub, true)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
_ => cx.span_bug(span, "`#[derive(Clone)]` on wrong item kind"),
|
_ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on wrong item kind"),
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
|
_ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let trait_def = TraitDef {
|
let trait_def = TraitDef {
|
||||||
@ -144,7 +144,7 @@ fn cs_clone_simple(
|
|||||||
process_variant(&variant.data);
|
process_variant(&variant.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => cx.span_bug(
|
_ => cx.dcx().span_bug(
|
||||||
trait_span,
|
trait_span,
|
||||||
format!("unexpected substructure in simple `derive({name})`"),
|
format!("unexpected substructure in simple `derive({name})`"),
|
||||||
),
|
),
|
||||||
@ -180,10 +180,10 @@ fn cs_clone(
|
|||||||
vdata = &variant.data;
|
vdata = &variant.data;
|
||||||
}
|
}
|
||||||
EnumTag(..) | AllFieldlessEnum(..) => {
|
EnumTag(..) | AllFieldlessEnum(..) => {
|
||||||
cx.span_bug(trait_span, format!("enum tags in `derive({name})`",))
|
cx.dcx().span_bug(trait_span, format!("enum tags in `derive({name})`",))
|
||||||
}
|
}
|
||||||
StaticEnum(..) | StaticStruct(..) => {
|
StaticEnum(..) | StaticStruct(..) => {
|
||||||
cx.span_bug(trait_span, format!("associated function in `derive({name})`"))
|
cx.dcx().span_bug(trait_span, format!("associated function in `derive({name})`"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ fn cs_clone(
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let Some(ident) = field.name else {
|
let Some(ident) = field.name else {
|
||||||
cx.span_bug(
|
cx.dcx().span_bug(
|
||||||
trait_span,
|
trait_span,
|
||||||
format!("unnamed field in normal struct in `derive({name})`",),
|
format!("unnamed field in normal struct in `derive({name})`",),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -19,19 +19,6 @@ pub fn expand_deriving_eq(
|
|||||||
) {
|
) {
|
||||||
let span = cx.with_def_site_ctxt(span);
|
let span = cx.with_def_site_ctxt(span);
|
||||||
|
|
||||||
let structural_trait_def = TraitDef {
|
|
||||||
span,
|
|
||||||
path: path_std!(marker::StructuralEq),
|
|
||||||
skip_path_as_bound: true, // crucial!
|
|
||||||
needs_copy_as_bound_if_packed: false,
|
|
||||||
additional_bounds: Vec::new(),
|
|
||||||
supports_unions: true,
|
|
||||||
methods: Vec::new(),
|
|
||||||
associated_types: Vec::new(),
|
|
||||||
is_const: false,
|
|
||||||
};
|
|
||||||
structural_trait_def.expand(cx, mitem, item, push);
|
|
||||||
|
|
||||||
let trait_def = TraitDef {
|
let trait_def = TraitDef {
|
||||||
span,
|
span,
|
||||||
path: path_std!(cmp::Eq),
|
path: path_std!(cmp::Eq),
|
||||||
@ -99,7 +86,7 @@ fn cs_total_eq_assert(
|
|||||||
process_variant(&variant.data);
|
process_variant(&variant.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => cx.span_bug(trait_span, "unexpected substructure in `derive(Eq)`"),
|
_ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive(Eq)`"),
|
||||||
}
|
}
|
||||||
BlockOrExpr::new_stmts(stmts)
|
BlockOrExpr::new_stmts(stmts)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> Bl
|
|||||||
|cx, fold| match fold {
|
|cx, fold| match fold {
|
||||||
CsFold::Single(field) => {
|
CsFold::Single(field) => {
|
||||||
let [other_expr] = &field.other_selflike_exprs[..] else {
|
let [other_expr] = &field.other_selflike_exprs[..] else {
|
||||||
cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
|
cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
|
||||||
};
|
};
|
||||||
let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
|
let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
|
||||||
cx.expr_call_global(field.span, cmp_path.clone(), args)
|
cx.expr_call_global(field.span, cmp_path.clone(), args)
|
||||||
|
|||||||
@ -26,7 +26,8 @@ pub fn expand_deriving_partial_eq(
|
|||||||
|cx, fold| match fold {
|
|cx, fold| match fold {
|
||||||
CsFold::Single(field) => {
|
CsFold::Single(field) => {
|
||||||
let [other_expr] = &field.other_selflike_exprs[..] else {
|
let [other_expr] = &field.other_selflike_exprs[..] else {
|
||||||
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
|
cx.dcx()
|
||||||
|
.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
|
||||||
};
|
};
|
||||||
|
|
||||||
// We received arguments of type `&T`. Convert them to type `T` by stripping
|
// We received arguments of type `&T`. Convert them to type `T` by stripping
|
||||||
|
|||||||
@ -95,7 +95,7 @@ fn cs_partial_cmp(
|
|||||||
|cx, fold| match fold {
|
|cx, fold| match fold {
|
||||||
CsFold::Single(field) => {
|
CsFold::Single(field) => {
|
||||||
let [other_expr] = &field.other_selflike_exprs[..] else {
|
let [other_expr] = &field.other_selflike_exprs[..] else {
|
||||||
cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
|
cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
|
||||||
};
|
};
|
||||||
let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
|
let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
|
||||||
cx.expr_call_global(field.span, partial_cmp_path.clone(), args)
|
cx.expr_call_global(field.span, partial_cmp_path.clone(), args)
|
||||||
|
|||||||
@ -55,7 +55,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
|||||||
EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
|
EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
|
||||||
AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr),
|
AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr),
|
||||||
EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
|
EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
|
||||||
cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
|
cx.dcx().span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -177,7 +177,7 @@ fn decodable_substructure(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
|
_ => cx.dcx().bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
|
||||||
};
|
};
|
||||||
BlockOrExpr::new_expr(expr)
|
BlockOrExpr::new_expr(expr)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ pub fn expand_deriving_default(
|
|||||||
default_struct_substructure(cx, trait_span, substr, fields)
|
default_struct_substructure(cx, trait_span, substr, fields)
|
||||||
}
|
}
|
||||||
StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def),
|
StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def),
|
||||||
_ => cx.span_bug(trait_span, "method in `derive(Default)`"),
|
_ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"),
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
}],
|
}],
|
||||||
@ -120,7 +120,7 @@ fn extract_default_variant<'a>(
|
|||||||
let suggs = possible_defaults
|
let suggs = possible_defaults
|
||||||
.map(|v| errors::NoDefaultVariantSugg { span: v.span, ident: v.ident })
|
.map(|v| errors::NoDefaultVariantSugg { span: v.span, ident: v.ident })
|
||||||
.collect();
|
.collect();
|
||||||
cx.emit_err(errors::NoDefaultVariant { span: trait_span, suggs });
|
cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, suggs });
|
||||||
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ fn extract_default_variant<'a>(
|
|||||||
.then_some(errors::MultipleDefaultsSugg { spans, ident: variant.ident })
|
.then_some(errors::MultipleDefaultsSugg { spans, ident: variant.ident })
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
cx.emit_err(errors::MultipleDefaults {
|
cx.dcx().emit_err(errors::MultipleDefaults {
|
||||||
span: trait_span,
|
span: trait_span,
|
||||||
first: first.span,
|
first: first.span,
|
||||||
additional: rest.iter().map(|v| v.span).collect(),
|
additional: rest.iter().map(|v| v.span).collect(),
|
||||||
@ -151,12 +151,12 @@ fn extract_default_variant<'a>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !matches!(variant.data, VariantData::Unit(..)) {
|
if !matches!(variant.data, VariantData::Unit(..)) {
|
||||||
cx.emit_err(errors::NonUnitDefault { span: variant.ident.span });
|
cx.dcx().emit_err(errors::NonUnitDefault { span: variant.ident.span });
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(non_exhaustive_attr) = attr::find_by_name(&variant.attrs, sym::non_exhaustive) {
|
if let Some(non_exhaustive_attr) = attr::find_by_name(&variant.attrs, sym::non_exhaustive) {
|
||||||
cx.emit_err(errors::NonExhaustiveDefault {
|
cx.dcx().emit_err(errors::NonExhaustiveDefault {
|
||||||
span: variant.ident.span,
|
span: variant.ident.span,
|
||||||
non_exhaustive: non_exhaustive_attr.span,
|
non_exhaustive: non_exhaustive_attr.span,
|
||||||
});
|
});
|
||||||
@ -176,14 +176,14 @@ fn validate_default_attribute(
|
|||||||
|
|
||||||
let attr = match attrs.as_slice() {
|
let attr = match attrs.as_slice() {
|
||||||
[attr] => attr,
|
[attr] => attr,
|
||||||
[] => cx.bug(
|
[] => cx.dcx().bug(
|
||||||
"this method must only be called with a variant that has a `#[default]` attribute",
|
"this method must only be called with a variant that has a `#[default]` attribute",
|
||||||
),
|
),
|
||||||
[first, rest @ ..] => {
|
[first, rest @ ..] => {
|
||||||
let sugg = errors::MultipleDefaultAttrsSugg {
|
let sugg = errors::MultipleDefaultAttrsSugg {
|
||||||
spans: rest.iter().map(|attr| attr.span).collect(),
|
spans: rest.iter().map(|attr| attr.span).collect(),
|
||||||
};
|
};
|
||||||
cx.emit_err(errors::MultipleDefaultAttrs {
|
cx.dcx().emit_err(errors::MultipleDefaultAttrs {
|
||||||
span: default_variant.ident.span,
|
span: default_variant.ident.span,
|
||||||
first: first.span,
|
first: first.span,
|
||||||
first_rest: rest[0].span,
|
first_rest: rest[0].span,
|
||||||
@ -196,7 +196,7 @@ fn validate_default_attribute(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !attr.is_word() {
|
if !attr.is_word() {
|
||||||
cx.emit_err(errors::DefaultHasArg { span: attr.span });
|
cx.dcx().emit_err(errors::DefaultHasArg { span: attr.span });
|
||||||
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
@ -210,7 +210,7 @@ struct DetectNonVariantDefaultAttr<'a, 'b> {
|
|||||||
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
|
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
|
||||||
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
|
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
|
||||||
if attr.has_name(kw::Default) {
|
if attr.has_name(kw::Default) {
|
||||||
self.cx.emit_err(errors::NonUnitDefault { span: attr.span });
|
self.cx.dcx().emit_err(errors::NonUnitDefault { span: attr.span });
|
||||||
}
|
}
|
||||||
|
|
||||||
rustc_ast::visit::walk_attribute(self, attr);
|
rustc_ast::visit::walk_attribute(self, attr);
|
||||||
|
|||||||
@ -296,6 +296,6 @@ fn encodable_substructure(
|
|||||||
BlockOrExpr::new_mixed(thin_vec![me], Some(expr))
|
BlockOrExpr::new_mixed(thin_vec![me], Some(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"),
|
_ => cx.dcx().bug("expected Struct or EnumMatching in derive(Encodable)"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -430,7 +430,7 @@ fn find_type_parameters(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_mac_call(&mut self, mac: &ast::MacCall) {
|
fn visit_mac_call(&mut self, mac: &ast::MacCall) {
|
||||||
self.cx.emit_err(errors::DeriveMacroCall { span: mac.span() });
|
self.cx.dcx().emit_err(errors::DeriveMacroCall { span: mac.span() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +503,7 @@ impl<'a> TraitDef<'a> {
|
|||||||
is_packed,
|
is_packed,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
cx.emit_err(errors::DeriveUnion { span: mitem.span });
|
cx.dcx().emit_err(errors::DeriveUnion { span: mitem.span });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -974,7 +974,7 @@ impl<'a> MethodDef<'a> {
|
|||||||
match ty {
|
match ty {
|
||||||
// Selflike (`&Self`) arguments only occur in non-static methods.
|
// Selflike (`&Self`) arguments only occur in non-static methods.
|
||||||
Ref(box Self_, _) if !self.is_static() => selflike_args.push(arg_expr),
|
Ref(box Self_, _) if !self.is_static() => selflike_args.push(arg_expr),
|
||||||
Self_ => cx.span_bug(span, "`Self` in non-return position"),
|
Self_ => cx.dcx().span_bug(span, "`Self` in non-return position"),
|
||||||
_ => nonselflike_args.push(arg_expr),
|
_ => nonselflike_args.push(arg_expr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1441,9 +1441,9 @@ impl<'a> TraitDef<'a> {
|
|||||||
|
|
||||||
let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..));
|
let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..));
|
||||||
match (just_spans.is_empty(), named_idents.is_empty()) {
|
match (just_spans.is_empty(), named_idents.is_empty()) {
|
||||||
(false, false) => {
|
(false, false) => cx
|
||||||
cx.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`")
|
.dcx()
|
||||||
}
|
.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`"),
|
||||||
// named fields
|
// named fields
|
||||||
(_, false) => Named(named_idents),
|
(_, false) => Named(named_idents),
|
||||||
// unnamed fields
|
// unnamed fields
|
||||||
@ -1489,7 +1489,7 @@ impl<'a> TraitDef<'a> {
|
|||||||
let field_pats = pieces_iter
|
let field_pats = pieces_iter
|
||||||
.map(|(sp, ident, pat)| {
|
.map(|(sp, ident, pat)| {
|
||||||
if ident.is_none() {
|
if ident.is_none() {
|
||||||
cx.span_bug(
|
cx.dcx().span_bug(
|
||||||
sp,
|
sp,
|
||||||
"a braced struct with unnamed fields in `derive`",
|
"a braced struct with unnamed fields in `derive`",
|
||||||
);
|
);
|
||||||
@ -1707,7 +1707,9 @@ where
|
|||||||
tag_check_expr
|
tag_check_expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
|
StaticEnum(..) | StaticStruct(..) => {
|
||||||
AllFieldlessEnum(..) => cx.span_bug(trait_span, "fieldless enum in `derive`"),
|
cx.dcx().span_bug(trait_span, "static function in `derive`")
|
||||||
|
}
|
||||||
|
AllFieldlessEnum(..) => cx.dcx().span_bug(trait_span, "fieldless enum in `derive`"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,8 +138,8 @@ impl Ty {
|
|||||||
cx.path_all(span, false, vec![self_ty], params)
|
cx.path_all(span, false, vec![self_ty], params)
|
||||||
}
|
}
|
||||||
Path(p) => p.to_path(cx, span, self_ty, generics),
|
Path(p) => p.to_path(cx, span, self_ty, generics),
|
||||||
Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"),
|
Ref(..) => cx.dcx().span_bug(span, "ref in a path in generic `derive`"),
|
||||||
Unit => cx.span_bug(span, "unit in a path in generic `derive`"),
|
Unit => cx.dcx().span_bug(span, "unit in a path in generic `derive`"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,7 @@ fn hash_substructure(
|
|||||||
substr: &Substructure<'_>,
|
substr: &Substructure<'_>,
|
||||||
) -> BlockOrExpr {
|
) -> BlockOrExpr {
|
||||||
let [state_expr] = substr.nonselflike_args else {
|
let [state_expr] = substr.nonselflike_args else {
|
||||||
cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`");
|
cx.dcx().span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`");
|
||||||
};
|
};
|
||||||
let call_hash = |span, expr| {
|
let call_hash = |span, expr| {
|
||||||
let hash_path = {
|
let hash_path = {
|
||||||
@ -75,7 +75,7 @@ fn hash_substructure(
|
|||||||
let stmts = thin_vec![call_hash(tag_field.span, tag_field.self_expr.clone())];
|
let stmts = thin_vec![call_hash(tag_field.span, tag_field.self_expr.clone())];
|
||||||
(stmts, match_expr.clone())
|
(stmts, match_expr.clone())
|
||||||
}
|
}
|
||||||
_ => cx.span_bug(trait_span, "impossible substructure in `derive(Hash)`"),
|
_ => cx.dcx().span_bug(trait_span, "impossible substructure in `derive(Hash)`"),
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockOrExpr::new_mixed(stmts, match_expr)
|
BlockOrExpr::new_mixed(stmts, match_expr)
|
||||||
|
|||||||
@ -18,7 +18,7 @@ fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Option<Symbol> {
|
|||||||
if let Some(value) = cx.sess.opts.logical_env.get(var) {
|
if let Some(value) = cx.sess.opts.logical_env.get(var) {
|
||||||
return Some(Symbol::intern(value));
|
return Some(Symbol::intern(value));
|
||||||
}
|
}
|
||||||
// If the environment variable was not defined with the `--env` option, we try to retrieve it
|
// If the environment variable was not defined with the `--env-set` option, we try to retrieve it
|
||||||
// from rustc's environment.
|
// from rustc's environment.
|
||||||
env::var(var).ok().as_deref().map(Symbol::intern)
|
env::var(var).ok().as_deref().map(Symbol::intern)
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ pub fn expand_env<'cx>(
|
|||||||
) -> Box<dyn base::MacResult + 'cx> {
|
) -> Box<dyn base::MacResult + 'cx> {
|
||||||
let mut exprs = match get_exprs_from_tts(cx, tts) {
|
let mut exprs = match get_exprs_from_tts(cx, tts) {
|
||||||
Some(exprs) if exprs.is_empty() || exprs.len() > 2 => {
|
Some(exprs) if exprs.is_empty() || exprs.len() > 2 => {
|
||||||
cx.emit_err(errors::EnvTakesArgs { span: sp });
|
cx.dcx().emit_err(errors::EnvTakesArgs { span: sp });
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
None => return DummyResult::any(sp),
|
None => return DummyResult::any(sp),
|
||||||
@ -101,15 +101,15 @@ pub fn expand_env<'cx>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(msg_from_user) = custom_msg {
|
if let Some(msg_from_user) = custom_msg {
|
||||||
cx.emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user });
|
cx.dcx().emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user });
|
||||||
} else if is_cargo_env_var(var.as_str()) {
|
} else if is_cargo_env_var(var.as_str()) {
|
||||||
cx.emit_err(errors::EnvNotDefined::CargoEnvVar {
|
cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVar {
|
||||||
span,
|
span,
|
||||||
var: *symbol,
|
var: *symbol,
|
||||||
var_expr: var_expr.ast_deref(),
|
var_expr: var_expr.ast_deref(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cx.emit_err(errors::EnvNotDefined::CustomEnvVar {
|
cx.dcx().emit_err(errors::EnvNotDefined::CustomEnvVar {
|
||||||
span,
|
span,
|
||||||
var: *symbol,
|
var: *symbol,
|
||||||
var_expr: var_expr.ast_deref(),
|
var_expr: var_expr.ast_deref(),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
AddToDiagnostic, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
|
codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
|
||||||
SingleLabelManySpans,
|
Level, MultiSpan, SingleLabelManySpans,
|
||||||
};
|
};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
@ -269,7 +269,7 @@ pub(crate) struct ConcatIdentsIdentArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(builtin_macros_bad_derive_target, code = "E0774")]
|
#[diag(builtin_macros_bad_derive_target, code = E0774)]
|
||||||
pub(crate) struct BadDeriveTarget {
|
pub(crate) struct BadDeriveTarget {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
@ -283,7 +283,7 @@ pub(crate) struct BadDeriveTarget {
|
|||||||
pub(crate) struct TestsNotSupport {}
|
pub(crate) struct TestsNotSupport {}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(builtin_macros_unexpected_lit, code = "E0777")]
|
#[diag(builtin_macros_unexpected_lit, code = E0777)]
|
||||||
pub(crate) struct BadDeriveLit {
|
pub(crate) struct BadDeriveLit {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
@ -446,15 +446,15 @@ pub(crate) struct EnvNotDefinedWithUserMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hand-written implementation to support custom user messages.
|
// Hand-written implementation to support custom user messages.
|
||||||
impl<'a> IntoDiagnostic<'a> for EnvNotDefinedWithUserMessage {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||||
#[expect(
|
#[expect(
|
||||||
rustc::untranslatable_diagnostic,
|
rustc::untranslatable_diagnostic,
|
||||||
reason = "cannot translate user-provided messages"
|
reason = "cannot translate user-provided messages"
|
||||||
)]
|
)]
|
||||||
let mut diag = dcx.struct_err(self.msg_from_user.to_string());
|
let mut diag = DiagnosticBuilder::new(dcx, level, self.msg_from_user.to_string());
|
||||||
diag.set_span(self.span);
|
diag.span(self.span);
|
||||||
diag
|
diag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,7 +618,7 @@ impl AddToDiagnostic for FormatUnusedArg {
|
|||||||
rustc_errors::SubdiagnosticMessage,
|
rustc_errors::SubdiagnosticMessage,
|
||||||
) -> rustc_errors::SubdiagnosticMessage,
|
) -> rustc_errors::SubdiagnosticMessage,
|
||||||
{
|
{
|
||||||
diag.set_arg("named", self.named);
|
diag.arg("named", self.named);
|
||||||
let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
|
let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
|
||||||
diag.span_label(self.span, msg);
|
diag.span_label(self.span, msg);
|
||||||
}
|
}
|
||||||
@ -801,22 +801,25 @@ pub(crate) struct AsmClobberNoReg {
|
|||||||
pub(crate) clobbers: Vec<Span>,
|
pub(crate) clobbers: Vec<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoDiagnostic<'a> for AsmClobberNoReg {
|
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg {
|
||||||
fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
|
||||||
let mut diag = dcx.struct_err(crate::fluent_generated::builtin_macros_asm_clobber_no_reg);
|
|
||||||
diag.set_span(self.spans.clone());
|
|
||||||
// eager translation as `span_labels` takes `AsRef<str>`
|
// eager translation as `span_labels` takes `AsRef<str>`
|
||||||
let lbl1 = dcx.eagerly_translate_to_string(
|
let lbl1 = dcx.eagerly_translate_to_string(
|
||||||
crate::fluent_generated::builtin_macros_asm_clobber_abi,
|
crate::fluent_generated::builtin_macros_asm_clobber_abi,
|
||||||
[].into_iter(),
|
[].into_iter(),
|
||||||
);
|
);
|
||||||
diag.span_labels(self.clobbers, &lbl1);
|
|
||||||
let lbl2 = dcx.eagerly_translate_to_string(
|
let lbl2 = dcx.eagerly_translate_to_string(
|
||||||
crate::fluent_generated::builtin_macros_asm_clobber_outputs,
|
crate::fluent_generated::builtin_macros_asm_clobber_outputs,
|
||||||
[].into_iter(),
|
[].into_iter(),
|
||||||
);
|
);
|
||||||
diag.span_labels(self.spans, &lbl2);
|
DiagnosticBuilder::new(
|
||||||
diag
|
dcx,
|
||||||
|
level,
|
||||||
|
crate::fluent_generated::builtin_macros_asm_clobber_no_reg,
|
||||||
|
)
|
||||||
|
.with_span(self.spans.clone())
|
||||||
|
.with_span_labels(self.clobbers, &lbl1)
|
||||||
|
.with_span_labels(self.spans, &lbl2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,7 @@ use rustc_ast::{
|
|||||||
FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait,
|
FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait,
|
||||||
};
|
};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::{
|
use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan, PResult, SingleLabelManySpans};
|
||||||
Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult, SingleLabelManySpans,
|
|
||||||
};
|
|
||||||
use rustc_expand::base::{self, *};
|
use rustc_expand::base::{self, *};
|
||||||
use rustc_parse_format as parse;
|
use rustc_parse_format as parse;
|
||||||
use rustc_span::symbol::{Ident, Symbol};
|
use rustc_span::symbol::{Ident, Symbol};
|
||||||
@ -71,7 +69,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
|
|||||||
let mut p = ecx.new_parser_from_tts(tts);
|
let mut p = ecx.new_parser_from_tts(tts);
|
||||||
|
|
||||||
if p.token == token::Eof {
|
if p.token == token::Eof {
|
||||||
return Err(ecx.create_err(errors::FormatRequiresString { span: sp }));
|
return Err(ecx.dcx().create_err(errors::FormatRequiresString { span: sp }));
|
||||||
}
|
}
|
||||||
|
|
||||||
let first_token = &p.token;
|
let first_token = &p.token;
|
||||||
@ -101,7 +99,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
|
|||||||
}
|
}
|
||||||
|
|
||||||
match p.expect(&token::Comma) {
|
match p.expect(&token::Comma) {
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
match token::TokenKind::Comma.similar_tokens() {
|
match token::TokenKind::Comma.similar_tokens() {
|
||||||
Some(tks) if tks.contains(&p.token.kind) => {
|
Some(tks) if tks.contains(&p.token.kind) => {
|
||||||
// If a similar token is found, then it may be a typo. We
|
// If a similar token is found, then it may be a typo. We
|
||||||
@ -128,7 +126,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
|
|||||||
p.expect(&token::Eq)?;
|
p.expect(&token::Eq)?;
|
||||||
let expr = p.parse_expr()?;
|
let expr = p.parse_expr()?;
|
||||||
if let Some((_, prev)) = args.by_name(ident.name) {
|
if let Some((_, prev)) = args.by_name(ident.name) {
|
||||||
ecx.emit_err(errors::FormatDuplicateArg {
|
ecx.dcx().emit_err(errors::FormatDuplicateArg {
|
||||||
span: ident.span,
|
span: ident.span,
|
||||||
prev: prev.kind.ident().unwrap().span,
|
prev: prev.kind.ident().unwrap().span,
|
||||||
duplicate: ident.span,
|
duplicate: ident.span,
|
||||||
@ -141,7 +139,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
|
|||||||
_ => {
|
_ => {
|
||||||
let expr = p.parse_expr()?;
|
let expr = p.parse_expr()?;
|
||||||
if !args.named_args().is_empty() {
|
if !args.named_args().is_empty() {
|
||||||
ecx.emit_err(errors::PositionalAfterNamed {
|
return Err(ecx.dcx().create_err(errors::PositionalAfterNamed {
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
args: args
|
args: args
|
||||||
.named_args()
|
.named_args()
|
||||||
@ -149,7 +147,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
|
|||||||
.filter_map(|a| a.kind.ident().map(|ident| (a, ident)))
|
.filter_map(|a| a.kind.ident().map(|ident| (a, ident)))
|
||||||
.map(|(arg, n)| n.span.to(arg.expr.span))
|
.map(|(arg, n)| n.span.to(arg.expr.span))
|
||||||
.collect(),
|
.collect(),
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
args.add(FormatArgument { kind: FormatArgumentKind::Normal, expr });
|
args.add(FormatArgument { kind: FormatArgumentKind::Normal, expr });
|
||||||
}
|
}
|
||||||
@ -295,7 +293,7 @@ fn make_format_args(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ecx.emit_err(e);
|
ecx.dcx().emit_err(e);
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +313,8 @@ fn make_format_args(
|
|||||||
}
|
}
|
||||||
use ArgRef::*;
|
use ArgRef::*;
|
||||||
|
|
||||||
|
let mut unnamed_arg_after_named_arg = false;
|
||||||
|
|
||||||
let mut lookup_arg = |arg: ArgRef<'_>,
|
let mut lookup_arg = |arg: ArgRef<'_>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
used_as: PositionUsedAs,
|
used_as: PositionUsedAs,
|
||||||
@ -353,7 +353,8 @@ fn make_format_args(
|
|||||||
} else {
|
} else {
|
||||||
// For the moment capturing variables from format strings expanded from macros is
|
// For the moment capturing variables from format strings expanded from macros is
|
||||||
// disabled (see RFC #2795)
|
// disabled (see RFC #2795)
|
||||||
ecx.emit_err(errors::FormatNoArgNamed { span, name });
|
ecx.dcx().emit_err(errors::FormatNoArgNamed { span, name });
|
||||||
|
unnamed_arg_after_named_arg = true;
|
||||||
DummyResult::raw_expr(span, true)
|
DummyResult::raw_expr(span, true)
|
||||||
};
|
};
|
||||||
Ok(args.add(FormatArgument { kind: FormatArgumentKind::Captured(ident), expr }))
|
Ok(args.add(FormatArgument { kind: FormatArgumentKind::Captured(ident), expr }))
|
||||||
@ -512,7 +513,8 @@ fn make_format_args(
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if !unused.is_empty() {
|
let has_unused = !unused.is_empty();
|
||||||
|
if has_unused {
|
||||||
// If there's a lot of unused arguments,
|
// If there's a lot of unused arguments,
|
||||||
// let's check if this format arguments looks like another syntax (printf / shell).
|
// let's check if this format arguments looks like another syntax (printf / shell).
|
||||||
let detect_foreign_fmt = unused.len() > args.explicit_args().len() / 2;
|
let detect_foreign_fmt = unused.len() > args.explicit_args().len() / 2;
|
||||||
@ -531,7 +533,7 @@ fn make_format_args(
|
|||||||
|
|
||||||
// Only check for unused named argument names if there are no other errors to avoid causing
|
// Only check for unused named argument names if there are no other errors to avoid causing
|
||||||
// too much noise in output errors, such as when a named argument is entirely unused.
|
// too much noise in output errors, such as when a named argument is entirely unused.
|
||||||
if invalid_refs.is_empty() && ecx.sess.err_count() == 0 {
|
if invalid_refs.is_empty() && !has_unused && !unnamed_arg_after_named_arg {
|
||||||
for &(index, span, used_as) in &numeric_refences_to_named_arg {
|
for &(index, span, used_as) in &numeric_refences_to_named_arg {
|
||||||
let (position_sp_to_replace, position_sp_for_msg) = match used_as {
|
let (position_sp_to_replace, position_sp_for_msg) = match used_as {
|
||||||
Placeholder(pspan) => (span, pspan),
|
Placeholder(pspan) => (span, pspan),
|
||||||
@ -587,7 +589,7 @@ fn invalid_placeholder_type_error(
|
|||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
ecx.emit_err(errors::FormatUnknownTrait { span: sp.unwrap_or(fmt_span), ty, suggs });
|
ecx.dcx().emit_err(errors::FormatUnknownTrait { span: sp.unwrap_or(fmt_span), ty, suggs });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_missing_placeholders(
|
fn report_missing_placeholders(
|
||||||
@ -602,12 +604,12 @@ fn report_missing_placeholders(
|
|||||||
fmt_span: Span,
|
fmt_span: Span,
|
||||||
) {
|
) {
|
||||||
let mut diag = if let &[(span, named)] = &unused[..] {
|
let mut diag = if let &[(span, named)] = &unused[..] {
|
||||||
ecx.create_err(errors::FormatUnusedArg { span, named })
|
ecx.dcx().create_err(errors::FormatUnusedArg { span, named })
|
||||||
} else {
|
} else {
|
||||||
let unused_labels =
|
let unused_labels =
|
||||||
unused.iter().map(|&(span, named)| errors::FormatUnusedArg { span, named }).collect();
|
unused.iter().map(|&(span, named)| errors::FormatUnusedArg { span, named }).collect();
|
||||||
let unused_spans = unused.iter().map(|&(span, _)| span).collect();
|
let unused_spans = unused.iter().map(|&(span, _)| span).collect();
|
||||||
ecx.create_err(errors::FormatUnusedArgs {
|
ecx.dcx().create_err(errors::FormatUnusedArgs {
|
||||||
fmt: fmt_span,
|
fmt: fmt_span,
|
||||||
unused: unused_spans,
|
unused: unused_spans,
|
||||||
unused_labels,
|
unused_labels,
|
||||||
@ -632,8 +634,7 @@ fn report_missing_placeholders(
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if !placeholders.is_empty() {
|
if !placeholders.is_empty() {
|
||||||
if let Some(mut new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders)
|
if let Some(new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders) {
|
||||||
{
|
|
||||||
diag.cancel();
|
diag.cancel();
|
||||||
new_diag.emit();
|
new_diag.emit();
|
||||||
return;
|
return;
|
||||||
@ -726,7 +727,7 @@ fn report_redundant_format_arguments<'a>(
|
|||||||
args: &FormatArguments,
|
args: &FormatArguments,
|
||||||
used: &[bool],
|
used: &[bool],
|
||||||
placeholders: Vec<(Span, &str)>,
|
placeholders: Vec<(Span, &str)>,
|
||||||
) -> Option<DiagnosticBuilder<'a, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'a>> {
|
||||||
let mut fmt_arg_indices = vec![];
|
let mut fmt_arg_indices = vec![];
|
||||||
let mut args_spans = vec![];
|
let mut args_spans = vec![];
|
||||||
let mut fmt_spans = vec![];
|
let mut fmt_spans = vec![];
|
||||||
@ -778,7 +779,7 @@ fn report_redundant_format_arguments<'a>(
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
return Some(ecx.create_err(errors::FormatRedundantArgs {
|
return Some(ecx.dcx().create_err(errors::FormatRedundantArgs {
|
||||||
n: args_spans.len(),
|
n: args_spans.len(),
|
||||||
span: MultiSpan::from(args_spans),
|
span: MultiSpan::from(args_spans),
|
||||||
note: multispan,
|
note: multispan,
|
||||||
@ -878,14 +879,13 @@ fn report_invalid_references(
|
|||||||
} else {
|
} else {
|
||||||
MultiSpan::from_spans(spans)
|
MultiSpan::from_spans(spans)
|
||||||
};
|
};
|
||||||
e = ecx.create_err(errors::FormatPositionalMismatch {
|
e = ecx.dcx().create_err(errors::FormatPositionalMismatch {
|
||||||
span,
|
span,
|
||||||
n: num_placeholders,
|
n: num_placeholders,
|
||||||
desc: num_args_desc,
|
desc: num_args_desc,
|
||||||
highlight: SingleLabelManySpans {
|
highlight: SingleLabelManySpans {
|
||||||
spans: args.explicit_args().iter().map(|arg| arg.expr.span).collect(),
|
spans: args.explicit_args().iter().map(|arg| arg.expr.span).collect(),
|
||||||
label: "",
|
label: "",
|
||||||
kind: rustc_errors::LabelKind::Label,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// Point out `{:.*}` placeholders: those take an extra argument.
|
// Point out `{:.*}` placeholders: those take an extra argument.
|
||||||
@ -945,7 +945,7 @@ fn report_invalid_references(
|
|||||||
head = indexes.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(", ")
|
head = indexes.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(", ")
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
e = ecx.struct_span_err(
|
e = ecx.dcx().struct_span_err(
|
||||||
span,
|
span,
|
||||||
format!("invalid reference to positional {arg_list} ({num_args_desc})"),
|
format!("invalid reference to positional {arg_list} ({num_args_desc})"),
|
||||||
);
|
);
|
||||||
@ -979,7 +979,7 @@ fn expand_format_args_impl<'cx>(
|
|||||||
MacEager::expr(DummyResult::raw_expr(sp, true))
|
MacEager::expr(DummyResult::raw_expr(sp, true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ pub fn expand(
|
|||||||
{
|
{
|
||||||
(item, true, ecx.with_def_site_ctxt(ty.span))
|
(item, true, ecx.with_def_site_ctxt(ty.span))
|
||||||
} else {
|
} else {
|
||||||
ecx.sess.dcx().emit_err(errors::AllocMustStatics { span: item.span() });
|
ecx.dcx().emit_err(errors::AllocMustStatics { span: item.span() });
|
||||||
return vec![orig_item];
|
return vec![orig_item];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,16 +5,14 @@
|
|||||||
#![feature(rustdoc_internals)]
|
#![feature(rustdoc_internals)]
|
||||||
#![doc(rust_logo)]
|
#![doc(rust_logo)]
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![feature(array_windows)]
|
#![feature(assert_matches)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(is_sorted)]
|
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(lint_reasons)]
|
#![feature(lint_reasons)]
|
||||||
#![feature(proc_macro_internals)]
|
#![feature(proc_macro_internals)]
|
||||||
#![feature(proc_macro_quote)]
|
#![feature(proc_macro_quote)]
|
||||||
#![recursion_limit = "256"]
|
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
|||||||
@ -194,7 +194,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
|||||||
|
|
||||||
self.dcx
|
self.dcx
|
||||||
.struct_span_err(attr.span, msg)
|
.struct_span_err(attr.span, msg)
|
||||||
.span_label(prev_attr.span, "previous attribute here")
|
.with_span_label(prev_attr.span, "previous attribute here")
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -107,9 +107,9 @@ pub fn expand_include<'cx>(
|
|||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
};
|
};
|
||||||
// The file will be added to the code map by the parser
|
// The file will be added to the code map by the parser
|
||||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ pub fn expand_include<'cx>(
|
|||||||
let mut ret = SmallVec::new();
|
let mut ret = SmallVec::new();
|
||||||
loop {
|
loop {
|
||||||
match self.p.parse_item(ForceCollect::No) {
|
match self.p.parse_item(ForceCollect::No) {
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ pub fn expand_include<'cx>(
|
|||||||
if self.p.token != token::Eof {
|
if self.p.token != token::Eof {
|
||||||
let token = pprust::token_to_string(&self.p.token);
|
let token = pprust::token_to_string(&self.p.token);
|
||||||
let msg = format!("expected item, found `{token}`");
|
let msg = format!("expected item, found `{token}`");
|
||||||
self.p.struct_span_err(self.p.token.span, msg).emit();
|
self.p.dcx().span_err(self.p.token.span, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -179,9 +179,9 @@ pub fn expand_include_str(
|
|||||||
let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else {
|
let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else {
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
};
|
};
|
||||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
@ -193,12 +193,12 @@ pub fn expand_include_str(
|
|||||||
base::MacEager::expr(cx.expr_str(sp, interned_src))
|
base::MacEager::expr(cx.expr_str(sp, interned_src))
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
|
cx.dcx().span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
|
||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
|
cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
|
||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,9 +213,9 @@ pub fn expand_include_bytes(
|
|||||||
let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else {
|
let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else {
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
};
|
};
|
||||||
let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
|
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ pub fn expand_include_bytes(
|
|||||||
base::MacEager::expr(expr)
|
base::MacEager::expr(expr)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
|
cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
|
||||||
DummyResult::any(sp)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,11 @@ use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
|||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::{self as ast, attr, GenericParamKind};
|
use rustc_ast::{self as ast, attr, GenericParamKind};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::{Applicability, DiagnosticBuilder, Level};
|
||||||
use rustc_expand::base::*;
|
use rustc_expand::base::*;
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
|
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
|
||||||
|
use std::assert_matches::assert_matches;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use thin_vec::{thin_vec, ThinVec};
|
use thin_vec::{thin_vec, ThinVec};
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ pub fn expand_test_case(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
ecx.emit_err(errors::TestCaseNonItem { span: anno_item.span() });
|
ecx.dcx().emit_err(errors::TestCaseNonItem { span: anno_item.span() });
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -182,6 +183,16 @@ pub fn expand_test_or_bench(
|
|||||||
// creates $name: $expr
|
// creates $name: $expr
|
||||||
let field = |name, expr| cx.field_imm(sp, Ident::from_str_and_span(name, sp), expr);
|
let field = |name, expr| cx.field_imm(sp, Ident::from_str_and_span(name, sp), expr);
|
||||||
|
|
||||||
|
// Adds `#[coverage(off)]` to a closure, so it won't be instrumented in
|
||||||
|
// `-Cinstrument-coverage` builds.
|
||||||
|
// This requires `#[allow_internal_unstable(coverage_attribute)]` on the
|
||||||
|
// corresponding macro declaration in `core::macros`.
|
||||||
|
let coverage_off = |mut expr: P<ast::Expr>| {
|
||||||
|
assert_matches!(expr.kind, ast::ExprKind::Closure(_));
|
||||||
|
expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp));
|
||||||
|
expr
|
||||||
|
};
|
||||||
|
|
||||||
let test_fn = if is_bench {
|
let test_fn = if is_bench {
|
||||||
// A simple ident for a lambda
|
// A simple ident for a lambda
|
||||||
let b = Ident::from_str_and_span("b", attr_sp);
|
let b = Ident::from_str_and_span("b", attr_sp);
|
||||||
@ -190,8 +201,9 @@ pub fn expand_test_or_bench(
|
|||||||
sp,
|
sp,
|
||||||
cx.expr_path(test_path("StaticBenchFn")),
|
cx.expr_path(test_path("StaticBenchFn")),
|
||||||
thin_vec![
|
thin_vec![
|
||||||
|
// #[coverage(off)]
|
||||||
// |b| self::test::assert_test_result(
|
// |b| self::test::assert_test_result(
|
||||||
cx.lambda1(
|
coverage_off(cx.lambda1(
|
||||||
sp,
|
sp,
|
||||||
cx.expr_call(
|
cx.expr_call(
|
||||||
sp,
|
sp,
|
||||||
@ -206,7 +218,7 @@ pub fn expand_test_or_bench(
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
b,
|
b,
|
||||||
), // )
|
)), // )
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -214,8 +226,9 @@ pub fn expand_test_or_bench(
|
|||||||
sp,
|
sp,
|
||||||
cx.expr_path(test_path("StaticTestFn")),
|
cx.expr_path(test_path("StaticTestFn")),
|
||||||
thin_vec![
|
thin_vec![
|
||||||
|
// #[coverage(off)]
|
||||||
// || {
|
// || {
|
||||||
cx.lambda0(
|
coverage_off(cx.lambda0(
|
||||||
sp,
|
sp,
|
||||||
// test::assert_test_result(
|
// test::assert_test_result(
|
||||||
cx.expr_call(
|
cx.expr_call(
|
||||||
@ -230,7 +243,7 @@ pub fn expand_test_or_bench(
|
|||||||
), // )
|
), // )
|
||||||
],
|
],
|
||||||
), // }
|
), // }
|
||||||
), // )
|
)), // )
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -389,17 +402,16 @@ pub fn expand_test_or_bench(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) {
|
fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) {
|
||||||
let dcx = cx.sess.dcx();
|
let dcx = cx.dcx();
|
||||||
let msg = "the `#[test]` attribute may only be used on a non-associated function";
|
let msg = "the `#[test]` attribute may only be used on a non-associated function";
|
||||||
let mut err = match item.map(|i| &i.kind) {
|
let level = match item.map(|i| &i.kind) {
|
||||||
// These were a warning before #92959 and need to continue being that to avoid breaking
|
// These were a warning before #92959 and need to continue being that to avoid breaking
|
||||||
// stable user code (#94508).
|
// stable user code (#94508).
|
||||||
Some(ast::ItemKind::MacCall(_)) => dcx.struct_span_warn(attr_sp, msg),
|
Some(ast::ItemKind::MacCall(_)) => Level::Warning,
|
||||||
// `.forget_guarantee()` needed to get these two arms to match types. Because of how
|
_ => Level::Error,
|
||||||
// locally close the `.emit()` call is I'm comfortable with it, but if it can be
|
|
||||||
// reworked in the future to not need it, it'd be nice.
|
|
||||||
_ => dcx.struct_span_err(attr_sp, msg).forget_guarantee(),
|
|
||||||
};
|
};
|
||||||
|
let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg);
|
||||||
|
err.span(attr_sp);
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
err.span_label(
|
err.span_label(
|
||||||
item.span,
|
item.span,
|
||||||
@ -410,8 +422,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>)
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
err.span_label(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions")
|
err.with_span_label(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions")
|
||||||
.span_suggestion(attr_sp,
|
.with_span_suggestion(attr_sp,
|
||||||
"replace with conditional compilation to make the item only exist when tests are being run",
|
"replace with conditional compilation to make the item only exist when tests are being run",
|
||||||
"#[cfg(test)]",
|
"#[cfg(test)]",
|
||||||
Applicability::MaybeIncorrect)
|
Applicability::MaybeIncorrect)
|
||||||
@ -466,8 +478,6 @@ fn should_ignore_message(i: &ast::Item) -> Option<Symbol> {
|
|||||||
fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
|
fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
|
||||||
match attr::find_by_name(&i.attrs, sym::should_panic) {
|
match attr::find_by_name(&i.attrs, sym::should_panic) {
|
||||||
Some(attr) => {
|
Some(attr) => {
|
||||||
let dcx = cx.sess.dcx();
|
|
||||||
|
|
||||||
match attr.meta_item_list() {
|
match attr.meta_item_list() {
|
||||||
// Handle #[should_panic(expected = "foo")]
|
// Handle #[should_panic(expected = "foo")]
|
||||||
Some(list) => {
|
Some(list) => {
|
||||||
@ -477,17 +487,18 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
|
|||||||
.and_then(|mi| mi.meta_item())
|
.and_then(|mi| mi.meta_item())
|
||||||
.and_then(|mi| mi.value_str());
|
.and_then(|mi| mi.value_str());
|
||||||
if list.len() != 1 || msg.is_none() {
|
if list.len() != 1 || msg.is_none() {
|
||||||
dcx.struct_span_warn(
|
cx.dcx()
|
||||||
attr.span,
|
.struct_span_warn(
|
||||||
"argument must be of the form: \
|
attr.span,
|
||||||
|
"argument must be of the form: \
|
||||||
`expected = \"error message\"`",
|
`expected = \"error message\"`",
|
||||||
)
|
)
|
||||||
.note(
|
.with_note(
|
||||||
"errors in this attribute were erroneously \
|
"errors in this attribute were erroneously \
|
||||||
allowed and will become a hard error in a \
|
allowed and will become a hard error in a \
|
||||||
future release",
|
future release",
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
ShouldPanic::Yes(None)
|
ShouldPanic::Yes(None)
|
||||||
} else {
|
} else {
|
||||||
ShouldPanic::Yes(msg)
|
ShouldPanic::Yes(msg)
|
||||||
@ -535,7 +546,7 @@ fn check_test_signature(
|
|||||||
f: &ast::Fn,
|
f: &ast::Fn,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
|
let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
|
||||||
let dcx = cx.sess.dcx();
|
let dcx = cx.dcx();
|
||||||
|
|
||||||
if let ast::Unsafe::Yes(span) = f.sig.header.unsafety {
|
if let ast::Unsafe::Yes(span) = f.sig.header.unsafety {
|
||||||
return Err(dcx.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }));
|
return Err(dcx.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }));
|
||||||
@ -601,7 +612,7 @@ fn check_bench_signature(
|
|||||||
// N.B., inadequate check, but we're running
|
// N.B., inadequate check, but we're running
|
||||||
// well before resolve, can't get too deep.
|
// well before resolve, can't get too deep.
|
||||||
if f.sig.decl.inputs.len() != 1 {
|
if f.sig.decl.inputs.len() != 1 {
|
||||||
return Err(cx.sess.dcx().emit_err(errors::BenchSig { span: i.span }));
|
return Err(cx.dcx().emit_err(errors::BenchSig { span: i.span }));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ pub fn expand_trace_macros(
|
|||||||
};
|
};
|
||||||
err |= cursor.next().is_some();
|
err |= cursor.next().is_some();
|
||||||
if err {
|
if err {
|
||||||
cx.emit_err(errors::TraceMacros { span: sp });
|
cx.dcx().emit_err(errors::TraceMacros { span: sp });
|
||||||
} else {
|
} else {
|
||||||
cx.set_trace_macros(value);
|
cx.set_trace_macros(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ pub fn expand_type_ascribe(
|
|||||||
) -> Box<dyn base::MacResult + 'static> {
|
) -> Box<dyn base::MacResult + 'static> {
|
||||||
let (expr, ty) = match parse_ascribe(cx, tts) {
|
let (expr, ty) = match parse_ascribe(cx, tts) {
|
||||||
Ok(parsed) => parsed,
|
Ok(parsed) => parsed,
|
||||||
Err(mut err) => {
|
Err(err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
return DummyResult::any(span);
|
return DummyResult::any(span);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,14 +33,14 @@ jobs:
|
|||||||
TARGET_TRIPLE: x86_64-pc-windows-gnu
|
TARGET_TRIPLE: x86_64-pc-windows-gnu
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: CPU features
|
- name: CPU features
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
run: cat /proc/cpuinfo
|
run: cat /proc/cpuinfo
|
||||||
|
|
||||||
- name: Cache cargo target dir
|
- name: Cache cargo target dir
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: build/cg_clif
|
path: build/cg_clif
|
||||||
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user