Auto merge of #2753 - RalfJung:rustup, r=RalfJung
Rustup Pulls in https://github.com/rust-lang/rust/pull/104658
This commit is contained in:
commit
d61d359d5e
807 changed files with 11197 additions and 6287 deletions
543
Cargo.lock
543
Cargo.lock
|
@ -30,7 +30,7 @@ version = "0.7.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
|
||||
dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -50,7 +50,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"rand 0.7.3",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
]
|
||||
|
||||
|
@ -197,6 +197,18 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -259,6 +271,10 @@ dependencies = [
|
|||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_helper"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "bump-stage0"
|
||||
version = "0.1.0"
|
||||
|
@ -271,6 +287,12 @@ dependencies = [
|
|||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||
|
||||
[[package]]
|
||||
name = "bytecount"
|
||||
version = "0.6.2"
|
||||
|
@ -341,6 +363,7 @@ dependencies = [
|
|||
"opener",
|
||||
"openssl",
|
||||
"os_info",
|
||||
"pasetors",
|
||||
"pathdiff",
|
||||
"percent-encoding",
|
||||
"pretty_env_logger",
|
||||
|
@ -358,6 +381,7 @@ dependencies = [
|
|||
"tar",
|
||||
"tempfile",
|
||||
"termcolor",
|
||||
"time 0.3.17",
|
||||
"toml_edit",
|
||||
"unicode-width",
|
||||
"unicode-xid",
|
||||
|
@ -443,10 +467,13 @@ dependencies = [
|
|||
"glob",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"pasetors",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"snapbox",
|
||||
"tar",
|
||||
"termcolor",
|
||||
"time 0.3.17",
|
||||
"toml_edit",
|
||||
"url",
|
||||
"winapi",
|
||||
|
@ -585,7 +612,7 @@ dependencies = [
|
|||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"time 0.1.43",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -597,7 +624,7 @@ checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
|
|||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_derive 3.2.18",
|
||||
"clap_lex 0.2.2",
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
|
@ -614,7 +641,9 @@ checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
|
|||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive 4.0.13",
|
||||
"clap_lex 0.3.0",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
]
|
||||
|
@ -641,6 +670,19 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.2"
|
||||
|
@ -884,6 +926,12 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b"
|
||||
|
||||
[[package]]
|
||||
name = "content_inspector"
|
||||
version = "0.2.4"
|
||||
|
@ -903,7 +951,7 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
|
|||
name = "core"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand 0.7.3",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
]
|
||||
|
||||
|
@ -938,7 +986,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crates-io"
|
||||
version = "0.35.0"
|
||||
version = "0.35.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"curl",
|
||||
|
@ -1001,12 +1049,25 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.2"
|
||||
name = "crypto-bigint"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"
|
||||
checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1031,6 +1092,12 @@ dependencies = [
|
|||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ct-codecs"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df"
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.26"
|
||||
|
@ -1087,6 +1154,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"pem-rfc7468",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive-new"
|
||||
version = "0.5.8"
|
||||
|
@ -1125,12 +1203,13 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
|||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.2"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"
|
||||
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1217,6 +1296,27 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.14.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
|
||||
dependencies = [
|
||||
"der",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-compact"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a3d382e8464107391c8706b4c14b087808ecb909f6c15c34114bc42e53a9e4c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.0"
|
||||
|
@ -1235,6 +1335,28 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint",
|
||||
"der",
|
||||
"digest",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"group",
|
||||
"hkdf",
|
||||
"pem-rfc7468",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.0"
|
||||
|
@ -1354,6 +1476,22 @@ dependencies = [
|
|||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a214f5bb88731d436478f3ae1f8a277b62124089ba9fb67f4f93fb100ef73c90"
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.14"
|
||||
|
@ -1611,17 +1749,6 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
|
@ -1629,8 +1756,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1693,6 +1822,17 @@ dependencies = [
|
|||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gsgdt"
|
||||
version = "0.1.2"
|
||||
|
@ -1782,6 +1922,24 @@ version = "0.4.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
|
||||
|
||||
[[package]]
|
||||
name = "hkdf"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
|
||||
dependencies = [
|
||||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.3"
|
||||
|
@ -1946,7 +2104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
|
||||
dependencies = [
|
||||
"bitmaps",
|
||||
"rand_core 0.6.2",
|
||||
"rand_core",
|
||||
"rand_xoshiro",
|
||||
"sized-chunks",
|
||||
"typenum",
|
||||
|
@ -2079,6 +2237,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsondocck"
|
||||
version = "0.1.0"
|
||||
|
@ -2097,8 +2264,10 @@ name = "jsondoclint"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.15",
|
||||
"fs-err",
|
||||
"rustdoc-json-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
|
@ -2480,14 +2649,14 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"colored",
|
||||
"env_logger 0.9.0",
|
||||
"getrandom 0.2.8",
|
||||
"getrandom",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"libffi",
|
||||
"libloading",
|
||||
"log",
|
||||
"measureme",
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
"regex",
|
||||
"rustc-workspace-hack",
|
||||
"rustc_version",
|
||||
|
@ -2647,6 +2816,17 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "orion"
|
||||
version = "0.17.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2baf7fd2e326e3895c681176788dd227fcd8369350e53c570592d8563fecbb6"
|
||||
dependencies = [
|
||||
"fiat-crypto",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.5.0"
|
||||
|
@ -2679,6 +2859,17 @@ version = "3.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "p384"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa"
|
||||
dependencies = [
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packed_simd_2"
|
||||
version = "0.3.8"
|
||||
|
@ -2760,12 +2951,42 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pasetors"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed20c4c21d893414f42e0cbfebe8a8036b5ae9b0264611fb6504e395eda6ceec"
|
||||
dependencies = [
|
||||
"ct-codecs",
|
||||
"ed25519-compact",
|
||||
"getrandom",
|
||||
"orion",
|
||||
"p384",
|
||||
"rand_core",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"subtle",
|
||||
"time 0.3.17",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathdiff"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||
|
||||
[[package]]
|
||||
name = "pem-rfc7468"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
|
@ -2861,7 +3082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2885,6 +3106,16 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.25"
|
||||
|
@ -3056,19 +3287,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
"libc",
|
||||
"rand_chacha 0.2.2",
|
||||
"rand_core 0.5.1",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
|
@ -3076,18 +3294,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.0",
|
||||
"rand_core 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.5.1",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3097,43 +3305,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.2",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
|
||||
checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3142,7 +3332,7 @@ version = "0.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
|
||||
dependencies = [
|
||||
"rand_core 0.6.2",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3184,7 +3374,7 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
||||
dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
|
@ -3248,6 +3438,17 @@ dependencies = [
|
|||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
|
||||
dependencies = [
|
||||
"crypto-bigint",
|
||||
"hmac",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rls"
|
||||
version = "2.0.0"
|
||||
|
@ -3387,9 +3588,10 @@ version = "1.0.0"
|
|||
dependencies = [
|
||||
"bstr 0.2.17",
|
||||
"clap 3.2.20",
|
||||
"getrandom",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"syn",
|
||||
|
@ -3402,7 +3604,7 @@ name = "rustc_abi"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
"rand_xoshiro",
|
||||
"rustc_data_structures",
|
||||
"rustc_index",
|
||||
|
@ -3636,6 +3838,7 @@ dependencies = [
|
|||
"rustc_span",
|
||||
"rustc_symbol_mangling",
|
||||
"rustc_target",
|
||||
"rustc_type_ir",
|
||||
"serde_json",
|
||||
"smallvec",
|
||||
"snap",
|
||||
|
@ -3770,6 +3973,7 @@ dependencies = [
|
|||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_type_ir",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"termcolor",
|
||||
|
@ -3906,7 +4110,7 @@ dependencies = [
|
|||
name = "rustc_incremental"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
@ -4226,6 +4430,8 @@ dependencies = [
|
|||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
]
|
||||
|
@ -4774,6 +4980,20 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"der",
|
||||
"generic-array",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.0.0"
|
||||
|
@ -4805,18 +5025,18 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
|
|||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.12"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1"
|
||||
checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.147"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -4833,9 +5053,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.147"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4853,9 +5073,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.85"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
|
@ -4876,9 +5096,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.1"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
|
||||
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
|
@ -4906,6 +5126,16 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "1.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
||||
dependencies = [
|
||||
"digest",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
version = "2.1.0"
|
||||
|
@ -5009,6 +5239,16 @@ dependencies = [
|
|||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
|
@ -5053,11 +5293,12 @@ dependencies = [
|
|||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"profiler_builtins",
|
||||
"rand 0.7.3",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
"rustc-demangle",
|
||||
"std_detect",
|
||||
"unwind",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5132,10 +5373,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.102"
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
|
||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -5309,6 +5556,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"miropt-test-tools",
|
||||
"regex",
|
||||
"semver",
|
||||
"termcolor",
|
||||
"walkdir",
|
||||
]
|
||||
|
@ -5327,6 +5575,33 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.7.0"
|
||||
|
@ -5495,7 +5770,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"rand 0.8.5",
|
||||
"rand",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
|
@ -5510,9 +5785,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.12.0"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-parse"
|
||||
|
@ -5778,7 +6053,7 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5819,12 +6094,6 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -5836,6 +6105,60 @@ dependencies = [
|
|||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -6028,6 +6351,12 @@ dependencies = [
|
|||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.9.0"
|
||||
|
|
|
@ -4,6 +4,7 @@ members = [
|
|||
"library/std",
|
||||
"library/test",
|
||||
"src/rustdoc-json-types",
|
||||
"src/tools/build_helper",
|
||||
"src/tools/cargotest",
|
||||
"src/tools/clippy",
|
||||
"src/tools/clippy/clippy_dev",
|
||||
|
|
|
@ -2170,10 +2170,10 @@ impl fmt::Display for InlineAsmTemplatePiece {
|
|||
Ok(())
|
||||
}
|
||||
Self::Placeholder { operand_idx, modifier: Some(modifier), .. } => {
|
||||
write!(f, "{{{}:{}}}", operand_idx, modifier)
|
||||
write!(f, "{{{operand_idx}:{modifier}}}")
|
||||
}
|
||||
Self::Placeholder { operand_idx, modifier: None, .. } => {
|
||||
write!(f, "{{{}}}", operand_idx)
|
||||
write!(f, "{{{operand_idx}}}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2185,7 +2185,7 @@ impl InlineAsmTemplatePiece {
|
|||
use fmt::Write;
|
||||
let mut out = String::new();
|
||||
for p in s.iter() {
|
||||
let _ = write!(out, "{}", p);
|
||||
let _ = write!(out, "{p}");
|
||||
}
|
||||
out
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ impl HasTokens for Attribute {
|
|||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.tokens.as_ref(),
|
||||
kind @ AttrKind::DocComment(..) => {
|
||||
panic!("Called tokens on doc comment attr {:?}", kind)
|
||||
panic!("Called tokens on doc comment attr {kind:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ impl HasTokens for Attribute {
|
|||
Some(match &mut self.kind {
|
||||
AttrKind::Normal(normal) => &mut normal.tokens,
|
||||
kind @ AttrKind::DocComment(..) => {
|
||||
panic!("Called tokens_mut on doc comment attr {:?}", kind)
|
||||
panic!("Called tokens_mut on doc comment attr {kind:?}")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -310,7 +310,7 @@ impl Attribute {
|
|||
AttrKind::Normal(normal) => normal
|
||||
.tokens
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self))
|
||||
.unwrap_or_else(|| panic!("attribute is missing tokens: {self:?}"))
|
||||
.to_attr_token_stream()
|
||||
.to_tokenstream(),
|
||||
&AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token(
|
||||
|
|
|
@ -9,8 +9,8 @@ pub enum AllocatorKind {
|
|||
impl AllocatorKind {
|
||||
pub fn fn_name(&self, base: Symbol) -> String {
|
||||
match *self {
|
||||
AllocatorKind::Global => format!("__rg_{}", base),
|
||||
AllocatorKind::Default => format!("__rdl_{}", base),
|
||||
AllocatorKind::Global => format!("__rg_{base}"),
|
||||
AllocatorKind::Default => format!("__rdl_{base}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,27 +125,27 @@ impl fmt::Display for Lit {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Lit { kind, symbol, suffix } = *self;
|
||||
match kind {
|
||||
Byte => write!(f, "b'{}'", symbol)?,
|
||||
Char => write!(f, "'{}'", symbol)?,
|
||||
Str => write!(f, "\"{}\"", symbol)?,
|
||||
Byte => write!(f, "b'{symbol}'")?,
|
||||
Char => write!(f, "'{symbol}'")?,
|
||||
Str => write!(f, "\"{symbol}\"")?,
|
||||
StrRaw(n) => write!(
|
||||
f,
|
||||
"r{delim}\"{string}\"{delim}",
|
||||
delim = "#".repeat(n as usize),
|
||||
string = symbol
|
||||
)?,
|
||||
ByteStr => write!(f, "b\"{}\"", symbol)?,
|
||||
ByteStr => write!(f, "b\"{symbol}\"")?,
|
||||
ByteStrRaw(n) => write!(
|
||||
f,
|
||||
"br{delim}\"{string}\"{delim}",
|
||||
delim = "#".repeat(n as usize),
|
||||
string = symbol
|
||||
)?,
|
||||
Integer | Float | Bool | Err => write!(f, "{}", symbol)?,
|
||||
Integer | Float | Bool | Err => write!(f, "{symbol}")?,
|
||||
}
|
||||
|
||||
if let Some(suffix) = suffix {
|
||||
write!(f, "{}", suffix)?;
|
||||
write!(f, "{suffix}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -756,7 +756,7 @@ impl Token {
|
|||
_ => return None,
|
||||
},
|
||||
SingleQuote => match joint.kind {
|
||||
Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))),
|
||||
Ident(name, false) => Lifetime(Symbol::intern(&format!("'{name}"))),
|
||||
_ => return None,
|
||||
},
|
||||
|
||||
|
|
|
@ -258,8 +258,7 @@ impl AttrTokenStream {
|
|||
|
||||
assert!(
|
||||
found,
|
||||
"Failed to find trailing delimited group in: {:?}",
|
||||
target_tokens
|
||||
"Failed to find trailing delimited group in: {target_tokens:?}"
|
||||
);
|
||||
}
|
||||
let mut flat: SmallVec<[_; 1]> = SmallVec::new();
|
||||
|
|
|
@ -34,7 +34,7 @@ pub enum LitError {
|
|||
InvalidIntSuffix,
|
||||
InvalidFloatSuffix,
|
||||
NonDecimalFloat(u32),
|
||||
IntTooLarge,
|
||||
IntTooLarge(u32),
|
||||
}
|
||||
|
||||
impl LitKind {
|
||||
|
@ -168,7 +168,7 @@ impl fmt::Display for LitKind {
|
|||
match *self {
|
||||
LitKind::Byte(b) => {
|
||||
let b: String = ascii::escape_default(b).map(Into::<char>::into).collect();
|
||||
write!(f, "b'{}'", b)?;
|
||||
write!(f, "b'{b}'")?;
|
||||
}
|
||||
LitKind::Char(ch) => write!(f, "'{}'", escape_char_symbol(ch))?,
|
||||
LitKind::Str(sym, StrStyle::Cooked) => write!(f, "\"{}\"", escape_string_symbol(sym))?,
|
||||
|
@ -192,7 +192,7 @@ impl fmt::Display for LitKind {
|
|||
)?;
|
||||
}
|
||||
LitKind::Int(n, ty) => {
|
||||
write!(f, "{}", n)?;
|
||||
write!(f, "{n}")?;
|
||||
match ty {
|
||||
ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?,
|
||||
ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?,
|
||||
|
@ -200,7 +200,7 @@ impl fmt::Display for LitKind {
|
|||
}
|
||||
}
|
||||
LitKind::Float(symbol, ty) => {
|
||||
write!(f, "{}", symbol)?;
|
||||
write!(f, "{symbol}")?;
|
||||
match ty {
|
||||
ast::LitFloatType::Suffixed(ty) => write!(f, "{}", ty.name())?,
|
||||
ast::LitFloatType::Unsuffixed => {}
|
||||
|
@ -333,6 +333,6 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
|
|||
// but these kinds of errors are already reported by the lexer.
|
||||
let from_lexer =
|
||||
base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
|
||||
if from_lexer { LitError::LexerError } else { LitError::IntTooLarge }
|
||||
if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) }
|
||||
})
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
Err(supported_abis) => {
|
||||
let mut abis = format!("`{}`", supported_abis[0]);
|
||||
for m in &supported_abis[1..] {
|
||||
let _ = write!(abis, ", `{}`", m);
|
||||
let _ = write!(abis, ", `{m}`");
|
||||
}
|
||||
self.tcx.sess.emit_err(InvalidAbiClobberAbi {
|
||||
abi_span: *abi_span,
|
||||
|
@ -262,7 +262,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let sub = if !valid_modifiers.is_empty() {
|
||||
let mut mods = format!("`{}`", valid_modifiers[0]);
|
||||
for m in &valid_modifiers[1..] {
|
||||
let _ = write!(mods, ", `{}`", m);
|
||||
let _ = write!(mods, ", `{m}`");
|
||||
}
|
||||
InvalidAsmTemplateModifierRegClassSub::SupportModifier {
|
||||
class_name: class.name(),
|
||||
|
|
|
@ -1051,7 +1051,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
_ => {
|
||||
// Replace the ident for bindings that aren't simple.
|
||||
let name = format!("__arg{}", index);
|
||||
let name = format!("__arg{index}");
|
||||
let ident = Ident::from_str(&name);
|
||||
|
||||
(ident, false)
|
||||
|
|
|
@ -296,7 +296,7 @@ impl std::fmt::Display for ImplTraitPosition {
|
|||
ImplTraitPosition::ImplReturn => "`impl` method return",
|
||||
};
|
||||
|
||||
write!(f, "{}", name)
|
||||
write!(f, "{name}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,7 +503,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
fn orig_local_def_id(&self, node: NodeId) -> LocalDefId {
|
||||
self.orig_opt_local_def_id(node)
|
||||
.unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
|
||||
.unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
|
||||
}
|
||||
|
||||
/// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
|
||||
|
@ -524,7 +524,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
fn local_def_id(&self, node: NodeId) -> LocalDefId {
|
||||
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
|
||||
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
|
||||
}
|
||||
|
||||
/// Get the previously recorded `to` local def id given the `from` local def id, obtained using
|
||||
|
@ -2197,7 +2197,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
|
||||
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
|
||||
hir::QPath::Resolved(None, path) => path,
|
||||
qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
|
||||
qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
|
||||
};
|
||||
hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) }
|
||||
}
|
||||
|
|
|
@ -191,23 +191,23 @@ fn doc_comment_to_string(
|
|||
data: Symbol,
|
||||
) -> String {
|
||||
match (comment_kind, attr_style) {
|
||||
(CommentKind::Line, ast::AttrStyle::Outer) => format!("///{}", data),
|
||||
(CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{}", data),
|
||||
(CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{}*/", data),
|
||||
(CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{}*/", data),
|
||||
(CommentKind::Line, ast::AttrStyle::Outer) => format!("///{data}"),
|
||||
(CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{data}"),
|
||||
(CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{data}*/"),
|
||||
(CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{data}*/"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn literal_to_string(lit: token::Lit) -> String {
|
||||
let token::Lit { kind, symbol, suffix } = lit;
|
||||
let mut out = match kind {
|
||||
token::Byte => format!("b'{}'", symbol),
|
||||
token::Char => format!("'{}'", symbol),
|
||||
token::Str => format!("\"{}\"", symbol),
|
||||
token::Byte => format!("b'{symbol}'"),
|
||||
token::Char => format!("'{symbol}'"),
|
||||
token::Str => format!("\"{symbol}\""),
|
||||
token::StrRaw(n) => {
|
||||
format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
|
||||
}
|
||||
token::ByteStr => format!("b\"{}\"", symbol),
|
||||
token::ByteStr => format!("b\"{symbol}\""),
|
||||
token::ByteStrRaw(n) => {
|
||||
format!("br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
|
||||
}
|
||||
|
|
|
@ -411,9 +411,9 @@ impl<'a> State<'a> {
|
|||
ast::VisibilityKind::Restricted { path, shorthand, .. } => {
|
||||
let path = Self::to_string(|s| s.print_path(path, false, 0));
|
||||
if *shorthand && (path == "crate" || path == "self" || path == "super") {
|
||||
self.word_nbsp(format!("pub({})", path))
|
||||
self.word_nbsp(format!("pub({path})"))
|
||||
} else {
|
||||
self.word_nbsp(format!("pub(in {})", path))
|
||||
self.word_nbsp(format!("pub(in {path})"))
|
||||
}
|
||||
}
|
||||
ast::VisibilityKind::Inherited => {}
|
||||
|
|
|
@ -619,7 +619,7 @@ fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Fe
|
|||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) {
|
||||
let (cfg, feature, has_feature) = gated_cfg;
|
||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||
let explain = format!("`cfg({})` is experimental and subject to change", cfg);
|
||||
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
||||
feature_err(sess, *feature, cfg_span, &explain).emit();
|
||||
}
|
||||
}
|
||||
|
@ -975,7 +975,7 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
}
|
||||
|
||||
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::*;
|
||||
let mut acc = Vec::new();
|
||||
let diagnostic = &sess.parse_sess.span_diagnostic;
|
||||
|
|
|
@ -51,7 +51,7 @@ pub(crate) struct UnknownMetaItem<'a> {
|
|||
// Manual implementation to be able to format `expected` items correctly.
|
||||
impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
|
||||
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
|
||||
let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
|
||||
let mut diag = handler.struct_span_err_with_code(
|
||||
self.span,
|
||||
fluent::attr_unknown_meta_item,
|
||||
|
|
|
@ -440,15 +440,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
closure_kind: &str,
|
||||
borrowed_path: &str,
|
||||
capture_span: Span,
|
||||
scope: &str,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
closure_span,
|
||||
E0373,
|
||||
"{} may outlive the current function, but it borrows {}, which is owned by the current \
|
||||
function",
|
||||
closure_kind,
|
||||
borrowed_path,
|
||||
"{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
|
||||
which is owned by the current {scope}",
|
||||
);
|
||||
err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
|
||||
.span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
|
||||
|
|
|
@ -394,7 +394,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
let hir_id = hir.get_parent_node(expr.hir_id);
|
||||
let hir_id = hir.parent_id(expr.hir_id);
|
||||
if let Some(parent) = hir.find(hir_id) {
|
||||
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
|
||||
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
|
||||
|
@ -527,26 +527,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// that are *partially* initialized by assigning to a field of an uninitialized
|
||||
// binding. We differentiate between them for more accurate wording here.
|
||||
"isn't fully initialized"
|
||||
} else if spans
|
||||
.iter()
|
||||
.filter(|i| {
|
||||
// We filter these to avoid misleading wording in cases like the following,
|
||||
// where `x` has an `init`, but it is in the same place we're looking at:
|
||||
// ```
|
||||
// let x;
|
||||
// x += 1;
|
||||
// ```
|
||||
!i.contains(span)
|
||||
// We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
|
||||
&& !visitor
|
||||
.errors
|
||||
.iter()
|
||||
.map(|(sp, _)| *sp)
|
||||
.any(|sp| span < sp && !sp.contains(span))
|
||||
})
|
||||
.count()
|
||||
== 0
|
||||
{
|
||||
} else if !spans.iter().any(|i| {
|
||||
// We filter these to avoid misleading wording in cases like the following,
|
||||
// where `x` has an `init`, but it is in the same place we're looking at:
|
||||
// ```
|
||||
// let x;
|
||||
// x += 1;
|
||||
// ```
|
||||
!i.contains(span)
|
||||
// We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
|
||||
&& !visitor
|
||||
.errors
|
||||
.iter()
|
||||
.map(|(sp, _)| *sp)
|
||||
.any(|sp| span < sp && !sp.contains(span))
|
||||
}) {
|
||||
show_assign_sugg = true;
|
||||
"isn't initialized"
|
||||
} else {
|
||||
|
@ -1428,6 +1423,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
//
|
||||
// then just use the normal error. The closure isn't escaping
|
||||
// and `move` will not help here.
|
||||
(
|
||||
Some(name),
|
||||
BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
|
||||
) => self.report_escaping_closure_capture(
|
||||
borrow_spans,
|
||||
borrow_span,
|
||||
&RegionName {
|
||||
name: self.synthesize_region_name(),
|
||||
source: RegionNameSource::Static,
|
||||
},
|
||||
ConstraintCategory::CallArgument(None),
|
||||
var_or_use_span,
|
||||
&format!("`{}`", name),
|
||||
"block",
|
||||
),
|
||||
(
|
||||
Some(name),
|
||||
BorrowExplanation::MustBeValidFor {
|
||||
|
@ -1448,6 +1458,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
category,
|
||||
span,
|
||||
&format!("`{}`", name),
|
||||
"function",
|
||||
),
|
||||
(
|
||||
name,
|
||||
|
@ -1900,6 +1911,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
Some(err)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn report_escaping_closure_capture(
|
||||
&mut self,
|
||||
use_span: UseSpans<'tcx>,
|
||||
|
@ -1908,6 +1920,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
category: ConstraintCategory<'tcx>,
|
||||
constraint_span: Span,
|
||||
captured_var: &str,
|
||||
scope: &str,
|
||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let args_span = use_span.args_or_use();
|
||||
|
@ -1938,8 +1951,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
None => "closure",
|
||||
};
|
||||
|
||||
let mut err =
|
||||
self.cannot_capture_in_long_lived_closure(args_span, kind, captured_var, var_span);
|
||||
let mut err = self.cannot_capture_in_long_lived_closure(
|
||||
args_span,
|
||||
kind,
|
||||
captured_var,
|
||||
var_span,
|
||||
scope,
|
||||
);
|
||||
err.span_suggestion_verbose(
|
||||
sugg_span,
|
||||
&format!(
|
||||
|
@ -1961,10 +1979,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
|
||||
err.note(
|
||||
"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",
|
||||
);
|
||||
} else {
|
||||
let msg = format!("function requires argument type to outlive `{}`", fr_name);
|
||||
let msg = format!("{scope} requires argument type to outlive `{fr_name}`");
|
||||
err.span_note(constraint_span, &msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -444,6 +444,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
/// First span returned points to the location of the conflicting use
|
||||
/// Second span if `Some` is returned in the case of closures and points
|
||||
/// to the use of the path
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn later_use_kind(
|
||||
&self,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
|
@ -461,11 +462,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let block = &self.body.basic_blocks[location.block];
|
||||
|
||||
let kind = if let Some(&Statement {
|
||||
kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)),
|
||||
kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)),
|
||||
..
|
||||
}) = block.statements.get(location.statement_index)
|
||||
{
|
||||
LaterUseKind::FakeLetRead
|
||||
if let Some(l) = place.as_local()
|
||||
&& let local_decl = &self.body.local_decls[l]
|
||||
&& local_decl.ty.is_closure()
|
||||
{
|
||||
LaterUseKind::ClosureCapture
|
||||
} else {
|
||||
LaterUseKind::FakeLetRead
|
||||
}
|
||||
} else if self.was_captured_by_trait_object(borrow) {
|
||||
LaterUseKind::TraitCapture
|
||||
} else if location.statement_index == block.statements.len() {
|
||||
|
|
|
@ -344,20 +344,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
err.span_help(source_info.span, "try removing `&mut` here");
|
||||
}
|
||||
} else if decl.mutability == Mutability::Not
|
||||
&& !matches!(
|
||||
} else if decl.mutability == Mutability::Not {
|
||||
if matches!(
|
||||
decl.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
hir::ImplicitSelfKind::MutRef
|
||||
))))
|
||||
)
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
decl.source_info.span.shrink_to_lo(),
|
||||
"consider making the binding mutable",
|
||||
"mut ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
),)))
|
||||
) {
|
||||
err.note(
|
||||
"as `Self` may be unsized, this call attempts to take `&mut &mut self`",
|
||||
);
|
||||
err.note("however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably");
|
||||
} else {
|
||||
err.span_suggestion_verbose(
|
||||
decl.source_info.span.shrink_to_lo(),
|
||||
"consider making the binding mutable",
|
||||
"mut ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1004,7 +1009,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let hir = self.infcx.tcx.hir();
|
||||
let closure_id = self.mir_hir_id();
|
||||
let closure_span = self.infcx.tcx.def_span(self.mir_def_id());
|
||||
let fn_call_id = hir.get_parent_node(closure_id);
|
||||
let fn_call_id = hir.parent_id(closure_id);
|
||||
let node = hir.get(fn_call_id);
|
||||
let def_id = hir.enclosing_body_owner(fn_call_id);
|
||||
let mut look_at_return = true;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{self as hir, Item, ItemKind, Node};
|
||||
use rustc_infer::infer::{
|
||||
error_reporting::nice_region_error::{
|
||||
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
|
||||
|
@ -192,6 +192,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
// buffered in the `MirBorrowckCtxt`.
|
||||
|
||||
let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
|
||||
let mut last_unexpected_hidden_region: Option<(Span, Ty<'_>, ty::OpaqueTypeKey<'tcx>)> =
|
||||
None;
|
||||
|
||||
for nll_error in nll_errors.into_iter() {
|
||||
match nll_error {
|
||||
|
@ -234,13 +236,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
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_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||
self.buffer_error(unexpected_hidden_region_diagnostic(
|
||||
let mut diag = unexpected_hidden_region_diagnostic(
|
||||
self.infcx.tcx,
|
||||
span,
|
||||
named_ty,
|
||||
named_region,
|
||||
named_key,
|
||||
));
|
||||
);
|
||||
if last_unexpected_hidden_region != Some((span, named_ty, named_key)) {
|
||||
self.buffer_error(diag);
|
||||
last_unexpected_hidden_region = Some((span, named_ty, named_key));
|
||||
} else {
|
||||
diag.delay_as_bug();
|
||||
}
|
||||
}
|
||||
|
||||
RegionErrorKind::BoundUniversalRegionError {
|
||||
|
@ -291,71 +299,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
outlives_suggestion.add_suggestion(self);
|
||||
}
|
||||
|
||||
fn get_impl_ident_and_self_ty_from_trait(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
trait_objects: &FxIndexSet<DefId>,
|
||||
) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
|
||||
let tcx = self.infcx.tcx;
|
||||
match tcx.hir().get_if_local(def_id) {
|
||||
Some(Node::ImplItem(impl_item)) => {
|
||||
match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
|
||||
{
|
||||
Some(Node::Item(Item {
|
||||
kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
|
||||
..
|
||||
})) => Some((impl_item.ident, self_ty)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
Some(Node::TraitItem(trait_item)) => {
|
||||
let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
|
||||
match tcx.hir().find_by_def_id(trait_did.def_id) {
|
||||
Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
|
||||
// The method being called is defined in the `trait`, but the `'static`
|
||||
// obligation comes from the `impl`. Find that `impl` so that we can point
|
||||
// at it in the suggestion.
|
||||
let trait_did = trait_did.to_def_id();
|
||||
match tcx
|
||||
.hir()
|
||||
.trait_impls(trait_did)
|
||||
.iter()
|
||||
.filter_map(|&impl_did| {
|
||||
match tcx.hir().get_if_local(impl_did.to_def_id()) {
|
||||
Some(Node::Item(Item {
|
||||
kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
|
||||
..
|
||||
})) if trait_objects.iter().all(|did| {
|
||||
// FIXME: we should check `self_ty` against the receiver
|
||||
// type in the `UnifyReceiver` context, but for now, use
|
||||
// this imperfect proxy. This will fail if there are
|
||||
// multiple `impl`s for the same trait like
|
||||
// `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
|
||||
// In that case, only the first one will get suggestions.
|
||||
let mut traits = vec![];
|
||||
let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
|
||||
hir_v.visit_ty(self_ty);
|
||||
!traits.is_empty()
|
||||
}) =>
|
||||
{
|
||||
Some(self_ty)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.next()
|
||||
{
|
||||
Some(self_ty) => Some((trait_item.ident, self_ty)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Report an error because the universal region `fr` was required to outlive
|
||||
/// `outlived_fr` but it is not known to do so. For example:
|
||||
///
|
||||
|
@ -795,6 +738,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
Some(arg),
|
||||
captures,
|
||||
Some((param.param_ty_span, param.param_ty.to_string())),
|
||||
self.infcx.tcx.is_suitable_region(f).map(|r| r.def_id),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -850,7 +794,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
visitor.visit_ty(param.param_ty);
|
||||
|
||||
let Some((ident, self_ty)) =
|
||||
self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &visitor.0) else {return};
|
||||
NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &visitor.0) else { return; };
|
||||
|
||||
self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty);
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
/// increment the counter.
|
||||
///
|
||||
/// This is _not_ idempotent. Call `give_region_a_name` when possible.
|
||||
fn synthesize_region_name(&self) -> Symbol {
|
||||
pub(crate) fn synthesize_region_name(&self) -> Symbol {
|
||||
let c = self.next_region_name.replace_with(|counter| *counter + 1);
|
||||
Symbol::intern(&format!("'{:?}", c))
|
||||
}
|
||||
|
|
|
@ -863,7 +863,6 @@ enum WriteKind {
|
|||
/// local place can be mutated.
|
||||
//
|
||||
// FIXME: @nikomatsakis suggested that this flag could be removed with the following modifications:
|
||||
// - Merge `check_access_permissions()` and `check_if_reassignment_to_immutable_state()`.
|
||||
// - Split `is_mutable()` into `is_assignable()` (can be directly assigned) and
|
||||
// `is_declared_mutable()`.
|
||||
// - Take flow state into consideration in `is_assignable()` for local variables.
|
||||
|
@ -1132,20 +1131,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// Write of P[i] or *P requires P init'd.
|
||||
self.check_if_assigned_path_is_moved(location, place_span, flow_state);
|
||||
|
||||
// Special case: you can assign an immutable local variable
|
||||
// (e.g., `x = ...`) so long as it has never been initialized
|
||||
// before (at this point in the flow).
|
||||
if let Some(local) = place_span.0.as_local() {
|
||||
if let Mutability::Not = self.body.local_decls[local].mutability {
|
||||
// check for reassignments to immutable local variables
|
||||
self.check_if_reassignment_to_immutable_state(
|
||||
location, local, place_span, flow_state,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, use the normal access permission rules.
|
||||
self.access_place(
|
||||
location,
|
||||
place_span,
|
||||
|
@ -1554,24 +1539,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_if_reassignment_to_immutable_state(
|
||||
&mut self,
|
||||
location: Location,
|
||||
local: Local,
|
||||
place_span: (Place<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
) {
|
||||
debug!("check_if_reassignment_to_immutable_state({:?})", local);
|
||||
|
||||
// Check if any of the initializations of `local` have happened yet:
|
||||
if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) {
|
||||
// And, if so, report an error.
|
||||
let init = &self.move_data.inits[init_index];
|
||||
let span = init.span(&self.body);
|
||||
self.report_illegal_reassignment(location, place_span, span, place_span.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_if_full_path_is_moved(
|
||||
&mut self,
|
||||
location: Location,
|
||||
|
@ -2037,12 +2004,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// partial initialization, do not complain about mutability
|
||||
// errors except for actual mutation (as opposed to an attempt
|
||||
// to do a partial initialization).
|
||||
let previously_initialized =
|
||||
self.is_local_ever_initialized(place.local, flow_state).is_some();
|
||||
let previously_initialized = self.is_local_ever_initialized(place.local, flow_state);
|
||||
|
||||
// at this point, we have set up the error reporting state.
|
||||
if previously_initialized {
|
||||
self.report_mutability_error(place, span, the_place_err, error_access, location);
|
||||
if let Some(init_index) = previously_initialized {
|
||||
if let (AccessKind::Mutate, Some(_)) = (error_access, place.as_local()) {
|
||||
// If this is a mutate access to an immutable local variable with no projections
|
||||
// report the error as an illegal reassignment
|
||||
let init = &self.move_data.inits[init_index];
|
||||
let assigned_span = init.span(&self.body);
|
||||
self.report_illegal_reassignment(location, (place, span), assigned_span, place);
|
||||
} else {
|
||||
self.report_mutability_error(place, span, the_place_err, error_access, location)
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
|
|
@ -638,7 +638,7 @@ fn report_missing_placeholders(
|
|||
if show_doc_note {
|
||||
diag.note(concat!(
|
||||
stringify!($kind),
|
||||
" formatting not supported; see the documentation for `std::fmt`",
|
||||
" formatting is not supported; see the documentation for `std::fmt`",
|
||||
));
|
||||
}
|
||||
if suggestions.len() > 0 {
|
||||
|
|
|
@ -1244,7 +1244,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
) -> RValue<'gcc> {
|
||||
// FIXME(antoyo): remove when having a proper API.
|
||||
let gcc_func = unsafe { std::mem::transmute(func) };
|
||||
let call = if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() {
|
||||
let call = if self.functions.borrow().values().any(|value| *value == gcc_func) {
|
||||
self.function_call(func, args, funclet)
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -253,7 +253,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
|
||||
pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
|
||||
let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
|
||||
debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(),
|
||||
debug_assert!(self.functions.borrow().values().any(|value| *value == function),
|
||||
"{:?} ({:?}) is not a function", value, value.get_type());
|
||||
function
|
||||
}
|
||||
|
|
|
@ -34,13 +34,6 @@ pub trait ArgAttributesExt {
|
|||
);
|
||||
}
|
||||
|
||||
fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
|
||||
// LLVM prior to version 12 had known miscompiles in the presence of
|
||||
// noalias attributes (see #54878), but we don't support earlier
|
||||
// versions at all anymore. We now enable mutable noalias by default.
|
||||
cx.tcx.sess.opts.unstable_opts.mutable_noalias.unwrap_or(true)
|
||||
}
|
||||
|
||||
const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] =
|
||||
[(ArgAttribute::InReg, llvm::AttributeKind::InReg)];
|
||||
|
||||
|
@ -88,9 +81,6 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
|
|||
attrs.push(llattr.create_attr(cx.llcx));
|
||||
}
|
||||
}
|
||||
if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) {
|
||||
attrs.push(llvm::AttributeKind::NoAlias.create_attr(cx.llcx));
|
||||
}
|
||||
} else if cx.tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
|
||||
// If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects
|
||||
// memory sanitizer's behavior.
|
||||
|
|
|
@ -8,8 +8,8 @@ use crate::va_arg::emit_va_arg;
|
|||
use crate::value::Value;
|
||||
|
||||
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
|
||||
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
|
||||
use rustc_codegen_ssa::mir::operand::OperandRef;
|
||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
@ -284,15 +284,11 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
_ => bug!(),
|
||||
},
|
||||
None => {
|
||||
span_invalid_monomorphization_error(
|
||||
tcx.sess,
|
||||
tcx.sess.emit_err(InvalidMonomorphization::BasicIntegerType {
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic integer type, found `{}`",
|
||||
name, ty
|
||||
),
|
||||
);
|
||||
name,
|
||||
ty,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -838,40 +834,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
llret_ty: &'ll Type,
|
||||
span: Span,
|
||||
) -> Result<&'ll Value, ()> {
|
||||
// macros for error handling:
|
||||
#[allow(unused_macro_rules)]
|
||||
macro_rules! emit_error {
|
||||
($msg: tt) => {
|
||||
emit_error!($msg, )
|
||||
};
|
||||
($msg: tt, $($fmt: tt)*) => {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.sess(), span,
|
||||
&format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
|
||||
name, $($fmt)*));
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! return_error {
|
||||
($($fmt: tt)*) => {
|
||||
{
|
||||
emit_error!($($fmt)*);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
($diag: expr) => {{
|
||||
bx.sess().emit_err($diag);
|
||||
return Err(());
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! require {
|
||||
($cond: expr, $($fmt: tt)*) => {
|
||||
($cond: expr, $diag: expr) => {
|
||||
if !$cond {
|
||||
return_error!($($fmt)*);
|
||||
return_error!($diag);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! require_simd {
|
||||
($ty: expr, $position: expr) => {
|
||||
require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
|
||||
($ty: expr, $diag: expr) => {
|
||||
require!($ty.is_simd(), $diag)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -881,7 +861,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let arg_tys = sig.inputs();
|
||||
|
||||
if name == sym::simd_select_bitmask {
|
||||
require_simd!(arg_tys[1], "argument");
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
|
||||
let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
|
||||
let expected_int_bits = (len.max(8) - 1).next_power_of_two();
|
||||
|
@ -902,12 +886,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
|
||||
bx.load(int_ty, ptr, Align::ONE)
|
||||
}
|
||||
_ => return_error!(
|
||||
"invalid bitmask `{}`, expected `u{}` or `[u8; {}]`",
|
||||
_ => return_error!(InvalidMonomorphization::InvalidBitmask {
|
||||
span,
|
||||
name,
|
||||
mask_ty,
|
||||
expected_int_bits,
|
||||
expected_bytes
|
||||
),
|
||||
}),
|
||||
};
|
||||
|
||||
let i1 = bx.type_i1();
|
||||
|
@ -919,7 +904,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
|
||||
// every intrinsic below takes a SIMD vector as its first argument
|
||||
require_simd!(arg_tys[0], "input");
|
||||
require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] });
|
||||
let in_ty = arg_tys[0];
|
||||
|
||||
let comparison = match name {
|
||||
|
@ -934,23 +919,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
|
||||
let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||
if let Some(cmp_op) = comparison {
|
||||
require_simd!(ret_ty, "return");
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
|
||||
require!(
|
||||
in_len == out_len,
|
||||
"expected return type with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
require!(
|
||||
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
|
||||
"expected return type with integer elements, found `{}` with non-integer `{}`",
|
||||
ret_ty,
|
||||
out_ty
|
||||
InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty }
|
||||
);
|
||||
|
||||
return Ok(compare_simd_types(
|
||||
|
@ -975,10 +961,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
span_bug!(span, "could not evaluate shuffle index array length")
|
||||
})
|
||||
}
|
||||
_ => return_error!(
|
||||
"simd_shuffle index must be an array of `u32`, got `{}`",
|
||||
args[2].layout.ty
|
||||
),
|
||||
_ => return_error!(InvalidMonomorphization::SimdShuffle {
|
||||
span,
|
||||
name,
|
||||
ty: args[2].layout.ty
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
stripped.parse().unwrap_or_else(|_| {
|
||||
|
@ -986,23 +973,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
})
|
||||
};
|
||||
|
||||
require_simd!(ret_ty, "return");
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
out_len == n,
|
||||
"expected return type of length {}, found `{}` with length {}",
|
||||
n,
|
||||
ret_ty,
|
||||
out_len
|
||||
InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len }
|
||||
);
|
||||
require!(
|
||||
in_elem == out_ty,
|
||||
"expected return element type `{}` (element of input `{}`), \
|
||||
found `{}` with element type `{}`",
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_ty
|
||||
InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
|
||||
);
|
||||
|
||||
let total_len = u128::from(in_len) * 2;
|
||||
|
@ -1015,15 +994,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let val = bx.const_get_elt(vector, i as u64);
|
||||
match bx.const_to_opt_u128(val, true) {
|
||||
None => {
|
||||
emit_error!("shuffle index #{} is not a constant", arg_idx);
|
||||
bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexNotConstant {
|
||||
span,
|
||||
name,
|
||||
arg_idx,
|
||||
});
|
||||
None
|
||||
}
|
||||
Some(idx) if idx >= total_len => {
|
||||
emit_error!(
|
||||
"shuffle index #{} is out of bounds (limit {})",
|
||||
bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds {
|
||||
span,
|
||||
name,
|
||||
arg_idx,
|
||||
total_len
|
||||
);
|
||||
total_len,
|
||||
});
|
||||
None
|
||||
}
|
||||
Some(idx) => Some(bx.const_i32(idx as i32)),
|
||||
|
@ -1044,10 +1028,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
if name == sym::simd_insert {
|
||||
require!(
|
||||
in_elem == arg_tys[2],
|
||||
"expected inserted type `{}` (element of input `{}`), found `{}`",
|
||||
in_elem,
|
||||
in_ty,
|
||||
arg_tys[2]
|
||||
InvalidMonomorphization::InsertedType {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
out_ty: arg_tys[2]
|
||||
}
|
||||
);
|
||||
return Ok(bx.insert_element(
|
||||
args[0].immediate(),
|
||||
|
@ -1058,10 +1045,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
if name == sym::simd_extract {
|
||||
require!(
|
||||
ret_ty == in_elem,
|
||||
"expected return type `{}` (element of input `{}`), found `{}`",
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()));
|
||||
}
|
||||
|
@ -1069,17 +1053,18 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
if name == sym::simd_select {
|
||||
let m_elem_ty = in_elem;
|
||||
let m_len = in_len;
|
||||
require_simd!(arg_tys[1], "argument");
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
m_len == v_len,
|
||||
"mismatched lengths: mask length `{}` != other vector length `{}`",
|
||||
m_len,
|
||||
v_len
|
||||
InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
|
||||
);
|
||||
match m_elem_ty.kind() {
|
||||
ty::Int(_) => {}
|
||||
_ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty),
|
||||
_ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }),
|
||||
}
|
||||
// truncate the mask to a vector of i1s
|
||||
let i1 = bx.type_i1();
|
||||
|
@ -1111,11 +1096,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
args[0].immediate(),
|
||||
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
|
||||
),
|
||||
_ => return_error!(
|
||||
"vector argument `{}`'s element type `{}`, expected integer element type",
|
||||
_ => return_error!(InvalidMonomorphization::VectorArgument {
|
||||
span,
|
||||
name,
|
||||
in_ty,
|
||||
in_elem
|
||||
),
|
||||
}),
|
||||
};
|
||||
|
||||
// Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position.
|
||||
|
@ -1150,12 +1136,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
|
||||
return Ok(bx.load(array_ty, ptr, Align::ONE));
|
||||
}
|
||||
_ => return_error!(
|
||||
"cannot return `{}`, expected `u{}` or `[u8; {}]`",
|
||||
_ => return_error!(InvalidMonomorphization::CannotReturn {
|
||||
span,
|
||||
name,
|
||||
ret_ty,
|
||||
expected_int_bits,
|
||||
expected_bytes
|
||||
),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1168,25 +1155,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
span: Span,
|
||||
args: &[OperandRef<'tcx, &'ll Value>],
|
||||
) -> Result<&'ll Value, ()> {
|
||||
#[allow(unused_macro_rules)]
|
||||
macro_rules! emit_error {
|
||||
($msg: tt) => {
|
||||
emit_error!($msg, )
|
||||
};
|
||||
($msg: tt, $($fmt: tt)*) => {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.sess(), span,
|
||||
&format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
|
||||
name, $($fmt)*));
|
||||
}
|
||||
}
|
||||
macro_rules! return_error {
|
||||
($($fmt: tt)*) => {
|
||||
{
|
||||
emit_error!($($fmt)*);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
($diag: expr) => {{
|
||||
bx.sess().emit_err($diag);
|
||||
return Err(());
|
||||
}};
|
||||
}
|
||||
|
||||
let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() {
|
||||
|
@ -1194,16 +1167,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
match f.bit_width() {
|
||||
32 => ("f32", elem_ty),
|
||||
64 => ("f64", elem_ty),
|
||||
_ => {
|
||||
return_error!(
|
||||
"unsupported element type `{}` of floating-point vector `{}`",
|
||||
f.name_str(),
|
||||
in_ty
|
||||
);
|
||||
}
|
||||
_ => return_error!(InvalidMonomorphization::FloatingPointVector {
|
||||
span,
|
||||
name,
|
||||
f_ty: *f,
|
||||
in_ty,
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
return_error!("`{}` is not a floating-point type", in_ty);
|
||||
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
|
||||
};
|
||||
|
||||
let vec_ty = bx.type_vector(elem_ty, in_len);
|
||||
|
@ -1225,7 +1197,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
|
||||
sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
|
||||
sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)),
|
||||
_ => return_error!("unrecognized intrinsic `{}`", name),
|
||||
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
|
||||
};
|
||||
let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str);
|
||||
let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty);
|
||||
|
@ -1319,37 +1291,48 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
// * M: any integer width is supported, will be truncated to i1
|
||||
|
||||
// All types must be simd vector types
|
||||
require_simd!(in_ty, "first");
|
||||
require_simd!(arg_tys[1], "second");
|
||||
require_simd!(arg_tys[2], "third");
|
||||
require_simd!(ret_ty, "return");
|
||||
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
require_simd!(
|
||||
arg_tys[2],
|
||||
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
|
||||
);
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
// Of the same length:
|
||||
let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
in_len == out_len,
|
||||
"expected {} argument with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
"second",
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_tys[1],
|
||||
out_len
|
||||
InvalidMonomorphization::SecondArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[1],
|
||||
out_len
|
||||
}
|
||||
);
|
||||
require!(
|
||||
in_len == out_len2,
|
||||
"expected {} argument with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
"third",
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_tys[2],
|
||||
out_len2
|
||||
InvalidMonomorphization::ThirdArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[2],
|
||||
out_len: out_len2
|
||||
}
|
||||
);
|
||||
|
||||
// The return type must match the first argument type
|
||||
require!(ret_ty == in_ty, "expected return type `{}`, found `{}`", in_ty, ret_ty);
|
||||
require!(
|
||||
ret_ty == in_ty,
|
||||
InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty }
|
||||
);
|
||||
|
||||
// This counts how many pointers
|
||||
fn ptr_count(t: Ty<'_>) -> usize {
|
||||
|
@ -1376,15 +1359,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
_ => {
|
||||
require!(
|
||||
false,
|
||||
"expected element type `{}` of second argument `{}` \
|
||||
to be a pointer to the element type `{}` of the first \
|
||||
argument `{}`, found `{}` != `*_ {}`",
|
||||
element_ty1,
|
||||
arg_tys[1],
|
||||
in_elem,
|
||||
in_ty,
|
||||
element_ty1,
|
||||
in_elem
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty1,
|
||||
second_arg: arg_tys[1],
|
||||
in_elem,
|
||||
in_ty,
|
||||
mutability: ExpectedPointerMutability::Not,
|
||||
}
|
||||
);
|
||||
unreachable!();
|
||||
}
|
||||
|
@ -1400,10 +1383,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
_ => {
|
||||
require!(
|
||||
false,
|
||||
"expected element type `{}` of third argument `{}` \
|
||||
to be a signed integer type",
|
||||
element_ty2,
|
||||
arg_tys[2]
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1452,32 +1437,40 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
// * M: any integer width is supported, will be truncated to i1
|
||||
|
||||
// All types must be simd vector types
|
||||
require_simd!(in_ty, "first");
|
||||
require_simd!(arg_tys[1], "second");
|
||||
require_simd!(arg_tys[2], "third");
|
||||
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
require_simd!(
|
||||
arg_tys[2],
|
||||
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
|
||||
);
|
||||
|
||||
// Of the same length:
|
||||
let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
in_len == element_len1,
|
||||
"expected {} argument with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
"second",
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_tys[1],
|
||||
element_len1
|
||||
InvalidMonomorphization::SecondArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[1],
|
||||
out_len: element_len1
|
||||
}
|
||||
);
|
||||
require!(
|
||||
in_len == element_len2,
|
||||
"expected {} argument with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
"third",
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_tys[2],
|
||||
element_len2
|
||||
InvalidMonomorphization::ThirdArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[2],
|
||||
out_len: element_len2
|
||||
}
|
||||
);
|
||||
|
||||
// This counts how many pointers
|
||||
|
@ -1508,15 +1501,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
_ => {
|
||||
require!(
|
||||
false,
|
||||
"expected element type `{}` of second argument `{}` \
|
||||
to be a pointer to the element type `{}` of the first \
|
||||
argument `{}`, found `{}` != `*mut {}`",
|
||||
element_ty1,
|
||||
arg_tys[1],
|
||||
in_elem,
|
||||
in_ty,
|
||||
element_ty1,
|
||||
in_elem
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty1,
|
||||
second_arg: arg_tys[1],
|
||||
in_elem,
|
||||
in_ty,
|
||||
mutability: ExpectedPointerMutability::Mut,
|
||||
}
|
||||
);
|
||||
unreachable!();
|
||||
}
|
||||
|
@ -1531,10 +1524,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
_ => {
|
||||
require!(
|
||||
false,
|
||||
"expected element type `{}` of third argument `{}` \
|
||||
be a signed integer type",
|
||||
element_ty2,
|
||||
arg_tys[2]
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1581,10 +1576,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
if name == sym::$name {
|
||||
require!(
|
||||
ret_ty == in_elem,
|
||||
"expected return type `{}` (element of input `{}`), found `{}`",
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
return match in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {
|
||||
|
@ -1607,25 +1599,28 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
32 => bx.const_real(bx.type_f32(), $identity),
|
||||
64 => bx.const_real(bx.type_f64(), $identity),
|
||||
v => return_error!(
|
||||
r#"
|
||||
unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
||||
sym::$name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
v,
|
||||
ret_ty
|
||||
InvalidMonomorphization::UnsupportedSymbolOfSize {
|
||||
span,
|
||||
name,
|
||||
symbol: sym::$name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
size: v,
|
||||
ret_ty
|
||||
}
|
||||
),
|
||||
}
|
||||
};
|
||||
Ok(bx.$float_reduce(acc, args[0].immediate()))
|
||||
}
|
||||
_ => return_error!(
|
||||
"unsupported {} from `{}` with element `{}` to `{}`",
|
||||
sym::$name,
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
name,
|
||||
symbol: sym::$name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty
|
||||
),
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -1653,22 +1648,20 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
if name == sym::$name {
|
||||
require!(
|
||||
ret_ty == in_elem,
|
||||
"expected return type `{}` (element of input `{}`), found `{}`",
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
return match in_elem.kind() {
|
||||
ty::Int(_i) => Ok(bx.$int_red(args[0].immediate(), true)),
|
||||
ty::Uint(_u) => Ok(bx.$int_red(args[0].immediate(), false)),
|
||||
ty::Float(_f) => Ok(bx.$float_red(args[0].immediate())),
|
||||
_ => return_error!(
|
||||
"unsupported {} from `{}` with element `{}` to `{}`",
|
||||
sym::$name,
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
name,
|
||||
symbol: sym::$name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty
|
||||
),
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -1686,22 +1679,20 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
let input = if !$boolean {
|
||||
require!(
|
||||
ret_ty == in_elem,
|
||||
"expected return type `{}` (element of input `{}`), found `{}`",
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
args[0].immediate()
|
||||
} else {
|
||||
match in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {}
|
||||
_ => return_error!(
|
||||
"unsupported {} from `{}` with element `{}` to `{}`",
|
||||
sym::$name,
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
name,
|
||||
symbol: sym::$name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty
|
||||
),
|
||||
}),
|
||||
}
|
||||
|
||||
// boolean reductions operate on vectors of i1s:
|
||||
|
@ -1714,13 +1705,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
let r = bx.$red(input);
|
||||
Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) })
|
||||
}
|
||||
_ => return_error!(
|
||||
"unsupported {} from `{}` with element `{}` to `{}`",
|
||||
sym::$name,
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
name,
|
||||
symbol: sym::$name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty
|
||||
),
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -1733,16 +1725,18 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
bitwise_red!(simd_reduce_any: vector_reduce_or, true);
|
||||
|
||||
if name == sym::simd_cast_ptr {
|
||||
require_simd!(ret_ty, "return");
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
in_len == out_len,
|
||||
"expected return type with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
|
||||
match in_elem.kind() {
|
||||
|
@ -1751,9 +1745,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
assert!(!check_sized); // we are in codegen, so we shouldn't see these types
|
||||
require!(metadata.is_unit(), "cannot cast fat pointer `{}`", in_elem)
|
||||
require!(
|
||||
metadata.is_unit(),
|
||||
InvalidMonomorphization::CastFatPointer { span, name, ty: in_elem }
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem })
|
||||
}
|
||||
_ => return_error!("expected pointer, got `{}`", in_elem),
|
||||
}
|
||||
match out_elem.kind() {
|
||||
ty::RawPtr(p) => {
|
||||
|
@ -1761,9 +1760,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
assert!(!check_sized); // we are in codegen, so we shouldn't see these types
|
||||
require!(metadata.is_unit(), "cannot cast to fat pointer `{}`", out_elem)
|
||||
require!(
|
||||
metadata.is_unit(),
|
||||
InvalidMonomorphization::CastFatPointer { span, name, ty: out_elem }
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem })
|
||||
}
|
||||
_ => return_error!("expected pointer, got `{}`", out_elem),
|
||||
}
|
||||
|
||||
if in_elem == out_elem {
|
||||
|
@ -1774,66 +1778,76 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
}
|
||||
|
||||
if name == sym::simd_expose_addr {
|
||||
require_simd!(ret_ty, "return");
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
in_len == out_len,
|
||||
"expected return type with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
|
||||
match in_elem.kind() {
|
||||
ty::RawPtr(_) => {}
|
||||
_ => return_error!("expected pointer, got `{}`", in_elem),
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem })
|
||||
}
|
||||
}
|
||||
match out_elem.kind() {
|
||||
ty::Uint(ty::UintTy::Usize) => {}
|
||||
_ => return_error!("expected `usize`, got `{}`", out_elem),
|
||||
_ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: out_elem }),
|
||||
}
|
||||
|
||||
return Ok(bx.ptrtoint(args[0].immediate(), llret_ty));
|
||||
}
|
||||
|
||||
if name == sym::simd_from_exposed_addr {
|
||||
require_simd!(ret_ty, "return");
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
in_len == out_len,
|
||||
"expected return type with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
|
||||
match in_elem.kind() {
|
||||
ty::Uint(ty::UintTy::Usize) => {}
|
||||
_ => return_error!("expected `usize`, got `{}`", in_elem),
|
||||
_ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: in_elem }),
|
||||
}
|
||||
match out_elem.kind() {
|
||||
ty::RawPtr(_) => {}
|
||||
_ => return_error!("expected pointer, got `{}`", out_elem),
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem })
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(bx.inttoptr(args[0].immediate(), llret_ty));
|
||||
}
|
||||
|
||||
if name == sym::simd_cast || name == sym::simd_as {
|
||||
require_simd!(ret_ty, "return");
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
in_len == out_len,
|
||||
"expected return type with length {} (same as input type `{}`), \
|
||||
found `{}` with length {}",
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
// casting cares about nominal type, not just structural type
|
||||
if in_elem == out_elem {
|
||||
|
@ -1912,11 +1926,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
}
|
||||
require!(
|
||||
false,
|
||||
"unsupported cast from `{}` with element `{}` to `{}` with element `{}`",
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty,
|
||||
out_elem
|
||||
InvalidMonomorphization::UnsupportedCast {
|
||||
span,
|
||||
name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty,
|
||||
out_elem
|
||||
}
|
||||
);
|
||||
}
|
||||
macro_rules! arith_binary {
|
||||
|
@ -1928,10 +1945,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
})*
|
||||
_ => {},
|
||||
}
|
||||
require!(false,
|
||||
"unsupported operation on `{}` with element `{}`",
|
||||
in_ty,
|
||||
in_elem)
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }
|
||||
);
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
@ -1959,10 +1976,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
})*
|
||||
_ => {},
|
||||
}
|
||||
require!(false,
|
||||
"unsupported operation on `{}` with element `{}`",
|
||||
in_ty,
|
||||
in_elem)
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }
|
||||
);
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
@ -2000,12 +2017,12 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_int_from_ty(i)),
|
||||
ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_uint_from_ty(i)),
|
||||
_ => {
|
||||
return_error!(
|
||||
"expected element type `{}` of vector type `{}` \
|
||||
to be a signed or unsigned integer type",
|
||||
arg_tys[0].simd_size_and_type(bx.tcx()).1,
|
||||
arg_tys[0]
|
||||
);
|
||||
return_error!(InvalidMonomorphization::ExpectedVectorElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1,
|
||||
vector_type: arg_tys[0]
|
||||
});
|
||||
}
|
||||
};
|
||||
let llvm_intrinsic = &format!(
|
||||
|
|
|
@ -27,6 +27,7 @@ rustc_arena = { path = "../rustc_arena" }
|
|||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_type_ir = { path = "../rustc_type_ir" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
|
|||
use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
|
||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||
|
@ -208,16 +208,16 @@ pub fn link_binary<'a>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Crate type is not passed when calculating the dylibs to include for LTO. In that case all
|
||||
// crate types must use the same dependency formats.
|
||||
pub fn each_linked_rlib(
|
||||
sess: &Session,
|
||||
info: &CrateInfo,
|
||||
crate_type: Option<CrateType>,
|
||||
f: &mut dyn FnMut(CrateNum, &Path),
|
||||
) -> Result<(), errors::LinkRlibError> {
|
||||
let crates = info.used_crates.iter();
|
||||
let mut fmts = None;
|
||||
|
||||
let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
|
||||
if lto_active {
|
||||
let fmts = if crate_type.is_none() {
|
||||
for combination in info.dependency_formats.iter().combinations(2) {
|
||||
let (ty1, list1) = &combination[0];
|
||||
let (ty2, list2) = &combination[1];
|
||||
|
@ -230,27 +230,23 @@ pub fn each_linked_rlib(
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ty, list) in info.dependency_formats.iter() {
|
||||
match ty {
|
||||
CrateType::Executable
|
||||
| CrateType::Staticlib
|
||||
| CrateType::Cdylib
|
||||
| CrateType::ProcMacro => {
|
||||
fmts = Some(list);
|
||||
break;
|
||||
}
|
||||
CrateType::Dylib if lto_active => {
|
||||
fmts = Some(list);
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
if info.dependency_formats.is_empty() {
|
||||
return Err(errors::LinkRlibError::MissingFormat);
|
||||
}
|
||||
}
|
||||
let Some(fmts) = fmts else {
|
||||
return Err(errors::LinkRlibError::MissingFormat);
|
||||
&info.dependency_formats[0].1
|
||||
} else {
|
||||
let fmts = info
|
||||
.dependency_formats
|
||||
.iter()
|
||||
.find_map(|&(ty, ref list)| if Some(ty) == crate_type { Some(list) } else { None });
|
||||
|
||||
let Some(fmts) = fmts else {
|
||||
return Err(errors::LinkRlibError::MissingFormat);
|
||||
};
|
||||
|
||||
fmts
|
||||
};
|
||||
|
||||
for &cnum in crates {
|
||||
match fmts.get(cnum.as_usize() - 1) {
|
||||
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
||||
|
@ -516,64 +512,71 @@ fn link_staticlib<'a>(
|
|||
)?;
|
||||
let mut all_native_libs = vec![];
|
||||
|
||||
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
|
||||
let name = codegen_results.crate_info.crate_name[&cnum];
|
||||
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||
let res = each_linked_rlib(
|
||||
&codegen_results.crate_info,
|
||||
Some(CrateType::Staticlib),
|
||||
&mut |cnum, path| {
|
||||
let name = codegen_results.crate_info.crate_name[&cnum];
|
||||
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||
|
||||
// Here when we include the rlib into our staticlib we need to make a
|
||||
// decision whether to include the extra object files along the way.
|
||||
// These extra object files come from statically included native
|
||||
// libraries, but they may be cfg'd away with #[link(cfg(..))].
|
||||
//
|
||||
// This unstable feature, though, only needs liblibc to work. The only
|
||||
// use case there is where musl is statically included in liblibc.rlib,
|
||||
// so if we don't want the included version we just need to skip it. As
|
||||
// a result the logic here is that if *any* linked library is cfg'd away
|
||||
// we just skip all object files.
|
||||
//
|
||||
// Clearly this is not sufficient for a general purpose feature, and
|
||||
// we'd want to read from the library's metadata to determine which
|
||||
// object files come from where and selectively skip them.
|
||||
let skip_object_files = native_libs.iter().any(|lib| {
|
||||
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
|
||||
&& !relevant_lib(sess, lib)
|
||||
});
|
||||
// Here when we include the rlib into our staticlib we need to make a
|
||||
// decision whether to include the extra object files along the way.
|
||||
// These extra object files come from statically included native
|
||||
// libraries, but they may be cfg'd away with #[link(cfg(..))].
|
||||
//
|
||||
// This unstable feature, though, only needs liblibc to work. The only
|
||||
// use case there is where musl is statically included in liblibc.rlib,
|
||||
// so if we don't want the included version we just need to skip it. As
|
||||
// a result the logic here is that if *any* linked library is cfg'd away
|
||||
// we just skip all object files.
|
||||
//
|
||||
// Clearly this is not sufficient for a general purpose feature, and
|
||||
// we'd want to read from the library's metadata to determine which
|
||||
// object files come from where and selectively skip them.
|
||||
let skip_object_files = native_libs.iter().any(|lib| {
|
||||
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
|
||||
&& !relevant_lib(sess, lib)
|
||||
});
|
||||
|
||||
let lto = are_upstream_rust_objects_already_included(sess)
|
||||
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
|
||||
let lto = are_upstream_rust_objects_already_included(sess)
|
||||
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
|
||||
|
||||
// Ignoring obj file starting with the crate name
|
||||
// as simple comparison is not enough - there
|
||||
// might be also an extra name suffix
|
||||
let obj_start = name.as_str().to_owned();
|
||||
// Ignoring obj file starting with the crate name
|
||||
// as simple comparison is not enough - there
|
||||
// might be also an extra name suffix
|
||||
let obj_start = name.as_str().to_owned();
|
||||
|
||||
ab.add_archive(
|
||||
path,
|
||||
Box::new(move |fname: &str| {
|
||||
// Ignore metadata files, no matter the name.
|
||||
if fname == METADATA_FILENAME {
|
||||
return true;
|
||||
}
|
||||
ab.add_archive(
|
||||
path,
|
||||
Box::new(move |fname: &str| {
|
||||
// Ignore metadata files, no matter the name.
|
||||
if fname == METADATA_FILENAME {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't include Rust objects if LTO is enabled
|
||||
if lto && looks_like_rust_object_file(fname) {
|
||||
return true;
|
||||
}
|
||||
// Don't include Rust objects if LTO is enabled
|
||||
if lto && looks_like_rust_object_file(fname) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise if this is *not* a rust object and we're skipping
|
||||
// objects then skip this file
|
||||
if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
|
||||
return true;
|
||||
}
|
||||
// Otherwise if this is *not* a rust object and we're skipping
|
||||
// objects then skip this file
|
||||
if skip_object_files
|
||||
&& (!fname.starts_with(&obj_start) || !fname.ends_with(".o"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// ok, don't skip this
|
||||
false
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
// ok, don't skip this
|
||||
false
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
|
||||
});
|
||||
all_native_libs
|
||||
.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
|
||||
},
|
||||
);
|
||||
if let Err(e) = res {
|
||||
sess.emit_fatal(e);
|
||||
}
|
||||
|
@ -1354,7 +1357,8 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
|
|||
if !lib_args.is_empty() {
|
||||
sess.emit_note(errors::StaticLibraryNativeArtifacts);
|
||||
// Prefix for greppability
|
||||
sess.emit_note(errors::NativeStaticLibs { arguments: lib_args.join(" ") });
|
||||
// Note: This must not be translated as tools are allowed to depend on this exact string.
|
||||
sess.note_without_error(&format!("native-static-libs: {}", &lib_args.join(" ")));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2612,7 +2616,7 @@ fn add_static_crate<'a>(
|
|||
sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
|
||||
|
||||
let mut archive = archive_builder_builder.new_archive_builder(sess);
|
||||
if let Err(e) = archive.add_archive(
|
||||
if let Err(error) = archive.add_archive(
|
||||
cratepath,
|
||||
Box::new(move |f| {
|
||||
if f == METADATA_FILENAME {
|
||||
|
@ -2652,7 +2656,7 @@ fn add_static_crate<'a>(
|
|||
false
|
||||
}),
|
||||
) {
|
||||
sess.fatal(&format!("failed to build archive from rlib: {}", e));
|
||||
sess.emit_fatal(errors::RlibArchiveBuildFailure { error });
|
||||
}
|
||||
if archive.build(&dst) {
|
||||
link_upstream(&dst);
|
||||
|
@ -2822,11 +2826,30 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|
|||
// Implement the "linker flavor" part of -Zgcc-ld
|
||||
// by asking cc to use some kind of lld.
|
||||
cmd.arg("-fuse-ld=lld");
|
||||
|
||||
if !flavor.is_gnu() {
|
||||
// Tell clang to use a non-default LLD flavor.
|
||||
// Gcc doesn't understand the target option, but we currently assume
|
||||
// that gcc is not used for Apple and Wasm targets (#97402).
|
||||
cmd.arg(format!("--target={}", sess.target.llvm_target));
|
||||
//
|
||||
// Note that we don't want to do that by default on macOS: e.g. passing a
|
||||
// 10.7 target to LLVM works, but not to recent versions of clang/macOS, as
|
||||
// shown in issue #101653 and the discussion in PR #101792.
|
||||
//
|
||||
// It could be required in some cases of cross-compiling with
|
||||
// `-Zgcc-ld=lld`, but this is generally unspecified, and we don't know
|
||||
// which specific versions of clang, macOS SDK, host and target OS
|
||||
// combinations impact us here.
|
||||
//
|
||||
// So we do a simple first-approximation until we know more of what the
|
||||
// Apple targets require (and which would be handled prior to hitting this
|
||||
// `-Zgcc-ld=lld` codepath anyway), but the expectation is that until then
|
||||
// this should be manually passed if needed. We specify the target when
|
||||
// targeting a different linker flavor on macOS, and that's also always
|
||||
// the case when targeting WASM.
|
||||
if sess.target.linker_flavor != sess.host.linker_flavor {
|
||||
cmd.arg(format!("--target={}", sess.target.llvm_target));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1002,7 +1002,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
let sess = tcx.sess;
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
|
||||
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::back::write::{
|
|||
submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
|
||||
};
|
||||
use crate::common::{IntPredicate, RealPredicate, TypeKind};
|
||||
use crate::errors;
|
||||
use crate::meth;
|
||||
use crate::mir;
|
||||
use crate::mir::operand::OperandValue;
|
||||
|
@ -451,10 +452,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
let Some(llfn) = cx.declare_c_main(llfty) else {
|
||||
// FIXME: We should be smart and show a better diagnostic here.
|
||||
let span = cx.tcx().def_span(rust_main_def_id);
|
||||
cx.sess()
|
||||
.struct_span_err(span, "entry symbol `main` declared multiple times")
|
||||
.help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
|
||||
.emit();
|
||||
cx.sess().emit_err(errors::MultipleMainFunctions { span });
|
||||
cx.sess().abort_if_errors();
|
||||
bug!();
|
||||
};
|
||||
|
@ -595,8 +593,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
&metadata,
|
||||
&exported_symbols::metadata_symbol_name(tcx),
|
||||
);
|
||||
if let Err(err) = std::fs::write(&file_name, data) {
|
||||
tcx.sess.fatal(&format!("error writing metadata object file: {}", err));
|
||||
if let Err(error) = std::fs::write(&file_name, data) {
|
||||
tcx.sess.emit_fatal(errors::MetadataObjectFileWrite { error });
|
||||
}
|
||||
Some(CompiledModule {
|
||||
name: metadata_cgu_name,
|
||||
|
@ -815,11 +813,7 @@ impl CrateInfo {
|
|||
let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
|
||||
let windows_subsystem = subsystem.map(|subsystem| {
|
||||
if subsystem != sym::windows && subsystem != sym::console {
|
||||
tcx.sess.fatal(&format!(
|
||||
"invalid windows subsystem `{}`, only \
|
||||
`windows` and `console` are allowed",
|
||||
subsystem
|
||||
));
|
||||
tcx.sess.emit_fatal(errors::InvalidWindowsSubsystem { subsystem });
|
||||
}
|
||||
subsystem.to_string()
|
||||
});
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::base;
|
||||
|
@ -193,10 +191,6 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
|
||||
struct_span_err!(a, b, E0511, "{}", c).emit();
|
||||
}
|
||||
|
||||
pub fn asm_const_to_str<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sp: Span,
|
||||
|
|
|
@ -93,6 +93,7 @@ fn push_debuginfo_type_name<'tcx>(
|
|||
Err(e) => {
|
||||
// Computing the layout can still fail here, e.g. if the target architecture
|
||||
// cannot represent the type. See https://github.com/rust-lang/rust/issues/94961.
|
||||
// FIXME: migrate once `rustc_middle::mir::interpret::InterpError` is translatable.
|
||||
tcx.sess.fatal(&format!("{}", e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@ use rustc_errors::{
|
|||
IntoDiagnosticArg,
|
||||
};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_type_ir::FloatTy;
|
||||
use std::borrow::Cow;
|
||||
use std::io::Error;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -444,12 +446,6 @@ pub struct LinkerFileStem;
|
|||
#[diag(codegen_ssa_static_library_native_artifacts)]
|
||||
pub struct StaticLibraryNativeArtifacts;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_native_static_libs)]
|
||||
pub struct NativeStaticLibs {
|
||||
pub arguments: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_link_script_unavailable)]
|
||||
pub struct LinkScriptUnavailable;
|
||||
|
@ -555,3 +551,432 @@ pub struct ExpectedUsedSymbol {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_multiple_main_functions)]
|
||||
#[help]
|
||||
pub struct MultipleMainFunctions {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_metadata_object_file_write)]
|
||||
pub struct MetadataObjectFileWrite {
|
||||
pub error: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_invalid_windows_subsystem)]
|
||||
pub struct InvalidWindowsSubsystem {
|
||||
pub subsystem: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_erroneous_constant)]
|
||||
pub struct ErroneousConstant {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_polymorphic_constant_too_generic)]
|
||||
pub struct PolymorphicConstantTooGeneric {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_shuffle_indices_evaluation)]
|
||||
pub struct ShuffleIndicesEvaluation {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_missing_memory_ordering)]
|
||||
pub struct MissingMemoryOrdering;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_unknown_atomic_ordering)]
|
||||
pub struct UnknownAtomicOrdering;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_atomic_compare_exchange)]
|
||||
pub struct AtomicCompareExchange;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_unknown_atomic_operation)]
|
||||
pub struct UnknownAtomicOperation;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub enum InvalidMonomorphization<'tcx> {
|
||||
#[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = "E0511")]
|
||||
BasicIntegerType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = "E0511")]
|
||||
BasicFloatType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = "E0511")]
|
||||
FloatToIntUnchecked {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = "E0511")]
|
||||
FloatingPointVector {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
f_ty: FloatTy,
|
||||
in_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = "E0511")]
|
||||
FloatingPointType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = "E0511")]
|
||||
UnrecognizedIntrinsic {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = "E0511")]
|
||||
SimdArgument {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_simd_input, code = "E0511")]
|
||||
SimdInput {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_simd_first, code = "E0511")]
|
||||
SimdFirst {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_simd_second, code = "E0511")]
|
||||
SimdSecond {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_simd_third, code = "E0511")]
|
||||
SimdThird {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_simd_return, code = "E0511")]
|
||||
SimdReturn {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = "E0511")]
|
||||
InvalidBitmask {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
mask_ty: Ty<'tcx>,
|
||||
expected_int_bits: u64,
|
||||
expected_bytes: u64,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = "E0511")]
|
||||
ReturnLengthInputType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_len: u64,
|
||||
in_ty: Ty<'tcx>,
|
||||
ret_ty: Ty<'tcx>,
|
||||
out_len: u64,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = "E0511")]
|
||||
SecondArgumentLength {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_len: u64,
|
||||
in_ty: Ty<'tcx>,
|
||||
arg_ty: Ty<'tcx>,
|
||||
out_len: u64,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = "E0511")]
|
||||
ThirdArgumentLength {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_len: u64,
|
||||
in_ty: Ty<'tcx>,
|
||||
arg_ty: Ty<'tcx>,
|
||||
out_len: u64,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = "E0511")]
|
||||
ReturnIntegerType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ret_ty: Ty<'tcx>,
|
||||
out_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = "E0511")]
|
||||
SimdShuffle {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_return_length, code = "E0511")]
|
||||
ReturnLength {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_len: u64,
|
||||
ret_ty: Ty<'tcx>,
|
||||
out_len: u64,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_return_element, code = "E0511")]
|
||||
ReturnElement {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_elem: Ty<'tcx>,
|
||||
in_ty: Ty<'tcx>,
|
||||
ret_ty: Ty<'tcx>,
|
||||
out_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = "E0511")]
|
||||
ShuffleIndexNotConstant {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
arg_idx: u64,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = "E0511")]
|
||||
ShuffleIndexOutOfBounds {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
arg_idx: u64,
|
||||
total_len: u128,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = "E0511")]
|
||||
InsertedType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_elem: Ty<'tcx>,
|
||||
in_ty: Ty<'tcx>,
|
||||
out_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_return_type, code = "E0511")]
|
||||
ReturnType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_elem: Ty<'tcx>,
|
||||
in_ty: Ty<'tcx>,
|
||||
ret_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = "E0511")]
|
||||
ExpectedReturnType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_ty: Ty<'tcx>,
|
||||
ret_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = "E0511")]
|
||||
MismatchedLengths {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
m_len: u64,
|
||||
v_len: u64,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_mask_type, code = "E0511")]
|
||||
MaskType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = "E0511")]
|
||||
VectorArgument {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_ty: Ty<'tcx>,
|
||||
in_elem: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = "E0511")]
|
||||
CannotReturn {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ret_ty: Ty<'tcx>,
|
||||
expected_int_bits: u64,
|
||||
expected_bytes: u64,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = "E0511")]
|
||||
ExpectedElementType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
expected_element: Ty<'tcx>,
|
||||
second_arg: Ty<'tcx>,
|
||||
in_elem: Ty<'tcx>,
|
||||
in_ty: Ty<'tcx>,
|
||||
mutability: ExpectedPointerMutability,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = "E0511")]
|
||||
ThirdArgElementType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
expected_element: Ty<'tcx>,
|
||||
third_arg: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = "E0511")]
|
||||
UnsupportedSymbolOfSize {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
symbol: Symbol,
|
||||
in_ty: Ty<'tcx>,
|
||||
in_elem: Ty<'tcx>,
|
||||
size: u64,
|
||||
ret_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = "E0511")]
|
||||
UnsupportedSymbol {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
symbol: Symbol,
|
||||
in_ty: Ty<'tcx>,
|
||||
in_elem: Ty<'tcx>,
|
||||
ret_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = "E0511")]
|
||||
CastFatPointer {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = "E0511")]
|
||||
ExpectedPointer {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = "E0511")]
|
||||
ExpectedUsize {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = "E0511")]
|
||||
UnsupportedCast {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_ty: Ty<'tcx>,
|
||||
in_elem: Ty<'tcx>,
|
||||
ret_ty: Ty<'tcx>,
|
||||
out_elem: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = "E0511")]
|
||||
UnsupportedOperation {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
in_ty: Ty<'tcx>,
|
||||
in_elem: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = "E0511")]
|
||||
ExpectedVectorElementType {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
expected_element: Ty<'tcx>,
|
||||
vector_type: Ty<'tcx>,
|
||||
},
|
||||
}
|
||||
|
||||
pub enum ExpectedPointerMutability {
|
||||
Mut,
|
||||
Not,
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for ExpectedPointerMutability {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
match self {
|
||||
ExpectedPointerMutability::Mut => DiagnosticArgValue::Str(Cow::Borrowed("*mut")),
|
||||
ExpectedPointerMutability::Not => DiagnosticArgValue::Str(Cow::Borrowed("*_")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::errors;
|
||||
use crate::mir::operand::OperandRef;
|
||||
use crate::traits::*;
|
||||
use rustc_middle::mir;
|
||||
|
@ -44,10 +45,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
|
||||
match err {
|
||||
ErrorHandled::Reported(_) => {
|
||||
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
|
||||
self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span });
|
||||
}
|
||||
ErrorHandled::TooGeneric => {
|
||||
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
|
||||
self.cx
|
||||
.tcx()
|
||||
.sess
|
||||
.diagnostic()
|
||||
.emit_bug(errors::PolymorphicConstantTooGeneric { span: constant.span });
|
||||
}
|
||||
}
|
||||
err
|
||||
|
@ -87,7 +92,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
(llval, c.ty())
|
||||
})
|
||||
.unwrap_or_else(|_| {
|
||||
bx.tcx().sess.span_err(span, "could not evaluate shuffle_indices at compile time");
|
||||
bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span });
|
||||
// We've errored, so we don't have to produce working code.
|
||||
let ty = self.monomorphize(ty);
|
||||
let llty = bx.backend_type(bx.layout_of(ty));
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::place::PlaceRef;
|
||||
use super::FunctionCx;
|
||||
use crate::common::{span_invalid_monomorphization_error, IntPredicate};
|
||||
use crate::common::IntPredicate;
|
||||
use crate::errors;
|
||||
use crate::errors::InvalidMonomorphization;
|
||||
use crate::glue;
|
||||
use crate::meth;
|
||||
use crate::traits::*;
|
||||
|
@ -305,15 +307,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
_ => bug!(),
|
||||
},
|
||||
None => {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic integer type, found `{}`",
|
||||
name, ty
|
||||
),
|
||||
);
|
||||
bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -329,15 +323,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
_ => bug!(),
|
||||
},
|
||||
None => {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic float type, found `{}`",
|
||||
name, arg_tys[0]
|
||||
),
|
||||
);
|
||||
bx.tcx().sess.emit_err(InvalidMonomorphization::BasicFloatType { span, name, ty: arg_tys[0] });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -345,29 +331,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
sym::float_to_int_unchecked => {
|
||||
if float_type_width(arg_tys[0]).is_none() {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `float_to_int_unchecked` \
|
||||
intrinsic: expected basic float type, \
|
||||
found `{}`",
|
||||
arg_tys[0]
|
||||
),
|
||||
);
|
||||
bx.tcx().sess.emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, ty: arg_tys[0] });
|
||||
return;
|
||||
}
|
||||
let Some((_width, signed)) = int_type_width_signed(ret_ty, bx.tcx()) else {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `float_to_int_unchecked` \
|
||||
intrinsic: expected basic integer type, \
|
||||
found `{}`",
|
||||
ret_ty
|
||||
),
|
||||
);
|
||||
bx.tcx().sess.emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, ty: ret_ty });
|
||||
return;
|
||||
};
|
||||
if signed {
|
||||
|
@ -402,7 +370,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
use crate::common::{AtomicRmwBinOp, SynchronizationScope};
|
||||
|
||||
let Some((instruction, ordering)) = atomic.split_once('_') else {
|
||||
bx.sess().fatal("Atomic intrinsic missing memory ordering");
|
||||
bx.sess().emit_fatal(errors::MissingMemoryOrdering);
|
||||
};
|
||||
|
||||
let parse_ordering = |bx: &Bx, s| match s {
|
||||
|
@ -412,25 +380,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
"release" => Release,
|
||||
"acqrel" => AcquireRelease,
|
||||
"seqcst" => SequentiallyConsistent,
|
||||
_ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
|
||||
_ => bx.sess().emit_fatal(errors::UnknownAtomicOrdering),
|
||||
};
|
||||
|
||||
let invalid_monomorphization = |ty| {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic integer type, found `{}`",
|
||||
name, ty
|
||||
),
|
||||
);
|
||||
bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
|
||||
};
|
||||
|
||||
match instruction {
|
||||
"cxchg" | "cxchgweak" => {
|
||||
let Some((success, failure)) = ordering.split_once('_') else {
|
||||
bx.sess().fatal("Atomic compare-exchange intrinsic missing failure memory ordering");
|
||||
bx.sess().emit_fatal(errors::AtomicCompareExchange);
|
||||
};
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
|
||||
|
@ -529,7 +489,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
"min" => AtomicRmwBinOp::AtomicMin,
|
||||
"umax" => AtomicRmwBinOp::AtomicUMax,
|
||||
"umin" => AtomicRmwBinOp::AtomicUMin,
|
||||
_ => bx.sess().fatal("unknown atomic operation"),
|
||||
_ => bx.sess().emit_fatal(errors::UnknownAtomicOperation),
|
||||
};
|
||||
|
||||
let ty = substs.type_at(0);
|
||||
|
|
|
@ -115,7 +115,7 @@ fn is_parent_const_stable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
|||
let local_def_id = def_id.expect_local();
|
||||
let hir_id = tcx.local_def_id_to_hir_id(local_def_id);
|
||||
|
||||
let Some(parent) = tcx.hir().find_parent_node(hir_id) else { return false };
|
||||
let Some(parent) = tcx.hir().opt_parent_id(hir_id) else { return false };
|
||||
let parent_def = tcx.hir().get(parent);
|
||||
|
||||
if !matches!(
|
||||
|
|
|
@ -277,12 +277,12 @@ impl<Node: Idx> Dominators<Node> {
|
|||
}
|
||||
|
||||
pub fn immediate_dominator(&self, node: Node) -> Node {
|
||||
assert!(self.is_reachable(node), "node {:?} is not reachable", node);
|
||||
assert!(self.is_reachable(node), "node {node:?} is not reachable");
|
||||
self.immediate_dominators[node].unwrap()
|
||||
}
|
||||
|
||||
pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
|
||||
assert!(self.is_reachable(node), "node {:?} is not reachable", node);
|
||||
assert!(self.is_reachable(node), "node {node:?} is not reachable");
|
||||
Iter { dominators: self, node: Some(node) }
|
||||
}
|
||||
|
||||
|
|
|
@ -233,10 +233,9 @@ where
|
|||
.map(G::Node::new)
|
||||
.map(|node| match this.start_walk_from(node) {
|
||||
WalkReturn::Complete { scc_index } => scc_index,
|
||||
WalkReturn::Cycle { min_depth } => panic!(
|
||||
"`start_walk_node({:?})` returned cycle with depth {:?}",
|
||||
node, min_depth
|
||||
),
|
||||
WalkReturn::Cycle { min_depth } => {
|
||||
panic!("`start_walk_node({node:?})` returned cycle with depth {min_depth:?}")
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -272,8 +271,7 @@ where
|
|||
NodeState::NotVisited => return None,
|
||||
|
||||
NodeState::InCycleWith { parent } => panic!(
|
||||
"`find_state` returned `InCycleWith({:?})`, which ought to be impossible",
|
||||
parent
|
||||
"`find_state` returned `InCycleWith({parent:?})`, which ought to be impossible"
|
||||
),
|
||||
})
|
||||
}
|
||||
|
@ -369,7 +367,7 @@ where
|
|||
previous_node = previous;
|
||||
}
|
||||
// Only InCycleWith nodes were added to the reverse linked list.
|
||||
other => panic!("Invalid previous link while compressing cycle: {:?}", other),
|
||||
other => panic!("Invalid previous link while compressing cycle: {other:?}"),
|
||||
}
|
||||
|
||||
debug!("find_state: parent_state = {:?}", node_state);
|
||||
|
@ -394,7 +392,7 @@ where
|
|||
// NotVisited can not be part of a cycle since it should
|
||||
// have instead gotten explored.
|
||||
NodeState::NotVisited | NodeState::InCycleWith { .. } => {
|
||||
panic!("invalid parent state: {:?}", node_state)
|
||||
panic!("invalid parent state: {node_state:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ impl<O: ForestObligation> ObligationForest<O> {
|
|||
|
||||
let counter = COUNTER.fetch_add(1, Ordering::AcqRel);
|
||||
|
||||
let file_path = dir.as_ref().join(format!("{:010}_{}.gv", counter, description));
|
||||
let file_path = dir.as_ref().join(format!("{counter:010}_{description}.gv"));
|
||||
|
||||
let mut gv_file = BufWriter::new(File::create(file_path).unwrap());
|
||||
|
||||
|
@ -47,7 +47,7 @@ impl<'a, O: ForestObligation + 'a> dot::Labeller<'a> for &'a ObligationForest<O>
|
|||
}
|
||||
|
||||
fn node_id(&self, index: &Self::Node) -> dot::Id<'_> {
|
||||
dot::Id::new(format!("obligation_{}", index)).unwrap()
|
||||
dot::Id::new(format!("obligation_{index}")).unwrap()
|
||||
}
|
||||
|
||||
fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> {
|
||||
|
|
|
@ -545,7 +545,7 @@ impl SelfProfiler {
|
|||
// length can behave as a source of entropy for heap addresses, when
|
||||
// ASLR is disabled and the heap is otherwise determinic.
|
||||
let pid: u32 = process::id();
|
||||
let filename = format!("{}-{:07}.rustc_profile", crate_name, pid);
|
||||
let filename = format!("{crate_name}-{pid:07}.rustc_profile");
|
||||
let path = output_directory.join(&filename);
|
||||
let profiler =
|
||||
Profiler::with_counter(&path, measureme::counters::Counter::by_name(counter_name)?)?;
|
||||
|
|
|
@ -30,7 +30,7 @@ impl SmallCStr {
|
|||
SmallVec::from_vec(data)
|
||||
};
|
||||
if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
|
||||
panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
|
||||
panic!("The string \"{s}\" cannot be converted into a CStr: {e}");
|
||||
}
|
||||
SmallCStr { data }
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ impl SmallCStr {
|
|||
pub fn new_with_nul(s: &str) -> SmallCStr {
|
||||
let b = s.as_bytes();
|
||||
if let Err(e) = ffi::CStr::from_bytes_with_nul(b) {
|
||||
panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
|
||||
panic!("The string \"{s}\" cannot be converted into a CStr: {e}");
|
||||
}
|
||||
SmallCStr { data: SmallVec::from_slice(s.as_bytes()) }
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ impl<'a> FromIterator<&'a str> for SmallCStr {
|
|||
iter.into_iter().flat_map(|s| s.as_bytes()).copied().collect::<SmallVec<_>>();
|
||||
data.push(0);
|
||||
if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
|
||||
panic!("The iterator {:?} cannot be converted into a CStr: {}", data, e);
|
||||
panic!("The iterator {data:?} cannot be converted into a CStr: {e}");
|
||||
}
|
||||
Self { data }
|
||||
}
|
||||
|
|
|
@ -71,8 +71,7 @@ where
|
|||
// This should return just one element, otherwise it's a bug
|
||||
assert!(
|
||||
filter.next().is_none(),
|
||||
"Collection {:#?} should have just one matching element",
|
||||
self
|
||||
"Collection {self:#?} should have just one matching element"
|
||||
);
|
||||
Some(value)
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
|
|||
Ok(arg) => args.extend(arg),
|
||||
Err(err) => rustc_session::early_error(
|
||||
rustc_session::config::ErrorOutputType::default(),
|
||||
&format!("Failed to load argument file: {}", err),
|
||||
&format!("Failed to load argument file: {err}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ impl fmt::Display for Error {
|
|||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
|
||||
Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path),
|
||||
Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err),
|
||||
Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
|
||||
Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -486,11 +486,8 @@ impl Compilation {
|
|||
|
||||
fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
|
||||
let upper_cased_code = code.to_ascii_uppercase();
|
||||
let normalised = if upper_cased_code.starts_with('E') {
|
||||
upper_cased_code
|
||||
} else {
|
||||
format!("E{0:0>4}", code)
|
||||
};
|
||||
let normalised =
|
||||
if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
|
||||
match registry.try_find_description(&normalised) {
|
||||
Ok(Some(description)) => {
|
||||
let mut is_in_code_block = false;
|
||||
|
@ -513,14 +510,14 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
|
|||
if io::stdout().is_terminal() {
|
||||
show_content_with_pager(&text);
|
||||
} else {
|
||||
print!("{}", text);
|
||||
print!("{text}");
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
early_error(output, &format!("no extended information for {}", code));
|
||||
early_error(output, &format!("no extended information for {code}"));
|
||||
}
|
||||
Err(InvalidErrorCode) => {
|
||||
early_error(output, &format!("{} is not a valid error code", code));
|
||||
early_error(output, &format!("{code} is not a valid error code"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -552,7 +549,7 @@ fn show_content_with_pager(content: &str) {
|
|||
// If pager fails for whatever reason, we should still print the content
|
||||
// to standard output
|
||||
if fallback_to_println {
|
||||
print!("{}", content);
|
||||
print!("{content}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -672,7 +669,7 @@ fn print_crate_info(
|
|||
);
|
||||
let id = rustc_session::output::find_crate_name(sess, attrs, input);
|
||||
if *req == PrintRequest::CrateName {
|
||||
println!("{}", id);
|
||||
println!("{id}");
|
||||
continue;
|
||||
}
|
||||
let crate_types = collect_crate_types(sess, attrs);
|
||||
|
@ -704,7 +701,7 @@ fn print_crate_info(
|
|||
}
|
||||
|
||||
if let Some(value) = value {
|
||||
Some(format!("{}=\"{}\"", name, value))
|
||||
Some(format!("{name}=\"{value}\""))
|
||||
} else {
|
||||
Some(name.to_string())
|
||||
}
|
||||
|
@ -713,7 +710,7 @@ fn print_crate_info(
|
|||
|
||||
cfgs.sort();
|
||||
for cfg in cfgs {
|
||||
println!("{}", cfg);
|
||||
println!("{cfg}");
|
||||
}
|
||||
}
|
||||
CallingConventions => {
|
||||
|
@ -739,7 +736,7 @@ fn print_crate_info(
|
|||
let stable = sess.target.options.supported_split_debuginfo.contains(split);
|
||||
let unstable_ok = sess.unstable_options();
|
||||
if stable || unstable_ok {
|
||||
println!("{}", split);
|
||||
println!("{split}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -776,14 +773,14 @@ pub fn version_at_macro_invocation(
|
|||
) {
|
||||
let verbose = matches.opt_present("verbose");
|
||||
|
||||
println!("{} {}", binary, version);
|
||||
println!("{binary} {version}");
|
||||
|
||||
if verbose {
|
||||
println!("binary: {}", binary);
|
||||
println!("commit-hash: {}", commit_hash);
|
||||
println!("commit-date: {}", commit_date);
|
||||
println!("binary: {binary}");
|
||||
println!("commit-hash: {commit_hash}");
|
||||
println!("commit-date: {commit_date}");
|
||||
println!("host: {}", config::host_triple());
|
||||
println!("release: {}", release);
|
||||
println!("release: {release}");
|
||||
|
||||
let debug_flags = matches.opt_strs("Z");
|
||||
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
|
||||
|
@ -1037,7 +1034,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
|
|||
.map(|&(name, ..)| ('C', name))
|
||||
.chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
|
||||
.find(|&(_, name)| *opt == name.replace('_', "-"))
|
||||
.map(|(flag, _)| format!("{}. Did you mean `-{} {}`?", e, flag, opt)),
|
||||
.map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
|
||||
_ => None,
|
||||
};
|
||||
early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
|
||||
|
@ -1148,7 +1145,7 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
|
|||
} else {
|
||||
result.push(a.to_string());
|
||||
match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
|
||||
Some(s) => result.push(format!("{}=[REDACTED]", s)),
|
||||
Some(s) => result.push(format!("{s}=[REDACTED]")),
|
||||
None => result.push(content),
|
||||
}
|
||||
}
|
||||
|
@ -1246,7 +1243,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
|||
|
||||
let mut xs: Vec<Cow<'static, str>> = vec![
|
||||
"the compiler unexpectedly panicked. this is a bug.".into(),
|
||||
format!("we would appreciate a bug report: {}", bug_report_url).into(),
|
||||
format!("we would appreciate a bug report: {bug_report_url}").into(),
|
||||
format!(
|
||||
"rustc {} running on {}",
|
||||
util::version_str!().unwrap_or("unknown_version"),
|
||||
|
@ -1379,7 +1376,7 @@ pub fn main() -> ! {
|
|||
arg.into_string().unwrap_or_else(|arg| {
|
||||
early_error(
|
||||
ErrorOutputType::default(),
|
||||
&format!("argument {} is not valid Unicode: {:?}", i, arg),
|
||||
&format!("argument {i} is not valid Unicode: {arg:?}"),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -360,7 +360,7 @@ fn get_source(input: &Input, sess: &Session) -> (String, FileName) {
|
|||
|
||||
fn write_or_print(out: &str, ofile: Option<&Path>, sess: &Session) {
|
||||
match ofile {
|
||||
None => print!("{}", out),
|
||||
None => print!("{out}"),
|
||||
Some(p) => {
|
||||
if let Err(e) = std::fs::write(p, out) {
|
||||
sess.emit_fatal(UnprettyDumpFail {
|
||||
|
@ -402,7 +402,7 @@ pub fn print_after_parsing(
|
|||
}
|
||||
AstTree(PpAstTreeMode::Normal) => {
|
||||
debug!("pretty printing AST tree");
|
||||
format!("{:#?}", krate)
|
||||
format!("{krate:#?}")
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -446,7 +446,7 @@ pub fn print_after_hir_lowering<'tcx>(
|
|||
|
||||
AstTree(PpAstTreeMode::Expanded) => {
|
||||
debug!("pretty-printing expanded AST");
|
||||
format!("{:#?}", krate)
|
||||
format!("{krate:#?}")
|
||||
}
|
||||
|
||||
Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| {
|
||||
|
|
|
@ -579,8 +579,7 @@ E0791: include_str!("./error_codes/E0791.md"),
|
|||
// E0300, // unexpanded macro
|
||||
// E0304, // expected signed integer constant
|
||||
// E0305, // expected constant
|
||||
E0313, // lifetime of borrowed pointer outlives lifetime of captured
|
||||
// variable
|
||||
// E0313, // removed: found unreachable
|
||||
// E0314, // closure outlives stack frame
|
||||
// E0315, // cannot invoke closure outside of its lifetime
|
||||
// E0319, // trait impls for defaulted traits allowed just for structs/enums
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
A constant item was initialized with something that is not a constant
|
||||
expression.
|
||||
A non-`const` function was called in a `const` context.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
|
@ -8,26 +7,20 @@ fn create_some() -> Option<u8> {
|
|||
Some(1)
|
||||
}
|
||||
|
||||
const FOO: Option<u8> = create_some(); // error!
|
||||
// error: cannot call non-const fn `create_some` in constants
|
||||
const FOO: Option<u8> = create_some();
|
||||
```
|
||||
|
||||
The only functions that can be called in static or constant expressions are
|
||||
`const` functions, and struct/enum constructors.
|
||||
All functions used in a `const` context (constant or static expression) must
|
||||
be marked `const`.
|
||||
|
||||
To fix this error, you can declare `create_some` as a constant function:
|
||||
|
||||
```
|
||||
const fn create_some() -> Option<u8> { // declared as a const function
|
||||
// declared as a `const` function:
|
||||
const fn create_some() -> Option<u8> {
|
||||
Some(1)
|
||||
}
|
||||
|
||||
const FOO: Option<u8> = create_some(); // ok!
|
||||
|
||||
// These are also working:
|
||||
struct Bar {
|
||||
x: u8,
|
||||
}
|
||||
|
||||
const OTHER_FOO: Option<u8> = Some(1);
|
||||
const BAR: Bar = Bar {x: 1};
|
||||
const FOO: Option<u8> = create_some(); // no error!
|
||||
```
|
||||
|
|
|
@ -11,7 +11,7 @@ struct Aligned(i32);
|
|||
struct Packed(Aligned);
|
||||
```
|
||||
|
||||
Just like you cannot have both `align` and `packed` representation hints on a
|
||||
Just like you cannot have both `align` and `packed` representation hints on the
|
||||
same type, a `packed` type cannot contain another type with the `align`
|
||||
representation hint. However, you can do the opposite:
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#### Note: this error code is no longer emitted by the compiler
|
||||
|
||||
Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler
|
||||
since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow
|
||||
checker for NLL uncovered some bugs in the old borrow checker, which in some
|
||||
|
|
|
@ -157,8 +157,6 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
|
|||
|
||||
codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
|
||||
|
||||
codegen_ssa_native_static_libs = native-static-libs: {$arguments}
|
||||
|
||||
codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
|
||||
|
||||
codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
|
||||
|
@ -194,3 +192,102 @@ codegen_ssa_unknown_archive_kind =
|
|||
Don't know how to build archive of type: {$kind}
|
||||
|
||||
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
|
||||
|
||||
codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
|
||||
.help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
|
||||
|
||||
codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
|
||||
|
||||
codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
|
||||
|
||||
codegen_ssa_erroneous_constant = erroneous constant encountered
|
||||
|
||||
codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
|
||||
|
||||
codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
|
||||
|
||||
codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
|
||||
|
||||
codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
|
||||
|
||||
codegen_ssa_unknown_atomic_operation = unknown atomic operation
|
||||
|
||||
codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type
|
||||
|
||||
codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
|
||||
|
||||
codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric
|
||||
|
||||
codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
|
||||
|
||||
codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
|
||||
|
||||
codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
|
||||
|
||||
codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
|
||||
|
||||
codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
|
||||
|
||||
codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
|
||||
|
||||
codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type
|
||||
|
||||
codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type
|
||||
|
||||
codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
|
||||
|
|
|
@ -172,3 +172,142 @@ infer_msl_unmet_req = because this has an unmet lifetime requirement
|
|||
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
|
||||
infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
|
||||
infer_suggest_add_let_for_letchains = consider adding `let`
|
||||
|
||||
infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
|
||||
.label = lifetime `{$named}` required
|
||||
|
||||
infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
|
||||
.label = lifetime `{$named}` required
|
||||
|
||||
infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
|
||||
|
||||
infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
|
||||
|
||||
infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
|
||||
infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
|
||||
infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`...
|
||||
infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
|
||||
infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
|
||||
infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
|
||||
infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{lifetime_1}`...
|
||||
infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
|
||||
infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
|
||||
infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
|
||||
infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`...
|
||||
infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
|
||||
[true] ...
|
||||
*[false] {""}
|
||||
}`{$ty_or_sig}` must implement `{$trait_path}`
|
||||
|
||||
infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
|
||||
[true] , for some specific lifetime `'{$lifetime}`
|
||||
*[false] {""}
|
||||
}
|
||||
infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
|
||||
[true] , for some specific lifetime `'{$lifetime}`
|
||||
*[false] {""}
|
||||
}
|
||||
infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
|
||||
[true] , for some specific lifetime `'{$lifetime}`
|
||||
*[false] {""}
|
||||
}
|
||||
|
||||
infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
|
||||
.label_satisfy = doesn't satisfy where-clause
|
||||
.label_where = due to a where-clause on `{$def_id}`...
|
||||
.label_dup = implementation of `{$trait_def_id}` is not general enough
|
||||
|
||||
infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
|
||||
.found = found `{$found}`
|
||||
.expected = expected `{$expected}`
|
||||
.expected_found = expected signature `{$expected}`
|
||||
{" "}found signature `{$found}`
|
||||
|
||||
infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
|
||||
infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
|
||||
infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
|
||||
|
||||
infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
|
||||
infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement
|
||||
infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
|
||||
infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
|
||||
|
||||
infer_but_calling_introduces = {$has_param_name ->
|
||||
[true] `{$param_name}`
|
||||
*[false] `fn` parameter
|
||||
} has {$lifetime_kind ->
|
||||
[named] lifetime `{lifetime}`
|
||||
*[anon] an anonymous lifetime `'_`
|
||||
} but calling `{assoc_item}` introduces an implicit `'static` lifetime requirement
|
||||
.label1 = {$has_lifetime ->
|
||||
[named] lifetime `{lifetime}`
|
||||
*[anon] an anonymous lifetime `'_`
|
||||
}
|
||||
.label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
|
||||
[named] `impl` of `{$impl_path}`
|
||||
*[anon] inherent `impl`
|
||||
}
|
||||
|
||||
infer_but_needs_to_satisfy = {$has_param_name ->
|
||||
[true] `{$param_name}`
|
||||
*[false] `fn` parameter
|
||||
} has {$has_lifetime ->
|
||||
[named] lifetime `{lifetime}`
|
||||
*[anon] an anonymous lifetime `'_`
|
||||
} but it needs to satisfy a `'static` lifetime requirement
|
||||
.influencer = this data with {$has_lifetime ->
|
||||
[named] lifetime `{lifetime}`
|
||||
*[anon] an anonymous lifetime `'_`
|
||||
}...
|
||||
.require = {$spans_empty ->
|
||||
*[true] ...is used and required to live as long as `'static` here
|
||||
[false] ...and is required to live as long as `'static` here
|
||||
}
|
||||
.used_here = ...is used here...
|
||||
.introduced_by_bound = 'static` lifetime requirement introduced by this bound
|
||||
|
||||
infer_more_targeted = {$has_param_name ->
|
||||
[true] `{$param_name}`
|
||||
*[false] `fn` parameter
|
||||
} has {$has_lifetime ->
|
||||
[named] lifetime `{lifetime}`
|
||||
*[anon] an anonymous lifetime `'_`
|
||||
} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
|
||||
|
||||
infer_ril_introduced_here = `'static` requirement introduced here
|
||||
infer_ril_introduced_by = requirement introduced by this return type
|
||||
infer_ril_because_of = because of this returned expression
|
||||
infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
|
||||
|
|
|
@ -85,6 +85,7 @@ session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float lite
|
|||
.help = valid suffixes are `f32` and `f64`
|
||||
|
||||
session_int_literal_too_large = integer literal is too large
|
||||
.note = value exceeds limit of `{$limit}`
|
||||
|
||||
session_invalid_int_literal_width = invalid width `{$width}` for integer literal
|
||||
.help = valid widths are 8, 16, 32, 64 and 128
|
||||
|
|
|
@ -17,6 +17,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
|||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||
rustc_type_ir = { path = "../rustc_type_ir" }
|
||||
unicode-width = "0.1.4"
|
||||
termcolor = "1.0"
|
||||
annotate-snippets = "0.9"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::diagnostic::IntoDiagnosticArg;
|
||||
use crate::{
|
||||
Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed,
|
||||
SubdiagnosticMessage,
|
||||
ExplicitBug, SubdiagnosticMessage,
|
||||
};
|
||||
use crate::{Handler, Level, MultiSpan, StashKey};
|
||||
use rustc_lint_defs::Applicability;
|
||||
|
@ -12,6 +12,7 @@ use std::borrow::Cow;
|
|||
use std::fmt::{self, Debug};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::panic;
|
||||
use std::thread::panicking;
|
||||
|
||||
/// Trait implemented by error types. This should not be implemented manually. Instead, use
|
||||
|
@ -308,6 +309,58 @@ impl EmissionGuarantee for Noted {
|
|||
}
|
||||
}
|
||||
|
||||
/// Marker type which enables implementation of `create_bug` and `emit_bug` functions for
|
||||
/// bug struct diagnostics.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Bug;
|
||||
|
||||
impl<'a> DiagnosticBuilder<'a, Bug> {
|
||||
/// Convenience function for internal use, clients should use one of the
|
||||
/// `struct_*` methods on [`Handler`].
|
||||
#[track_caller]
|
||||
pub(crate) fn new_bug(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
|
||||
let diagnostic = Diagnostic::new_with_code(Level::Bug, None, message);
|
||||
Self::new_diagnostic_bug(handler, diagnostic)
|
||||
}
|
||||
|
||||
/// Creates a new `DiagnosticBuilder` with an already constructed
|
||||
/// diagnostic.
|
||||
pub(crate) fn new_diagnostic_bug(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
|
||||
debug!("Created new diagnostic bug");
|
||||
Self {
|
||||
inner: DiagnosticBuilderInner {
|
||||
state: DiagnosticBuilderState::Emittable(handler),
|
||||
diagnostic: Box::new(diagnostic),
|
||||
},
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EmissionGuarantee for Bug {
|
||||
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
|
||||
match db.inner.state {
|
||||
// First `.emit()` call, the `&Handler` is still available.
|
||||
DiagnosticBuilderState::Emittable(handler) => {
|
||||
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
|
||||
|
||||
handler.emit_diagnostic(&mut db.inner.diagnostic);
|
||||
}
|
||||
// `.emit()` was previously called, disallowed from repeating it.
|
||||
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
|
||||
}
|
||||
// Then panic. No need to return the marker type.
|
||||
panic::panic_any(ExplicitBug);
|
||||
}
|
||||
|
||||
fn make_diagnostic_builder(
|
||||
handler: &Handler,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
) -> DiagnosticBuilder<'_, Self> {
|
||||
DiagnosticBuilder::new_bug(handler, msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DiagnosticBuilder<'a, !> {
|
||||
/// Convenience function for internal use, clients should use one of the
|
||||
/// `struct_*` methods on [`Handler`].
|
||||
|
|
|
@ -9,6 +9,7 @@ use rustc_span::edition::Edition;
|
|||
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
|
||||
use rustc_target::abi::TargetDataLayoutErrors;
|
||||
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
|
||||
use rustc_type_ir as type_ir;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::num::ParseIntError;
|
||||
|
@ -170,6 +171,12 @@ impl IntoDiagnosticArg for ast::token::TokenKind {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for type_ir::FloatTy {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Borrowed(self.name_str()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for Level {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Borrowed(match self {
|
||||
|
|
|
@ -978,6 +978,7 @@ impl Handler {
|
|||
self.inner.borrow_mut().span_bug(span, msg)
|
||||
}
|
||||
|
||||
/// For documentation on this, see `Session::delay_span_bug`.
|
||||
#[track_caller]
|
||||
pub fn delay_span_bug(
|
||||
&self,
|
||||
|
@ -1132,6 +1133,20 @@ impl Handler {
|
|||
self.create_fatal(fatal).emit()
|
||||
}
|
||||
|
||||
pub fn create_bug<'a>(
|
||||
&'a self,
|
||||
bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>,
|
||||
) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> {
|
||||
bug.into_diagnostic(self)
|
||||
}
|
||||
|
||||
pub fn emit_bug<'a>(
|
||||
&'a self,
|
||||
bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>,
|
||||
) -> diagnostic_builder::Bug {
|
||||
self.create_bug(bug).emit()
|
||||
}
|
||||
|
||||
fn emit_diag_at_span(
|
||||
&self,
|
||||
mut diag: Diagnostic,
|
||||
|
@ -1529,6 +1544,7 @@ impl HandlerInner {
|
|||
self.emit_diagnostic(diag.set_span(sp));
|
||||
}
|
||||
|
||||
/// For documentation on this, see `Session::delay_span_bug`.
|
||||
#[track_caller]
|
||||
fn delay_span_bug(
|
||||
&mut self,
|
||||
|
|
|
@ -114,6 +114,12 @@ impl BestFailure {
|
|||
}
|
||||
|
||||
impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
|
||||
type Failure = (Token, usize, &'static str);
|
||||
|
||||
fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure {
|
||||
(tok, position, msg)
|
||||
}
|
||||
|
||||
fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) {
|
||||
if self.remaining_matcher.is_none()
|
||||
|| (parser.has_no_remaining_items_for_step() && *matcher != MatcherLoc::Eof)
|
||||
|
@ -122,7 +128,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
|
|||
}
|
||||
}
|
||||
|
||||
fn after_arm(&mut self, result: &NamedParseResult) {
|
||||
fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
|
||||
match result {
|
||||
Success(_) => {
|
||||
// Nonterminal parser recovery might turn failed matches into successful ones,
|
||||
|
@ -132,7 +138,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
|
|||
"should not collect detailed info for successful macro match",
|
||||
);
|
||||
}
|
||||
Failure(token, approx_position, msg) => {
|
||||
Failure((token, approx_position, msg)) => {
|
||||
debug!(?token, ?msg, "a new failure of an arm");
|
||||
|
||||
if self
|
||||
|
@ -175,6 +181,21 @@ impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Currently used by macro_rules! compilation to extract a little information from the `Failure` case.
|
||||
pub struct FailureForwarder;
|
||||
|
||||
impl<'matcher> Tracker<'matcher> for FailureForwarder {
|
||||
type Failure = (Token, usize, &'static str);
|
||||
|
||||
fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure {
|
||||
(tok, position, msg)
|
||||
}
|
||||
|
||||
fn description() -> &'static str {
|
||||
"failure-forwarder"
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn emit_frag_parse_err(
|
||||
mut e: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed>,
|
||||
parser: &Parser<'_>,
|
||||
|
|
|
@ -305,13 +305,13 @@ enum EofMatcherPositions {
|
|||
}
|
||||
|
||||
/// Represents the possible results of an attempted parse.
|
||||
pub(crate) enum ParseResult<T> {
|
||||
pub(crate) enum ParseResult<T, F> {
|
||||
/// Parsed successfully.
|
||||
Success(T),
|
||||
/// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected
|
||||
/// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
|
||||
/// The usize is the approximate position of the token in the input token stream.
|
||||
Failure(Token, usize, &'static str),
|
||||
Failure(F),
|
||||
/// Fatal error (malformed macro?). Abort compilation.
|
||||
Error(rustc_span::Span, String),
|
||||
ErrorReported(ErrorGuaranteed),
|
||||
|
@ -320,7 +320,7 @@ pub(crate) enum ParseResult<T> {
|
|||
/// A `ParseResult` where the `Success` variant contains a mapping of
|
||||
/// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping
|
||||
/// of metavars to the token trees they bind to.
|
||||
pub(crate) type NamedParseResult = ParseResult<NamedMatches>;
|
||||
pub(crate) type NamedParseResult<F> = ParseResult<NamedMatches, F>;
|
||||
|
||||
/// Contains a mapping of `MacroRulesNormalizedIdent`s to `NamedMatch`es.
|
||||
/// This represents the mapping of metavars to the token trees they bind to.
|
||||
|
@ -458,7 +458,7 @@ impl TtParser {
|
|||
token: &Token,
|
||||
approx_position: usize,
|
||||
track: &mut T,
|
||||
) -> Option<NamedParseResult> {
|
||||
) -> Option<NamedParseResult<T::Failure>> {
|
||||
// Matcher positions that would be valid if the macro invocation was over now. Only
|
||||
// modified if `token == Eof`.
|
||||
let mut eof_mps = EofMatcherPositions::None;
|
||||
|
@ -595,14 +595,14 @@ impl TtParser {
|
|||
EofMatcherPositions::Multiple => {
|
||||
Error(token.span, "ambiguity: multiple successful parses".to_string())
|
||||
}
|
||||
EofMatcherPositions::None => Failure(
|
||||
EofMatcherPositions::None => Failure(T::build_failure(
|
||||
Token::new(
|
||||
token::Eof,
|
||||
if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() },
|
||||
),
|
||||
approx_position,
|
||||
"missing tokens in macro arguments",
|
||||
),
|
||||
)),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
@ -615,7 +615,7 @@ impl TtParser {
|
|||
parser: &mut Cow<'_, Parser<'_>>,
|
||||
matcher: &'matcher [MatcherLoc],
|
||||
track: &mut T,
|
||||
) -> NamedParseResult {
|
||||
) -> NamedParseResult<T::Failure> {
|
||||
// A queue of possible matcher positions. We initialize it with the matcher position in
|
||||
// which the "dot" is before the first token of the first token tree in `matcher`.
|
||||
// `parse_tt_inner` then processes all of these possible matcher positions and produces
|
||||
|
@ -648,11 +648,11 @@ impl TtParser {
|
|||
(0, 0) => {
|
||||
// There are no possible next positions AND we aren't waiting for the black-box
|
||||
// parser: syntax error.
|
||||
return Failure(
|
||||
return Failure(T::build_failure(
|
||||
parser.token.clone(),
|
||||
parser.approx_token_stream_pos(),
|
||||
"no rules expected this token in macro call",
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
(_, 0) => {
|
||||
|
@ -711,11 +711,11 @@ impl TtParser {
|
|||
}
|
||||
}
|
||||
|
||||
fn ambiguity_error(
|
||||
fn ambiguity_error<F>(
|
||||
&self,
|
||||
matcher: &[MatcherLoc],
|
||||
token_span: rustc_span::Span,
|
||||
) -> NamedParseResult {
|
||||
) -> NamedParseResult<F> {
|
||||
let nts = self
|
||||
.bb_mps
|
||||
.iter()
|
||||
|
@ -741,11 +741,11 @@ impl TtParser {
|
|||
)
|
||||
}
|
||||
|
||||
fn nameize<I: Iterator<Item = NamedMatch>>(
|
||||
fn nameize<I: Iterator<Item = NamedMatch>, F>(
|
||||
&self,
|
||||
matcher: &[MatcherLoc],
|
||||
mut res: I,
|
||||
) -> NamedParseResult {
|
||||
) -> NamedParseResult<F> {
|
||||
// Make that each metavar has _exactly one_ binding. If so, insert the binding into the
|
||||
// `NamedParseResult`. Otherwise, it's an error.
|
||||
let mut ret_val = FxHashMap::default();
|
||||
|
|
|
@ -141,31 +141,40 @@ fn trace_macros_note(cx_expansions: &mut FxIndexMap<Span, Vec<String>>, sp: Span
|
|||
}
|
||||
|
||||
pub(super) trait Tracker<'matcher> {
|
||||
/// The contents of `ParseResult::Failure`.
|
||||
type Failure;
|
||||
|
||||
/// Arm failed to match. If the token is `token::Eof`, it indicates an unexpected
|
||||
/// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
|
||||
/// The usize is the approximate position of the token in the input token stream.
|
||||
fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure;
|
||||
|
||||
/// This is called before trying to match next MatcherLoc on the current token.
|
||||
fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc);
|
||||
fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {}
|
||||
|
||||
/// This is called after an arm has been parsed, either successfully or unsuccessfully. When this is called,
|
||||
/// `before_match_loc` was called at least once (with a `MatcherLoc::Eof`).
|
||||
fn after_arm(&mut self, result: &NamedParseResult);
|
||||
fn after_arm(&mut self, _result: &NamedParseResult<Self::Failure>) {}
|
||||
|
||||
/// For tracing.
|
||||
fn description() -> &'static str;
|
||||
|
||||
fn recovery() -> Recovery;
|
||||
fn recovery() -> Recovery {
|
||||
Recovery::Forbidden
|
||||
}
|
||||
}
|
||||
|
||||
/// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization.
|
||||
pub(super) struct NoopTracker;
|
||||
|
||||
impl<'matcher> Tracker<'matcher> for NoopTracker {
|
||||
fn before_match_loc(&mut self, _: &TtParser, _: &'matcher MatcherLoc) {}
|
||||
fn after_arm(&mut self, _: &NamedParseResult) {}
|
||||
type Failure = ();
|
||||
|
||||
fn build_failure(_tok: Token, _position: usize, _msg: &'static str) -> Self::Failure {}
|
||||
|
||||
fn description() -> &'static str {
|
||||
"none"
|
||||
}
|
||||
fn recovery() -> Recovery {
|
||||
Recovery::Forbidden
|
||||
}
|
||||
}
|
||||
|
||||
/// Expands the rules based macro defined by `lhses` and `rhses` for a given
|
||||
|
@ -326,8 +335,8 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
|
|||
|
||||
return Ok((i, named_matches));
|
||||
}
|
||||
Failure(_, reached_position, _) => {
|
||||
trace!(%reached_position, "Failed to match arm, trying the next one");
|
||||
Failure(_) => {
|
||||
trace!("Failed to match arm, trying the next one");
|
||||
// Try the next arm.
|
||||
}
|
||||
Error(_, _) => {
|
||||
|
@ -381,11 +390,13 @@ pub fn compile_declarative_macro(
|
|||
let rhs_nm = Ident::new(sym::rhs, def.span);
|
||||
let tt_spec = Some(NonterminalKind::TT);
|
||||
|
||||
// Parse the macro_rules! invocation
|
||||
let (macro_rules, body) = match &def.kind {
|
||||
ast::ItemKind::MacroDef(def) => (def.macro_rules, def.body.tokens.clone()),
|
||||
let macro_def = match &def.kind {
|
||||
ast::ItemKind::MacroDef(def) => def,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let macro_rules = macro_def.macro_rules;
|
||||
|
||||
// Parse the macro_rules! invocation
|
||||
|
||||
// The pattern that macro_rules matches.
|
||||
// The grammar for macro_rules! is:
|
||||
|
@ -426,13 +437,32 @@ pub fn compile_declarative_macro(
|
|||
// Convert it into `MatcherLoc` form.
|
||||
let argument_gram = mbe::macro_parser::compute_locs(&argument_gram);
|
||||
|
||||
let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS);
|
||||
let create_parser = || {
|
||||
let body = macro_def.body.tokens.clone();
|
||||
Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS)
|
||||
};
|
||||
|
||||
let parser = create_parser();
|
||||
let mut tt_parser =
|
||||
TtParser::new(Ident::with_dummy_span(if macro_rules { kw::MacroRules } else { kw::Macro }));
|
||||
let argument_map =
|
||||
match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) {
|
||||
Success(m) => m,
|
||||
Failure(token, _, msg) => {
|
||||
Failure(()) => {
|
||||
// The fast `NoopTracker` doesn't have any info on failure, so we need to retry it with another one
|
||||
// that gives us the information we need.
|
||||
// For this we need to reclone the macro body as the previous parser consumed it.
|
||||
let retry_parser = create_parser();
|
||||
|
||||
let parse_result = tt_parser.parse_tt(
|
||||
&mut Cow::Owned(retry_parser),
|
||||
&argument_gram,
|
||||
&mut diagnostics::FailureForwarder,
|
||||
);
|
||||
let Failure((token, _, msg)) = parse_result else {
|
||||
unreachable!("matcher returned something other than Failure after retry");
|
||||
};
|
||||
|
||||
let s = parse_failure_msg(&token);
|
||||
let sp = token.span.substitute_dummy(def.span);
|
||||
let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s);
|
||||
|
|
|
@ -70,7 +70,7 @@ impl std::fmt::Debug for AttributeGate {
|
|||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
Self::Gated(ref stab, name, expl, _) => {
|
||||
write!(fmt, "Gated({:?}, {}, {})", stab, name, expl)
|
||||
write!(fmt, "Gated({stab:?}, {name}, {expl})")
|
||||
}
|
||||
Self::Ungated => write!(fmt, "Ungated"),
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
|
|||
.find(|t| t.name == feature);
|
||||
match found {
|
||||
Some(found) => found.issue,
|
||||
None => panic!("feature `{}` is not declared anywhere", feature),
|
||||
None => panic!("feature `{feature}` is not declared anywhere"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -516,7 +516,7 @@ impl<'a> LabelText<'a> {
|
|||
match *self {
|
||||
LabelStr(ref s) => format!("\"{}\"", s.escape_default()),
|
||||
EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(s)),
|
||||
HtmlStr(ref s) => format!("<{}>", s),
|
||||
HtmlStr(ref s) => format!("<{s}>"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,7 +622,7 @@ where
|
|||
if let Some(fontname) = options.iter().find_map(|option| {
|
||||
if let RenderOption::Fontname(fontname) = option { Some(fontname) } else { None }
|
||||
}) {
|
||||
font = format!(r#"fontname="{}""#, fontname);
|
||||
font = format!(r#"fontname="{fontname}""#);
|
||||
graph_attrs.push(&font[..]);
|
||||
content_attrs.push(&font[..]);
|
||||
}
|
||||
|
@ -635,8 +635,8 @@ where
|
|||
if !(graph_attrs.is_empty() && content_attrs.is_empty()) {
|
||||
writeln!(w, r#" graph[{}];"#, graph_attrs.join(" "))?;
|
||||
let content_attrs_str = content_attrs.join(" ");
|
||||
writeln!(w, r#" node[{}];"#, content_attrs_str)?;
|
||||
writeln!(w, r#" edge[{}];"#, content_attrs_str)?;
|
||||
writeln!(w, r#" node[{content_attrs_str}];"#)?;
|
||||
writeln!(w, r#" edge[{content_attrs_str}];"#)?;
|
||||
}
|
||||
|
||||
let mut text = Vec::new();
|
||||
|
@ -649,7 +649,7 @@ where
|
|||
write!(text, "{}", id.as_slice()).unwrap();
|
||||
|
||||
if !options.contains(&RenderOption::NoNodeLabels) {
|
||||
write!(text, "[label={}]", escaped).unwrap();
|
||||
write!(text, "[label={escaped}]").unwrap();
|
||||
}
|
||||
|
||||
let style = g.node_style(n);
|
||||
|
@ -678,7 +678,7 @@ where
|
|||
write!(text, "{} -> {}", source_id.as_slice(), target_id.as_slice()).unwrap();
|
||||
|
||||
if !options.contains(&RenderOption::NoEdgeLabels) {
|
||||
write!(text, "[label={}]", escaped_label).unwrap();
|
||||
write!(text, "[label={escaped_label}]").unwrap();
|
||||
}
|
||||
|
||||
let style = g.edge_style(e);
|
||||
|
|
|
@ -597,8 +597,7 @@ impl<Id> Res<Id> {
|
|||
where
|
||||
Id: Debug,
|
||||
{
|
||||
self.opt_def_id()
|
||||
.unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {:?}", self))
|
||||
self.opt_def_id().unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {self:?}"))
|
||||
}
|
||||
|
||||
/// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
|
||||
|
|
|
@ -53,9 +53,8 @@ impl DefPathTable {
|
|||
//
|
||||
// See the documentation for DefPathHash for more information.
|
||||
panic!(
|
||||
"found DefPathHash collision between {:?} and {:?}. \
|
||||
Compilation cannot continue.",
|
||||
def_path1, def_path2
|
||||
"found DefPathHash collision between {def_path1:?} and {def_path2:?}. \
|
||||
Compilation cannot continue."
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -224,7 +223,7 @@ impl DefPath {
|
|||
let mut s = String::with_capacity(self.data.len() * 16);
|
||||
|
||||
for component in &self.data {
|
||||
write!(s, "::{}", component).unwrap();
|
||||
write!(s, "::{component}").unwrap();
|
||||
}
|
||||
|
||||
s
|
||||
|
@ -240,7 +239,7 @@ impl DefPath {
|
|||
for component in &self.data {
|
||||
s.extend(opt_delimiter);
|
||||
opt_delimiter = Some('-');
|
||||
write!(s, "{}", component).unwrap();
|
||||
write!(s, "{component}").unwrap();
|
||||
}
|
||||
|
||||
s
|
||||
|
@ -433,7 +432,7 @@ impl fmt::Display for DefPathData {
|
|||
match self.name() {
|
||||
DefPathDataName::Named(name) => f.write_str(name.as_str()),
|
||||
// FIXME(#70334): this will generate legacy {{closure}}, {{impl}}, etc
|
||||
DefPathDataName::Anon { namespace } => write!(f, "{{{{{}}}}}", namespace),
|
||||
DefPathDataName::Anon { namespace } => write!(f, "{{{{{namespace}}}}}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3460,7 +3460,7 @@ impl<'hir> Node<'hir> {
|
|||
/// ```ignore (illustrative)
|
||||
/// ctor
|
||||
/// .ctor_hir_id()
|
||||
/// .and_then(|ctor_id| tcx.hir().find(tcx.hir().get_parent_node(ctor_id)))
|
||||
/// .and_then(|ctor_id| tcx.hir().find_parent(ctor_id))
|
||||
/// .and_then(|parent| parent.ident())
|
||||
/// ```
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
|
|
|
@ -119,7 +119,7 @@ impl HirId {
|
|||
|
||||
impl fmt::Display for HirId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
write!(f, "{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -682,7 +682,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
|
||||
|
||||
debug!(?poly_trait_ref, ?assoc_bindings);
|
||||
bounds.trait_bounds.push((poly_trait_ref, span, constness));
|
||||
bounds.push_trait_bound(tcx, poly_trait_ref, span, constness);
|
||||
|
||||
let mut dup_bindings = FxHashMap::default();
|
||||
for binding in &assoc_bindings {
|
||||
|
@ -853,18 +853,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
|
||||
/// Sets `implicitly_sized` to true on `Bounds` if necessary
|
||||
pub(crate) fn add_implicitly_sized<'hir>(
|
||||
pub(crate) fn add_implicitly_sized(
|
||||
&self,
|
||||
bounds: &mut Bounds<'hir>,
|
||||
ast_bounds: &'hir [hir::GenericBound<'hir>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'hir [hir::WherePredicate<'hir>])>,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
span: Span,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
|
||||
// Try to find an unbound in bounds.
|
||||
let mut unbound = None;
|
||||
let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| {
|
||||
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
|
||||
for ab in ast_bounds {
|
||||
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
|
||||
if unbound.is_none() {
|
||||
|
@ -912,7 +913,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// No lang item for `Sized`, so we can't add it as a bound.
|
||||
return;
|
||||
}
|
||||
bounds.implicitly_sized = Some(span);
|
||||
bounds.push_sized(tcx, self_ty, span);
|
||||
}
|
||||
|
||||
/// This helper takes a *converted* parameter type (`param_ty`)
|
||||
|
@ -963,10 +964,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
hir::GenericBound::Outlives(lifetime) => {
|
||||
let region = self.ast_region_to_region(lifetime, None);
|
||||
bounds.region_bounds.push((
|
||||
ty::Binder::bind_with_vars(region, bound_vars),
|
||||
bounds.push_region_bound(
|
||||
self.tcx(),
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::OutlivesPredicate(param_ty, region),
|
||||
bound_vars,
|
||||
),
|
||||
lifetime.ident.span,
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1199,17 +1204,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
(_, _) => {
|
||||
let got = if let Some(_) = term.ty() { "type" } else { "constant" };
|
||||
let expected = def_kind.descr(assoc_item_def_id);
|
||||
let reported = tcx
|
||||
.sess
|
||||
.struct_span_err(
|
||||
let mut err = tcx.sess.struct_span_err(
|
||||
binding.span,
|
||||
&format!("expected {expected} bound, found {got}"),
|
||||
);
|
||||
err.span_note(
|
||||
tcx.def_span(assoc_item_def_id),
|
||||
&format!("{expected} defined here"),
|
||||
);
|
||||
|
||||
if let hir::def::DefKind::AssocConst = def_kind
|
||||
&& let Some(t) = term.ty() && (t.is_enum() || t.references_error())
|
||||
&& tcx.features().associated_const_equality {
|
||||
err.span_suggestion(
|
||||
binding.span,
|
||||
&format!("expected {expected} bound, found {got}"),
|
||||
)
|
||||
.span_note(
|
||||
tcx.def_span(assoc_item_def_id),
|
||||
&format!("{expected} defined here"),
|
||||
)
|
||||
.emit();
|
||||
"if equating a const, try wrapping with braces",
|
||||
format!("{} = {{ const }}", binding.item_name),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
let reported = err.emit();
|
||||
term = match def_kind {
|
||||
hir::def::DefKind::AssocTy => {
|
||||
tcx.ty_error_with_guaranteed(reported).into()
|
||||
|
@ -1225,13 +1239,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
};
|
||||
}
|
||||
}
|
||||
bounds.projection_bounds.push((
|
||||
projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
term: term,
|
||||
}),
|
||||
bounds.push_projection_bound(
|
||||
tcx,
|
||||
projection_ty
|
||||
.map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }),
|
||||
binding.span,
|
||||
));
|
||||
);
|
||||
}
|
||||
ConvertedBindingKind::Constraint(ast_bounds) => {
|
||||
// "Desugar" a constraint like `T: Iterator<Item: Debug>` to
|
||||
|
@ -1260,7 +1273,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
fn conv_object_ty_poly_trait_ref(
|
||||
&self,
|
||||
span: Span,
|
||||
trait_bounds: &[hir::PolyTraitRef<'_>],
|
||||
hir_trait_bounds: &[hir::PolyTraitRef<'_>],
|
||||
lifetime: &hir::Lifetime,
|
||||
borrowed: bool,
|
||||
representation: DynKind,
|
||||
|
@ -1270,7 +1283,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let mut bounds = Bounds::default();
|
||||
let mut potential_assoc_types = Vec::new();
|
||||
let dummy_self = self.tcx().types.trait_object_dummy_self;
|
||||
for trait_bound in trait_bounds.iter().rev() {
|
||||
for trait_bound in hir_trait_bounds.iter().rev() {
|
||||
if let GenericArgCountResult {
|
||||
correct:
|
||||
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
|
||||
|
@ -1287,10 +1300,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
}
|
||||
|
||||
let mut trait_bounds = vec![];
|
||||
let mut projection_bounds = vec![];
|
||||
for (pred, span) in bounds.predicates() {
|
||||
let bound_pred = pred.kind();
|
||||
match bound_pred.skip_binder() {
|
||||
ty::PredicateKind::Clause(clause) => match clause {
|
||||
ty::Clause::Trait(trait_pred) => {
|
||||
assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
|
||||
trait_bounds.push((
|
||||
bound_pred.rebind(trait_pred.trait_ref),
|
||||
span,
|
||||
trait_pred.constness,
|
||||
));
|
||||
}
|
||||
ty::Clause::Projection(proj) => {
|
||||
projection_bounds.push((bound_pred.rebind(proj), span));
|
||||
}
|
||||
ty::Clause::TypeOutlives(_) => {
|
||||
// Do nothing, we deal with regions separately
|
||||
}
|
||||
ty::Clause::RegionOutlives(_) => bug!(),
|
||||
},
|
||||
ty::PredicateKind::WellFormed(_)
|
||||
| ty::PredicateKind::ObjectSafe(_)
|
||||
| ty::PredicateKind::ClosureKind(_, _, _)
|
||||
| ty::PredicateKind::Subtype(_)
|
||||
| ty::PredicateKind::Coerce(_)
|
||||
| ty::PredicateKind::ConstEvaluatable(_)
|
||||
| ty::PredicateKind::ConstEquate(_, _)
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(_)
|
||||
| ty::PredicateKind::Ambiguous => bug!(),
|
||||
}
|
||||
}
|
||||
|
||||
// Expand trait aliases recursively and check that only one regular (non-auto) trait
|
||||
// is used and no 'maybe' bounds are used.
|
||||
let expanded_traits =
|
||||
traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b)));
|
||||
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b)));
|
||||
|
||||
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
|
||||
.filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
|
||||
.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
|
||||
|
@ -1327,8 +1375,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
|
||||
if regular_traits.is_empty() && auto_traits.is_empty() {
|
||||
let trait_alias_span = bounds
|
||||
.trait_bounds
|
||||
let trait_alias_span = trait_bounds
|
||||
.iter()
|
||||
.map(|&(trait_ref, _, _)| trait_ref.def_id())
|
||||
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
|
||||
|
@ -1359,8 +1406,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// Use a `BTreeSet` to keep output in a more consistent order.
|
||||
let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
|
||||
|
||||
let regular_traits_refs_spans = bounds
|
||||
.trait_bounds
|
||||
let regular_traits_refs_spans = trait_bounds
|
||||
.into_iter()
|
||||
.filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
|
||||
|
||||
|
@ -1414,7 +1460,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// the discussion in #56288 for alternatives.
|
||||
if !references_self {
|
||||
// Include projections defined on supertraits.
|
||||
bounds.projection_bounds.push((pred, span));
|
||||
projection_bounds.push((pred, span));
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
@ -1422,7 +1468,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
}
|
||||
|
||||
for (projection_bound, _) in &bounds.projection_bounds {
|
||||
for (projection_bound, _) in &projection_bounds {
|
||||
for def_ids in associated_types.values_mut() {
|
||||
def_ids.remove(&projection_bound.projection_def_id());
|
||||
}
|
||||
|
@ -1431,7 +1477,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self.complain_about_missing_associated_types(
|
||||
associated_types,
|
||||
potential_assoc_types,
|
||||
trait_bounds,
|
||||
hir_trait_bounds,
|
||||
);
|
||||
|
||||
// De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
|
||||
|
@ -1473,7 +1519,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let substs = tcx.intern_substs(&substs[..]);
|
||||
|
||||
let span = i.bottom().1;
|
||||
let empty_generic_args = trait_bounds.iter().any(|hir_bound| {
|
||||
let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
|
||||
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
|
||||
&& hir_bound.span.contains(span)
|
||||
});
|
||||
|
@ -1505,7 +1551,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
})
|
||||
});
|
||||
|
||||
let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
|
||||
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
||||
bound.map_bound(|mut b| {
|
||||
assert_eq!(b.projection_ty.self_ty(), dummy_self);
|
||||
|
||||
|
@ -2936,7 +2982,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
|
||||
hir.get(fn_hir_id) else { return None };
|
||||
let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
|
||||
hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") };
|
||||
hir.get_parent(fn_hir_id) else { bug!("ImplItem should have Impl parent") };
|
||||
|
||||
let trait_ref = self.instantiate_mono_trait_ref(
|
||||
i.of_trait.as_ref()?,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Bounds are restrictions applied to some types after they've been converted into the
|
||||
//! `ty` form from the HIR.
|
||||
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -15,73 +16,53 @@ use rustc_span::Span;
|
|||
/// ^^^^^^^^^ bounding the type parameter `T`
|
||||
///
|
||||
/// impl dyn Bar + Baz
|
||||
/// ^^^^^^^^^ bounding the forgotten dynamic type
|
||||
/// ^^^^^^^^^ bounding the type-erased dynamic type
|
||||
/// ```
|
||||
///
|
||||
/// Our representation is a bit mixed here -- in some cases, we
|
||||
/// include the self type (e.g., `trait_bounds`) but in others we do not
|
||||
#[derive(Default, PartialEq, Eq, Clone, Debug)]
|
||||
pub struct Bounds<'tcx> {
|
||||
/// A list of region bounds on the (implicit) self type. So if you
|
||||
/// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
|
||||
/// the `T` is not explicitly included).
|
||||
pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>,
|
||||
|
||||
/// A list of trait bounds. So if you had `T: Debug` this would be
|
||||
/// `T: Debug`. Note that the self-type is explicit here.
|
||||
pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>,
|
||||
|
||||
/// A list of projection equality bounds. So if you had `T:
|
||||
/// Iterator<Item = u32>` this would include `<T as
|
||||
/// Iterator>::Item => u32`. Note that the self-type is explicit
|
||||
/// here.
|
||||
pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
|
||||
|
||||
/// `Some` if there is *no* `?Sized` predicate. The `span`
|
||||
/// is the location in the source of the `T` declaration which can
|
||||
/// be cited as the source of the `T: Sized` requirement.
|
||||
pub implicitly_sized: Option<Span>,
|
||||
pub predicates: Vec<(ty::Predicate<'tcx>, Span)>,
|
||||
}
|
||||
|
||||
impl<'tcx> Bounds<'tcx> {
|
||||
/// Converts a bounds list into a flat set of predicates (like
|
||||
/// where-clauses). Because some of our bounds listings (e.g.,
|
||||
/// regions) don't include the self-type, you must supply the
|
||||
/// self-type here (the `param_ty` parameter).
|
||||
pub fn predicates<'out, 's>(
|
||||
&'s self,
|
||||
pub fn push_region_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_ty: Ty<'tcx>,
|
||||
// the output must live shorter than the duration of the borrow of self and 'tcx.
|
||||
) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> + 'out
|
||||
where
|
||||
'tcx: 'out,
|
||||
's: 'out,
|
||||
{
|
||||
// If it could be sized, and is, add the `Sized` predicate.
|
||||
let sized_predicate = self.implicitly_sized.and_then(|span| {
|
||||
// FIXME: use tcx.at(span).mk_trait_ref(LangItem::Sized) here? This may make no-core code harder to write.
|
||||
let sized = tcx.lang_items().sized_trait()?;
|
||||
let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized, [param_ty]));
|
||||
Some((trait_ref.without_const().to_predicate(tcx), span))
|
||||
});
|
||||
region: ty::PolyTypeOutlivesPredicate<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
self.predicates.push((region.to_predicate(tcx), span));
|
||||
}
|
||||
|
||||
let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| {
|
||||
let pred = region_bound
|
||||
.map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound))
|
||||
.to_predicate(tcx);
|
||||
(pred, span)
|
||||
});
|
||||
let trait_bounds =
|
||||
self.trait_bounds.iter().map(move |&(bound_trait_ref, span, constness)| {
|
||||
let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
|
||||
(predicate, span)
|
||||
});
|
||||
let projection_bounds = self
|
||||
.projection_bounds
|
||||
.iter()
|
||||
.map(move |&(projection, span)| (projection.to_predicate(tcx), span));
|
||||
pub fn push_trait_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
span: Span,
|
||||
constness: ty::BoundConstness,
|
||||
) {
|
||||
self.predicates.push((trait_ref.with_constness(constness).to_predicate(tcx), span));
|
||||
}
|
||||
|
||||
sized_predicate.into_iter().chain(region_preds).chain(trait_bounds).chain(projection_bounds)
|
||||
pub fn push_projection_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
projection: ty::PolyProjectionPredicate<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
self.predicates.push((projection.to_predicate(tcx), span));
|
||||
}
|
||||
|
||||
pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
|
||||
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
|
||||
let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [ty]));
|
||||
// Preferrable to put this obligation first, since we report better errors for sized ambiguity.
|
||||
self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span));
|
||||
}
|
||||
|
||||
pub fn predicates(&self) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> + '_ {
|
||||
self.predicates.iter().cloned()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -270,8 +270,8 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig));
|
||||
|
||||
let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
|
||||
let impl_fty = ocx.normalize(&norm_cause, param_env, unnormalized_impl_fty);
|
||||
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
||||
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
|
||||
debug!("compare_impl_method: impl_fty={:?}", impl_sig);
|
||||
|
||||
let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
|
||||
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
|
||||
|
@ -294,18 +294,17 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
// type would be more appropriate. In other places we have a `Vec<Span>`
|
||||
// corresponding to their `Vec<Predicate>`, but we don't have that here.
|
||||
// Fixing this would improve the output of test `issue-83765.rs`.
|
||||
let result = ocx.sup(&cause, param_env, trait_fty, impl_fty);
|
||||
let result = ocx.sup(&cause, param_env, trait_sig, impl_sig);
|
||||
|
||||
if let Err(terr) = result {
|
||||
debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
|
||||
debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed");
|
||||
|
||||
let emitted = report_trait_method_mismatch(
|
||||
&infcx,
|
||||
cause,
|
||||
terr,
|
||||
(trait_m, trait_fty),
|
||||
(impl_m, impl_fty),
|
||||
trait_sig,
|
||||
(trait_m, trait_sig),
|
||||
(impl_m, impl_sig),
|
||||
impl_trait_ref,
|
||||
);
|
||||
return Err(emitted);
|
||||
|
@ -484,7 +483,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
|
||||
let param_env = tcx.param_env(def_id);
|
||||
|
||||
// First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later.
|
||||
// First, check a few of the same things as `compare_impl_method`,
|
||||
// just so we don't ICE during substitution later.
|
||||
compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
|
||||
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
|
||||
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
|
||||
|
@ -577,14 +577,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
|
||||
debug!(?trait_sig, ?impl_sig, "equating function signatures");
|
||||
|
||||
let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
|
||||
let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
|
||||
|
||||
// Unify the whole function signature. We need to do this to fully infer
|
||||
// the lifetimes of the return type, but do this after unifying just the
|
||||
// return types, since we want to avoid duplicating errors from
|
||||
// `compare_method_predicate_entailment`.
|
||||
match ocx.eq(&cause, param_env, trait_fty, impl_fty) {
|
||||
match ocx.eq(&cause, param_env, trait_sig, impl_sig) {
|
||||
Ok(()) => {}
|
||||
Err(terr) => {
|
||||
// This function gets called during `compare_method_predicate_entailment` when normalizing a
|
||||
|
@ -595,9 +592,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
infcx,
|
||||
cause,
|
||||
terr,
|
||||
(trait_m, trait_fty),
|
||||
(impl_m, impl_fty),
|
||||
trait_sig,
|
||||
(trait_m, trait_sig),
|
||||
(impl_m, impl_sig),
|
||||
impl_trait_ref,
|
||||
);
|
||||
return Err(emitted);
|
||||
|
@ -771,9 +767,8 @@ fn report_trait_method_mismatch<'tcx>(
|
|||
infcx: &InferCtxt<'tcx>,
|
||||
mut cause: ObligationCause<'tcx>,
|
||||
terr: TypeError<'tcx>,
|
||||
(trait_m, trait_fty): (&ty::AssocItem, Ty<'tcx>),
|
||||
(impl_m, impl_fty): (&ty::AssocItem, Ty<'tcx>),
|
||||
trait_sig: ty::FnSig<'tcx>,
|
||||
(trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
|
||||
(impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> ErrorGuaranteed {
|
||||
let tcx = infcx.tcx;
|
||||
|
@ -858,10 +853,7 @@ fn report_trait_method_mismatch<'tcx>(
|
|||
&mut diag,
|
||||
&cause,
|
||||
trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
|
||||
Some(infer::ValuePairs::Terms(ExpectedFound {
|
||||
expected: trait_fty.into(),
|
||||
found: impl_fty.into(),
|
||||
})),
|
||||
Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
|
||||
terr,
|
||||
false,
|
||||
false,
|
||||
|
|
|
@ -97,21 +97,22 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
|||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
|
||||
let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id);
|
||||
|
||||
let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
|
||||
|
||||
if !tcx.features().trivial_bounds {
|
||||
wfcx.check_false_global_bounds()
|
||||
}
|
||||
f(&mut wfcx);
|
||||
|
||||
let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
|
||||
|
||||
let errors = wfcx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
return;
|
||||
}
|
||||
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
|
||||
let outlives_environment =
|
||||
OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
|
||||
|
||||
|
@ -1489,54 +1490,38 @@ fn check_fn_or_method<'tcx>(
|
|||
def_id: LocalDefId,
|
||||
) {
|
||||
let tcx = wfcx.tcx();
|
||||
let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
|
||||
let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
|
||||
|
||||
// Normalize the input and output types one at a time, using a different
|
||||
// `WellFormedLoc` for each. We cannot call `normalize_associated_types`
|
||||
// on the entire `FnSig`, since this would use the same `WellFormedLoc`
|
||||
// for each type, preventing the HIR wf check from generating
|
||||
// a nice error message.
|
||||
let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig;
|
||||
inputs_and_output = tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| {
|
||||
wfcx.normalize(
|
||||
span,
|
||||
Some(WellFormedLoc::Param {
|
||||
function: def_id,
|
||||
// Note that the `param_idx` of the output type is
|
||||
// one greater than the index of the last input type.
|
||||
param_idx: i.try_into().unwrap(),
|
||||
}),
|
||||
ty,
|
||||
)
|
||||
}));
|
||||
// Manually call `normalize_associated_types_in` on the other types
|
||||
// in `FnSig`. This ensures that if the types of these fields
|
||||
// ever change to include projections, we will start normalizing
|
||||
// them automatically.
|
||||
let sig = ty::FnSig {
|
||||
inputs_and_output,
|
||||
c_variadic: wfcx.normalize(span, None, c_variadic),
|
||||
unsafety: wfcx.normalize(span, None, unsafety),
|
||||
abi: wfcx.normalize(span, None, abi),
|
||||
};
|
||||
let arg_span =
|
||||
|idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span);
|
||||
|
||||
for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() {
|
||||
sig.inputs_and_output =
|
||||
tcx.mk_type_list(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {
|
||||
wfcx.normalize(
|
||||
arg_span(idx),
|
||||
Some(WellFormedLoc::Param {
|
||||
function: def_id,
|
||||
// Note that the `param_idx` of the output type is
|
||||
// one greater than the index of the last input type.
|
||||
param_idx: idx.try_into().unwrap(),
|
||||
}),
|
||||
ty,
|
||||
)
|
||||
}));
|
||||
|
||||
for (idx, ty) in sig.inputs_and_output.iter().enumerate() {
|
||||
wfcx.register_wf_obligation(
|
||||
ty.span,
|
||||
Some(WellFormedLoc::Param { function: def_id, param_idx: i.try_into().unwrap() }),
|
||||
input_ty.into(),
|
||||
arg_span(idx),
|
||||
Some(WellFormedLoc::Param { function: def_id, param_idx: idx.try_into().unwrap() }),
|
||||
ty.into(),
|
||||
);
|
||||
}
|
||||
|
||||
wfcx.register_wf_obligation(
|
||||
hir_decl.output.span(),
|
||||
Some(WellFormedLoc::Param {
|
||||
function: def_id,
|
||||
param_idx: sig.inputs().len().try_into().unwrap(),
|
||||
}),
|
||||
sig.output().into(),
|
||||
);
|
||||
|
||||
check_where_clauses(wfcx, span, def_id);
|
||||
|
||||
check_return_position_impl_trait_in_trait_bounds(
|
||||
|
@ -1912,7 +1897,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
}
|
||||
let pred = obligation.predicate;
|
||||
// Match the existing behavior.
|
||||
if pred.is_global() && !pred.has_late_bound_regions() {
|
||||
if pred.is_global() && !pred.has_late_bound_vars() {
|
||||
let pred = self.normalize(span, None, pred);
|
||||
let hir_node = tcx.hir().find(self.body_id);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
item.span,
|
||||
tcx.def_span(def_id),
|
||||
E0199,
|
||||
"implementing the trait `{}` is not unsafe",
|
||||
trait_ref.print_only_trait_path()
|
||||
|
@ -38,7 +38,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
item.span,
|
||||
tcx.def_span(def_id),
|
||||
E0200,
|
||||
"the trait `{}` requires an `unsafe impl` declaration",
|
||||
trait_ref.print_only_trait_path()
|
||||
|
@ -61,7 +61,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
(Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
item.span,
|
||||
tcx.def_span(def_id),
|
||||
E0569,
|
||||
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
|
||||
attr_name
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
use crate::astconv::AstConv;
|
||||
use crate::check::intrinsic::intrinsic_operation_unsafety;
|
||||
use crate::errors;
|
||||
use hir::def::DefKind;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
|
||||
|
@ -24,8 +25,8 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{GenericParamKind, Node};
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||
|
@ -212,7 +213,7 @@ pub(crate) fn placeholder_type_error_diag<'tcx>(
|
|||
is_fn = true;
|
||||
|
||||
// Check if parent is const or static
|
||||
let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
|
||||
let parent_id = tcx.hir().parent_id(hir_ty.hir_id);
|
||||
let parent_node = tcx.hir().get(parent_id);
|
||||
|
||||
is_const_or_static = matches!(
|
||||
|
@ -1108,7 +1109,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
|||
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
|
||||
// Do not try to infer the return type for a impl method coming from a trait
|
||||
if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
|
||||
tcx.hir().get(tcx.hir().get_parent_node(hir_id))
|
||||
tcx.hir().get_parent(hir_id)
|
||||
&& i.of_trait.is_some()
|
||||
{
|
||||
<dyn AstConv<'_>>::ty_of_fn(
|
||||
|
@ -1195,12 +1196,11 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
|||
ty::ReErased => tcx.lifetimes.re_static,
|
||||
_ => r,
|
||||
});
|
||||
let fn_sig = ty::Binder::dummy(fn_sig);
|
||||
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_ty(ty);
|
||||
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
|
||||
let ret_ty = fn_sig.skip_binder().output();
|
||||
let ret_ty = fn_sig.output();
|
||||
if ret_ty.is_suggestable(tcx, false) {
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
|
@ -1223,26 +1223,26 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
} else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) {
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
"replace with an appropriate return type",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if ret_ty.is_closure() {
|
||||
// We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
|
||||
// to prevent the user from getting a papercut while trying to use the unique closure
|
||||
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
|
||||
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
|
||||
}
|
||||
// Also note how `Fn` traits work just in case!
|
||||
if ret_ty.is_closure() {
|
||||
diag.note(
|
||||
"for more information on `Fn` traits and closure types, see \
|
||||
https://doc.rust-lang.org/book/ch13-01-closures.html",
|
||||
);
|
||||
} else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) {
|
||||
diag.span_suggestion(
|
||||
ty.span,
|
||||
"replace with an appropriate return type",
|
||||
format!("impl Iterator<Item = {}>", i_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
diag.emit();
|
||||
|
||||
fn_sig
|
||||
ty::Binder::dummy(fn_sig)
|
||||
}
|
||||
None => <dyn AstConv<'_>>::ty_of_fn(
|
||||
icx,
|
||||
|
@ -1256,47 +1256,94 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn suggest_impl_iterator<'tcx>(
|
||||
fn suggest_impl_trait<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ret_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
hir_id: hir::HirId,
|
||||
def_id: LocalDefId,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; };
|
||||
let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; };
|
||||
if !tcx
|
||||
.infer_ctxt()
|
||||
.build()
|
||||
.type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id))
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
|
||||
// Find the type of `Iterator::Item`.
|
||||
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
|
||||
let ty_var = infcx.next_ty_var(origin);
|
||||
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())),
|
||||
term: ty_var.into(),
|
||||
},
|
||||
)));
|
||||
// Add `<ret_ty as Iterator>::Item = _` obligation.
|
||||
ocx.register_obligation(crate::traits::Obligation::misc(
|
||||
tcx,
|
||||
span,
|
||||
hir_id,
|
||||
tcx.param_env(def_id),
|
||||
projection,
|
||||
));
|
||||
if ocx.select_where_possible().is_empty()
|
||||
&& let item_ty = infcx.resolve_vars_if_possible(ty_var)
|
||||
&& item_ty.is_suggestable(tcx, false)
|
||||
{
|
||||
return Some(item_ty);
|
||||
) -> Option<String> {
|
||||
let format_as_assoc: fn(_, _, _, _, _) -> _ =
|
||||
|tcx: TyCtxt<'tcx>,
|
||||
_: ty::SubstsRef<'tcx>,
|
||||
trait_def_id: DefId,
|
||||
assoc_item_def_id: DefId,
|
||||
item_ty: Ty<'tcx>| {
|
||||
let trait_name = tcx.item_name(trait_def_id);
|
||||
let assoc_name = tcx.item_name(assoc_item_def_id);
|
||||
Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
|
||||
};
|
||||
let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
|
||||
|tcx: TyCtxt<'tcx>,
|
||||
substs: ty::SubstsRef<'tcx>,
|
||||
trait_def_id: DefId,
|
||||
_: DefId,
|
||||
item_ty: Ty<'tcx>| {
|
||||
let trait_name = tcx.item_name(trait_def_id);
|
||||
let args_tuple = substs.type_at(1);
|
||||
let ty::Tuple(types) = *args_tuple.kind() else { return None; };
|
||||
if !types.is_suggestable(tcx, false) {
|
||||
return None;
|
||||
}
|
||||
let maybe_ret =
|
||||
if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
|
||||
Some(format!(
|
||||
"impl {trait_name}({}){maybe_ret}",
|
||||
types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
|
||||
))
|
||||
};
|
||||
|
||||
for (trait_def_id, assoc_item_def_id, formatter) in [
|
||||
(
|
||||
tcx.get_diagnostic_item(sym::Iterator),
|
||||
tcx.get_diagnostic_item(sym::IteratorItem),
|
||||
format_as_assoc,
|
||||
),
|
||||
(
|
||||
tcx.lang_items().future_trait(),
|
||||
tcx.get_diagnostic_item(sym::FutureOutput),
|
||||
format_as_assoc,
|
||||
),
|
||||
(tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized),
|
||||
(
|
||||
tcx.lang_items().fn_mut_trait(),
|
||||
tcx.lang_items().fn_once_output(),
|
||||
format_as_parenthesized,
|
||||
),
|
||||
(
|
||||
tcx.lang_items().fn_once_trait(),
|
||||
tcx.lang_items().fn_once_output(),
|
||||
format_as_parenthesized,
|
||||
),
|
||||
] {
|
||||
let Some(trait_def_id) = trait_def_id else { continue; };
|
||||
let Some(assoc_item_def_id) = assoc_item_def_id else { continue; };
|
||||
if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
|
||||
continue;
|
||||
}
|
||||
let param_env = tcx.param_env(def_id);
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
|
||||
if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
|
||||
});
|
||||
if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
|
||||
let item_ty = ocx.normalize(
|
||||
&ObligationCause::misc(span, hir_id),
|
||||
param_env,
|
||||
tcx.mk_projection(assoc_item_def_id, substs),
|
||||
);
|
||||
// FIXME(compiler-errors): We may benefit from resolving regions here.
|
||||
if ocx.select_where_possible().is_empty()
|
||||
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
|
||||
&& item_ty.is_suggestable(tcx, false)
|
||||
&& let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
|
||||
{
|
||||
return Some(sugg);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||
// `min_const_generics`.
|
||||
Some(parent_def_id.to_def_id())
|
||||
} else {
|
||||
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
|
||||
let parent_node = tcx.hir().get_parent(hir_id);
|
||||
match parent_node {
|
||||
// HACK(eddyb) this provides the correct generics for repeat
|
||||
// expressions' count (i.e. `N` in `[x; N]`), and explicit
|
||||
|
@ -320,7 +320,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||
|
||||
// provide junk type parameter defs for const blocks.
|
||||
if let Node::AnonConst(_) = node {
|
||||
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
|
||||
let parent_node = tcx.hir().get_parent(hir_id);
|
||||
if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
|
||||
params.push(ty::GenericParamDef {
|
||||
index: next_index(),
|
||||
|
|
|
@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>(
|
|||
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
|
||||
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
|
||||
// Associated types are implicitly sized unless a `?Sized` bound is found
|
||||
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
|
||||
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span);
|
||||
|
||||
let trait_def_id = tcx.parent(assoc_item_def_id);
|
||||
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
|
||||
|
@ -44,9 +44,7 @@ fn associated_type_bounds<'tcx>(
|
|||
}
|
||||
});
|
||||
|
||||
let all_bounds = tcx
|
||||
.arena
|
||||
.alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent));
|
||||
let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent));
|
||||
debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
|
||||
all_bounds
|
||||
}
|
||||
|
@ -74,10 +72,10 @@ fn opaque_type_bounds<'tcx>(
|
|||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
|
||||
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
|
||||
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span);
|
||||
debug!(?bounds);
|
||||
|
||||
tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
|
||||
tcx.arena.alloc_from_iter(bounds.predicates())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -682,7 +682,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
};
|
||||
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
// Ensure that the parent of the def is an item, not HRTB
|
||||
let parent_id = self.tcx.hir().get_parent_node(hir_id);
|
||||
let parent_id = self.tcx.hir().parent_id(hir_id);
|
||||
if !parent_id.is_owner() {
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
|
@ -1195,8 +1195,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
// Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
|
||||
// regular fns.
|
||||
if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
|
||||
&& let hir::LifetimeName::Param(_) = lifetime_ref.res
|
||||
&& lifetime_ref.is_anonymous()
|
||||
&& let hir::LifetimeName::Param(param_id) = lifetime_ref.res
|
||||
&& let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
|
||||
&& let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
|
||||
&& param.is_elided_lifetime()
|
||||
&& let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
|
||||
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
|
||||
{
|
||||
|
|
|
@ -165,12 +165,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||
<dyn AstConv<'_>>::add_implicitly_sized(
|
||||
&icx,
|
||||
&mut bounds,
|
||||
param_ty,
|
||||
&[],
|
||||
Some((param.def_id, ast_generics.predicates)),
|
||||
param.span,
|
||||
);
|
||||
trace!(?bounds);
|
||||
predicates.extend(bounds.predicates(tcx, param_ty));
|
||||
predicates.extend(bounds.predicates());
|
||||
trace!(?predicates);
|
||||
}
|
||||
GenericParamKind::Const { .. } => {
|
||||
|
@ -217,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||
&mut bounds,
|
||||
bound_vars,
|
||||
);
|
||||
predicates.extend(bounds.predicates(tcx, ty));
|
||||
predicates.extend(bounds.predicates());
|
||||
}
|
||||
|
||||
hir::WherePredicate::RegionPredicate(region_pred) => {
|
||||
|
@ -270,7 +271,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
|||
// We create bi-directional Outlives predicates between the original
|
||||
// and the duplicated parameter, to ensure that they do not get out of sync.
|
||||
if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node {
|
||||
let opaque_ty_id = tcx.hir().get_parent_node(hir_id);
|
||||
let opaque_ty_id = tcx.hir().parent_id(hir_id);
|
||||
let opaque_ty_node = tcx.hir().get(opaque_ty_id);
|
||||
let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else {
|
||||
bug!("unexpected {opaque_ty_node:?}")
|
||||
|
@ -536,7 +537,7 @@ pub(super) fn super_predicates_that_define_assoc_type(
|
|||
<dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds)
|
||||
};
|
||||
|
||||
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
|
||||
let superbounds1 = superbounds1.predicates();
|
||||
|
||||
// Convert any explicit superbounds in the where-clause,
|
||||
// e.g., `trait Foo where Self: Bar`.
|
||||
|
@ -745,5 +746,5 @@ fn predicates_from_bound<'tcx>(
|
|||
) -> Vec<(ty::Predicate<'tcx>, Span)> {
|
||||
let mut bounds = Bounds::default();
|
||||
astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
|
||||
bounds.predicates(astconv.tcx(), param_ty).collect()
|
||||
bounds.predicates().collect()
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
|
|||
_ => return None,
|
||||
};
|
||||
|
||||
let parent_node_id = tcx.hir().get_parent_node(hir_id);
|
||||
let parent_node_id = tcx.hir().parent_id(hir_id);
|
||||
let parent_node = tcx.hir().get(parent_node_id);
|
||||
|
||||
let (generics, arg_idx) = match parent_node {
|
||||
|
@ -402,7 +402,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
|||
}
|
||||
|
||||
Node::AnonConst(_) => {
|
||||
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
|
||||
let parent_node = tcx.hir().get_parent(hir_id);
|
||||
match parent_node {
|
||||
Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
|
||||
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
||||
|
@ -445,7 +445,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
|||
..
|
||||
},
|
||||
) if let Node::TraitRef(trait_ref) =
|
||||
tcx.hir().get(tcx.hir().get_parent_node(binding_id))
|
||||
tcx.hir().get_parent(binding_id)
|
||||
&& e.hir_id == hir_id =>
|
||||
{
|
||||
let Some(trait_def_id) = trait_ref.trait_def_id() else {
|
||||
|
@ -472,7 +472,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
|||
Node::TypeBinding(
|
||||
binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. },
|
||||
) if let Node::TraitRef(trait_ref) =
|
||||
tcx.hir().get(tcx.hir().get_parent_node(binding_id))
|
||||
tcx.hir().get_parent(binding_id)
|
||||
&& let Some((idx, _)) =
|
||||
gen_args.args.iter().enumerate().find(|(_, arg)| {
|
||||
if let GenericArg::Const(ct) = arg {
|
||||
|
|
|
@ -597,11 +597,15 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
let span = self.path_segment.ident.span;
|
||||
|
||||
// insert a suggestion of the form "Y<'a, 'b>"
|
||||
let ident = self.path_segment.ident.name.to_ident_string();
|
||||
let sugg = format!("{}<{}>", ident, suggested_args);
|
||||
let sugg = format!("<{}>", suggested_args);
|
||||
debug!("sugg: {:?}", sugg);
|
||||
|
||||
err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_hi(),
|
||||
&msg,
|
||||
sugg,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
|
||||
AngleBrackets::Available => {
|
||||
|
@ -643,11 +647,15 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
let span = self.path_segment.ident.span;
|
||||
|
||||
// insert a suggestion of the form "Y<T, U>"
|
||||
let ident = self.path_segment.ident.name.to_ident_string();
|
||||
let sugg = format!("{}<{}>", ident, suggested_args);
|
||||
let sugg = format!("<{}>", suggested_args);
|
||||
debug!("sugg: {:?}", sugg);
|
||||
|
||||
err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_hi(),
|
||||
&msg,
|
||||
sugg,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
AngleBrackets::Available => {
|
||||
let gen_args_span = self.gen_args.span().unwrap();
|
||||
|
@ -716,7 +724,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
num = num_trait_generics_except_self,
|
||||
);
|
||||
|
||||
if let Some(parent_node) = self.tcx.hir().find_parent_node(self.path_segment.hir_id)
|
||||
if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id)
|
||||
&& let Some(parent_node) = self.tcx.hir().find(parent_node)
|
||||
&& let hir::Node::Expr(expr) = parent_node {
|
||||
match expr.kind {
|
||||
|
|
|
@ -1268,7 +1268,7 @@ impl<'a> State<'a> {
|
|||
hir::InlineAsmOperand::In { reg, ref expr } => {
|
||||
s.word("in");
|
||||
s.popen();
|
||||
s.word(format!("{}", reg));
|
||||
s.word(format!("{reg}"));
|
||||
s.pclose();
|
||||
s.space();
|
||||
s.print_expr(expr);
|
||||
|
@ -1276,7 +1276,7 @@ impl<'a> State<'a> {
|
|||
hir::InlineAsmOperand::Out { reg, late, ref expr } => {
|
||||
s.word(if late { "lateout" } else { "out" });
|
||||
s.popen();
|
||||
s.word(format!("{}", reg));
|
||||
s.word(format!("{reg}"));
|
||||
s.pclose();
|
||||
s.space();
|
||||
match expr {
|
||||
|
@ -1287,7 +1287,7 @@ impl<'a> State<'a> {
|
|||
hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
|
||||
s.word(if late { "inlateout" } else { "inout" });
|
||||
s.popen();
|
||||
s.word(format!("{}", reg));
|
||||
s.word(format!("{reg}"));
|
||||
s.pclose();
|
||||
s.space();
|
||||
s.print_expr(expr);
|
||||
|
@ -1295,7 +1295,7 @@ impl<'a> State<'a> {
|
|||
hir::InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
|
||||
s.word(if late { "inlateout" } else { "inout" });
|
||||
s.popen();
|
||||
s.word(format!("{}", reg));
|
||||
s.word(format!("{reg}"));
|
||||
s.pclose();
|
||||
s.space();
|
||||
s.print_expr(in_expr);
|
||||
|
|
|
@ -224,14 +224,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut ret_span: MultiSpan = semi_span.into();
|
||||
ret_span.push_span_label(
|
||||
expr.span,
|
||||
"this could be implicitly returned but it is a statement, not a \
|
||||
tail expression",
|
||||
"this could be implicitly returned but it is a statement, not a tail expression",
|
||||
);
|
||||
ret_span.push_span_label(ret, "the `match` arms can conform to this return type");
|
||||
ret_span.push_span_label(
|
||||
semi_span,
|
||||
"the `match` is a statement because of this semicolon, consider \
|
||||
removing it",
|
||||
"the `match` is a statement because of this semicolon, consider removing it",
|
||||
);
|
||||
diag.span_note(ret_span, "you might have meant to return the `match` expression");
|
||||
diag.tool_only_span_suggestion(
|
||||
|
@ -289,15 +287,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> {
|
||||
let node = {
|
||||
let rslt = self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(hir_id));
|
||||
let rslt = self.tcx.hir().parent_id(self.tcx.hir().parent_id(hir_id));
|
||||
self.tcx.hir().get(rslt)
|
||||
};
|
||||
if let hir::Node::Block(block) = node {
|
||||
// check that the body's parent is an fn
|
||||
let parent = self
|
||||
.tcx
|
||||
.hir()
|
||||
.get(self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(block.hir_id)));
|
||||
let parent = self.tcx.hir().get_parent(self.tcx.hir().parent_id(block.hir_id));
|
||||
if let (Some(expr), hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })) =
|
||||
(&block.expr, parent)
|
||||
{
|
||||
|
@ -526,7 +521,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
None
|
||||
}
|
||||
})?;
|
||||
let opaque_ty = self.tcx.mk_opaque(rpit_def_id, substs);
|
||||
|
||||
if !self.can_coerce(first_ty, expected) || !self.can_coerce(second_ty, expected) {
|
||||
return None;
|
||||
|
@ -540,13 +534,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
let pred = pred.kind().rebind(match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
|
||||
assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
|
||||
// FIXME(rpitit): This will need to be fixed when we move to associated types
|
||||
assert!(matches!(
|
||||
*trait_pred.trait_ref.self_ty().kind(),
|
||||
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
|
||||
if def_id == rpit_def_id && substs == substs
|
||||
));
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(
|
||||
trait_pred.with_self_ty(self.tcx, ty),
|
||||
))
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => {
|
||||
assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
|
||||
assert!(matches!(
|
||||
*proj_pred.projection_ty.self_ty().kind(),
|
||||
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
|
||||
if def_id == rpit_def_id && substs == substs
|
||||
));
|
||||
proj_pred = proj_pred.with_self_ty(self.tcx, ty);
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred))
|
||||
}
|
||||
|
|
|
@ -288,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
callee_span: Span,
|
||||
) {
|
||||
let hir = self.tcx.hir();
|
||||
let parent_hir_id = hir.get_parent_node(hir_id);
|
||||
let parent_hir_id = hir.parent_id(hir_id);
|
||||
let parent_node = hir.get(parent_hir_id);
|
||||
if let (
|
||||
hir::Node::Expr(hir::Expr {
|
||||
|
@ -303,7 +303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
// Actually need to unwrap a few more layers of HIR to get to
|
||||
// the _real_ closure...
|
||||
let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id));
|
||||
let async_closure = hir.parent_id(hir.parent_id(parent_hir_id));
|
||||
if let hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
|
||||
..
|
||||
|
@ -336,7 +336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
call_expr: &'tcx hir::Expr<'tcx>,
|
||||
callee_expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> bool {
|
||||
let hir_id = self.tcx.hir().get_parent_node(call_expr.hir_id);
|
||||
let hir_id = self.tcx.hir().parent_id(call_expr.hir_id);
|
||||
let parent_node = self.tcx.hir().get(hir_id);
|
||||
if let (
|
||||
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }),
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_infer::infer::{InferOk, InferResult};
|
|||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::ty::{self, Ty, TypeSuperVisitable, TypeVisitor};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
|
@ -21,6 +21,7 @@ use rustc_trait_selection::traits::error_reporting::ArgKind;
|
|||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
||||
use std::cmp;
|
||||
use std::iter;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
/// What signature do we *expect* the closure to have from context?
|
||||
#[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
|
||||
|
@ -54,7 +55,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// closure sooner rather than later, so first examine the expected
|
||||
// type, and see if can glean a closure kind from there.
|
||||
let (expected_sig, expected_kind) = match expected.to_option(self) {
|
||||
Some(ty) => self.deduce_expectations_from_expected_type(ty),
|
||||
Some(ty) => self.deduce_closure_signature(ty),
|
||||
None => (None, None),
|
||||
};
|
||||
let body = self.tcx.hir().body(closure.body);
|
||||
|
@ -162,13 +163,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Given the expected type, figures out what it can about this closure we
|
||||
/// are about to type check:
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn deduce_expectations_from_expected_type(
|
||||
fn deduce_closure_signature(
|
||||
&self,
|
||||
expected_ty: Ty<'tcx>,
|
||||
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
|
||||
match *expected_ty.kind() {
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
|
||||
.deduce_signature_from_predicates(
|
||||
.deduce_closure_signature_from_predicates(
|
||||
expected_ty,
|
||||
self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
|
||||
),
|
||||
ty::Dynamic(ref object_type, ..) => {
|
||||
|
@ -181,7 +183,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.and_then(|did| self.tcx.fn_trait_kind_from_def_id(did));
|
||||
(sig, kind)
|
||||
}
|
||||
ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates(
|
||||
ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates(
|
||||
self.tcx.mk_ty_var(self.root_var(vid)),
|
||||
self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
|
||||
),
|
||||
ty::FnPtr(sig) => {
|
||||
|
@ -192,8 +195,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn deduce_signature_from_predicates(
|
||||
fn deduce_closure_signature_from_predicates(
|
||||
&self,
|
||||
expected_ty: Ty<'tcx>,
|
||||
predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
|
||||
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
|
||||
let mut expected_sig = None;
|
||||
|
@ -214,13 +218,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if expected_sig.is_none()
|
||||
&& let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder()
|
||||
{
|
||||
expected_sig = self.normalize(
|
||||
let inferred_sig = self.normalize(
|
||||
obligation.cause.span,
|
||||
self.deduce_sig_from_projection(
|
||||
Some(obligation.cause.span),
|
||||
bound_predicate.rebind(proj_predicate),
|
||||
),
|
||||
);
|
||||
// Make sure that we didn't infer a signature that mentions itself.
|
||||
// This can happen when we elaborate certain supertrait bounds that
|
||||
// mention projections containing the `Self` type. See #105401.
|
||||
struct MentionsTy<'tcx> {
|
||||
expected_ty: Ty<'tcx>,
|
||||
}
|
||||
impl<'tcx> TypeVisitor<'tcx> for MentionsTy<'tcx> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if t == self.expected_ty {
|
||||
ControlFlow::BREAK
|
||||
} else {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
|
||||
expected_sig = inferred_sig;
|
||||
}
|
||||
}
|
||||
|
||||
// Even if we can't infer the full signature, we may be able to
|
||||
|
|
|
@ -1547,7 +1547,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
err.span_label(cause.span, "return type is not `()`");
|
||||
}
|
||||
ObligationCauseCode::BlockTailExpression(blk_id) => {
|
||||
let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
|
||||
let parent_id = fcx.tcx.hir().parent_id(blk_id);
|
||||
err = self.report_return_mismatched_types(
|
||||
cause,
|
||||
expected,
|
||||
|
@ -1578,7 +1578,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
None,
|
||||
);
|
||||
if !fcx.tcx.features().unsized_locals {
|
||||
let id = fcx.tcx.hir().get_parent_node(id);
|
||||
let id = fcx.tcx.hir().parent_id(id);
|
||||
unsized_return = self.is_return_ty_unsized(fcx, id);
|
||||
}
|
||||
}
|
||||
|
@ -1668,7 +1668,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
let mut pointing_at_return_type = false;
|
||||
let mut fn_output = None;
|
||||
|
||||
let parent_id = fcx.tcx.hir().get_parent_node(id);
|
||||
let parent_id = fcx.tcx.hir().parent_id(id);
|
||||
let parent = fcx.tcx.hir().get(parent_id);
|
||||
if let Some(expr) = expression
|
||||
&& let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { body, .. }), .. }) = parent
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use crate::FnCtxt;
|
||||
use rustc_ast::util::parser::PREC_POSTFIX;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::CtorKind;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{is_range_literal, Node};
|
||||
use rustc_infer::infer::InferOk;
|
||||
|
@ -11,11 +13,14 @@ use rustc_middle::lint::in_external_macro;
|
|||
use rustc_middle::middle::stability::EvalResult;
|
||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut};
|
||||
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder};
|
||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeVisitable};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::error_reporting::method_chain::CollectAllMismatches;
|
||||
use rustc_trait_selection::traits::ObligationCause;
|
||||
|
||||
use super::method::probe;
|
||||
|
@ -40,7 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.annotate_alternative_method_deref(err, expr, error);
|
||||
|
||||
// Use `||` to give these suggestions a precedence
|
||||
let _ = self.suggest_missing_parentheses(err, expr)
|
||||
let suggested = self.suggest_missing_parentheses(err, expr)
|
||||
|| self.suggest_remove_last_method_call(err, expr, expected)
|
||||
|| self.suggest_associated_const(err, expr, expected)
|
||||
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
|
||||
|
@ -52,8 +57,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|| self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
|
||||
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
|
||||
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|
||||
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|
||||
|| self.suggest_into(err, expr, expr_ty, expected)
|
||||
|| self.suggest_floating_point_literal(err, expr, expected);
|
||||
if !suggested {
|
||||
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_coerce_suggestions(
|
||||
|
@ -75,6 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
||||
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
|
||||
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
|
||||
self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
|
||||
}
|
||||
|
||||
/// Requires that the two types unify, and prints an error message if
|
||||
|
@ -205,13 +215,222 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
(expected, Some(err))
|
||||
}
|
||||
|
||||
pub fn point_at_expr_source_of_inferred_type(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
found: Ty<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
) -> bool {
|
||||
let map = self.tcx.hir();
|
||||
|
||||
let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; };
|
||||
let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; };
|
||||
let hir::def::Res::Local(hir_id) = p.res else { return false; };
|
||||
let Some(hir::Node::Pat(pat)) = map.find(hir_id) else { return false; };
|
||||
let Some(hir::Node::Local(hir::Local {
|
||||
ty: None,
|
||||
init: Some(init),
|
||||
..
|
||||
})) = map.find_parent(pat.hir_id) else { return false; };
|
||||
let Some(ty) = self.node_ty_opt(init.hir_id) else { return false; };
|
||||
if ty.is_closure() || init.span.overlaps(expr.span) || pat.span.from_expansion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Locate all the usages of the relevant binding.
|
||||
struct FindExprs<'hir> {
|
||||
hir_id: hir::HirId,
|
||||
uses: Vec<&'hir hir::Expr<'hir>>,
|
||||
}
|
||||
impl<'v> Visitor<'v> for FindExprs<'v> {
|
||||
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind
|
||||
&& let hir::def::Res::Local(hir_id) = path.res
|
||||
&& hir_id == self.hir_id
|
||||
{
|
||||
self.uses.push(ex);
|
||||
}
|
||||
hir::intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
let mut expr_finder = FindExprs { hir_id, uses: vec![] };
|
||||
let id = map.get_parent_item(hir_id);
|
||||
let hir_id: hir::HirId = id.into();
|
||||
|
||||
let Some(node) = map.find(hir_id) else { return false; };
|
||||
let Some(body_id) = node.body_id() else { return false; };
|
||||
let body = map.body(body_id);
|
||||
expr_finder.visit_expr(body.value);
|
||||
// Hack to make equality checks on types with inference variables and regions useful.
|
||||
let mut eraser = BottomUpFolder {
|
||||
tcx: self.tcx,
|
||||
lt_op: |_| self.tcx.lifetimes.re_erased,
|
||||
ct_op: |c| c,
|
||||
ty_op: |t| match *t.kind() {
|
||||
ty::Infer(ty::TyVar(vid)) => self.tcx.mk_ty_infer(ty::TyVar(self.root_var(vid))),
|
||||
ty::Infer(ty::IntVar(_)) => {
|
||||
self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 }))
|
||||
}
|
||||
ty::Infer(ty::FloatVar(_)) => {
|
||||
self.tcx.mk_ty_infer(ty::FloatVar(ty::FloatVid { index: 0 }))
|
||||
}
|
||||
_ => t,
|
||||
},
|
||||
};
|
||||
let mut prev = eraser.fold_ty(ty);
|
||||
let mut prev_span = None;
|
||||
|
||||
for binding in expr_finder.uses {
|
||||
// In every expression where the binding is referenced, we will look at that
|
||||
// expression's type and see if it is where the incorrect found type was fully
|
||||
// "materialized" and point at it. We will also try to provide a suggestion there.
|
||||
if let Some(hir::Node::Expr(expr)
|
||||
| hir::Node::Stmt(hir::Stmt {
|
||||
kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr),
|
||||
..
|
||||
})) = &map.find_parent(binding.hir_id)
|
||||
&& let hir::ExprKind::MethodCall(segment, rcvr, args, _span) = expr.kind
|
||||
&& rcvr.hir_id == binding.hir_id
|
||||
&& let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id)
|
||||
{
|
||||
// We special case methods, because they can influence inference through the
|
||||
// call's arguments and we can provide a more explicit span.
|
||||
let sig = self.tcx.fn_sig(def_id);
|
||||
let def_self_ty = sig.input(0).skip_binder();
|
||||
let rcvr_ty = self.node_ty(rcvr.hir_id);
|
||||
// Get the evaluated type *after* calling the method call, so that the influence
|
||||
// of the arguments can be reflected in the receiver type. The receiver
|
||||
// expression has the type *before* theis analysis is done.
|
||||
let ty = match self.lookup_probe(
|
||||
segment.ident,
|
||||
rcvr_ty,
|
||||
expr,
|
||||
probe::ProbeScope::TraitsInScope,
|
||||
) {
|
||||
Ok(pick) => pick.self_ty,
|
||||
Err(_) => rcvr_ty,
|
||||
};
|
||||
// Remove one layer of references to account for `&mut self` and
|
||||
// `&self`, so that we can compare it against the binding.
|
||||
let (ty, def_self_ty) = match (ty.kind(), def_self_ty.kind()) {
|
||||
(ty::Ref(_, ty, a), ty::Ref(_, self_ty, b)) if a == b => (*ty, *self_ty),
|
||||
_ => (ty, def_self_ty),
|
||||
};
|
||||
let mut param_args = FxHashMap::default();
|
||||
let mut param_expected = FxHashMap::default();
|
||||
let mut param_found = FxHashMap::default();
|
||||
if self.can_eq(self.param_env, ty, found).is_ok() {
|
||||
// We only point at the first place where the found type was inferred.
|
||||
for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() {
|
||||
if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() {
|
||||
// We found an argument that references a type parameter in `Self`,
|
||||
// so we assume that this is the argument that caused the found
|
||||
// type, which we know already because of `can_eq` above was first
|
||||
// inferred in this method call.
|
||||
let arg = &args[i];
|
||||
let arg_ty = self.node_ty(arg.hir_id);
|
||||
err.span_label(
|
||||
arg.span,
|
||||
&format!(
|
||||
"this is of type `{arg_ty}`, which causes `{ident}` to be \
|
||||
inferred as `{ty}`",
|
||||
),
|
||||
);
|
||||
param_args.insert(param_ty, (arg, arg_ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Here we find, for a type param `T`, the type that `T` is in the current
|
||||
// method call *and* in the original expected type. That way, we can see if we
|
||||
// can give any structured suggestion for the function argument.
|
||||
let mut c = CollectAllMismatches {
|
||||
infcx: &self.infcx,
|
||||
param_env: self.param_env,
|
||||
errors: vec![],
|
||||
};
|
||||
let _ = c.relate(def_self_ty, ty);
|
||||
for error in c.errors {
|
||||
if let TypeError::Sorts(error) = error {
|
||||
param_found.insert(error.expected, error.found);
|
||||
}
|
||||
}
|
||||
c.errors = vec![];
|
||||
let _ = c.relate(def_self_ty, expected);
|
||||
for error in c.errors {
|
||||
if let TypeError::Sorts(error) = error {
|
||||
param_expected.insert(error.expected, error.found);
|
||||
}
|
||||
}
|
||||
for (param, (arg, arg_ty)) in param_args.iter() {
|
||||
let Some(expected) = param_expected.get(param) else { continue; };
|
||||
let Some(found) = param_found.get(param) else { continue; };
|
||||
if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; }
|
||||
self.emit_coerce_suggestions(err, arg, *found, *expected, None, None);
|
||||
}
|
||||
|
||||
let ty = eraser.fold_ty(ty);
|
||||
if ty.references_error() {
|
||||
break;
|
||||
}
|
||||
if ty != prev
|
||||
&& param_args.is_empty()
|
||||
&& self.can_eq(self.param_env, ty, found).is_ok()
|
||||
{
|
||||
// We only point at the first place where the found type was inferred.
|
||||
err.span_label(
|
||||
segment.ident.span,
|
||||
with_forced_trimmed_paths!(format!(
|
||||
"here the type of `{ident}` is inferred to be `{ty}`",
|
||||
)),
|
||||
);
|
||||
break;
|
||||
} else if !param_args.is_empty() {
|
||||
break;
|
||||
}
|
||||
prev = ty;
|
||||
} else {
|
||||
let ty = eraser.fold_ty(self.node_ty(binding.hir_id));
|
||||
if ty.references_error() {
|
||||
break;
|
||||
}
|
||||
if ty != prev
|
||||
&& let Some(span) = prev_span
|
||||
&& self.can_eq(self.param_env, ty, found).is_ok()
|
||||
{
|
||||
// We only point at the first place where the found type was inferred.
|
||||
// We use the *previous* span because if the type is known *here* it means
|
||||
// it was *evaluated earlier*. We don't do this for method calls because we
|
||||
// evaluate the method's self type eagerly, but not in any other case.
|
||||
err.span_label(
|
||||
span,
|
||||
with_forced_trimmed_paths!(format!(
|
||||
"here the type of `{ident}` is inferred to be `{ty}`",
|
||||
)),
|
||||
);
|
||||
break;
|
||||
}
|
||||
prev = ty;
|
||||
}
|
||||
if binding.hir_id == expr.hir_id {
|
||||
// Do not look at expressions that come after the expression we were originally
|
||||
// evaluating and had a type error.
|
||||
break;
|
||||
}
|
||||
prev_span = Some(binding.span);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn annotate_expected_due_to_let_ty(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
error: Option<TypeError<'tcx>>,
|
||||
) {
|
||||
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
|
||||
let parent = self.tcx.hir().parent_id(expr.hir_id);
|
||||
match (self.tcx.hir().find(parent), error) {
|
||||
(Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _)
|
||||
if init.hir_id == expr.hir_id =>
|
||||
|
@ -258,10 +477,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
hir::Path { res: hir::def::Res::Local(hir_id), .. },
|
||||
)) => {
|
||||
if let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(*hir_id) {
|
||||
let parent = self.tcx.hir().get_parent_node(pat.hir_id);
|
||||
primary_span = pat.span;
|
||||
secondary_span = pat.span;
|
||||
match self.tcx.hir().find(parent) {
|
||||
match self.tcx.hir().find_parent(pat.hir_id) {
|
||||
Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => {
|
||||
primary_span = ty.span;
|
||||
post_message = " type";
|
||||
|
@ -326,7 +544,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expr: &hir::Expr<'_>,
|
||||
error: Option<TypeError<'tcx>>,
|
||||
) {
|
||||
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
|
||||
let parent = self.tcx.hir().parent_id(expr.hir_id);
|
||||
let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {return;};
|
||||
let Some(hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Assign(lhs, rhs, _), ..
|
||||
|
@ -510,7 +728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Unroll desugaring, to make sure this works for `for` loops etc.
|
||||
loop {
|
||||
parent = self.tcx.hir().get_parent_node(id);
|
||||
parent = self.tcx.hir().parent_id(id);
|
||||
if let Some(parent_span) = self.tcx.hir().opt_span(parent) {
|
||||
if parent_span.find_ancestor_inside(expr.span).is_some() {
|
||||
// The parent node is part of the same span, so is the result of the
|
||||
|
@ -790,12 +1008,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
};
|
||||
|
||||
let local_parent = self.tcx.hir().get_parent_node(local_id);
|
||||
let local_parent = self.tcx.hir().parent_id(local_id);
|
||||
let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) = self.tcx.hir().find(local_parent) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let param_parent = self.tcx.hir().get_parent_node(*param_hir_id);
|
||||
let param_parent = self.tcx.hir().parent_id(*param_hir_id);
|
||||
let Some(Node::Expr(hir::Expr {
|
||||
hir_id: expr_hir_id,
|
||||
kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }),
|
||||
|
@ -804,7 +1022,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
};
|
||||
|
||||
let expr_parent = self.tcx.hir().get_parent_node(*expr_hir_id);
|
||||
let expr_parent = self.tcx.hir().parent_id(*expr_hir_id);
|
||||
let hir = self.tcx.hir().find(expr_parent);
|
||||
let closure_params_len = closure_fn_decl.inputs.len();
|
||||
let (
|
||||
|
@ -857,7 +1075,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
_ => None,
|
||||
}?;
|
||||
|
||||
match hir.find(hir.get_parent_node(expr.hir_id))? {
|
||||
match hir.find_parent(expr.hir_id)? {
|
||||
Node::ExprField(field) => {
|
||||
if field.ident.name == local.name && field.is_shorthand {
|
||||
return Some(local.name);
|
||||
|
@ -883,7 +1101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Returns whether the given expression is an `else if`.
|
||||
pub(crate) fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
|
||||
if let hir::ExprKind::If(..) = expr.kind {
|
||||
let parent_id = self.tcx.hir().get_parent_node(expr.hir_id);
|
||||
let parent_id = self.tcx.hir().parent_id(expr.hir_id);
|
||||
if let Some(Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::If(_, _, Some(else_expr)),
|
||||
..
|
||||
|
@ -1040,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Assign(..),
|
||||
..
|
||||
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
|
||||
})) = self.tcx.hir().find_parent(expr.hir_id)
|
||||
{
|
||||
if mutability.is_mut() {
|
||||
// Suppressing this diagnostic, we'll properly print it in `check_expr_assign`
|
||||
|
@ -1162,7 +1380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
// If we've reached our target type with just removing `&`, then just print now.
|
||||
if steps == 0 {
|
||||
if steps == 0 && !remove.trim().is_empty() {
|
||||
return Some((
|
||||
prefix_span,
|
||||
format!("consider removing the `{}`", remove.trim()),
|
||||
|
@ -1221,6 +1439,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
(prefix_span, format!("{}{}", prefix, "*".repeat(steps)))
|
||||
};
|
||||
if suggestion.trim().is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
return Some((
|
||||
span,
|
||||
|
@ -1267,9 +1488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let mut sugg = vec![];
|
||||
|
||||
if let Some(hir::Node::ExprField(field)) =
|
||||
self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
|
||||
{
|
||||
if let Some(hir::Node::ExprField(field)) = self.tcx.hir().find_parent(expr.hir_id) {
|
||||
// `expr` is a literal field for a struct, only suggest if appropriate
|
||||
if field.is_shorthand {
|
||||
// This is a field literal
|
||||
|
@ -1625,7 +1844,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
[start, end],
|
||||
_,
|
||||
) = expr.kind else { return; };
|
||||
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
|
||||
let parent = self.tcx.hir().parent_id(expr.hir_id);
|
||||
if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) {
|
||||
// Ignore `Foo { field: a..Default::default() }`
|
||||
return;
|
||||
|
@ -1673,4 +1892,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
||||
/// Identify when the type error is because `()` is found in a binding that was assigned a
|
||||
/// block without a tail expression.
|
||||
fn check_for_binding_assigned_block_without_tail_expression(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
checked_ty: Ty<'tcx>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
) {
|
||||
if !checked_ty.is_unit() {
|
||||
return;
|
||||
}
|
||||
let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; };
|
||||
let hir::def::Res::Local(hir_id) = path.res else { return; };
|
||||
let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
|
||||
return;
|
||||
};
|
||||
let Some(hir::Node::Local(hir::Local {
|
||||
ty: None,
|
||||
init: Some(init),
|
||||
..
|
||||
})) = self.tcx.hir().find_parent(pat.hir_id) else { return; };
|
||||
let hir::ExprKind::Block(block, None) = init.kind else { return; };
|
||||
if block.expr.is_some() {
|
||||
return;
|
||||
}
|
||||
let [.., stmt] = block.stmts else {
|
||||
err.span_label(block.span, "this empty block is missing a tail expression");
|
||||
return;
|
||||
};
|
||||
let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
|
||||
let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; };
|
||||
if self.can_eq(self.param_env, expected_ty, ty).is_ok() {
|
||||
err.span_suggestion_short(
|
||||
stmt.span.with_lo(tail_expr.span.hi()),
|
||||
"remove this semicolon",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.span_label(block.span, "this block is missing a tail expression");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) => self.check_expr_path(qpath, expr, args),
|
||||
_ => self.check_expr_kind(expr, expected),
|
||||
});
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
|
||||
// Warn for non-block expressions with diverging children.
|
||||
match expr.kind {
|
||||
|
@ -920,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
original_expr_id: HirId,
|
||||
then: impl FnOnce(&hir::Expr<'_>),
|
||||
) {
|
||||
let mut parent = self.tcx.hir().get_parent_node(original_expr_id);
|
||||
let mut parent = self.tcx.hir().parent_id(original_expr_id);
|
||||
while let Some(node) = self.tcx.hir().find(parent) {
|
||||
match node {
|
||||
hir::Node::Expr(hir::Expr {
|
||||
|
@ -943,7 +944,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}) => {
|
||||
// Check if our original expression is a child of the condition of a while loop
|
||||
let expr_is_ancestor = std::iter::successors(Some(original_expr_id), |id| {
|
||||
self.tcx.hir().find_parent_node(*id)
|
||||
self.tcx.hir().opt_parent_id(*id)
|
||||
})
|
||||
.take_while(|id| *id != parent)
|
||||
.any(|id| id == expr.hir_id);
|
||||
|
@ -959,7 +960,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
| hir::Node::TraitItem(_)
|
||||
| hir::Node::Crate(_) => break,
|
||||
_ => {
|
||||
parent = self.tcx.hir().get_parent_node(parent);
|
||||
parent = self.tcx.hir().parent_id(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1083,7 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Do not suggest `if let x = y` as `==` is way more likely to be the intention.
|
||||
let hir = self.tcx.hir();
|
||||
if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
|
||||
hir.get(hir.get_parent_node(hir.get_parent_node(expr.hir_id)))
|
||||
hir.get_parent(hir.parent_id(expr.hir_id))
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
expr.span.shrink_to_lo(),
|
||||
|
@ -2216,7 +2217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
|
||||
return field_ty;
|
||||
}
|
||||
private_candidate = Some((adjustments, base_def.did(), field_ty));
|
||||
private_candidate = Some((adjustments, base_def.did()));
|
||||
}
|
||||
}
|
||||
ty::Tuple(tys) => {
|
||||
|
@ -2239,12 +2240,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
|
||||
if let Some((adjustments, did, field_ty)) = private_candidate {
|
||||
if let Some((adjustments, did)) = private_candidate {
|
||||
// (#90483) apply adjustments to avoid ExprUseVisitor from
|
||||
// creating erroneous projection.
|
||||
self.apply_adjustments(base, adjustments);
|
||||
self.ban_private_field_access(expr, base_ty, field, did);
|
||||
return field_ty;
|
||||
return self.tcx().ty_error();
|
||||
}
|
||||
|
||||
if field.name == kw::Empty {
|
||||
|
@ -2462,7 +2463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.span_label(field.span, "method, not a field");
|
||||
let expr_is_call =
|
||||
if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) =
|
||||
self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id))
|
||||
self.tcx.hir().get_parent(expr.hir_id)
|
||||
{
|
||||
expr.hir_id == callee.hir_id
|
||||
} else {
|
||||
|
|
|
@ -1435,9 +1435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pub(in super::super) fn expr_in_place(&self, mut expr_id: hir::HirId) -> bool {
|
||||
let mut contained_in_place = false;
|
||||
|
||||
while let hir::Node::Expr(parent_expr) =
|
||||
self.tcx.hir().get(self.tcx.hir().get_parent_node(expr_id))
|
||||
{
|
||||
while let hir::Node::Expr(parent_expr) = self.tcx.hir().get_parent(expr_id) {
|
||||
match &parent_expr.kind {
|
||||
hir::ExprKind::Assign(lhs, ..) | hir::ExprKind::AssignOp(_, lhs, ..) => {
|
||||
if lhs.hir_id == expr_id {
|
||||
|
|
|
@ -473,7 +473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
call_expr: &hir::Expr<'tcx>,
|
||||
) {
|
||||
// Next, let's construct the error
|
||||
let (error_span, full_call_span, ctor_of, is_method) = match &call_expr.kind {
|
||||
let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind {
|
||||
hir::ExprKind::Call(
|
||||
hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
|
||||
_,
|
||||
|
@ -481,12 +481,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Res::Def(DefKind::Ctor(of, _), _) =
|
||||
self.typeck_results.borrow().qpath_res(qpath, *hir_id)
|
||||
{
|
||||
(call_span, *span, Some(of), false)
|
||||
let name = match of {
|
||||
CtorOf::Struct => "struct",
|
||||
CtorOf::Variant => "enum variant",
|
||||
};
|
||||
(call_span, *span, name, false)
|
||||
} else {
|
||||
(call_span, *span, None, false)
|
||||
(call_span, *span, "function", false)
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false),
|
||||
hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, "function", false),
|
||||
hir::ExprKind::MethodCall(path_segment, _, _, span) => {
|
||||
let ident_span = path_segment.ident.span;
|
||||
let ident_span = if let Some(args) = path_segment.args {
|
||||
|
@ -494,17 +498,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
ident_span
|
||||
};
|
||||
// methods are never ctors
|
||||
(*span, ident_span, None, true)
|
||||
(*span, ident_span, "method", true)
|
||||
}
|
||||
k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
|
||||
};
|
||||
let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
|
||||
let call_name = match ctor_of {
|
||||
Some(CtorOf::Struct) => "struct",
|
||||
Some(CtorOf::Variant) => "enum variant",
|
||||
None => "function",
|
||||
};
|
||||
|
||||
// Don't print if it has error types or is just plain `_`
|
||||
fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
|
||||
|
@ -690,8 +688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err = tcx.sess.struct_span_err_with_code(
|
||||
full_call_span,
|
||||
&format!(
|
||||
"this {} takes {}{} but {} {} supplied",
|
||||
call_name,
|
||||
"{call_name} takes {}{} but {} {} supplied",
|
||||
if c_variadic { "at least " } else { "" },
|
||||
potentially_plural_count(
|
||||
formal_and_expected_inputs.len(),
|
||||
|
@ -801,6 +798,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
full_call_span,
|
||||
format!("arguments to this {} are incorrect", call_name),
|
||||
);
|
||||
if let (Some(callee_ty), hir::ExprKind::MethodCall(_, rcvr, _, _)) =
|
||||
(callee_ty, &call_expr.kind)
|
||||
{
|
||||
// Type that would have accepted this argument if it hadn't been inferred earlier.
|
||||
// FIXME: We leave an inference variable for now, but it'd be nice to get a more
|
||||
// specific type to increase the accuracy of the diagnostic.
|
||||
let expected = self.infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: full_call_span,
|
||||
});
|
||||
self.point_at_expr_source_of_inferred_type(&mut err, rcvr, expected, callee_ty);
|
||||
}
|
||||
// Call out where the function is defined
|
||||
self.label_fn_like(
|
||||
&mut err,
|
||||
|
@ -1803,7 +1812,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
hir_id: call_hir_id,
|
||||
span: call_span,
|
||||
..
|
||||
}) = hir.get(hir.get_parent_node(expr.hir_id))
|
||||
}) = hir.get_parent(expr.hir_id)
|
||||
&& callee.hir_id == expr.hir_id
|
||||
{
|
||||
if self.closure_span_overlaps_error(error, *call_span) {
|
||||
|
|
|
@ -32,7 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.typeck_results
|
||||
.borrow()
|
||||
.liberated_fn_sigs()
|
||||
.get(self.tcx.hir().get_parent_node(self.body_id))
|
||||
.get(self.tcx.hir().parent_id(self.body_id))
|
||||
.copied()
|
||||
}
|
||||
|
||||
|
@ -642,7 +642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Check if the parent expression is a call to Pin::new. If it
|
||||
// is and we were expecting a Box, ergo Pin<Box<expected>>, we
|
||||
// can suggest Box::pin.
|
||||
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
|
||||
let parent = self.tcx.hir().parent_id(expr.hir_id);
|
||||
let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) = self.tcx.hir().find(parent) else {
|
||||
return false;
|
||||
};
|
||||
|
@ -1014,6 +1014,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_clone_for_ref(
|
||||
&self,
|
||||
diag: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
expr_ty: Ty<'tcx>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
if let ty::Ref(_, inner_ty, hir::Mutability::Not) = expr_ty.kind()
|
||||
&& let Some(clone_trait_def) = self.tcx.lang_items().clone_trait()
|
||||
&& expected_ty == *inner_ty
|
||||
&& self
|
||||
.infcx
|
||||
.type_implements_trait(
|
||||
clone_trait_def,
|
||||
[self.tcx.erase_regions(expected_ty)],
|
||||
self.param_env
|
||||
)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
"consider using clone here",
|
||||
".clone()",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_copied_or_cloned(
|
||||
&self,
|
||||
diag: &mut Diagnostic,
|
||||
|
|
|
@ -140,7 +140,7 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
|
|||
diag_expr_id: HirId,
|
||||
) {
|
||||
let hir = self.tcx.hir();
|
||||
let parent = match hir.find_parent_node(place_with_id.hir_id) {
|
||||
let parent = match hir.opt_parent_id(place_with_id.hir_id) {
|
||||
Some(parent) => parent,
|
||||
None => place_with_id.hir_id,
|
||||
};
|
||||
|
|
|
@ -224,7 +224,7 @@ fn typeck_with_fallback<'tcx>(
|
|||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| match tcx.hir().get(id) {
|
||||
Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
|
||||
Node::AnonConst(_) => match tcx.hir().get(tcx.hir().parent_id(id)) {
|
||||
Node::Expr(&hir::Expr {
|
||||
kind: hir::ExprKind::ConstBlock(ref anon_const),
|
||||
..
|
||||
|
@ -240,10 +240,8 @@ fn typeck_with_fallback<'tcx>(
|
|||
}),
|
||||
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
|
||||
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
|
||||
let operand_ty = asm
|
||||
.operands
|
||||
.iter()
|
||||
.filter_map(|(op, _op_sp)| match op {
|
||||
let operand_ty =
|
||||
asm.operands.iter().find_map(|(op, _op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const }
|
||||
if anon_const.hir_id == id =>
|
||||
{
|
||||
|
@ -259,8 +257,7 @@ fn typeck_with_fallback<'tcx>(
|
|||
}))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.next();
|
||||
});
|
||||
operand_ty.unwrap_or_else(fallback)
|
||||
}
|
||||
_ => fallback(),
|
||||
|
|
|
@ -57,7 +57,12 @@ pub enum MethodError<'tcx> {
|
|||
PrivateMatch(DefKind, DefId, Vec<DefId>),
|
||||
|
||||
// Found a `Self: Sized` bound where `Self` is a trait object.
|
||||
IllegalSizedBound(Vec<DefId>, bool, Span),
|
||||
IllegalSizedBound {
|
||||
candidates: Vec<DefId>,
|
||||
needs_mut: bool,
|
||||
bound_span: Span,
|
||||
self_expr: &'tcx hir::Expr<'tcx>,
|
||||
},
|
||||
|
||||
// Found a match, but the return type is wrong
|
||||
BadReturnType,
|
||||
|
@ -112,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Err(NoMatch(..)) => false,
|
||||
Err(Ambiguity(..)) => true,
|
||||
Err(PrivateMatch(..)) => allow_private,
|
||||
Err(IllegalSizedBound(..)) => true,
|
||||
Err(IllegalSizedBound { .. }) => true,
|
||||
Err(BadReturnType) => bug!("no return type expectations but got BadReturnType"),
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
return Err(IllegalSizedBound(candidates, needs_mut, span));
|
||||
return Err(IllegalSizedBound { candidates, needs_mut, bound_span: span, self_expr });
|
||||
}
|
||||
|
||||
Ok(result.callee)
|
||||
|
|
|
@ -341,8 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Find an identifier with which this trait was imported (note that `_` doesn't count).
|
||||
let any_id = import_items
|
||||
.iter()
|
||||
.filter_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None })
|
||||
.next();
|
||||
.find_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None });
|
||||
if let Some(any_id) = any_id {
|
||||
if any_id.name == Empty {
|
||||
// Glob import, so just use its name.
|
||||
|
|
|
@ -1111,7 +1111,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
// a raw pointer
|
||||
!step.self_ty.references_error() && !step.from_unsafe_deref
|
||||
})
|
||||
.flat_map(|step| {
|
||||
.find_map(|step| {
|
||||
let InferOk { value: self_ty, obligations: _ } = self
|
||||
.fcx
|
||||
.probe_instantiate_query_response(
|
||||
|
@ -1147,7 +1147,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
})
|
||||
})
|
||||
})
|
||||
.next()
|
||||
}
|
||||
|
||||
/// For each type `T` in the step list, this attempts to find a method where
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -553,6 +553,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
(lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
|
||||
_ => span_bug!(span, "Impossible, verified above."),
|
||||
}
|
||||
if (lhs, rhs).references_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
if self.tcx.sess.teach(&err.get_code().unwrap()) {
|
||||
err.note(
|
||||
"In a match expression, only numbers and characters can be matched \
|
||||
|
@ -692,7 +695,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let tcx = self.tcx;
|
||||
if let PatKind::Ref(inner, mutbl) = pat.kind
|
||||
&& let PatKind::Binding(_, _, binding, ..) = inner.kind {
|
||||
let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
|
||||
let binding_parent_id = tcx.hir().parent_id(pat.hir_id);
|
||||
let binding_parent = tcx.hir().get(binding_parent_id);
|
||||
debug!(?inner, ?pat, ?binding_parent);
|
||||
|
||||
|
@ -936,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
res.descr(),
|
||||
),
|
||||
);
|
||||
match self.tcx.hir().get(self.tcx.hir().get_parent_node(pat.hir_id)) {
|
||||
match self.tcx.hir().get_parent(pat.hir_id) {
|
||||
hir::Node::PatField(..) => {
|
||||
e.span_suggestion_verbose(
|
||||
ident.span.shrink_to_hi(),
|
||||
|
|
|
@ -1091,7 +1091,7 @@ impl<T: Idx> ToString for BitSet<T> {
|
|||
assert!(mask <= 0xFF);
|
||||
let byte = word & mask;
|
||||
|
||||
result.push_str(&format!("{}{:02x}", sep, byte));
|
||||
result.push_str(&format!("{sep}{byte:02x}"));
|
||||
|
||||
if remain <= 8 {
|
||||
break;
|
||||
|
|
|
@ -135,10 +135,7 @@ impl<I: Idx> IntervalSet<I> {
|
|||
};
|
||||
debug_assert!(
|
||||
self.check_invariants(),
|
||||
"wrong intervals after insert {:?}..={:?} to {:?}",
|
||||
start,
|
||||
end,
|
||||
self
|
||||
"wrong intervals after insert {start:?}..={end:?} to {self:?}"
|
||||
);
|
||||
result
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
use hir::GenericParamKind;
|
||||
use rustc_errors::{
|
||||
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
|
||||
MultiSpan, SubdiagnosticMessage,
|
||||
IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{FnRetTy, Ty};
|
||||
use rustc_hir::FnRetTy;
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{Region, TyCtxt};
|
||||
use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath;
|
||||
use rustc_middle::ty::{Binder, FnSig, Region, Ty, TyCtxt};
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{symbol::Ident, BytePos, Span};
|
||||
|
||||
use crate::infer::error_reporting::nice_region_error::placeholder_error::Highlighted;
|
||||
use crate::infer::error_reporting::{
|
||||
need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
|
||||
ObligationCauseAsDiagArg,
|
||||
|
@ -357,8 +360,8 @@ impl AddToDiagnostic for LifetimeMismatchLabels {
|
|||
pub struct AddLifetimeParamsSuggestion<'a> {
|
||||
pub tcx: TyCtxt<'a>,
|
||||
pub sub: Region<'a>,
|
||||
pub ty_sup: &'a Ty<'a>,
|
||||
pub ty_sub: &'a Ty<'a>,
|
||||
pub ty_sup: &'a hir::Ty<'a>,
|
||||
pub ty_sub: &'a hir::Ty<'a>,
|
||||
pub add_note: bool,
|
||||
}
|
||||
|
||||
|
@ -520,3 +523,411 @@ pub struct MismatchedStaticLifetime<'a> {
|
|||
#[subdiagnostic]
|
||||
pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub enum ExplicitLifetimeRequired<'a> {
|
||||
#[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")]
|
||||
WithIdent {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
span: Span,
|
||||
simple_ident: Ident,
|
||||
named: String,
|
||||
#[suggestion(
|
||||
infer_explicit_lifetime_required_sugg_with_ident,
|
||||
code = "{new_ty}",
|
||||
applicability = "unspecified"
|
||||
)]
|
||||
new_ty_span: Span,
|
||||
#[skip_arg]
|
||||
new_ty: Ty<'a>,
|
||||
},
|
||||
#[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")]
|
||||
WithParamType {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
span: Span,
|
||||
named: String,
|
||||
#[suggestion(
|
||||
infer_explicit_lifetime_required_sugg_with_param_type,
|
||||
code = "{new_ty}",
|
||||
applicability = "unspecified"
|
||||
)]
|
||||
new_ty_span: Span,
|
||||
#[skip_arg]
|
||||
new_ty: Ty<'a>,
|
||||
},
|
||||
}
|
||||
|
||||
pub enum TyOrSig<'tcx> {
|
||||
Ty(Highlighted<'tcx, Ty<'tcx>>),
|
||||
ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for TyOrSig<'_> {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||
match self {
|
||||
TyOrSig::Ty(ty) => ty.into_diagnostic_arg(),
|
||||
TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum ActualImplExplNotes<'tcx> {
|
||||
#[note(infer_actual_impl_expl_expected_signature_two)]
|
||||
ExpectedSignatureTwo {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
lifetime_2: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_signature_any)]
|
||||
ExpectedSignatureAny {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_signature_some)]
|
||||
ExpectedSignatureSome {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_signature_nothing)]
|
||||
ExpectedSignatureNothing {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_passive_two)]
|
||||
ExpectedPassiveTwo {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
lifetime_2: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_passive_any)]
|
||||
ExpectedPassiveAny {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_passive_some)]
|
||||
ExpectedPassiveSome {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_passive_nothing)]
|
||||
ExpectedPassiveNothing {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_other_two)]
|
||||
ExpectedOtherTwo {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
lifetime_2: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_other_any)]
|
||||
ExpectedOtherAny {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_other_some)]
|
||||
ExpectedOtherSome {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_expected_other_nothing)]
|
||||
ExpectedOtherNothing {
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_but_actually_implements_trait)]
|
||||
ButActuallyImplementsTrait {
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
has_lifetime: bool,
|
||||
lifetime: usize,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_but_actually_implemented_for_ty)]
|
||||
ButActuallyImplementedForTy {
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
has_lifetime: bool,
|
||||
lifetime: usize,
|
||||
ty: String,
|
||||
},
|
||||
#[note(infer_actual_impl_expl_but_actually_ty_implements)]
|
||||
ButActuallyTyImplements {
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
has_lifetime: bool,
|
||||
lifetime: usize,
|
||||
ty: String,
|
||||
},
|
||||
}
|
||||
|
||||
pub enum ActualImplExpectedKind {
|
||||
Signature,
|
||||
Passive,
|
||||
Other,
|
||||
}
|
||||
|
||||
pub enum ActualImplExpectedLifetimeKind {
|
||||
Two,
|
||||
Any,
|
||||
Some,
|
||||
Nothing,
|
||||
}
|
||||
|
||||
impl<'tcx> ActualImplExplNotes<'tcx> {
|
||||
pub fn new_expected(
|
||||
kind: ActualImplExpectedKind,
|
||||
lt_kind: ActualImplExpectedLifetimeKind,
|
||||
leading_ellipsis: bool,
|
||||
ty_or_sig: TyOrSig<'tcx>,
|
||||
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
lifetime_1: usize,
|
||||
lifetime_2: usize,
|
||||
) -> Self {
|
||||
match (kind, lt_kind) {
|
||||
(ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
|
||||
Self::ExpectedSignatureTwo {
|
||||
leading_ellipsis,
|
||||
ty_or_sig,
|
||||
trait_path,
|
||||
lifetime_1,
|
||||
lifetime_2,
|
||||
}
|
||||
}
|
||||
(ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
|
||||
Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||
}
|
||||
(ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
|
||||
Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||
}
|
||||
(ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
|
||||
Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
|
||||
}
|
||||
(ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
|
||||
Self::ExpectedPassiveTwo {
|
||||
leading_ellipsis,
|
||||
ty_or_sig,
|
||||
trait_path,
|
||||
lifetime_1,
|
||||
lifetime_2,
|
||||
}
|
||||
}
|
||||
(ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
|
||||
Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||
}
|
||||
(ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
|
||||
Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||
}
|
||||
(ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
|
||||
Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
|
||||
}
|
||||
(ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
|
||||
Self::ExpectedOtherTwo {
|
||||
leading_ellipsis,
|
||||
ty_or_sig,
|
||||
trait_path,
|
||||
lifetime_1,
|
||||
lifetime_2,
|
||||
}
|
||||
}
|
||||
(ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
|
||||
Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||
}
|
||||
(ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
|
||||
Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||
}
|
||||
(ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
|
||||
Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(infer_trait_placeholder_mismatch)]
|
||||
pub struct TraitPlaceholderMismatch<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label(label_satisfy)]
|
||||
pub satisfy_span: Option<Span>,
|
||||
#[label(label_where)]
|
||||
pub where_span: Option<Span>,
|
||||
#[label(label_dup)]
|
||||
pub dup_span: Option<Span>,
|
||||
pub def_id: String,
|
||||
pub trait_def_id: String,
|
||||
|
||||
#[subdiagnostic]
|
||||
pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
|
||||
}
|
||||
|
||||
pub struct ConsiderBorrowingParamHelp {
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
impl AddToDiagnostic for ConsiderBorrowingParamHelp {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
let mut type_param_span: MultiSpan = self.spans.clone().into();
|
||||
for &span in &self.spans {
|
||||
// Seems like we can't call f() here as Into<DiagnosticMessage> is required
|
||||
type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing);
|
||||
}
|
||||
let msg = f(diag, fluent::infer_tid_param_help.into());
|
||||
diag.span_help(type_param_span, msg);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[help(infer_tid_rel_help)]
|
||||
pub struct RelationshipHelp;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(infer_trait_impl_diff)]
|
||||
pub struct TraitImplDiff {
|
||||
#[primary_span]
|
||||
#[label(found)]
|
||||
pub sp: Span,
|
||||
#[label(expected)]
|
||||
pub trait_sp: Span,
|
||||
#[note(expected_found)]
|
||||
pub note: (),
|
||||
#[subdiagnostic]
|
||||
pub param_help: ConsiderBorrowingParamHelp,
|
||||
#[subdiagnostic]
|
||||
// Seems like subdiagnostics are always pushed to the end, so this one
|
||||
// also has to be a subdiagnostic to maintain order.
|
||||
pub rel_help: Option<RelationshipHelp>,
|
||||
pub expected: String,
|
||||
pub found: String,
|
||||
}
|
||||
|
||||
pub struct DynTraitConstraintSuggestion {
|
||||
pub span: Span,
|
||||
pub ident: Ident,
|
||||
}
|
||||
|
||||
impl AddToDiagnostic for DynTraitConstraintSuggestion {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
let mut multi_span: MultiSpan = vec![self.span].into();
|
||||
multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
|
||||
multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement);
|
||||
let msg = f(diag, fluent::infer_dtcs_has_req_note.into());
|
||||
diag.span_note(multi_span, msg);
|
||||
let msg = f(diag, fluent::infer_dtcs_suggestion.into());
|
||||
diag.span_suggestion_verbose(
|
||||
self.span.shrink_to_hi(),
|
||||
msg,
|
||||
" + '_",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(infer_but_calling_introduces, code = "E0772")]
|
||||
pub struct ButCallingIntroduces {
|
||||
#[label(label1)]
|
||||
pub param_ty_span: Span,
|
||||
#[primary_span]
|
||||
#[label(label2)]
|
||||
pub cause_span: Span,
|
||||
|
||||
pub has_param_name: bool,
|
||||
pub param_name: String,
|
||||
pub has_lifetime: bool,
|
||||
pub lifetime: String,
|
||||
pub assoc_item: Symbol,
|
||||
pub has_impl_path: bool,
|
||||
pub impl_path: String,
|
||||
}
|
||||
|
||||
pub struct ReqIntroducedLocations {
|
||||
pub span: MultiSpan,
|
||||
pub spans: Vec<Span>,
|
||||
pub fn_decl_span: Span,
|
||||
pub cause_span: Span,
|
||||
pub add_label: bool,
|
||||
}
|
||||
|
||||
impl AddToDiagnostic for ReqIntroducedLocations {
|
||||
fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
for sp in self.spans {
|
||||
self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
|
||||
}
|
||||
|
||||
if self.add_label {
|
||||
self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by);
|
||||
}
|
||||
self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of);
|
||||
let msg = f(diag, fluent::infer_ril_static_introduced_by.into());
|
||||
diag.span_note(self.span, msg);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MoreTargeted {
|
||||
pub ident: Symbol,
|
||||
}
|
||||
|
||||
impl AddToDiagnostic for MoreTargeted {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.code(rustc_errors::error_code!(E0772));
|
||||
diag.set_primary_message(fluent::infer_more_targeted);
|
||||
diag.set_arg("ident", self.ident);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(infer_but_needs_to_satisfy, code = "E0759")]
|
||||
pub struct ButNeedsToSatisfy {
|
||||
#[primary_span]
|
||||
pub sp: Span,
|
||||
#[label(influencer)]
|
||||
pub influencer_point: Span,
|
||||
#[label(used_here)]
|
||||
pub spans: Vec<Span>,
|
||||
#[label(require)]
|
||||
pub require_span_as_label: Option<Span>,
|
||||
#[note(require)]
|
||||
pub require_span_as_note: Option<Span>,
|
||||
#[note(introduced_by_bound)]
|
||||
pub bound: Option<Span>,
|
||||
|
||||
#[subdiagnostic]
|
||||
pub req_introduces_loc: Option<ReqIntroducedLocations>,
|
||||
|
||||
pub spans_empty: bool,
|
||||
pub has_lifetime: bool,
|
||||
pub lifetime: String,
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue