Rollup merge of #144651 - connortsui20:nonpoison_condvar, r=joboet
Implementation: `#[feature(nonpoison_condvar)]`
Tracking Issue: https://github.com/rust-lang/rust/issues/134645
This PR continues the effort made in https://github.com/rust-lang/rust/pull/144022 by adding the implementation of `nonpoison::condvar`.
Many of the changes here are similar to the changes made to implement `nonpoison::mutex`.
There are two other changes here. The first is that the `Barrier` implementation is migrated to use the `nonpoison::Condvar` instead of the `poison` variant. The second (which might be subject to some discussion) is that `WaitTimeoutResult` is moved up to `mod.rs`, as both `condvar` variants need that type (and I do not know if there is a better place to put it now).
### Related PRs
- `nonpoison_rwlock` implementation: https://github.com/rust-lang/rust/pull/144648
- `nonpoison_once` implementation: https://github.com/rust-lang/rust/pull/144653
diff --git a/.mailmap b/.mailmap
index 2b75f5a..6e3eed1 100644
--- a/.mailmap
+++ b/.mailmap
@@ -255,6 +255,7 @@
Guillaume Gomez <guillaume1.gomez@gmail.com> ggomez <ggomez@ggo.ifr.lan>
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <ggomez@ggo.ifr.lan>
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume.gomez@huawei.com>
+gnzlbg <gonzalobg88@gmail.com> <gnzlbg@users.noreply.github.com>
hamidreza kalbasi <hamidrezakalbasi@protonmail.com>
Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com>
Heather <heather@cynede.net> <Cynede@Gentoo.org>
diff --git a/Cargo.lock b/Cargo.lock
index 1d36ba4..8b9c243 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -152,9 +152,9 @@
[[package]]
name = "anyhow"
-version = "1.0.98"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
+checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
[[package]]
name = "ar_archive_writer"
@@ -204,7 +204,7 @@
"rustc-hash 2.1.1",
"serde",
"serde_derive",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -266,9 +266,9 @@
[[package]]
name = "bitflags"
-version = "2.9.1"
+version = "2.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
[[package]]
name = "blake3"
@@ -315,7 +315,7 @@
"serde_json",
"sha2",
"tar",
- "toml 0.5.11",
+ "toml 0.7.8",
"xz2",
]
@@ -336,7 +336,7 @@
"curl",
"indexmap",
"serde",
- "toml 0.5.11",
+ "toml 0.7.8",
]
[[package]]
@@ -421,7 +421,7 @@
"serde",
"serde-untagged",
"serde-value",
- "thiserror 2.0.12",
+ "thiserror 2.0.15",
"toml 0.8.23",
"unicode-xid",
"url",
@@ -453,7 +453,7 @@
"semver",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.15",
]
[[package]]
@@ -518,9 +518,9 @@
[[package]]
name = "clap"
-version = "4.5.43"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50fd97c9dc2399518aa331917ac6f274280ec5eb34e555dd291899745c48ec6f"
+checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
dependencies = [
"clap_builder",
"clap_derive",
@@ -538,9 +538,9 @@
[[package]]
name = "clap_builder"
-version = "4.5.43"
+version = "4.5.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c35b5830294e1fa0462034af85cc95225a4cb07092c088c55bda3147cfcd8f65"
+checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
dependencies = [
"anstream",
"anstyle",
@@ -550,14 +550,14 @@
[[package]]
name = "clap_derive"
-version = "4.5.41"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
+checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -720,7 +720,7 @@
"nom",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -907,9 +907,9 @@
[[package]]
name = "curl"
-version = "0.4.48"
+version = "0.4.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e2d5c8f48d9c0c23250e52b55e82a6ab4fdba6650c931f5a0a57a43abda812b"
+checksum = "79fc3b6dd0b87ba36e565715bf9a2ced221311db47bd18011676f24a6066edbc"
dependencies = [
"curl-sys",
"libc",
@@ -922,9 +922,9 @@
[[package]]
name = "curl-sys"
-version = "0.4.82+curl-8.14.1"
+version = "0.4.83+curl-8.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4d63638b5ec65f1a4ae945287b3fd035be4554bbaf211901159c9a2a74fb5be"
+checksum = "5830daf304027db10c82632a464879d46a3f7c4ba17a31592657ad16c719b483"
dependencies = [
"cc",
"libc",
@@ -937,9 +937,9 @@
[[package]]
name = "cxx"
-version = "1.0.166"
+version = "1.0.168"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5287274dfdf7e7eaa3d97d460eb2a94922539e6af214bda423f292105011ee2"
+checksum = "7aa144b12f11741f0dab5b4182896afad46faa0598b6a061f7b9d17a21837ba7"
dependencies = [
"cc",
"cxxbridge-cmd",
@@ -951,9 +951,9 @@
[[package]]
name = "cxx-build"
-version = "1.0.166"
+version = "1.0.168"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65f3ce027a744135db10a1ebffa0863dab685aeef48f40a02c201f5e70c667d3"
+checksum = "12d3cbb84fb003242941c231b45ca9417e786e66e94baa39584bd99df3a270b6"
dependencies = [
"cc",
"codespan-reporting",
@@ -961,40 +961,40 @@
"proc-macro2",
"quote",
"scratch",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "cxxbridge-cmd"
-version = "1.0.166"
+version = "1.0.168"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a07dc23f2eea4774297f4c9a17ae4065fecb63127da556e6c9fadb0216d93595"
+checksum = "3fa36b7b249d43f67a3f54bd65788e35e7afe64bbc671396387a48b3e8aaea94"
dependencies = [
"clap",
"codespan-reporting",
"indexmap",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "cxxbridge-flags"
-version = "1.0.166"
+version = "1.0.168"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7a4dbad6171f763c4066c83dcd27546b6e93c5c5ae2229f9813bda7233f571d"
+checksum = "77707c70f6563edc5429618ca34a07241b75ebab35bd01d46697c75d58f8ddfe"
[[package]]
name = "cxxbridge-macro"
-version = "1.0.166"
+version = "1.0.168"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9be4b527950fc42db06163705e78e73eedc8fd723708e942afe3572a9a2c366"
+checksum = "ede6c0fb7e318f0a11799b86ee29dcf17b9be2960bd379a6c38e1a96a6010fff"
dependencies = [
"indexmap",
"proc-macro2",
"quote",
"rustversion",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1018,7 +1018,7 @@
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1029,7 +1029,7 @@
dependencies = [
"darling_core",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1061,7 +1061,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1082,7 +1082,7 @@
"darling",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1092,7 +1092,7 @@
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1104,7 +1104,7 @@
"darling",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1129,16 +1129,16 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d"
dependencies = [
- "dirs-sys 0.5.0",
+ "dirs-sys",
]
[[package]]
name = "dirs"
-version = "5.0.1"
+version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
+checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
dependencies = [
- "dirs-sys 0.4.1",
+ "dirs-sys",
]
[[package]]
@@ -1153,18 +1153,6 @@
[[package]]
name = "dirs-sys"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
-dependencies = [
- "libc",
- "option-ext",
- "redox_users 0.4.6",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "dirs-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
@@ -1194,7 +1182,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1379,7 +1367,7 @@
checksum = "54f0d287c53ffd184d04d8677f590f4ac5379785529e5e08b1c8083acdd5c198"
dependencies = [
"memchr",
- "thiserror 2.0.12",
+ "thiserror 2.0.15",
]
[[package]]
@@ -1539,9 +1527,9 @@
[[package]]
name = "glob"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
+checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
name = "globset"
@@ -1686,30 +1674,40 @@
dependencies = [
"displaydoc",
"potential_utf",
- "yoke 0.8.0",
+ "yoke",
"zerofrom",
- "zerovec 0.11.4",
+ "zerovec",
]
[[package]]
name = "icu_list"
-version = "1.5.0"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbfeda1d7775b6548edd4e8b7562304a559a91ed56ab56e18961a053f367c365"
+checksum = "e26f94ec776bb8b28cedc7dcf91033b822c5cb4c1783cf7a3f796fc168aa0c8b"
dependencies = [
"displaydoc",
- "icu_list_data",
- "icu_locid_transform",
- "icu_provider 1.5.0",
- "regex-automata 0.2.0",
- "writeable 0.5.5",
+ "icu_provider",
+ "regex-automata 0.4.9",
+ "serde",
+ "writeable",
+ "zerovec",
]
[[package]]
-name = "icu_list_data"
-version = "1.5.1"
+name = "icu_locale"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52b1a7fbdbf3958f1be8354cb59ac73f165b7b7082d447ff2090355c9a069120"
+checksum = "6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locale_core",
+ "icu_locale_data",
+ "icu_provider",
+ "potential_utf",
+ "tinystr",
+ "zerovec",
+]
[[package]]
name = "icu_locale_core"
@@ -1718,44 +1716,17 @@
checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
dependencies = [
"displaydoc",
- "litemap 0.8.0",
- "tinystr 0.8.1",
- "writeable 0.6.1",
- "zerovec 0.11.4",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
]
[[package]]
-name = "icu_locid"
-version = "1.5.0"
+name = "icu_locale_data"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
-dependencies = [
- "displaydoc",
- "litemap 0.7.5",
- "tinystr 0.7.6",
- "writeable 0.5.5",
- "zerovec 0.10.4",
-]
-
-[[package]]
-name = "icu_locid_transform"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_locid_transform_data",
- "icu_provider 1.5.0",
- "tinystr 0.7.6",
- "zerovec 0.10.4",
-]
-
-[[package]]
-name = "icu_locid_transform_data"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
+checksum = "4fdef0c124749d06a743c69e938350816554eb63ac979166590e2b4ee4252765"
[[package]]
name = "icu_normalizer"
@@ -1767,9 +1738,9 @@
"icu_collections",
"icu_normalizer_data",
"icu_properties",
- "icu_provider 2.0.0",
+ "icu_provider",
"smallvec",
- "zerovec 0.11.4",
+ "zerovec",
]
[[package]]
@@ -1788,10 +1759,10 @@
"icu_collections",
"icu_locale_core",
"icu_properties_data",
- "icu_provider 2.0.0",
+ "icu_provider",
"potential_utf",
"zerotrie",
- "zerovec 0.11.4",
+ "zerovec",
]
[[package]]
@@ -1802,23 +1773,6 @@
[[package]]
name = "icu_provider"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_provider_macros",
- "stable_deref_trait",
- "tinystr 0.7.6",
- "writeable 0.5.5",
- "yoke 0.7.5",
- "zerofrom",
- "zerovec 0.10.4",
-]
-
-[[package]]
-name = "icu_provider"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
@@ -1826,36 +1780,12 @@
"displaydoc",
"icu_locale_core",
"stable_deref_trait",
- "tinystr 0.8.1",
- "writeable 0.6.1",
- "yoke 0.8.0",
+ "tinystr",
+ "writeable",
+ "yoke",
"zerofrom",
"zerotrie",
- "zerovec 0.11.4",
-]
-
-[[package]]
-name = "icu_provider_adapters"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6324dfd08348a8e0374a447ebd334044d766b1839bb8d5ccf2482a99a77c0bc"
-dependencies = [
- "icu_locid",
- "icu_locid_transform",
- "icu_provider 1.5.0",
- "tinystr 0.7.6",
- "zerovec 0.10.4",
-]
-
-[[package]]
-name = "icu_provider_macros"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.104",
+ "zerovec",
]
[[package]]
@@ -2044,7 +1974,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2102,7 +2032,7 @@
"pest_derive",
"regex",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.15",
]
[[package]]
@@ -2257,12 +2187,6 @@
[[package]]
name = "litemap"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
-
-[[package]]
-name = "litemap"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
@@ -2337,7 +2261,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2643,9 +2567,9 @@
[[package]]
name = "object"
-version = "0.37.2"
+version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3e3d0a7419f081f4a808147e845310313a39f322d7ae1f996b7f001d6cbed04"
+checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
"crc32fast",
"flate2",
@@ -2653,7 +2577,7 @@
"indexmap",
"memchr",
"ruzstd 0.8.1",
- "wasmparser 0.236.0",
+ "wasmparser 0.236.1",
]
[[package]]
@@ -2834,7 +2758,7 @@
checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323"
dependencies = [
"memchr",
- "thiserror 2.0.12",
+ "thiserror 2.0.15",
"ucd-trie",
]
@@ -2858,7 +2782,7 @@
"pest_meta",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2971,7 +2895,8 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
dependencies = [
- "zerovec 0.11.4",
+ "serde",
+ "zerovec",
]
[[package]]
@@ -3007,9 +2932,9 @@
[[package]]
name = "proc-macro2"
-version = "1.0.95"
+version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
@@ -3147,9 +3072,9 @@
[[package]]
name = "rayon"
-version = "1.10.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
@@ -3157,9 +3082,9 @@
[[package]]
name = "rayon-core"
-version = "1.12.1"
+version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
@@ -3193,7 +3118,7 @@
dependencies = [
"getrandom 0.2.16",
"libredox",
- "thiserror 2.0.12",
+ "thiserror 2.0.15",
]
[[package]]
@@ -3219,15 +3144,6 @@
[[package]]
name = "regex-automata"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9368763f5a9b804326f3af749e16f9abf378d227bcdee7634b13d8f17793782"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
@@ -3279,11 +3195,11 @@
"build_helper",
"gimli 0.32.0",
"libc",
- "object 0.37.2",
+ "object 0.37.3",
"regex",
"serde_json",
"similar",
- "wasmparser 0.236.0",
+ "wasmparser 0.236.1",
]
[[package]]
@@ -3492,6 +3408,7 @@
"rustc_parse",
"rustc_session",
"rustc_span",
+ "rustc_target",
"thin-vec",
]
@@ -3500,10 +3417,9 @@
version = "0.0.0"
dependencies = [
"icu_list",
- "icu_locid",
- "icu_locid_transform",
- "icu_provider 1.5.0",
- "zerovec 0.10.4",
+ "icu_locale",
+ "icu_provider",
+ "zerovec",
]
[[package]]
@@ -3570,7 +3486,7 @@
"itertools",
"libc",
"measureme",
- "object 0.37.2",
+ "object 0.37.3",
"rustc-demangle",
"rustc_abi",
"rustc_ast",
@@ -3608,7 +3524,7 @@
"cc",
"itertools",
"libc",
- "object 0.37.2",
+ "object 0.37.3",
"pathdiff",
"regex",
"rustc_abi",
@@ -3776,8 +3692,7 @@
"fluent-bundle",
"fluent-syntax",
"icu_list",
- "icu_locid",
- "icu_provider_adapters",
+ "icu_locale",
"intl-memoizer",
"rustc_ast",
"rustc_ast_pretty",
@@ -3803,7 +3718,6 @@
"rustc_error_messages",
"rustc_fluent_macro",
"rustc_hashes",
- "rustc_hir_id",
"rustc_index",
"rustc_lexer",
"rustc_lint_defs",
@@ -3864,7 +3778,7 @@
"fluent-syntax",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"unic-langid",
]
@@ -4024,7 +3938,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -4169,7 +4083,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"synstructure",
]
@@ -4653,7 +4567,7 @@
version = "0.0.0"
dependencies = [
"bitflags",
- "object 0.37.2",
+ "object 0.37.3",
"rustc_abi",
"rustc_data_structures",
"rustc_error_messages",
@@ -4791,7 +4705,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"synstructure",
]
@@ -4883,7 +4797,7 @@
"proc-macro2",
"quote",
"serde",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -5020,9 +4934,9 @@
[[package]]
name = "serde-untagged"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e"
+checksum = "34836a629bcbc6f1afdf0907a744870039b1e14c0561cb26094fa683b158eff3"
dependencies = [
"erased-serde",
"serde",
@@ -5047,7 +4961,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -5138,12 +5052,12 @@
[[package]]
name = "socket2"
-version = "0.5.10"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -5283,9 +5197,9 @@
[[package]]
name = "syn"
-version = "2.0.104"
+version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
@@ -5300,7 +5214,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -5418,11 +5332,11 @@
[[package]]
name = "thiserror"
-version = "2.0.12"
+version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850"
dependencies = [
- "thiserror-impl 2.0.12",
+ "thiserror-impl 2.0.15",
]
[[package]]
@@ -5433,18 +5347,18 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.12"
+version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -5512,22 +5426,12 @@
[[package]]
name = "tinystr"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
-dependencies = [
- "displaydoc",
- "zerovec 0.10.4",
-]
-
-[[package]]
-name = "tinystr"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
dependencies = [
"displaydoc",
- "zerovec 0.11.4",
+ "zerovec",
]
[[package]]
@@ -5547,15 +5451,6 @@
[[package]]
name = "toml"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "toml"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
@@ -5641,7 +5536,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -5801,7 +5696,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658"
dependencies = [
- "tinystr 0.8.1",
+ "tinystr",
]
[[package]]
@@ -5811,7 +5706,7 @@
checksum = "d5957eb82e346d7add14182a3315a7e298f04e1ba4baac36f7f0dbfedba5fc25"
dependencies = [
"proc-macro-hack",
- "tinystr 0.8.1",
+ "tinystr",
"unic-langid-impl",
"unic-langid-macros-impl",
]
@@ -5824,7 +5719,7 @@
dependencies = [
"proc-macro-hack",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"unic-langid-impl",
]
@@ -5956,9 +5851,9 @@
[[package]]
name = "uuid"
-version = "1.17.0"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
+checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
dependencies = [
"getrandom 0.3.3",
"js-sys",
@@ -6010,9 +5905,9 @@
[[package]]
name = "wasi-preview1-component-adapter-provider"
-version = "34.0.2"
+version = "36.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33696c5f1ff1e083de9f36c3da471abd736362bc173e093f8b0b1ed5a387e39b"
+checksum = "20689c88791776219f78c2529700d15e6a9bd57a27858c62e9ef8487956b571c"
[[package]]
name = "wasm-bindgen"
@@ -6036,7 +5931,7 @@
"log",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"wasm-bindgen-shared",
]
@@ -6058,7 +5953,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -6074,9 +5969,9 @@
[[package]]
name = "wasm-component-ld"
-version = "0.5.15"
+version = "0.5.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d95124e34fee1316222e03b9bbf41af186ecbae2c8b79f8debe6e21b3ff60c5"
+checksum = "14cd35d6cae91109a0ffd207b573cf3c741cab7e921dd376ea7aaf2c52a3408c"
dependencies = [
"anyhow",
"clap",
@@ -6084,7 +5979,7 @@
"libc",
"tempfile",
"wasi-preview1-component-adapter-provider",
- "wasmparser 0.234.0",
+ "wasmparser 0.237.0",
"wat",
"windows-sys 0.59.0",
"winsplit",
@@ -6111,34 +6006,24 @@
[[package]]
name = "wasm-encoder"
-version = "0.234.0"
+version = "0.237.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "170a0157eef517a179f2d20ed7c68df9c3f7f6c1c047782d488bf5a464174684"
+checksum = "efe92d1321afa53ffc88a57c497bb7330c3cf84c98ffdba4a4caf6a0684fad3c"
dependencies = [
"leb128fmt",
- "wasmparser 0.234.0",
-]
-
-[[package]]
-name = "wasm-encoder"
-version = "0.236.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3108979166ab0d3c7262d2e16a2190ffe784b2a5beb963edef154b5e8e07680b"
-dependencies = [
- "leb128fmt",
- "wasmparser 0.236.0",
+ "wasmparser 0.237.0",
]
[[package]]
name = "wasm-metadata"
-version = "0.234.0"
+version = "0.237.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a42fe3f5cbfb56fc65311ef827930d06189160038e81db62188f66b4bf468e3a"
+checksum = "4cc0b0a0c4f35ca6efa7a797671372915d4e9659dba2d59edc6fafc931d19997"
dependencies = [
"anyhow",
"indexmap",
- "wasm-encoder 0.234.0",
- "wasmparser 0.234.0",
+ "wasm-encoder 0.237.0",
+ "wasmparser 0.237.0",
]
[[package]]
@@ -6153,9 +6038,19 @@
[[package]]
name = "wasmparser"
-version = "0.234.0"
+version = "0.236.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be22e5a8f600afce671dd53c8d2dd26b4b7aa810fd18ae27dfc49737f3e02fc5"
+checksum = "a9b1e81f3eb254cf7404a82cee6926a4a3ccc5aad80cc3d43608a070c67aa1d7"
+dependencies = [
+ "bitflags",
+ "indexmap",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.237.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d2a40ca0d2bdf4b0bf36c13a737d0b2c58e4c8aaefe1c57f336dd75369ca250"
dependencies = [
"bitflags",
"hashbrown",
@@ -6165,34 +6060,23 @@
]
[[package]]
-name = "wasmparser"
-version = "0.236.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16d1eee846a705f6f3cb9d7b9f79b54583810f1fb57a1e3aea76d1742db2e3d2"
-dependencies = [
- "bitflags",
- "indexmap",
- "semver",
-]
-
-[[package]]
name = "wast"
-version = "236.0.0"
+version = "237.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11d6b6faeab519ba6fbf9b26add41617ca6f5553f99ebc33d876e591d2f4f3c6"
+checksum = "fcf66f545acbd55082485cb9a6daab54579cb8628a027162253e8e9f5963c767"
dependencies = [
"bumpalo",
"leb128fmt",
"memchr",
"unicode-width 0.2.1",
- "wasm-encoder 0.236.0",
+ "wasm-encoder 0.237.0",
]
[[package]]
name = "wat"
-version = "1.236.0"
+version = "1.237.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc31704322400f461f7f31a5f9190d5488aaeafb63ae69ad2b5888d2704dcb08"
+checksum = "27975186f549e4b8d6878b627be732863883c72f7bf4dcf8f96e5f8242f73da9"
dependencies = [
"wast",
]
@@ -6326,7 +6210,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6337,7 +6221,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6348,7 +6232,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6359,7 +6243,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6681,9 +6565,9 @@
[[package]]
name = "wit-component"
-version = "0.234.0"
+version = "0.237.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a8888169acf4c6c4db535beb405b570eedac13215d6821ca9bd03190f7f8b8c"
+checksum = "bfb7674f76c10e82fe00b256a9d4ffb2b8d037d42ab8e9a83ebb3be35c9d0bf6"
dependencies = [
"anyhow",
"bitflags",
@@ -6692,17 +6576,17 @@
"serde",
"serde_derive",
"serde_json",
- "wasm-encoder 0.234.0",
+ "wasm-encoder 0.237.0",
"wasm-metadata",
- "wasmparser 0.234.0",
+ "wasmparser 0.237.0",
"wit-parser",
]
[[package]]
name = "wit-parser"
-version = "0.234.0"
+version = "0.237.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "465492df47d8dcc015a3b7f241aed8ea03688fee7c5e04162285c5b1a3539c8b"
+checksum = "ce2596a5bc7c24cc965b56ad6ff9e32394c4e401764f89620a888519c6e849ab"
dependencies = [
"anyhow",
"id-arena",
@@ -6713,17 +6597,11 @@
"serde_derive",
"serde_json",
"unicode-xid",
- "wasmparser 0.234.0",
+ "wasmparser 0.237.0",
]
[[package]]
name = "writeable"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
-
-[[package]]
-name = "writeable"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
@@ -6762,49 +6640,25 @@
[[package]]
name = "yoke"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
-dependencies = [
- "serde",
- "stable_deref_trait",
- "yoke-derive 0.7.5",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
dependencies = [
"serde",
"stable_deref_trait",
- "yoke-derive 0.8.0",
+ "yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.104",
- "synstructure",
-]
-
-[[package]]
-name = "yoke-derive"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"synstructure",
]
@@ -6825,7 +6679,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6845,7 +6699,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"synstructure",
]
@@ -6856,41 +6710,19 @@
checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
dependencies = [
"displaydoc",
- "yoke 0.8.0",
+ "yoke",
"zerofrom",
]
[[package]]
name = "zerovec"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
-dependencies = [
- "yoke 0.7.5",
- "zerofrom",
- "zerovec-derive 0.10.3",
-]
-
-[[package]]
-name = "zerovec"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
dependencies = [
- "yoke 0.8.0",
+ "yoke",
"zerofrom",
- "zerovec-derive 0.11.1",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.104",
+ "zerovec-derive",
]
[[package]]
@@ -6901,5 +6733,5 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
diff --git a/Cargo.toml b/Cargo.toml
index 67c7a9d..2c5044f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -59,6 +59,33 @@
"obj",
]
+[workspace.dependencies]
+# tidy-alphabetical-start
+bitflags = "2.9.3"
+derive-where = "1.6.0"
+either = "1.15.0"
+indexmap = "2.10.0"
+itertools = "0.12.1"
+# FIXME: Remove this pin once this rustix issue is resolved
+# https://github.com/bytecodealliance/rustix/issues/1496
+libc = "=0.2.174"
+measureme = "12.0.3"
+memchr = "2.7.5"
+odht = { version = "0.3.1", features = ["nightly"] }
+polonius-engine = "0.13.0"
+proc-macro2 = "1.0.101"
+quote = "1.0.40"
+rustc-demangle = "0.1.26"
+rustc-hash = "2.1.1"
+rustc-literal-escaper = "0.0.5"
+rustc_apfloat = "0.2.3"
+scoped-tls = "1.0.1"
+serde_json = "1.0.142"
+tempfile = "3.20.0"
+thin-vec = "0.2.14"
+tracing = "0.1.37"
+# tidy-alphabetical-end
+
[profile.release.package.rustc_thread_pool]
# The rustc fork of Rayon has deadlock detection code which intermittently
# causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227)
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index 4c18d5f..16fd924 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -407,8 +407,11 @@
#build.profiler = false
# Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics.
-# Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt`
-# sources are available.
+# Choosing true requires the LLVM submodule to be managed by bootstrap (i.e. not external)
+# so that `compiler-rt` sources are available.
+#
+# Setting this to a path removes the requirement for a C toolchain, but requires setting the
+# path to an existing library containing the builtins library from LLVM's compiler-rt.
#
# Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
# order to run `x check`.
@@ -1041,13 +1044,15 @@
#runner = <none> (string)
# Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics
-# on this target.
-# Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt`
-# sources are available.
+# on this target. Choosing true requires the LLVM submodule to be managed by bootstrap
+# (i.e. not external) so that `compiler-rt` sources are available.
+#
+# Setting this to a path removes the requirement for a C toolchain, but requires setting the
+# path to an existing library containing the builtins library from LLVM's compiler-rt.
#
# Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
# order to run `x check`.
-#optimized-compiler-builtins = build.optimized-compiler-builtins (bool)
+#optimized-compiler-builtins = build.optimized-compiler-builtins (bool or path)
# Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.
# This overrides the global `rust.jemalloc` option. See that option for more info.
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 83d96d8..3de6d18 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
rand = { version = "0.9.0", default-features = false, optional = true }
rand_xoshiro = { version = "0.7.0", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
@@ -15,7 +15,7 @@
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_span = { path = "../rustc_span", optional = true }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index c240555..5004d0c 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -594,23 +594,13 @@ fn layout_of_enum<
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
- // Until we've decided whether to use the tagged or
- // niche filling LayoutData, we don't want to intern the
- // variant layouts, so we can't store them in the
- // overall LayoutData. Store the overall LayoutData
- // and the variant LayoutDatas here until then.
- struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
- layout: LayoutData<FieldIdx, VariantIdx>,
- variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
- }
-
let dl = self.cx.data_layout();
// bail if the enum has an incoherent repr that cannot be computed
if repr.packed() {
return Err(LayoutCalculatorError::ReprConflict);
}
- let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> {
+ let calculate_niche_filling_layout = || -> Option<LayoutData<FieldIdx, VariantIdx>> {
if repr.inhibit_enum_layout_opt() {
return None;
}
@@ -746,7 +736,7 @@ struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
niche_start,
},
tag_field: FieldIdx::new(0),
- variants: IndexVec::new(),
+ variants: variant_layouts,
},
fields: FieldsShape::Arbitrary {
offsets: [niche_offset].into(),
@@ -762,7 +752,7 @@ struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
randomization_seed: combined_seed,
};
- Some(TmpLayout { layout, variants: variant_layouts })
+ Some(layout)
};
let niche_filling_layout = calculate_niche_filling_layout();
@@ -1093,7 +1083,7 @@ struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
tag,
tag_encoding: TagEncoding::Direct,
tag_field: FieldIdx::new(0),
- variants: IndexVec::new(),
+ variants: layout_variants,
},
fields: FieldsShape::Arbitrary {
offsets: [Size::ZERO].into(),
@@ -1109,18 +1099,16 @@ struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
randomization_seed: combined_seed,
};
- let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
-
- let mut best_layout = match (tagged_layout, niche_filling_layout) {
+ let best_layout = match (tagged_layout, niche_filling_layout) {
(tl, Some(nl)) => {
// Pick the smaller layout; otherwise,
// pick the layout with the larger niche; otherwise,
// pick tagged as it has simpler codegen.
use cmp::Ordering::*;
- let niche_size = |tmp_l: &TmpLayout<FieldIdx, VariantIdx>| {
- tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl))
+ let niche_size = |l: &LayoutData<FieldIdx, VariantIdx>| {
+ l.largest_niche.map_or(0, |n| n.available(dl))
};
- match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) {
+ match (tl.size.cmp(&nl.size), niche_size(&tl).cmp(&niche_size(&nl))) {
(Greater, _) => nl,
(Equal, Less) => nl,
_ => tl,
@@ -1129,16 +1117,7 @@ struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
(tl, None) => tl,
};
- // Now we can intern the variant layouts and store them in the enum layout.
- best_layout.layout.variants = match best_layout.layout.variants {
- Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
- Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants }
- }
- Variants::Single { .. } | Variants::Empty => {
- panic!("encountered a single-variant or empty enum during multi-variant layout")
- }
- };
- Ok(best_layout.layout)
+ Ok(best_layout)
}
fn univariant_biased<
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index 155e14a..7f948a6 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -5,9 +5,9 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
-memchr = "2.7.4"
-rustc-literal-escaper = "0.0.5"
+bitflags.workspace = true
+memchr.workspace = true
+rustc-literal-escaper.workspace = true
rustc_ast_ir = { path = "../rustc_ast_ir" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }
@@ -15,6 +15,6 @@
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index f4f35a4..a5d8fbf 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -3,15 +3,6 @@
//! `TokenStream`s represent syntactic objects before they are converted into ASTs.
//! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
-//!
-//! ## Ownership
-//!
-//! `TokenStream`s are persistent data structures constructed as ropes with reference
-//! counted-children. In general, this means that calling an operation on a `TokenStream`
-//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
-//! the original. This essentially coerces `TokenStream`s into "views" of their subparts,
-//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
-//! ownership of the original.
use std::borrow::Cow;
use std::ops::Range;
@@ -99,17 +90,6 @@ pub fn uninterpolate(&self) -> Cow<'_, TokenTree> {
}
}
-impl<CTX> HashStable<CTX> for TokenStream
-where
- CTX: crate::HashStableContext,
-{
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- for sub_tt in self.iter() {
- sub_tt.hash_stable(hcx, hasher);
- }
- }
-}
-
/// A lazy version of [`AttrTokenStream`], which defers creation of an actual
/// `AttrTokenStream` until it is needed.
#[derive(Clone)]
@@ -556,10 +536,6 @@ pub struct AttrsTarget {
pub tokens: LazyAttrTokenStream,
}
-/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
-#[derive(Clone, Debug, Default, Encodable, Decodable)]
-pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);
-
/// Indicates whether a token can join with the following token to form a
/// compound token. Used for conversions to `proc_macro::Spacing`. Also used to
/// guide pretty-printing, which is where the `JointHidden` value (which isn't
@@ -620,58 +596,9 @@ pub enum Spacing {
JointHidden,
}
-impl TokenStream {
- /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
- /// separating the two arguments with a comma for diagnostic suggestions.
- pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
- // Used to suggest if a user writes `foo!(a b);`
- let mut suggestion = None;
- let mut iter = self.0.iter().enumerate().peekable();
- while let Some((pos, ts)) = iter.next() {
- if let Some((_, next)) = iter.peek() {
- let sp = match (&ts, &next) {
- (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue,
- (
- TokenTree::Token(token_left, Spacing::Alone),
- TokenTree::Token(token_right, _),
- ) if (token_left.is_non_reserved_ident() || token_left.is_lit())
- && (token_right.is_non_reserved_ident() || token_right.is_lit()) =>
- {
- token_left.span
- }
- (TokenTree::Delimited(sp, ..), _) => sp.entire(),
- _ => continue,
- };
- let sp = sp.shrink_to_hi();
- let comma = TokenTree::token_alone(token::Comma, sp);
- suggestion = Some((pos, comma, sp));
- }
- }
- if let Some((pos, comma, sp)) = suggestion {
- let mut new_stream = Vec::with_capacity(self.0.len() + 1);
- let parts = self.0.split_at(pos + 1);
- new_stream.extend_from_slice(parts.0);
- new_stream.push(comma);
- new_stream.extend_from_slice(parts.1);
- return Some((TokenStream::new(new_stream), sp));
- }
- None
- }
-}
-
-impl FromIterator<TokenTree> for TokenStream {
- fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
- TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
- }
-}
-
-impl Eq for TokenStream {}
-
-impl PartialEq<TokenStream> for TokenStream {
- fn eq(&self, other: &TokenStream) -> bool {
- self.iter().eq(other.iter())
- }
-}
+/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
+#[derive(Clone, Debug, Default, Encodable, Decodable)]
+pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);
impl TokenStream {
pub fn new(tts: Vec<TokenTree>) -> TokenStream {
@@ -847,6 +774,68 @@ fn desugared_tts(attr_style: AttrStyle, data: Symbol, span: Span) -> Vec<TokenTr
}
}
}
+
+ /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
+ /// separating the two arguments with a comma for diagnostic suggestions.
+ pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
+ // Used to suggest if a user writes `foo!(a b);`
+ let mut suggestion = None;
+ let mut iter = self.0.iter().enumerate().peekable();
+ while let Some((pos, ts)) = iter.next() {
+ if let Some((_, next)) = iter.peek() {
+ let sp = match (&ts, &next) {
+ (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue,
+ (
+ TokenTree::Token(token_left, Spacing::Alone),
+ TokenTree::Token(token_right, _),
+ ) if (token_left.is_non_reserved_ident() || token_left.is_lit())
+ && (token_right.is_non_reserved_ident() || token_right.is_lit()) =>
+ {
+ token_left.span
+ }
+ (TokenTree::Delimited(sp, ..), _) => sp.entire(),
+ _ => continue,
+ };
+ let sp = sp.shrink_to_hi();
+ let comma = TokenTree::token_alone(token::Comma, sp);
+ suggestion = Some((pos, comma, sp));
+ }
+ }
+ if let Some((pos, comma, sp)) = suggestion {
+ let mut new_stream = Vec::with_capacity(self.0.len() + 1);
+ let parts = self.0.split_at(pos + 1);
+ new_stream.extend_from_slice(parts.0);
+ new_stream.push(comma);
+ new_stream.extend_from_slice(parts.1);
+ return Some((TokenStream::new(new_stream), sp));
+ }
+ None
+ }
+}
+
+impl PartialEq<TokenStream> for TokenStream {
+ fn eq(&self, other: &TokenStream) -> bool {
+ self.iter().eq(other.iter())
+ }
+}
+
+impl Eq for TokenStream {}
+
+impl FromIterator<TokenTree> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
+ TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
+ }
+}
+
+impl<CTX> HashStable<CTX> for TokenStream
+where
+ CTX: crate::HashStableContext,
+{
+ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+ for sub_tt in self.iter() {
+ sub_tt.hash_stable(hcx, hasher);
+ }
+ }
}
#[derive(Clone)]
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml
index 6ac2581..317742a 100644
--- a/compiler/rustc_ast_lowering/Cargo.toml
+++ b/compiler/rustc_ast_lowering/Cargo.toml
@@ -24,6 +24,6 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml
index 3e04f8b..6d2bcbe 100644
--- a/compiler/rustc_ast_passes/Cargo.toml
+++ b/compiler/rustc_ast_passes/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@@ -18,5 +18,5 @@
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
-thin-vec = "0.2.12"
+thin-vec.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index e763c9d..9ab5b0b 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -188,6 +188,7 @@ macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) =
notable_trait => doc_notable_trait
}
"meant for internal use only" {
+ attribute => rustdoc_internals
keyword => rustdoc_internals
fake_variadic => rustdoc_internals
search_unbox => rustdoc_internals
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index b704040..0c7e553 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
rustc_ast = { path = "../rustc_ast" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_span = { path = "../rustc_span" }
@@ -13,5 +13,5 @@
[dev-dependencies]
# tidy-alphabetical-start
-thin-vec = "0.2.12"
+thin-vec.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml
index fd8f7ff..8bfde43 100644
--- a/compiler/rustc_attr_parsing/Cargo.toml
+++ b/compiler/rustc_attr_parsing/Cargo.toml
@@ -17,5 +17,6 @@
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-thin-vec = "0.2.12"
+rustc_target = { path = "../rustc_target" }
+thin-vec.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl
index 40e9d59..b8a7485 100644
--- a/compiler/rustc_attr_parsing/messages.ftl
+++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -86,6 +86,12 @@
attr_parsing_invalid_since =
'since' must be a Rust version number, such as "1.31.0"
+attr_parsing_invalid_style = {$is_used_as_inner ->
+ [false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]`
+ *[other] the `#![{$name}]` attribute can only be used at the crate root
+ }
+ .note = This attribute does not have an `!`, which means it is applied to this {$target}
+
attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}`
.note = the value may not exceed `u16::MAX`
@@ -189,3 +195,55 @@
attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+attr_parsing_as_needed_compatibility =
+ linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
+
+attr_parsing_bundle_needs_static =
+ linking modifier `bundle` is only compatible with `static` linking kind
+
+attr_parsing_empty_link_name =
+ link name must not be empty
+ .label = empty link name
+
+attr_parsing_import_name_type_raw =
+ import name type can only be used with link kind `raw-dylib`
+
+attr_parsing_import_name_type_x86 =
+ import name type is only supported on x86
+
+attr_parsing_incompatible_wasm_link =
+ `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+
+attr_parsing_invalid_link_modifier =
+ invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+
+attr_parsing_link_arg_unstable =
+ link kind `link-arg` is unstable
+
+attr_parsing_link_cfg_unstable =
+ link cfg is unstable
+
+attr_parsing_link_framework_apple =
+ link kind `framework` is only supported on Apple targets
+
+attr_parsing_link_requires_name =
+ `#[link]` attribute requires a `name = "string"` argument
+ .label = missing `name` argument
+
+attr_parsing_multiple_modifiers =
+ multiple `{$modifier}` modifiers in a single `modifiers` argument
+
+attr_parsing_multiple_renamings =
+ multiple renamings were specified for library `{$lib_name}`
+attr_parsing_raw_dylib_no_nul =
+ link name must not contain NUL characters if link kind is `raw-dylib`
+
+attr_parsing_raw_dylib_elf_unstable =
+ link kind `raw-dylib` is unstable on ELF platforms
+
+attr_parsing_raw_dylib_only_windows =
+ link kind `raw-dylib` is only supported on Windows targets
+
+attr_parsing_whole_archive_needs_static =
+ linking modifier `whole-archive` is only compatible with `static` linking kind
diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
index 695ee66..7085561 100644
--- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
@@ -36,7 +36,7 @@ pub fn parse_cfg_attr<'c, S: Stage>(
parse_cfg_entry(cx, single)
}
-fn parse_cfg_entry<S: Stage>(
+pub(crate) fn parse_cfg_entry<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
item: &MetaItemOrLitParser<'_>,
) -> Option<CfgEntry> {
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index 9105381..ffdacff 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -1,4 +1,4 @@
-use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, UsedBy};
+use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
use rustc_session::parse::feature_err;
use super::prelude::*;
@@ -127,6 +127,7 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
Warn(Target::Field),
Warn(Target::Arm),
Warn(Target::MacroDef),
+ Warn(Target::MacroCall),
]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
@@ -174,6 +175,7 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
+ Warn(Target::MacroCall),
]);
fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
@@ -278,6 +280,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for TrackCallerParser {
Warn(Target::MacroDef),
Warn(Target::Arm),
Warn(Target::Field),
+ Warn(Target::MacroCall),
]);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller;
}
@@ -365,7 +368,8 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
}
},
)];
- const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]);
+ const ALLOWED_TARGETS: AllowedTargets =
+ AllowedTargets::AllowList(&[Allow(Target::Static), Warn(Target::MacroCall)]);
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
// Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker`
@@ -450,6 +454,7 @@ fn extend<'c>(
Warn(Target::Field),
Warn(Target::Arm),
Warn(Target::MacroDef),
+ Warn(Target::MacroCall),
]);
}
@@ -464,6 +469,12 @@ impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
was_forced: true,
};
const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
+ const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+ Allow(Target::Fn),
+ Allow(Target::Method(MethodKind::Inherent)),
+ Allow(Target::Method(MethodKind::Trait { body: true })),
+ Allow(Target::Method(MethodKind::TraitImpl)),
+ ]);
fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
@@ -471,11 +482,106 @@ fn extend<'c>(
) -> impl IntoIterator<Item = Self::Item> + 'c {
parse_tf_attribute(cx, args)
}
+}
- const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
- Allow(Target::Fn),
- Allow(Target::Method(MethodKind::Inherent)),
- Allow(Target::Method(MethodKind::Trait { body: true })),
- Allow(Target::Method(MethodKind::TraitImpl)),
+pub(crate) struct SanitizeParser;
+
+impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
+ const PATH: &[Symbol] = &[sym::sanitize];
+
+ // FIXME: still checked in check_attrs.rs
+ const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+
+ const TEMPLATE: AttributeTemplate = template!(List: &[
+ r#"address = "on|off""#,
+ r#"kernel_address = "on|off""#,
+ r#"cfi = "on|off""#,
+ r#"hwaddress = "on|off""#,
+ r#"kcfi = "on|off""#,
+ r#"memory = "on|off""#,
+ r#"memtag = "on|off""#,
+ r#"shadow_call_stack = "on|off""#,
+ r#"thread = "on|off""#
]);
+
+ const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+ const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+
+ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+ let Some(list) = args.list() else {
+ cx.expected_list(cx.attr_span);
+ return None;
+ };
+
+ let mut on_set = SanitizerSet::empty();
+ let mut off_set = SanitizerSet::empty();
+
+ for item in list.mixed() {
+ let Some(item) = item.meta_item() else {
+ cx.expected_name_value(item.span(), None);
+ continue;
+ };
+
+ let path = item.path().word_sym();
+ let Some(value) = item.args().name_value() else {
+ cx.expected_name_value(item.span(), path);
+ continue;
+ };
+
+ let mut apply = |s: SanitizerSet| {
+ let is_on = match value.value_as_str() {
+ Some(sym::on) => true,
+ Some(sym::off) => false,
+ Some(_) => {
+ cx.expected_specific_argument_strings(
+ value.value_span,
+ &[sym::on, sym::off],
+ );
+ return;
+ }
+ None => {
+ cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
+ return;
+ }
+ };
+
+ if is_on {
+ on_set |= s;
+ } else {
+ off_set |= s;
+ }
+ };
+
+ match path {
+ Some(sym::address) | Some(sym::kernel_address) => {
+ apply(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
+ }
+ Some(sym::cfi) => apply(SanitizerSet::CFI),
+ Some(sym::kcfi) => apply(SanitizerSet::KCFI),
+ Some(sym::memory) => apply(SanitizerSet::MEMORY),
+ Some(sym::memtag) => apply(SanitizerSet::MEMTAG),
+ Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
+ Some(sym::thread) => apply(SanitizerSet::THREAD),
+ Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
+ _ => {
+ cx.expected_specific_argument_strings(
+ item.path().span(),
+ &[
+ sym::address,
+ sym::cfi,
+ sym::kcfi,
+ sym::memory,
+ sym::memtag,
+ sym::shadow_call_stack,
+ sym::thread,
+ sym::hwaddress,
+ ],
+ );
+ continue;
+ }
+ }
+ }
+
+ Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
+ }
}
diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
new file mode 100644
index 0000000..2fed09b
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
@@ -0,0 +1,36 @@
+use rustc_feature::AttributeType;
+
+use super::prelude::*;
+
+pub(crate) struct CrateNameParser;
+
+impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
+ const PATH: &[Symbol] = &[sym::crate_name];
+ const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+ const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+ const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
+ const TYPE: AttributeType = AttributeType::CrateLevel;
+
+ // FIXME: crate name is allowed on all targets and ignored,
+ // even though it should only be valid on crates of course
+ const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+
+ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+ let ArgParser::NameValue(n) = args else {
+ cx.expected_name_value(cx.attr_span, None);
+ return None;
+ };
+
+ let Some(name) = n.value_as_str() else {
+ cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
+ return None;
+ };
+
+ Some(AttributeKind::CrateName {
+ name,
+ name_span: n.value_span,
+ attr_span: cx.attr_span,
+ style: cx.attr_style,
+ })
+ }
+}
diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs
index 39d5ff8..a73430c 100644
--- a/compiler/rustc_attr_parsing/src/attributes/inline.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs
@@ -25,6 +25,7 @@ impl<S: Stage> SingleAttributeParser<S> for InlineParser {
Warn(Target::MacroDef),
Warn(Target::Arm),
Warn(Target::AssocConst),
+ Warn(Target::MacroCall),
]);
const TEMPLATE: AttributeTemplate = template!(
Word,
diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
index 66b0269..d4942e5 100644
--- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
@@ -1,9 +1,21 @@
+use rustc_feature::Features;
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
-use rustc_hir::attrs::Linkage;
+use rustc_hir::attrs::*;
+use rustc_session::Session;
+use rustc_session::parse::feature_err;
+use rustc_span::kw;
+use rustc_target::spec::BinaryFormat;
use super::prelude::*;
use super::util::parse_single_integer;
-use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};
+use crate::attributes::cfg::parse_cfg_entry;
+use crate::fluent_generated;
+use crate::session_diagnostics::{
+ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86,
+ IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange,
+ LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows,
+ WholeArchiveNeedsStatic,
+};
pub(crate) struct LinkNameParser;
@@ -34,6 +46,409 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<At
}
}
+pub(crate) struct LinkParser;
+
+impl<S: Stage> CombineAttributeParser<S> for LinkParser {
+ type Item = LinkEntry;
+ const PATH: &[Symbol] = &[sym::link];
+ const CONVERT: ConvertFn<Self::Item> = AttributeKind::Link;
+ const TEMPLATE: AttributeTemplate = template!(List: &[
+ r#"name = "...""#,
+ r#"name = "...", kind = "dylib|static|...""#,
+ r#"name = "...", wasm_import_module = "...""#,
+ r#"name = "...", import_name_type = "decorated|noprefix|undecorated""#,
+ r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#,
+ ], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute");
+ const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
+
+ fn extend<'c>(
+ cx: &'c mut AcceptContext<'_, '_, S>,
+ args: &'c ArgParser<'_>,
+ ) -> impl IntoIterator<Item = Self::Item> + 'c {
+ let mut result = None;
+ let Some(items) = args.list() else {
+ cx.expected_list(cx.attr_span);
+ return result;
+ };
+
+ let sess = cx.sess();
+ let features = cx.features();
+
+ let mut name = None;
+ let mut kind = None;
+ let mut modifiers = None;
+ let mut cfg = None;
+ let mut wasm_import_module = None;
+ let mut import_name_type = None;
+ for item in items.mixed() {
+ let Some(item) = item.meta_item() else {
+ cx.unexpected_literal(item.span());
+ continue;
+ };
+
+ let cont = match item.path().word().map(|ident| ident.name) {
+ Some(sym::name) => Self::parse_link_name(item, &mut name, cx),
+ Some(sym::kind) => Self::parse_link_kind(item, &mut kind, cx, sess, features),
+ Some(sym::modifiers) => Self::parse_link_modifiers(item, &mut modifiers, cx),
+ Some(sym::cfg) => Self::parse_link_cfg(item, &mut cfg, cx, sess, features),
+ Some(sym::wasm_import_module) => {
+ Self::parse_link_wasm_import_module(item, &mut wasm_import_module, cx)
+ }
+ Some(sym::import_name_type) => {
+ Self::parse_link_import_name_type(item, &mut import_name_type, cx)
+ }
+ _ => {
+ cx.expected_specific_argument_strings(
+ item.span(),
+ &[
+ sym::name,
+ sym::kind,
+ sym::modifiers,
+ sym::cfg,
+ sym::wasm_import_module,
+ sym::import_name_type,
+ ],
+ );
+ true
+ }
+ };
+ if !cont {
+ return result;
+ }
+ }
+
+ // Do this outside the above loop so we don't depend on modifiers coming after kinds
+ let mut verbatim = None;
+ if let Some((modifiers, span)) = modifiers {
+ for modifier in modifiers.as_str().split(',') {
+ let (modifier, value): (Symbol, bool) = match modifier.strip_prefix(&['+', '-']) {
+ Some(m) => (Symbol::intern(m), modifier.starts_with('+')),
+ None => {
+ cx.emit_err(InvalidLinkModifier { span });
+ continue;
+ }
+ };
+
+ macro report_unstable_modifier($feature: ident) {
+ if !features.$feature() {
+ // FIXME: make this translatable
+ #[expect(rustc::untranslatable_diagnostic)]
+ feature_err(
+ sess,
+ sym::$feature,
+ span,
+ format!("linking modifier `{modifier}` is unstable"),
+ )
+ .emit();
+ }
+ }
+ let assign_modifier = |dst: &mut Option<bool>| {
+ if dst.is_some() {
+ cx.emit_err(MultipleModifiers { span, modifier });
+ } else {
+ *dst = Some(value);
+ }
+ };
+ match (modifier, &mut kind) {
+ (sym::bundle, Some(NativeLibKind::Static { bundle, .. })) => {
+ assign_modifier(bundle)
+ }
+ (sym::bundle, _) => {
+ cx.emit_err(BundleNeedsStatic { span });
+ }
+
+ (sym::verbatim, _) => assign_modifier(&mut verbatim),
+
+ (
+ sym::whole_dash_archive,
+ Some(NativeLibKind::Static { whole_archive, .. }),
+ ) => assign_modifier(whole_archive),
+ (sym::whole_dash_archive, _) => {
+ cx.emit_err(WholeArchiveNeedsStatic { span });
+ }
+
+ (sym::as_dash_needed, Some(NativeLibKind::Dylib { as_needed }))
+ | (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed })) => {
+ report_unstable_modifier!(native_link_modifiers_as_needed);
+ assign_modifier(as_needed)
+ }
+ (sym::as_dash_needed, _) => {
+ cx.emit_err(AsNeededCompatibility { span });
+ }
+
+ _ => {
+ cx.expected_specific_argument_strings(
+ span,
+ &[
+ sym::bundle,
+ sym::verbatim,
+ sym::whole_dash_archive,
+ sym::as_dash_needed,
+ ],
+ );
+ }
+ }
+ }
+ }
+
+ if let Some((_, span)) = wasm_import_module {
+ if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
+ cx.emit_err(IncompatibleWasmLink { span });
+ }
+ }
+
+ if wasm_import_module.is_some() {
+ (name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
+ }
+ let Some((name, name_span)) = name else {
+ cx.emit_err(LinkRequiresName { span: cx.attr_span });
+ return result;
+ };
+
+ // Do this outside of the loop so that `import_name_type` can be specified before `kind`.
+ if let Some((_, span)) = import_name_type {
+ if kind != Some(NativeLibKind::RawDylib) {
+ cx.emit_err(ImportNameTypeRaw { span });
+ }
+ }
+
+ if let Some(NativeLibKind::RawDylib) = kind
+ && name.as_str().contains('\0')
+ {
+ cx.emit_err(RawDylibNoNul { span: name_span });
+ }
+
+ result = Some(LinkEntry {
+ span: cx.attr_span,
+ kind: kind.unwrap_or(NativeLibKind::Unspecified),
+ name,
+ cfg,
+ verbatim,
+ import_name_type,
+ });
+ result
+ }
+}
+
+impl LinkParser {
+ fn parse_link_name<S: Stage>(
+ item: &MetaItemParser<'_>,
+ name: &mut Option<(Symbol, Span)>,
+ cx: &mut AcceptContext<'_, '_, S>,
+ ) -> bool {
+ if name.is_some() {
+ cx.duplicate_key(item.span(), sym::name);
+ return true;
+ }
+ let Some(nv) = item.args().name_value() else {
+ cx.expected_name_value(item.span(), Some(sym::name));
+ return false;
+ };
+ let Some(link_name) = nv.value_as_str() else {
+ cx.expected_name_value(item.span(), Some(sym::name));
+ return false;
+ };
+
+ if link_name.is_empty() {
+ cx.emit_err(EmptyLinkName { span: nv.value_span });
+ }
+ *name = Some((link_name, nv.value_span));
+ true
+ }
+
+ fn parse_link_kind<S: Stage>(
+ item: &MetaItemParser<'_>,
+ kind: &mut Option<NativeLibKind>,
+ cx: &mut AcceptContext<'_, '_, S>,
+ sess: &Session,
+ features: &Features,
+ ) -> bool {
+ if kind.is_some() {
+ cx.duplicate_key(item.span(), sym::kind);
+ return true;
+ }
+ let Some(nv) = item.args().name_value() else {
+ cx.expected_name_value(item.span(), Some(sym::kind));
+ return true;
+ };
+ let Some(link_kind) = nv.value_as_str() else {
+ cx.expected_name_value(item.span(), Some(sym::kind));
+ return true;
+ };
+
+ let link_kind = match link_kind {
+ kw::Static => NativeLibKind::Static { bundle: None, whole_archive: None },
+ sym::dylib => NativeLibKind::Dylib { as_needed: None },
+ sym::framework => {
+ if !sess.target.is_like_darwin {
+ cx.emit_err(LinkFrameworkApple { span: nv.value_span });
+ }
+ NativeLibKind::Framework { as_needed: None }
+ }
+ sym::raw_dash_dylib => {
+ if sess.target.is_like_windows {
+ // raw-dylib is stable and working on Windows
+ } else if sess.target.binary_format == BinaryFormat::Elf && features.raw_dylib_elf()
+ {
+ // raw-dylib is unstable on ELF, but the user opted in
+ } else if sess.target.binary_format == BinaryFormat::Elf && sess.is_nightly_build()
+ {
+ feature_err(
+ sess,
+ sym::raw_dylib_elf,
+ nv.value_span,
+ fluent_generated::attr_parsing_raw_dylib_elf_unstable,
+ )
+ .emit();
+ } else {
+ cx.emit_err(RawDylibOnlyWindows { span: nv.value_span });
+ }
+
+ NativeLibKind::RawDylib
+ }
+ sym::link_dash_arg => {
+ if !features.link_arg_attribute() {
+ feature_err(
+ sess,
+ sym::link_arg_attribute,
+ nv.value_span,
+ fluent_generated::attr_parsing_link_arg_unstable,
+ )
+ .emit();
+ }
+ NativeLibKind::LinkArg
+ }
+ _kind => {
+ cx.expected_specific_argument_strings(
+ nv.value_span,
+ &[
+ kw::Static,
+ sym::dylib,
+ sym::framework,
+ sym::raw_dash_dylib,
+ sym::link_dash_arg,
+ ],
+ );
+ return true;
+ }
+ };
+ *kind = Some(link_kind);
+ true
+ }
+
+ fn parse_link_modifiers<S: Stage>(
+ item: &MetaItemParser<'_>,
+ modifiers: &mut Option<(Symbol, Span)>,
+ cx: &mut AcceptContext<'_, '_, S>,
+ ) -> bool {
+ if modifiers.is_some() {
+ cx.duplicate_key(item.span(), sym::modifiers);
+ return true;
+ }
+ let Some(nv) = item.args().name_value() else {
+ cx.expected_name_value(item.span(), Some(sym::modifiers));
+ return true;
+ };
+ let Some(link_modifiers) = nv.value_as_str() else {
+ cx.expected_name_value(item.span(), Some(sym::modifiers));
+ return true;
+ };
+ *modifiers = Some((link_modifiers, nv.value_span));
+ true
+ }
+
+ fn parse_link_cfg<S: Stage>(
+ item: &MetaItemParser<'_>,
+ cfg: &mut Option<CfgEntry>,
+ cx: &mut AcceptContext<'_, '_, S>,
+ sess: &Session,
+ features: &Features,
+ ) -> bool {
+ if cfg.is_some() {
+ cx.duplicate_key(item.span(), sym::cfg);
+ return true;
+ }
+ let Some(link_cfg) = item.args().list() else {
+ cx.expected_list(item.span());
+ return true;
+ };
+ let Some(link_cfg) = link_cfg.single() else {
+ cx.expected_single_argument(item.span());
+ return true;
+ };
+ if !features.link_cfg() {
+ feature_err(
+ sess,
+ sym::link_cfg,
+ item.span(),
+ fluent_generated::attr_parsing_link_cfg_unstable,
+ )
+ .emit();
+ }
+ *cfg = parse_cfg_entry(cx, link_cfg);
+ true
+ }
+
+ fn parse_link_wasm_import_module<S: Stage>(
+ item: &MetaItemParser<'_>,
+ wasm_import_module: &mut Option<(Symbol, Span)>,
+ cx: &mut AcceptContext<'_, '_, S>,
+ ) -> bool {
+ if wasm_import_module.is_some() {
+ cx.duplicate_key(item.span(), sym::wasm_import_module);
+ return true;
+ }
+ let Some(nv) = item.args().name_value() else {
+ cx.expected_name_value(item.span(), Some(sym::wasm_import_module));
+ return true;
+ };
+ let Some(link_wasm_import_module) = nv.value_as_str() else {
+ cx.expected_name_value(item.span(), Some(sym::wasm_import_module));
+ return true;
+ };
+ *wasm_import_module = Some((link_wasm_import_module, item.span()));
+ true
+ }
+
+ fn parse_link_import_name_type<S: Stage>(
+ item: &MetaItemParser<'_>,
+ import_name_type: &mut Option<(PeImportNameType, Span)>,
+ cx: &mut AcceptContext<'_, '_, S>,
+ ) -> bool {
+ if import_name_type.is_some() {
+ cx.duplicate_key(item.span(), sym::import_name_type);
+ return true;
+ }
+ let Some(nv) = item.args().name_value() else {
+ cx.expected_name_value(item.span(), Some(sym::import_name_type));
+ return true;
+ };
+ let Some(link_import_name_type) = nv.value_as_str() else {
+ cx.expected_name_value(item.span(), Some(sym::import_name_type));
+ return true;
+ };
+ if cx.sess().target.arch != "x86" {
+ cx.emit_err(ImportNameTypeX86 { span: item.span() });
+ return true;
+ }
+
+ let link_import_name_type = match link_import_name_type {
+ sym::decorated => PeImportNameType::Decorated,
+ sym::noprefix => PeImportNameType::NoPrefix,
+ sym::undecorated => PeImportNameType::Undecorated,
+ _ => {
+ cx.expected_specific_argument_strings(
+ item.span(),
+ &[sym::decorated, sym::noprefix, sym::undecorated],
+ );
+ return true;
+ }
+ };
+ *import_name_type = Some((link_import_name_type, item.span()));
+ true
+ }
+}
+
pub(crate) struct LinkSectionParser;
impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
@@ -110,8 +525,11 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
const PATH: &[Symbol] = &[sym::link_ordinal];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
- const ALLOWED_TARGETS: AllowedTargets =
- AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]);
+ const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+ Allow(Target::ForeignFn),
+ Allow(Target::ForeignStatic),
+ Warn(Target::MacroCall),
+ ]);
const TEMPLATE: AttributeTemplate = template!(
List: &["ordinal"],
"https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute"
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index b986780..043bc92 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -12,11 +12,15 @@
//! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
//! contents of attributes, if an attribute appear multiple times in a list
//!
+//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
+//! at the crate root, consider setting the `TYPE` in the parser trait to
+//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
+//!
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
use std::marker::PhantomData;
-use rustc_feature::{AttributeTemplate, template};
+use rustc_feature::{AttributeTemplate, AttributeType, template};
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;
@@ -35,6 +39,7 @@
pub(crate) mod cfg_old;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
+pub(crate) mod crate_level;
pub(crate) mod deprecation;
pub(crate) mod dummy;
pub(crate) mod inline;
@@ -87,6 +92,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
const ALLOWED_TARGETS: AllowedTargets;
+ const TYPE: AttributeType = AttributeType::Normal;
+
/// The parser has gotten a chance to accept the attributes on an item,
/// here it can produce an attribute.
///
@@ -128,6 +135,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
/// The template this attribute parser should implement. Used for diagnostics.
const TEMPLATE: AttributeTemplate;
+ const TYPE: AttributeType = AttributeType::Normal;
+
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
}
@@ -174,6 +183,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
)];
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
+ const TYPE: AttributeType = T::TYPE;
+
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
Some(self.1?.0)
}
@@ -258,6 +269,7 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
const PATH: &[Symbol];
const ON_DUPLICATE: OnDuplicate<S>;
const ALLOWED_TARGETS: AllowedTargets;
+ const TYPE: AttributeType = AttributeType::Normal;
/// Create the [`AttributeKind`] given attribute's [`Span`].
const CREATE: fn(Span) -> AttributeKind;
@@ -277,6 +289,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
const TEMPLATE: AttributeTemplate = template!(Word);
+ const TYPE: AttributeType = T::TYPE;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
@@ -310,6 +323,8 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
/// The template this attribute parser should implement. Used for diagnostics.
const TEMPLATE: AttributeTemplate;
+ const TYPE: AttributeType = AttributeType::Normal;
+
/// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
@@ -345,6 +360,7 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
group.items.extend(T::extend(cx, args))
})];
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
+ const TYPE: AttributeType = T::TYPE;
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
if let Some(first_span) = self.first_span {
diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
index 4e6aec9..fc41c07 100644
--- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
@@ -19,6 +19,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for NonExhaustiveParser {
Warn(Target::Field),
Warn(Target::Arm),
Warn(Target::MacroDef),
+ Warn(Target::MacroCall),
]);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive;
}
diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
index 2bcdee5..6aef7e7 100644
--- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
@@ -1,20 +1,30 @@
-// parsing
// templates
+#[doc(hidden)]
pub(super) use rustc_feature::{AttributeTemplate, template};
// data structures
+#[doc(hidden)]
pub(super) use rustc_hir::attrs::AttributeKind;
+#[doc(hidden)]
pub(super) use rustc_hir::lints::AttributeLintKind;
+#[doc(hidden)]
pub(super) use rustc_hir::{MethodKind, Target};
+#[doc(hidden)]
pub(super) use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
+#[doc(hidden)]
pub(super) use thin_vec::ThinVec;
+#[doc(hidden)]
pub(super) use crate::attributes::{
AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
// contexts
+#[doc(hidden)]
pub(super) use crate::context::{AcceptContext, FinalizeContext, Stage};
+#[doc(hidden)]
pub(super) use crate::parser::*;
// target checking
+#[doc(hidden)]
pub(super) use crate::target_checking::Policy::{Allow, Error, Warn};
+#[doc(hidden)]
pub(super) use crate::target_checking::{ALL_TARGETS, AllowedTargets};
diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
index 9ac18c0..b9929d6 100644
--- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
@@ -1,11 +1,13 @@
use super::prelude::*;
+const PROC_MACRO_ALLOWED_TARGETS: AllowedTargets =
+ AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate), Warn(Target::MacroCall)]);
+
pub(crate) struct ProcMacroParser;
impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
const PATH: &[Symbol] = &[sym::proc_macro];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
- const ALLOWED_TARGETS: AllowedTargets =
- AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
+ const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro;
}
@@ -13,8 +15,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser {
const PATH: &[Symbol] = &[sym::proc_macro_attribute];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
- const ALLOWED_TARGETS: AllowedTargets =
- AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
+ const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute;
}
@@ -23,8 +24,7 @@ impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
const PATH: &[Symbol] = &[sym::proc_macro_derive];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
- const ALLOWED_TARGETS: AllowedTargets =
- AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
+ const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS;
const TEMPLATE: AttributeTemplate = template!(
List: &["TraitName", "TraitName, attributes(name1, name2, ...)"],
"https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros"
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index 89ac1b0..fbd9a48 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -1,5 +1,7 @@
use std::mem;
+use rustc_feature::AttributeType;
+
use super::prelude::*;
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
@@ -154,6 +156,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
+ const TYPE: AttributeType = AttributeType::CrateLevel;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
}
diff --git a/compiler/rustc_attr_parsing/src/attributes/util.rs b/compiler/rustc_attr_parsing/src/attributes/util.rs
index ef9701c..77e8c32 100644
--- a/compiler/rustc_attr_parsing/src/attributes/util.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/util.rs
@@ -1,5 +1,5 @@
use rustc_ast::LitKind;
-use rustc_ast::attr::{AttributeExt, first_attr_value_str_by_name};
+use rustc_ast::attr::AttributeExt;
use rustc_feature::is_builtin_attr_name;
use rustc_hir::RustcVersion;
use rustc_span::{Symbol, sym};
@@ -27,10 +27,6 @@ pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
}
-pub fn find_crate_name(attrs: &[impl AttributeExt]) -> Option<Symbol> {
- first_attr_value_str_by_name(attrs, sym::crate_name)
-}
-
pub fn is_doc_alias_attrs_contain_symbol<'tcx, T: AttributeExt + 'tcx>(
attrs: impl Iterator<Item = &'tcx T>,
symbol: Symbol,
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index b9c415e..7f5b810 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -4,12 +4,12 @@
use std::sync::LazyLock;
use private::Sealed;
-use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
-use rustc_errors::Diagnostic;
-use rustc_feature::AttributeTemplate;
+use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
+use rustc_errors::{Diag, Diagnostic, Level};
+use rustc_feature::{AttributeTemplate, AttributeType};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
-use rustc_hir::{AttrPath, HirId};
+use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
use rustc_session::Session;
use rustc_span::{ErrorGuaranteed, Span, Symbol};
@@ -20,15 +20,17 @@
use crate::attributes::body::CoroutineParser;
use crate::attributes::codegen_attrs::{
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
- NoMangleParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
+ NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser,
+ UsedParser,
};
use crate::attributes::confusables::ConfusablesParser;
+use crate::attributes::crate_level::CrateNameParser;
use crate::attributes::deprecation::DeprecationParser;
use crate::attributes::dummy::DummyParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
use crate::attributes::link_attrs::{
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
- LinkSectionParser, LinkageParser, StdInternalSymbolParser,
+ LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser,
};
use crate::attributes::lint_helpers::{
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
@@ -78,6 +80,7 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
pub(super) template: AttributeTemplate,
pub(super) accept_fn: AcceptFn<S>,
pub(super) allowed_targets: AllowedTargets,
+ pub(super) attribute_type: AttributeType,
}
type AcceptFn<S> =
@@ -127,6 +130,7 @@ mod late {
})
}),
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
+ attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
});
}
@@ -158,6 +162,7 @@ mod late {
Combine<AllowConstFnUnstableParser>,
Combine<AllowInternalUnstableParser>,
Combine<ForceTargetFeatureParser>,
+ Combine<LinkParser>,
Combine<ReprParser>,
Combine<TargetFeatureParser>,
Combine<UnstableFeatureBoundParser>,
@@ -165,6 +170,7 @@ mod late {
// tidy-alphabetical-start
Single<CoverageParser>,
+ Single<CrateNameParser>,
Single<CustomMirParser>,
Single<DeprecationParser>,
Single<DummyParser>,
@@ -184,6 +190,7 @@ mod late {
Single<RustcLayoutScalarValidRangeEnd>,
Single<RustcLayoutScalarValidRangeStart>,
Single<RustcObjectLifetimeDefaultParser>,
+ Single<SanitizeParser>,
Single<ShouldPanicParser>,
Single<SkipDuringMethodDispatchParser>,
Single<TransparencyParser>,
@@ -246,6 +253,8 @@ fn emit_err<'sess>(
) -> ErrorGuaranteed;
fn should_emit(&self) -> ShouldEmit;
+
+ fn id_is_crate_root(id: Self::Id) -> bool;
}
// allow because it's a sealed trait
@@ -261,16 +270,16 @@ fn emit_err<'sess>(
sess: &'sess Session,
diag: impl for<'x> Diagnostic<'x>,
) -> ErrorGuaranteed {
- if self.emit_errors.should_emit() {
- sess.dcx().emit_err(diag)
- } else {
- sess.dcx().create_err(diag).delay_as_bug()
- }
+ self.should_emit().emit_err(sess.dcx().create_err(diag))
}
fn should_emit(&self) -> ShouldEmit {
self.emit_errors
}
+
+ fn id_is_crate_root(id: Self::Id) -> bool {
+ id == CRATE_NODE_ID
+ }
}
// allow because it's a sealed trait
@@ -292,6 +301,10 @@ fn emit_err<'sess>(
fn should_emit(&self) -> ShouldEmit {
ShouldEmit::ErrorsAndLints
}
+
+ fn id_is_crate_root(id: Self::Id) -> bool {
+ id == CRATE_HIR_ID
+ }
}
/// used when parsing attributes for miscellaneous things *before* ast lowering
@@ -312,7 +325,9 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
/// The span of the attribute currently being parsed
pub(crate) attr_span: Span,
+ /// Whether it is an inner or outer attribute
pub(crate) attr_style: AttrStyle,
+
/// The expected structure of the attribute.
///
/// Used in reporting errors to give a hint to users what the attribute *should* look like.
@@ -331,7 +346,7 @@ pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuarant
/// must be delayed until after HIR is built. This method will take care of the details of
/// that.
pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
- if !self.stage.should_emit().should_emit() {
+ if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
return;
}
let id = self.target_id;
@@ -649,8 +664,13 @@ pub enum OmitDoc {
Skip,
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub enum ShouldEmit {
+ /// The operations will emit errors, and lints, and errors are fatal.
+ ///
+ /// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.
+ /// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.
+ EarlyFatal,
/// The operation will emit errors and lints.
/// This is usually what you need.
ErrorsAndLints,
@@ -660,10 +680,12 @@ pub enum ShouldEmit {
}
impl ShouldEmit {
- pub fn should_emit(&self) -> bool {
+ pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
match self {
- ShouldEmit::ErrorsAndLints => true,
- ShouldEmit::Nothing => false,
+ ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => diag.emit(),
+ ShouldEmit::EarlyFatal => diag.upgrade_to_fatal().emit(),
+ ShouldEmit::ErrorsAndLints => diag.emit(),
+ ShouldEmit::Nothing => diag.delay_as_bug(),
}
}
}
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs
index f652d39..0fe3c20 100644
--- a/compiler/rustc_attr_parsing/src/interface.rs
+++ b/compiler/rustc_attr_parsing/src/interface.rs
@@ -51,6 +51,27 @@ pub fn parse_limited(
target_node_id: NodeId,
features: Option<&'sess Features>,
) -> Option<Attribute> {
+ Self::parse_limited_should_emit(
+ sess,
+ attrs,
+ sym,
+ target_span,
+ target_node_id,
+ features,
+ ShouldEmit::Nothing,
+ )
+ }
+
+ /// Usually you want `parse_limited`, which defaults to no errors.
+ pub fn parse_limited_should_emit(
+ sess: &'sess Session,
+ attrs: &[ast::Attribute],
+ sym: Symbol,
+ target_span: Span,
+ target_node_id: NodeId,
+ features: Option<&'sess Features>,
+ should_emit: ShouldEmit,
+ ) -> Option<Attribute> {
let mut parsed = Self::parse_limited_all(
sess,
attrs,
@@ -59,7 +80,7 @@ pub fn parse_limited(
target_span,
target_node_id,
features,
- ShouldEmit::Nothing,
+ should_emit,
);
assert!(parsed.len() <= 1);
parsed.pop()
@@ -84,9 +105,8 @@ pub fn parse_limited_all(
target,
OmitDoc::Skip,
std::convert::identity,
- |_lint| {
- // FIXME: Can't emit lints here for now
- // This branch can be hit when an attribute produces a warning during early parsing (such as attributes on macro calls)
+ |lint| {
+ crate::lints::emit_attribute_lint(&lint, sess);
},
)
}
@@ -121,8 +141,8 @@ pub fn parse_single<T>(
cx: &mut parser,
target_span,
target_id: target_node_id,
- emit_lint: &mut |_lint| {
- panic!("can't emit lints here for now (nothing uses this atm)");
+ emit_lint: &mut |lint| {
+ crate::lints::emit_attribute_lint(&lint, sess);
},
},
attr_span: attr.span,
@@ -251,16 +271,9 @@ pub fn parse_attribute_list(
};
(accept.accept_fn)(&mut cx, args);
-
- if self.stage.should_emit().should_emit() {
- self.check_target(
- path.get_attribute_path(),
- attr.span,
- &accept.allowed_targets,
- target,
- target_id,
- &mut emit_lint,
- );
+ if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
+ Self::check_type(accept.attribute_type, target, &mut cx);
+ Self::check_target(&accept.allowed_targets, target, &mut cx);
}
}
} else {
diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs
index 969c24a4..f51cc8c 100644
--- a/compiler/rustc_attr_parsing/src/lib.rs
+++ b/compiler/rustc_attr_parsing/src/lib.rs
@@ -79,6 +79,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![doc(rust_logo)]
+#![feature(decl_macro)]
#![feature(rustdoc_internals)]
#![recursion_limit = "256"]
// tidy-alphabetical-end
@@ -106,9 +107,7 @@
pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr};
pub use attributes::cfg_old::*;
-pub use attributes::util::{
- find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
-};
+pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
pub use context::{Early, Late, OmitDoc, ShouldEmit};
pub use interface::AttributeParser;
pub use lints::emit_attribute_lint;
diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs
index 7030f28..b1a971e 100644
--- a/compiler/rustc_attr_parsing/src/lints.rs
+++ b/compiler/rustc_attr_parsing/src/lints.rs
@@ -1,13 +1,13 @@
use std::borrow::Cow;
use rustc_errors::{DiagArgValue, LintEmitter};
+use rustc_hir::Target;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
-use rustc_hir::{HirId, Target};
use rustc_span::sym;
use crate::session_diagnostics;
-pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emitter: L) {
+pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emitter: L) {
let AttributeLint { id, span, kind } = lint;
match kind {
@@ -41,8 +41,14 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
.emit_node_span_lint(
// This check is here because `deprecated` had its own lint group and removing this would be a breaking change
if name.segments[0].name == sym::deprecated
- && ![Target::Closure, Target::Expression, Target::Statement, Target::Arm]
- .contains(target)
+ && ![
+ Target::Closure,
+ Target::Expression,
+ Target::Statement,
+ Target::Arm,
+ Target::MacroCall,
+ ]
+ .contains(target)
{
rustc_session::lint::builtin::USELESS_DEPRECATED
} else {
@@ -51,7 +57,7 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
*id,
*span,
session_diagnostics::InvalidTargetLint {
- name,
+ name: name.clone(),
target: target.plural_name(),
applied: DiagArgValue::StrListSepByAnd(
applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
@@ -60,5 +66,19 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
attr_span: *span,
},
),
+
+ &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => {
+ lint_emitter.emit_node_span_lint(
+ rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
+ *id,
+ *span,
+ session_diagnostics::InvalidAttrStyle {
+ name: name.clone(),
+ is_used_as_inner,
+ target_span: (!is_used_as_inner).then_some(target_span),
+ target,
+ },
+ )
+ }
}
}
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index 364f881..4f90359 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -10,11 +10,11 @@
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path};
use rustc_ast_pretty::pprust;
-use rustc_errors::PResult;
+use rustc_errors::{Diag, PResult};
use rustc_hir::{self as hir, AttrPath};
use rustc_parse::exp;
use rustc_parse::parser::{Parser, PathStyle, token_descr};
-use rustc_session::errors::report_lit_error;
+use rustc_session::errors::{create_lit_error, report_lit_error};
use rustc_session::parse::ParseSess;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym};
use thin_vec::ThinVec;
@@ -328,15 +328,16 @@ fn expr_to_lit(
match res {
Ok(lit) => {
if token_lit.suffix.is_some() {
- psess
- .dcx()
- .create_err(SuffixedLiteralInAttribute { span: lit.span })
- .emit_unless_delay(!should_emit.should_emit());
+ should_emit.emit_err(
+ psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+ );
None
} else {
- if should_emit.should_emit() && !lit.kind.is_unsuffixed() {
+ if !lit.kind.is_unsuffixed() {
// Emit error and continue, we can still parse the attribute as if the suffix isn't there
- psess.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
+ should_emit.emit_err(
+ psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+ );
}
Some(lit)
@@ -354,6 +355,10 @@ fn expr_to_lit(
}
}
} else {
+ if matches!(should_emit, ShouldEmit::Nothing) {
+ return None;
+ }
+
// Example cases:
// - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
// - `#[foo = include_str!("nonexistent-file.rs")]`:
@@ -361,12 +366,8 @@ fn expr_to_lit(
// the error because an earlier error will have already
// been reported.
let msg = "attribute value must be a literal";
- let mut err = psess.dcx().struct_span_err(span, msg);
- if let ExprKind::Err(_) = expr.kind {
- err.downgrade_to_delayed_bug();
- }
-
- err.emit_unless_delay(!should_emit.should_emit());
+ let err = psess.dcx().struct_span_err(span, msg);
+ should_emit.emit_err(err);
None
}
}
@@ -378,28 +379,31 @@ struct MetaItemListParserContext<'a, 'sess> {
impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'sess, MetaItemLit> {
- let uninterpolated_span = self.parser.token_uninterpolated_span();
- let Some(token_lit) = self.parser.eat_token_lit() else {
- return self.parser.handle_missing_lit(Parser::mk_meta_item_lit_char);
- };
+ let Some(token_lit) = self.parser.eat_token_lit() else { return Err(self.expected_lit()) };
+ self.unsuffixed_meta_item_from_lit(token_lit)
+ }
+ fn unsuffixed_meta_item_from_lit(
+ &mut self,
+ token_lit: token::Lit,
+ ) -> PResult<'sess, MetaItemLit> {
let lit = match MetaItemLit::from_token_lit(token_lit, self.parser.prev_token.span) {
Ok(lit) => lit,
Err(err) => {
- let guar =
- report_lit_error(&self.parser.psess, err, token_lit, uninterpolated_span);
- // Pack possible quotes and prefixes from the original literal into
- // the error literal's symbol so they can be pretty-printed faithfully.
- let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None);
- let symbol = Symbol::intern(&suffixless_lit.to_string());
- let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix);
- MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap()
+ return Err(create_lit_error(
+ &self.parser.psess,
+ err,
+ token_lit,
+ self.parser.prev_token_uninterpolated_span(),
+ ));
}
};
- if self.should_emit.should_emit() && !lit.kind.is_unsuffixed() {
+ if !lit.kind.is_unsuffixed() {
// Emit error and continue, we can still parse the attribute as if the suffix isn't there
- self.parser.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
+ self.should_emit.emit_err(
+ self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+ );
}
Ok(lit)
@@ -445,16 +449,28 @@ fn parse_attr_item(&mut self) -> PResult<'sess, MetaItemParser<'static>> {
}
fn parse_meta_item_inner(&mut self) -> PResult<'sess, MetaItemOrLitParser<'static>> {
- match self.parse_unsuffixed_meta_item_lit() {
- Ok(lit) => return Ok(MetaItemOrLitParser::Lit(lit)),
- Err(err) => err.cancel(), // we provide a better error below
+ if let Some(token_lit) = self.parser.eat_token_lit() {
+ // If a literal token is parsed, we commit to parsing a MetaItemLit for better errors
+ Ok(MetaItemOrLitParser::Lit(self.unsuffixed_meta_item_from_lit(token_lit)?))
+ } else {
+ let prev_pros = self.parser.approx_token_stream_pos();
+ match self.parse_attr_item() {
+ Ok(item) => Ok(MetaItemOrLitParser::MetaItemParser(item)),
+ Err(err) => {
+ // If `parse_attr_item` made any progress, it likely has a more precise error we should prefer
+ // If it didn't make progress we use the `expected_lit` from below
+ if self.parser.approx_token_stream_pos() != prev_pros {
+ Err(err)
+ } else {
+ err.cancel();
+ Err(self.expected_lit())
+ }
+ }
+ }
}
+ }
- match self.parse_attr_item() {
- Ok(mi) => return Ok(MetaItemOrLitParser::MetaItemParser(mi)),
- Err(err) => err.cancel(), // we provide a better error below
- }
-
+ fn expected_lit(&mut self) -> Diag<'sess> {
let mut err = InvalidMetaItem {
span: self.parser.token.span,
descr: token_descr(&self.parser.token),
@@ -489,7 +505,7 @@ fn parse_meta_item_inner(&mut self) -> PResult<'sess, MetaItemOrLitParser<'stati
self.parser.bump();
}
- Err(self.parser.dcx().create_err(err))
+ self.parser.dcx().create_err(err)
}
fn parse(
@@ -539,7 +555,7 @@ fn new<'sess>(
) {
Ok(s) => Some(s),
Err(e) => {
- e.emit_unless_delay(!should_emit.should_emit());
+ should_emit.emit_err(e);
None
}
}
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 2192e8f..a9dee23 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -6,7 +6,7 @@
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
};
use rustc_feature::AttributeTemplate;
-use rustc_hir::AttrPath;
+use rustc_hir::{AttrPath, Target};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
@@ -484,9 +484,9 @@ pub(crate) struct EmptyAttributeList {
#[diag(attr_parsing_invalid_target_lint)]
#[warning]
#[help]
-pub(crate) struct InvalidTargetLint<'a> {
- pub name: &'a AttrPath,
- pub target: &'a str,
+pub(crate) struct InvalidTargetLint {
+ pub name: AttrPath,
+ pub target: &'static str,
pub applied: DiagArgValue,
pub only: &'static str,
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
@@ -826,3 +826,107 @@ pub(crate) struct SuffixedLiteralInAttribute {
#[primary_span]
pub span: Span,
}
+
+#[derive(LintDiagnostic)]
+#[diag(attr_parsing_invalid_style)]
+pub(crate) struct InvalidAttrStyle {
+ pub name: AttrPath,
+ pub is_used_as_inner: bool,
+ #[note]
+ pub target_span: Option<Span>,
+ pub target: Target,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_empty_link_name, code = E0454)]
+pub(crate) struct EmptyLinkName {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_link_framework_apple, code = E0455)]
+pub(crate) struct LinkFrameworkApple {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_incompatible_wasm_link)]
+pub(crate) struct IncompatibleWasmLink {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_link_requires_name, code = E0459)]
+pub(crate) struct LinkRequiresName {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_raw_dylib_no_nul)]
+pub(crate) struct RawDylibNoNul {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_raw_dylib_only_windows, code = E0455)]
+pub(crate) struct RawDylibOnlyWindows {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_invalid_link_modifier)]
+pub(crate) struct InvalidLinkModifier {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_multiple_modifiers)]
+pub(crate) struct MultipleModifiers {
+ #[primary_span]
+ pub span: Span,
+ pub modifier: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_import_name_type_x86)]
+pub(crate) struct ImportNameTypeX86 {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_bundle_needs_static)]
+pub(crate) struct BundleNeedsStatic {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_whole_archive_needs_static)]
+pub(crate) struct WholeArchiveNeedsStatic {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_as_needed_compatibility)]
+pub(crate) struct AsNeededCompatibility {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_import_name_type_raw)]
+pub(crate) struct ImportNameTypeRaw {
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs
index 9568b79..edc496b 100644
--- a/compiler/rustc_attr_parsing/src/target_checking.rs
+++ b/compiler/rustc_attr_parsing/src/target_checking.rs
@@ -1,13 +1,13 @@
use std::borrow::Cow;
+use rustc_ast::AttrStyle;
use rustc_errors::DiagArgValue;
-use rustc_feature::Features;
-use rustc_hir::lints::{AttributeLint, AttributeLintKind};
-use rustc_hir::{AttrPath, MethodKind, Target};
-use rustc_span::Span;
+use rustc_feature::{AttributeType, Features};
+use rustc_hir::lints::AttributeLintKind;
+use rustc_hir::{MethodKind, Target};
use crate::AttributeParser;
-use crate::context::Stage;
+use crate::context::{AcceptContext, Stage};
use crate::session_diagnostics::InvalidTarget;
#[derive(Debug)]
@@ -68,40 +68,36 @@ pub(crate) enum Policy {
Error(Target),
}
-impl<S: Stage> AttributeParser<'_, S> {
+impl<'sess, S: Stage> AttributeParser<'sess, S> {
pub(crate) fn check_target(
- &self,
- attr_name: AttrPath,
- attr_span: Span,
allowed_targets: &AllowedTargets,
target: Target,
- target_id: S::Id,
- mut emit_lint: impl FnMut(AttributeLint<S::Id>),
+ cx: &mut AcceptContext<'_, 'sess, S>,
) {
match allowed_targets.is_allowed(target) {
AllowedResult::Allowed => {}
AllowedResult::Warn => {
let allowed_targets = allowed_targets.allowed_targets();
- let (applied, only) =
- allowed_targets_applied(allowed_targets, target, self.features);
- emit_lint(AttributeLint {
- id: target_id,
- span: attr_span,
- kind: AttributeLintKind::InvalidTarget {
- name: attr_name,
+ let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
+ let name = cx.attr_path.clone();
+ let attr_span = cx.attr_span;
+ cx.emit_lint(
+ AttributeLintKind::InvalidTarget {
+ name,
target,
only: if only { "only " } else { "" },
applied,
},
- });
+ attr_span,
+ );
}
AllowedResult::Error => {
let allowed_targets = allowed_targets.allowed_targets();
- let (applied, only) =
- allowed_targets_applied(allowed_targets, target, self.features);
- self.dcx().emit_err(InvalidTarget {
- span: attr_span,
- name: attr_name,
+ let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
+ let name = cx.attr_path.clone();
+ cx.dcx().emit_err(InvalidTarget {
+ span: cx.attr_span.clone(),
+ name,
target: target.plural_name(),
only: if only { "only " } else { "" },
applied: DiagArgValue::StrListSepByAnd(
@@ -111,6 +107,32 @@ pub(crate) fn check_target(
}
}
}
+
+ pub(crate) fn check_type(
+ attribute_type: AttributeType,
+ target: Target,
+ cx: &mut AcceptContext<'_, 'sess, S>,
+ ) {
+ let is_crate_root = S::id_is_crate_root(cx.target_id);
+
+ if is_crate_root {
+ return;
+ }
+
+ if attribute_type != AttributeType::CrateLevel {
+ return;
+ }
+
+ let lint = AttributeLintKind::InvalidStyle {
+ name: cx.attr_path.clone(),
+ is_used_as_inner: cx.attr_style == AttrStyle::Inner,
+ target,
+ target_span: cx.target_span,
+ };
+ let attr_span = cx.attr_span;
+
+ cx.emit_lint(lint, attr_span);
+ }
}
/// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml
index cb0e145..2f1ab7d 100644
--- a/compiler/rustc_baked_icu_data/Cargo.toml
+++ b/compiler/rustc_baked_icu_data/Cargo.toml
@@ -5,9 +5,8 @@
[dependencies]
# tidy-alphabetical-start
-icu_list = "1.2"
-icu_locid = "1.2"
-icu_locid_transform = "1.3.2"
-icu_provider = { version = "1.2", features = ["sync"] }
-zerovec = "0.10.0"
+icu_list = { version = "2.0", default-features = false }
+icu_locale = { version = "2.0", default-features = false, features = ["compiled_data"] }
+icu_provider = { version = "2.0", features = ["baked", "sync"] }
+zerovec = "0.11.0"
# tidy-alphabetical-end
diff --git a/compiler/rustc_baked_icu_data/src/data/any.rs b/compiler/rustc_baked_icu_data/src/data/any.rs
deleted file mode 100644
index 2302887..0000000
--- a/compiler/rustc_baked_icu_data/src/data/any.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-// @generated
-impl_any_provider!(BakedDataProvider);
diff --git a/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data b/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data
new file mode 100644
index 0000000..1d60e00
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data
@@ -0,0 +1,71 @@
+// @generated
+/// Implement `DataProvider<ListAndV1>` on the given struct using the data
+/// hardcoded in this file. This allows the struct to be used with
+/// `icu`'s `_unstable` constructors.
+///
+/// Using this implementation will embed the following data in the binary's data segment:
+/// * 179B for the lookup data structure (33 data identifiers)
+/// * 4183B[^1] for the actual data (11 unique structs)
+///
+/// [^1]: these numbers can be smaller in practice due to linker deduplication
+///
+/// This macro requires the following crates:
+/// * `icu_list`
+/// * `icu_locale/compiled_data`
+/// * `icu_provider`
+/// * `icu_provider/baked`
+/// * `zerovec`
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __impl_list_and_v1 {
+ ($ provider : ty) => {
+ #[clippy::msrv = "1.82"]
+ const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
+ #[clippy::msrv = "1.82"]
+ impl $provider {
+ const DATA_LIST_AND_V1: icu_provider::baked::zerotrie::Data<icu_list::provider::ListAndV1> = {
+ const TRIE: icu_provider::baked::zerotrie::ZeroTrieSimpleAscii<&'static [u8]> = icu_provider::baked::zerotrie::ZeroTrieSimpleAscii { store: b"\xC8efijprtz\x18#.9DOZ\xC2ns\n\x1E\xC3NSW\x01\x02\x80\x85\x8A\x1E\xC3NSW\x01\x02\x81\x81\x81r\x1E\xC3NSW\x01\x02\x80\x86\x86t\x1E\xC3NSW\x01\x02\x82\x82\x82a\x1E\xC3NSW\x01\x02\x83\x83\x83t\x1E\xC3NSW\x01\x02\x80\x82\x82u\x1E\xC3NSW\x01\x02\x80\x87\x87r\x1E\xC3NSW\x01\x02\x80\x88\x88h\xC2\x1E-\t\xC3NSW\x01\x02\x83\x89\x89Han\xC2st\n\x1E\xC3NSW\x01\x02\x83\x89\x89\x1E\xC3NSW\x01\x02\x84\x89\x89" };
+ const VALUES: &'static [<icu_list::provider::ListAndV1 as icu_provider::baked::zerotrie::DynamicDataMarker>::DataStruct] = &[icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" y ") }, 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x02\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\x01\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x06\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF`\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\x12\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x02\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x80\x01\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\x05\x05\x05\x06\x06\x0C\x0C\r\r\0\0\0\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\x02\0\x1B\0\0\0\0\0\x12\0\0\0\x12\0\0\x03\x06\x06\r\r\0\0\0\0\0h\0\0\0h\0\0\0\0\0\0\x0E\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\x01\n\0\0\x01\x19\0\0\0\x12\0\0\x02\x0F\x11\0\0\0\0\0D\0\0\0\0\0\0\x02\x11\x11\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x0F\x11\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x0F\x10\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x10\x11\0\0\0\0\0\xDD\0\0\0\0\0\0\x02\x0F\x11\0\0\0\0\0\xDD\0\0\0\0\0\0\x02\x0F\x0F\0\0\0\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\x03\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\x01\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x06\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0`\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\x12\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" e ") }, 3u8) }) }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" e ") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE5\x92\x8C") }, 3u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), special_case: None }) }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", & ") }, 4u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" & ") }, 3u8), special_case: None }) }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" et ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" \xD0\xB8 ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" ve ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE5\x92\x8C") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", and ") }, 6u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" and ") }, 5u8), special_case: None }) }];
+ unsafe { icu_provider::baked::zerotrie::Data::from_trie_and_values_unchecked(TRIE, VALUES) }
+ };
+ }
+ #[clippy::msrv = "1.82"]
+ impl icu_provider::DataProvider<icu_list::provider::ListAndV1> for $provider {
+ fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_list::provider::ListAndV1>, icu_provider::DataError> {
+ let mut metadata = icu_provider::DataResponseMetadata::default();
+ let payload = if let Some(payload) = icu_provider::baked::DataStore::get(&Self::DATA_LIST_AND_V1, req.id, req.metadata.attributes_prefix_match) {
+ payload
+ } else {
+ const FALLBACKER: icu_locale::fallback::LocaleFallbackerWithConfig<'static> = icu_locale::fallback::LocaleFallbacker::new().for_config(<icu_list::provider::ListAndV1 as icu_provider::DataMarker>::INFO.fallback_config);
+ let mut fallback_iterator = FALLBACKER.fallback_for(req.id.locale.clone());
+ loop {
+ if let Some(payload) = icu_provider::baked::DataStore::get(&Self::DATA_LIST_AND_V1, icu_provider::DataIdentifierBorrowed::for_marker_attributes_and_locale(req.id.marker_attributes, fallback_iterator.get()), req.metadata.attributes_prefix_match) {
+ metadata.locale = Some(fallback_iterator.take());
+ break payload;
+ }
+ if fallback_iterator.get().is_unknown() {
+ return Err(icu_provider::DataErrorKind::IdentifierNotFound.with_req(<icu_list::provider::ListAndV1 as icu_provider::DataMarker>::INFO, req));
+ }
+ fallback_iterator.step();
+ }
+ };
+ Ok(icu_provider::DataResponse { payload, metadata })
+ }
+ }
+ };
+ ($ provider : ty , ITER) => {
+ __impl_list_and_v1!($provider);
+ #[clippy::msrv = "1.82"]
+ impl icu_provider::IterableDataProvider<icu_list::provider::ListAndV1> for $provider {
+ fn iter_ids(&self) -> Result<std::collections::BTreeSet<icu_provider::DataIdentifierCow<'static>>, icu_provider::DataError> {
+ Ok(icu_provider::baked::DataStore::iter(&Self::DATA_LIST_AND_V1).collect())
+ }
+ }
+ };
+ ($ provider : ty , DRY) => {};
+ ($ provider : ty , DRY , ITER) => {
+ __impl_list_and_v1!($provider, ITER);
+ };
+}
+#[doc(inline)]
+pub use __impl_list_and_v1 as impl_list_and_v1;
diff --git a/compiler/rustc_baked_icu_data/src/data/macros.rs b/compiler/rustc_baked_icu_data/src/data/macros.rs
deleted file mode 100644
index bee309f..0000000
--- a/compiler/rustc_baked_icu_data/src/data/macros.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-// @generated
-/// Marks a type as a data provider. You can then use macros like
-/// `impl_core_helloworld_v1` to add implementations.
-///
-/// ```ignore
-/// struct MyProvider;
-/// const _: () = {
-/// include!("path/to/generated/macros.rs");
-/// make_provider!(MyProvider);
-/// impl_core_helloworld_v1!(MyProvider);
-/// }
-/// ```
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __make_provider {
- ($ name : ty) => {
- #[clippy::msrv = "1.66"]
- impl $name {
- #[doc(hidden)]
- #[allow(dead_code)]
- pub const MUST_USE_MAKE_PROVIDER_MACRO: () = ();
- }
- };
-}
-#[doc(inline)]
-pub use __make_provider as make_provider;
-#[macro_use]
-#[path = "macros/fallback_likelysubtags_v1.data.rs"]
-mod fallback_likelysubtags_v1;
-#[doc(inline)]
-pub use __impl_fallback_likelysubtags_v1 as impl_fallback_likelysubtags_v1;
-#[macro_use]
-#[path = "macros/fallback_parents_v1.data.rs"]
-mod fallback_parents_v1;
-#[doc(inline)]
-pub use __impl_fallback_parents_v1 as impl_fallback_parents_v1;
-#[macro_use]
-#[path = "macros/fallback_supplement_co_v1.data.rs"]
-mod fallback_supplement_co_v1;
-#[doc(inline)]
-pub use __impl_fallback_supplement_co_v1 as impl_fallback_supplement_co_v1;
-#[macro_use]
-#[path = "macros/list_and_v1.data.rs"]
-mod list_and_v1;
-#[doc(inline)]
-pub use __impl_list_and_v1 as impl_list_and_v1;
diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs
deleted file mode 100644
index 1adb587..0000000
--- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// @generated
-/// Implement `DataProvider<LocaleFallbackLikelySubtagsV1Marker>` on the given struct using the data
-/// hardcoded in this file. This allows the struct to be used with
-/// `icu`'s `_unstable` constructors.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __impl_fallback_likelysubtags_v1 {
- ($ provider : ty) => {
- #[clippy::msrv = "1.66"]
- const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
- #[clippy::msrv = "1.66"]
- impl $provider {
- #[doc(hidden)]
- pub const SINGLETON_FALLBACK_LIKELYSUBTAGS_V1: &'static <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1 {
- l2s: unsafe {
- #[allow(unused_unsafe)]
- zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") })
- },
- lr2s: unsafe {
- #[allow(unused_unsafe)]
- zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") })
- },
- l2r: unsafe {
- #[allow(unused_unsafe)]
- zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") })
- },
- ls2r: unsafe {
- #[allow(unused_unsafe)]
- zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0") })
- },
- };
- }
- #[clippy::msrv = "1.66"]
- impl icu_provider::DataProvider<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider {
- fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>, icu_provider::DataError> {
- if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_LIKELYSUBTAGS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
- }
- }
- };
-}
diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs
deleted file mode 100644
index 6f8d659..0000000
--- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// @generated
-/// Implement `DataProvider<LocaleFallbackParentsV1Marker>` on the given struct using the data
-/// hardcoded in this file. This allows the struct to be used with
-/// `icu`'s `_unstable` constructors.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __impl_fallback_parents_v1 {
- ($ provider : ty) => {
- #[clippy::msrv = "1.66"]
- const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
- #[clippy::msrv = "1.66"]
- impl $provider {
- #[doc(hidden)]
- pub const SINGLETON_FALLBACK_PARENTS_V1: &'static <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackParentsV1 {
- parents: unsafe {
- #[allow(unused_unsafe)]
- zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") })
- },
- };
- }
- #[clippy::msrv = "1.66"]
- impl icu_provider::DataProvider<icu_locid_transform::provider::LocaleFallbackParentsV1Marker> for $provider {
- fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>, icu_provider::DataError> {
- if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_PARENTS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
- }
- }
- };
-}
diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs
deleted file mode 100644
index 02eec37..0000000
--- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// @generated
-/// Implement `DataProvider<CollationFallbackSupplementV1Marker>` on the given struct using the data
-/// hardcoded in this file. This allows the struct to be used with
-/// `icu`'s `_unstable` constructors.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __impl_fallback_supplement_co_v1 {
- ($ provider : ty) => {
- #[clippy::msrv = "1.66"]
- const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
- #[clippy::msrv = "1.66"]
- impl $provider {
- #[doc(hidden)]
- pub const SINGLETON_FALLBACK_SUPPLEMENT_CO_V1: &'static <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackSupplementV1 {
- parents: unsafe {
- #[allow(unused_unsafe)]
- zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") })
- },
- unicode_extension_defaults: unsafe {
- #[allow(unused_unsafe)]
- zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"co") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") })
- },
- };
- }
- #[clippy::msrv = "1.66"]
- impl icu_provider::DataProvider<icu_locid_transform::provider::CollationFallbackSupplementV1Marker> for $provider {
- fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>, icu_provider::DataError> {
- if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_SUPPLEMENT_CO_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
- }
- }
- };
-}
diff --git a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs
deleted file mode 100644
index 186f706..0000000
--- a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// @generated
-/// Implement `DataProvider<AndListV1Marker>` on the given struct using the data
-/// hardcoded in this file. This allows the struct to be used with
-/// `icu`'s `_unstable` constructors.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __impl_list_and_v1 {
- ($ provider : ty) => {
- #[clippy::msrv = "1.66"]
- const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
- #[clippy::msrv = "1.66"]
- impl icu_provider::DataProvider<icu_list::provider::AndListV1Marker> for $provider {
- fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_list::provider::AndListV1Marker>, icu_provider::DataError> {
- static EN_001: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
- static EN_IN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
- static IT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }]);
- static PT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
- static FR: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
- static TR: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
- static ES: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }]);
- static RU: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
- static UND: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
- static EN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", & ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" & ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
- static HI_LATN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }]);
- static JA: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]);
- static ZH_HK: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }]);
- static ZH: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]);
- static ZH_HANT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }]);
- static VALUES: [&<icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable; 215usize] = [&EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_IN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &HI_LATN, &IT, &IT, &IT, &IT, &JA, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &RU, &RU, &RU, &RU, &RU, &RU, &TR, &TR, &UND, &ZH, &ZH_HK, &ZH, &ZH, &ZH, &ZH_HANT, &ZH_HK, &ZH];
- static KEYS: [&str; 215usize] = ["en", "en-001", "en-150", "en-AE", "en-AG", "en-AI", "en-AS", "en-AT", "en-AU", "en-BB", "en-BE", "en-BI", "en-BM", "en-BS", "en-BW", "en-BZ", "en-CA", "en-CC", "en-CH", "en-CK", "en-CM", "en-CX", "en-CY", "en-DE", "en-DG", "en-DK", "en-DM", "en-ER", "en-FI", "en-FJ", "en-FK", "en-FM", "en-GB", "en-GD", "en-GG", "en-GH", "en-GI", "en-GM", "en-GU", "en-GY", "en-HK", "en-IE", "en-IL", "en-IM", "en-IN", "en-IO", "en-JE", "en-JM", "en-KE", "en-KI", "en-KN", "en-KY", "en-LC", "en-LR", "en-LS", "en-MG", "en-MH", "en-MO", "en-MP", "en-MS", "en-MT", "en-MU", "en-MV", "en-MW", "en-MY", "en-NA", "en-NF", "en-NG", "en-NL", "en-NR", "en-NU", "en-NZ", "en-PG", "en-PH", "en-PK", "en-PN", "en-PR", "en-PW", "en-RW", "en-SB", "en-SC", "en-SD", "en-SE", "en-SG", "en-SH", "en-SI", "en-SL", "en-SS", "en-SX", "en-SZ", "en-TC", "en-TK", "en-TO", "en-TT", "en-TV", "en-TZ", "en-UG", "en-UM", "en-VC", "en-VG", "en-VI", "en-VU", "en-WS", "en-ZA", "en-ZM", "en-ZW", "es", "es-419", "es-AR", "es-BO", "es-BR", "es-BZ", "es-CL", "es-CO", "es-CR", "es-CU", "es-DO", "es-EA", "es-EC", "es-GQ", "es-GT", "es-HN", "es-IC", "es-MX", "es-NI", "es-PA", "es-PE", "es-PH", "es-PR", "es-PY", "es-SV", "es-US", "es-UY", "es-VE", "fr", "fr-BE", "fr-BF", "fr-BI", "fr-BJ", "fr-BL", "fr-CA", "fr-CD", "fr-CF", "fr-CG", "fr-CH", "fr-CI", "fr-CM", "fr-DJ", "fr-DZ", "fr-GA", "fr-GF", "fr-GN", "fr-GP", "fr-GQ", "fr-HT", "fr-KM", "fr-LU", "fr-MA", "fr-MC", "fr-MF", "fr-MG", "fr-ML", "fr-MQ", "fr-MR", "fr-MU", "fr-NC", "fr-NE", "fr-PF", "fr-PM", "fr-RE", "fr-RW", "fr-SC", "fr-SN", "fr-SY", "fr-TD", "fr-TG", "fr-TN", "fr-VU", "fr-WF", "fr-YT", "hi-Latn", "it", "it-CH", "it-SM", "it-VA", "ja", "pt", "pt-AO", "pt-CH", "pt-CV", "pt-GQ", "pt-GW", "pt-LU", "pt-MO", "pt-MZ", "pt-PT", "pt-ST", "pt-TL", "ru", "ru-BY", "ru-KG", "ru-KZ", "ru-MD", "ru-UA", "tr", "tr-CY", "und", "zh", "zh-HK", "zh-Hans", "zh-Hans-HK", "zh-Hans-MO", "zh-Hant", "zh-MO", "zh-SG"];
- if let Ok(payload) = KEYS.binary_search_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).map(|i| *unsafe { VALUES.get_unchecked(i) }) { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(payload)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::MissingLocale.with_req(<icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
- }
- }
- };
-}
diff --git a/compiler/rustc_baked_icu_data/src/data/mod.rs b/compiler/rustc_baked_icu_data/src/data/mod.rs
index 465689f..3146188 100644
--- a/compiler/rustc_baked_icu_data/src/data/mod.rs
+++ b/compiler/rustc_baked_icu_data/src/data/mod.rs
@@ -1,31 +1,40 @@
// @generated
-include!("macros.rs");
+include!("list_and_v1.rs.data");
+/// Marks a type as a data provider. You can then use macros like
+/// `impl_core_helloworld_v1` to add implementations.
+///
+/// ```ignore
+/// struct MyProvider;
+/// const _: () = {
+/// include!("path/to/generated/macros.rs");
+/// make_provider!(MyProvider);
+/// impl_core_helloworld_v1!(MyProvider);
+/// }
+/// ```
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __make_provider {
+ ($ name : ty) => {
+ #[clippy::msrv = "1.82"]
+ impl $name {
+ #[allow(dead_code)]
+ pub(crate) const MUST_USE_MAKE_PROVIDER_MACRO: () = ();
+ }
+ icu_provider::marker::impl_data_provider_never_marker!($name);
+ };
+}
+#[doc(inline)]
+pub use __make_provider as make_provider;
+/// This macro requires the following crates:
+/// * `icu_list`
+/// * `icu_locale/compiled_data`
+/// * `icu_provider`
+/// * `icu_provider/baked`
+/// * `zerovec`
+#[allow(unused_macros)]
macro_rules! impl_data_provider {
($ provider : ty) => {
make_provider!($provider);
- impl_fallback_likelysubtags_v1!($provider);
- impl_fallback_parents_v1!($provider);
- impl_fallback_supplement_co_v1!($provider);
impl_list_and_v1!($provider);
};
}
-#[allow(unused_macros)]
-macro_rules! impl_any_provider {
- ($ provider : ty) => {
- #[clippy::msrv = "1.66"]
- impl icu_provider::AnyProvider for $provider {
- fn load_any(&self, key: icu_provider::DataKey, req: icu_provider::DataRequest) -> Result<icu_provider::AnyResponse, icu_provider::DataError> {
- match key.hashed() {
- h if h == <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
- h if h == <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
- h if h == <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
- h if h == <icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_list::provider::AndListV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
- _ => Err(icu_provider::DataErrorKind::MissingDataKey.with_req(key, req)),
- }
- }
- }
- };
-}
-#[clippy::msrv = "1.66"]
-pub struct BakedDataProvider;
-impl_data_provider!(BakedDataProvider);
diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs
index f3f6522..ea4c824 100644
--- a/compiler/rustc_baked_icu_data/src/lib.rs
+++ b/compiler/rustc_baked_icu_data/src/lib.rs
@@ -14,10 +14,9 @@
//! To regenerate the data, run this command:
//!
//! ```text
-//! icu4x-datagen -W --pretty --fingerprint --use-separate-crates \
-//! --format mod -l en es fr it ja pt ru tr zh zh-Hans zh-Hant \
-//! -k list/and@1 fallback/likelysubtags@1 fallback/parents@1 fallback/supplement/co@1 \
-//! --cldr-tag latest --icuexport-tag latest -o src/data
+//! icu4x-datagen -W --pretty --use-separate-crates \
+//! --format baked --locales @en @es @fr @it @ja @pt @ru @tr @zh @zh-Hans @zh-Hant \
+//! -m ListAndV1 -o src/data
//! ```
// tidy-alphabetical-start
@@ -29,26 +28,26 @@
// #![warn(unreachable_pub)] // don't use because this crate is mostly generated code
// tidy-alphabetical-end
-mod data {
- include!("data/mod.rs");
- include!("data/any.rs");
-}
+pub struct BakedDataProvider;
-pub use data::BakedDataProvider;
+include!("data/mod.rs");
+const _: () = {
+ impl_data_provider!(BakedDataProvider);
+};
pub const fn baked_data_provider() -> BakedDataProvider {
- data::BakedDataProvider
+ BakedDataProvider
}
pub mod supported_locales {
- pub const EN: icu_locid::Locale = icu_locid::locale!("en");
- pub const ES: icu_locid::Locale = icu_locid::locale!("es");
- pub const FR: icu_locid::Locale = icu_locid::locale!("fr");
- pub const IT: icu_locid::Locale = icu_locid::locale!("it");
- pub const JA: icu_locid::Locale = icu_locid::locale!("ja");
- pub const PT: icu_locid::Locale = icu_locid::locale!("pt");
- pub const RU: icu_locid::Locale = icu_locid::locale!("ru");
- pub const TR: icu_locid::Locale = icu_locid::locale!("tr");
- pub const ZH_HANS: icu_locid::Locale = icu_locid::locale!("zh-Hans");
- pub const ZH_HANT: icu_locid::Locale = icu_locid::locale!("zh-Hant");
+ pub const EN: icu_locale::Locale = icu_locale::locale!("en");
+ pub const ES: icu_locale::Locale = icu_locale::locale!("es");
+ pub const FR: icu_locale::Locale = icu_locale::locale!("fr");
+ pub const IT: icu_locale::Locale = icu_locale::locale!("it");
+ pub const JA: icu_locale::Locale = icu_locale::locale!("ja");
+ pub const PT: icu_locale::Locale = icu_locale::locale!("pt");
+ pub const RU: icu_locale::Locale = icu_locale::locale!("ru");
+ pub const TR: icu_locale::Locale = icu_locale::locale!("tr");
+ pub const ZH_HANS: icu_locale::Locale = icu_locale::locale!("zh-Hans");
+ pub const ZH_HANT: icu_locale::Locale = icu_locale::locale!("zh-Hant");
}
diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index 9e7d551..5f9dc41 100644
--- a/compiler/rustc_borrowck/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -5,9 +5,9 @@
[dependencies]
# tidy-alphabetical-start
-either = "1.5.0"
-itertools = "0.12"
-polonius-engine = "0.13.0"
+either.workspace = true
+itertools.workspace = true
+polonius-engine.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
@@ -25,5 +25,5 @@
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_traits = { path = "../rustc_traits" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index fdca6b5..fda96dd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -565,7 +565,7 @@ fn free_region_constraint_info(
let (blame_constraint, path) = self.regioncx.best_blame_constraint(
borrow_region,
NllRegionVariableOrigin::FreeRegion,
- |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
+ outlived_region,
);
let BlameConstraint { category, from_closure, cause, .. } = blame_constraint;
diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
index f77f759..9991362 100644
--- a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
@@ -243,10 +243,9 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
let opaque_region_vid = self.regioncx.to_region_vid(opaque_region);
// Find a path between the borrow region and our opaque capture.
- if let Some((path, _)) =
- self.regioncx.find_constraint_path_between_regions(self.borrow_region, |r| {
- r == opaque_region_vid
- })
+ if let Some(path) = self
+ .regioncx
+ .constraint_path_between_regions(self.borrow_region, opaque_region_vid)
{
for constraint in path {
// If we find a call in this path, then check if it defines the opaque.
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index c7d2267..bec4c93 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -61,7 +61,7 @@ fn description(&self) -> &'static str {
| ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal
- | ConstraintCategory::IllegalUniverse => "",
+ | ConstraintCategory::OutlivesUnnameablePlaceholder(..) => "",
}
}
}
@@ -369,11 +369,15 @@ pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
let error_vid = self.regioncx.region_from_element(longer_fr, &error_element);
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
- let (_, cause) = self.regioncx.find_outlives_blame_span(
- longer_fr,
- NllRegionVariableOrigin::Placeholder(placeholder),
- error_vid,
- );
+ let cause = self
+ .regioncx
+ .best_blame_constraint(
+ longer_fr,
+ NllRegionVariableOrigin::Placeholder(placeholder),
+ error_vid,
+ )
+ .0
+ .cause;
let universe = placeholder.universe;
let universe_info = self.regioncx.universe_info(universe);
@@ -429,9 +433,8 @@ pub(crate) fn report_region_error(
) {
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
- let (blame_constraint, path) = self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
- self.regioncx.provides_universal_region(r, fr, outlived_fr)
- });
+ let (blame_constraint, path) =
+ self.regioncx.best_blame_constraint(fr, fr_origin, outlived_fr);
let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs
index 4661906..94379cd 100644
--- a/compiler/rustc_borrowck/src/handle_placeholders.rs
+++ b/compiler/rustc_borrowck/src/handle_placeholders.rs
@@ -1,7 +1,6 @@
//! Logic for lowering higher-kinded outlives constraints
//! (with placeholders and universes) and turn them into regular
//! outlives constraints.
-
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::graph::scc;
@@ -10,7 +9,7 @@
use rustc_infer::infer::RegionVariableOrigin;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{RegionVid, UniverseIndex};
-use tracing::debug;
+use tracing::{debug, trace};
use crate::constraints::{ConstraintSccIndex, OutlivesConstraintSet};
use crate::consumers::OutlivesConstraint;
@@ -62,18 +61,71 @@ fn annotate_scc(&mut self, scc: ConstraintSccIndex, annotation: RegionTracker) {
type SccIdx = ConstraintSccIndex;
}
+#[derive(Copy, Debug, Clone, PartialEq, Eq)]
+enum PlaceholderReachability {
+ /// This SCC reaches no placeholders.
+ NoPlaceholders,
+ /// This SCC reaches at least one placeholder.
+ Placeholders {
+ /// The largest-universed placeholder we can reach
+ max_universe: (UniverseIndex, RegionVid),
+
+ /// The placeholder with the smallest ID
+ min_placeholder: RegionVid,
+
+ /// The placeholder with the largest ID
+ max_placeholder: RegionVid,
+ },
+}
+
+impl PlaceholderReachability {
+ /// Merge the reachable placeholders of two graph components.
+ fn merge(self, other: PlaceholderReachability) -> PlaceholderReachability {
+ use PlaceholderReachability::*;
+ match (self, other) {
+ (NoPlaceholders, NoPlaceholders) => NoPlaceholders,
+ (NoPlaceholders, p @ Placeholders { .. })
+ | (p @ Placeholders { .. }, NoPlaceholders) => p,
+ (
+ Placeholders {
+ min_placeholder: min_pl,
+ max_placeholder: max_pl,
+ max_universe: max_u,
+ },
+ Placeholders { min_placeholder, max_placeholder, max_universe },
+ ) => Placeholders {
+ min_placeholder: min_pl.min(min_placeholder),
+ max_placeholder: max_pl.max(max_placeholder),
+ max_universe: max_u.max(max_universe),
+ },
+ }
+ }
+
+ fn max_universe(&self) -> Option<(UniverseIndex, RegionVid)> {
+ match self {
+ Self::NoPlaceholders => None,
+ Self::Placeholders { max_universe, .. } => Some(*max_universe),
+ }
+ }
+
+ /// If we have reached placeholders, determine if they can
+ /// be named from this universe.
+ fn can_be_named_by(&self, from: UniverseIndex) -> bool {
+ self.max_universe()
+ .is_none_or(|(max_placeholder_universe, _)| from.can_name(max_placeholder_universe))
+ }
+}
+
/// An annotation for region graph SCCs that tracks
/// the values of its elements. This annotates a single SCC.
#[derive(Copy, Debug, Clone)]
pub(crate) struct RegionTracker {
- /// The largest universe of a placeholder reached from this SCC.
- /// This includes placeholders within this SCC.
- max_placeholder_universe_reached: UniverseIndex,
+ reachable_placeholders: PlaceholderReachability,
/// The largest universe nameable from this SCC.
/// It is the smallest nameable universes of all
- /// existential regions reachable from it.
- max_nameable_universe: UniverseIndex,
+ /// existential regions reachable from it. Small Rvids are preferred.
+ max_nameable_universe: (UniverseIndex, RegionVid),
/// The representative Region Variable Id for this SCC.
pub(crate) representative: Representative,
@@ -81,65 +133,73 @@ pub(crate) struct RegionTracker {
impl RegionTracker {
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
- let placeholder_universe =
+ let reachable_placeholders =
if matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_)) {
- definition.universe
+ PlaceholderReachability::Placeholders {
+ max_universe: (definition.universe, rvid),
+ min_placeholder: rvid,
+ max_placeholder: rvid,
+ }
} else {
- UniverseIndex::ROOT
+ PlaceholderReachability::NoPlaceholders
};
Self {
- max_placeholder_universe_reached: placeholder_universe,
- max_nameable_universe: definition.universe,
+ reachable_placeholders,
+ max_nameable_universe: (definition.universe, rvid),
representative: Representative::new(rvid, definition),
}
}
/// The largest universe this SCC can name. It's the smallest
- /// largest nameable uninverse of any reachable region.
+ /// largest nameable universe of any reachable region, or
+ /// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
- self.max_nameable_universe
+ self.max_nameable_universe.0
}
pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex {
- self.max_placeholder_universe_reached
- }
-
- fn merge_min_max_seen(&mut self, other: &Self) {
- self.max_placeholder_universe_reached = std::cmp::max(
- self.max_placeholder_universe_reached,
- other.max_placeholder_universe_reached,
- );
-
- self.max_nameable_universe =
- std::cmp::min(self.max_nameable_universe, other.max_nameable_universe);
- }
-
- /// Returns `true` if during the annotated SCC reaches a placeholder
- /// with a universe larger than the smallest nameable universe of any
- /// reachable existential region.
- pub(crate) fn has_incompatible_universes(&self) -> bool {
- self.max_nameable_universe().cannot_name(self.max_placeholder_universe_reached)
+ if let Some((universe, _)) = self.reachable_placeholders.max_universe() {
+ universe
+ } else {
+ UniverseIndex::ROOT
+ }
}
/// Determine if the tracked universes of the two SCCs are compatible.
pub(crate) fn universe_compatible_with(&self, other: Self) -> bool {
+ // HACK: We first check whether we can name the highest existential universe
+ // of `other`. This only exists to avoid errors in case that scc already
+ // depends on a placeholder it cannot name itself.
self.max_nameable_universe().can_name(other.max_nameable_universe())
- || self.max_nameable_universe().can_name(other.max_placeholder_universe_reached)
+ || other.reachable_placeholders.can_be_named_by(self.max_nameable_universe())
+ }
+
+ /// If this SCC reaches a placeholder it can't name, return it.
+ fn unnameable_placeholder(&self) -> Option<(UniverseIndex, RegionVid)> {
+ self.reachable_placeholders.max_universe().filter(|&(placeholder_universe, _)| {
+ !self.max_nameable_universe().can_name(placeholder_universe)
+ })
}
}
impl scc::Annotation for RegionTracker {
- fn merge_scc(mut self, other: Self) -> Self {
- self.representative = self.representative.merge_scc(other.representative);
- self.merge_min_max_seen(&other);
- self
+ fn merge_scc(self, other: Self) -> Self {
+ trace!("{:?} << {:?}", self.representative, other.representative);
+
+ Self {
+ representative: self.representative.min(other.representative),
+ max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
+ reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
+ }
}
- fn merge_reached(mut self, other: Self) -> Self {
- // No update to in-component values, only add seen values.
- self.merge_min_max_seen(&other);
- self
+ fn merge_reached(self, other: Self) -> Self {
+ Self {
+ max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
+ reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
+ representative: self.representative,
+ }
}
}
@@ -310,28 +370,52 @@ fn rewrite_placeholder_outlives<'tcx>(
let annotation = annotations[scc];
- // If this SCC participates in a universe violation,
- // e.g. if it reaches a region with a universe smaller than
- // the largest region reached, add a requirement that it must
- // outlive `'static`.
- if annotation.has_incompatible_universes() {
- // Optimisation opportunity: this will add more constraints than
- // needed for correctness, since an SCC upstream of another with
- // a universe violation will "infect" its downstream SCCs to also
- // outlive static.
- let scc_representative_outlives_static = OutlivesConstraint {
- sup: annotation.representative.rvid(),
- sub: fr_static,
- category: ConstraintCategory::IllegalUniverse,
- locations: Locations::All(rustc_span::DUMMY_SP),
- span: rustc_span::DUMMY_SP,
- variance_info: VarianceDiagInfo::None,
- from_closure: false,
- };
- outlives_constraints.push(scc_representative_outlives_static);
- added_constraints = true;
- debug!("Added {:?}: 'static!", annotation.representative.rvid());
- }
+ let Some((max_u, max_u_rvid)) = annotation.unnameable_placeholder() else {
+ continue;
+ };
+
+ debug!(
+ "Placeholder universe {max_u:?} is too large for its SCC, represented by {:?}",
+ annotation.representative
+ );
+
+ // We only add one `r: 'static` constraint per SCC, where `r` is the SCC representative.
+ // That constraint is annotated with some placeholder `unnameable` where
+ // `unnameable` is unnameable from `r` and there is a path in the constraint graph
+ // between them.
+ //
+ // There is one exception; if some other region in this SCC can't name `'r`, then
+ // we pick the region with the smallest universe in the SCC, so that a path can
+ // always start in `'r` to find a motivation that isn't cyclic.
+ let blame_to = if annotation.representative.rvid() == max_u_rvid {
+ // Assertion: the region that lowered our universe is an existential one and we are a placeholder!
+
+ // The SCC's representative is not nameable from some region
+ // that ends up in the SCC.
+ let small_universed_rvid = annotation.max_nameable_universe.1;
+ debug!(
+ "{small_universed_rvid:?} lowered our universe to {:?}",
+ annotation.max_nameable_universe()
+ );
+ small_universed_rvid
+ } else {
+ // `max_u_rvid` is not nameable by the SCC's representative.
+ max_u_rvid
+ };
+
+ // FIXME: if we can extract a useful blame span here, future error
+ // reporting and constraint search can be simplified.
+
+ added_constraints = true;
+ outlives_constraints.push(OutlivesConstraint {
+ sup: annotation.representative.rvid(),
+ sub: fr_static,
+ category: ConstraintCategory::OutlivesUnnameablePlaceholder(blame_to),
+ locations: Locations::All(rustc_span::DUMMY_SP),
+ span: rustc_span::DUMMY_SP,
+ variance_info: VarianceDiagInfo::None,
+ from_closure: false,
+ });
}
added_constraints
}
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index a081e0d..ce78ae2 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -300,7 +300,7 @@ fn do_mir_borrowck<'tcx>(
def: LocalDefId,
) -> PropagatedBorrowCheckResults<'tcx> {
let tcx = root_cx.tcx;
- let infcx = BorrowckInferCtxt::new(tcx, def);
+ let infcx = BorrowckInferCtxt::new(tcx, def, root_cx.root_def_id());
let (input_body, promoted) = tcx.mir_promoted(def);
let input_body: &Body<'_> = &input_body.borrow();
let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
@@ -590,12 +590,13 @@ fn get_flow_results<'a, 'tcx>(
pub(crate) struct BorrowckInferCtxt<'tcx> {
pub(crate) infcx: InferCtxt<'tcx>,
- pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
+ pub(crate) root_def_id: LocalDefId,
pub(crate) param_env: ParamEnv<'tcx>,
+ pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
}
impl<'tcx> BorrowckInferCtxt<'tcx> {
- pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
+ pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId, root_def_id: LocalDefId) -> Self {
let typing_mode = if tcx.use_typing_mode_borrowck() {
TypingMode::borrowck(tcx, def_id)
} else {
@@ -603,7 +604,12 @@ pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
};
let infcx = tcx.infer_ctxt().build(typing_mode);
let param_env = tcx.param_env(def_id);
- BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env }
+ BorrowckInferCtxt {
+ infcx,
+ root_def_id,
+ reg_var_to_origin: RefCell::new(Default::default()),
+ param_env,
+ }
}
pub(crate) fn next_region_var<F>(
diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
index b2f67c4..526e185 100644
--- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs
+++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
@@ -12,9 +12,13 @@
use super::*;
fn render_outlives_constraint(constraint: &OutlivesConstraint<'_>) -> String {
- match constraint.locations {
- Locations::All(_) => "All(...)".to_string(),
- Locations::Single(loc) => format!("{loc:?}"),
+ if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = constraint.category {
+ format!("{unnameable:?} unnameable")
+ } else {
+ match constraint.locations {
+ Locations::All(_) => "All(...)".to_string(),
+ Locations::Single(loc) => format!("{loc:?}"),
+ }
}
}
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 3d95eb4..9990f4c 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -3,7 +3,7 @@
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_data_structures::graph::scc::{self, Sccs};
+use rustc_data_structures::graph::scc::Sccs;
use rustc_errors::Diag;
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_index::IndexVec;
@@ -74,18 +74,6 @@ pub(crate) fn new(r: RegionVid, definition: &RegionDefinition<'_>) -> Self {
}
}
-impl scc::Annotation for Representative {
- fn merge_scc(self, other: Self) -> Self {
- // Just pick the smallest one. Note that we order by tag first!
- std::cmp::min(self, other)
- }
-
- // For reachability, we do nothing since the representative doesn't change.
- fn merge_reached(self, _other: Self) -> Self {
- self
- }
-}
-
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>;
pub struct RegionInferenceContext<'tcx> {
@@ -1285,11 +1273,9 @@ fn try_propagate_universal_region_error(
{
debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
- let blame_span_category = self.find_outlives_blame_span(
- longer_fr,
- NllRegionVariableOrigin::FreeRegion,
- shorter_fr,
- );
+ let blame_constraint = self
+ .best_blame_constraint(longer_fr, NllRegionVariableOrigin::FreeRegion, shorter_fr)
+ .0;
// Grow `shorter_fr` until we find some non-local regions. (We
// always will.) We'll call them `shorter_fr+` -- they're ever
@@ -1302,8 +1288,8 @@ fn try_propagate_universal_region_error(
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
subject: ClosureOutlivesSubject::Region(fr_minus),
outlived_free_region: fr,
- blame_span: blame_span_category.1.span,
- category: blame_span_category.0,
+ blame_span: blame_constraint.cause.span,
+ category: blame_constraint.category,
});
}
return RegionRelationCheckResult::Propagated;
@@ -1342,66 +1328,15 @@ fn check_bound_universal_region(
}
}
- /// We have a constraint `fr1: fr2` that is not satisfied, where
- /// `fr2` represents some universal region. Here, `r` is some
- /// region where we know that `fr1: r` and this function has the
- /// job of determining whether `r` is "to blame" for the fact that
- /// `fr1: fr2` is required.
- ///
- /// This is true under two conditions:
- ///
- /// - `r == fr2`
- /// - `fr2` is `'static` and `r` is some placeholder in a universe
- /// that cannot be named by `fr1`; in that case, we will require
- /// that `fr1: 'static` because it is the only way to `fr1: r` to
- /// be satisfied. (See `add_incompatible_universe`.)
- pub(crate) fn provides_universal_region(
+ pub(crate) fn constraint_path_between_regions(
&self,
- r: RegionVid,
- fr1: RegionVid,
- fr2: RegionVid,
- ) -> bool {
- debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
- let result = {
- r == fr2 || {
- fr2 == self.universal_regions().fr_static && self.cannot_name_placeholder(fr1, r)
- }
- };
- debug!("provides_universal_region: result = {:?}", result);
- result
- }
-
- /// If `r2` represents a placeholder region, then this returns
- /// `true` if `r1` cannot name that placeholder in its
- /// value; otherwise, returns `false`.
- pub(crate) fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
- match self.definitions[r2].origin {
- NllRegionVariableOrigin::Placeholder(placeholder) => {
- let r1_universe = self.definitions[r1].universe;
- debug!(
- "cannot_name_value_of: universe1={r1_universe:?} placeholder={:?}",
- placeholder
- );
- r1_universe.cannot_name(placeholder.universe)
- }
-
- NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { .. } => {
- false
- }
+ from_region: RegionVid,
+ to_region: RegionVid,
+ ) -> Option<Vec<OutlivesConstraint<'tcx>>> {
+ if from_region == to_region {
+ bug!("Tried to find a path between {from_region:?} and itself!");
}
- }
-
- /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
- pub(crate) fn find_outlives_blame_span(
- &self,
- fr1: RegionVid,
- fr1_origin: NllRegionVariableOrigin,
- fr2: RegionVid,
- ) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) {
- let BlameConstraint { category, cause, .. } = self
- .best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2))
- .0;
- (category, cause)
+ self.constraint_path_to(from_region, |to| to == to_region, true).map(|o| o.0)
}
/// Walks the graph of constraints (where `'a: 'b` is considered
@@ -1410,15 +1345,30 @@ pub(crate) fn find_outlives_blame_span(
///
/// Returns: a series of constraints as well as the region `R`
/// that passed the target test.
+ /// If `include_static_outlives_all` is `true`, then the synthetic
+ /// outlives constraints `'static -> a` for every region `a` are
+ /// considered in the search, otherwise they are ignored.
#[instrument(skip(self, target_test), ret)]
- pub(crate) fn find_constraint_path_between_regions(
+ pub(crate) fn constraint_path_to(
&self,
from_region: RegionVid,
target_test: impl Fn(RegionVid) -> bool,
+ include_placeholder_static: bool,
) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
- self.find_constraint_path_between_regions_inner(true, from_region, &target_test).or_else(
- || self.find_constraint_path_between_regions_inner(false, from_region, &target_test),
+ self.find_constraint_path_between_regions_inner(
+ true,
+ from_region,
+ &target_test,
+ include_placeholder_static,
)
+ .or_else(|| {
+ self.find_constraint_path_between_regions_inner(
+ false,
+ from_region,
+ &target_test,
+ include_placeholder_static,
+ )
+ })
}
/// The constraints we get from equating the hidden type of each use of an opaque
@@ -1438,6 +1388,7 @@ fn find_constraint_path_between_regions_inner(
ignore_opaque_type_constraints: bool,
from_region: RegionVid,
target_test: impl Fn(RegionVid) -> bool,
+ include_placeholder_static: bool,
) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
context[from_region] = Trace::StartRegion;
@@ -1452,7 +1403,7 @@ fn find_constraint_path_between_regions_inner(
while let Some(r) = deque.pop_front() {
debug!(
- "find_constraint_path_between_regions: from_region={:?} r={:?} value={}",
+ "constraint_path_to: from_region={:?} r={:?} value={}",
from_region,
r,
self.region_value_str(r),
@@ -1525,8 +1476,10 @@ fn find_constraint_path_between_regions_inner(
// This loop can be hot.
for constraint in edges {
match constraint.category {
- ConstraintCategory::IllegalUniverse => {
- debug!("Ignoring illegal universe constraint: {constraint:?}");
+ ConstraintCategory::OutlivesUnnameablePlaceholder(_)
+ if !include_placeholder_static =>
+ {
+ debug!("Ignoring illegal placeholder constraint: {constraint:?}");
continue;
}
ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => {
@@ -1535,6 +1488,7 @@ fn find_constraint_path_between_regions_inner(
}
_ => {}
}
+
debug_assert_eq!(constraint.sup, r);
handle_trace(constraint.sub, Trace::FromGraph(constraint));
}
@@ -1549,33 +1503,10 @@ fn find_constraint_path_between_regions_inner(
pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid {
trace!(scc = ?self.constraint_sccs.scc(fr1));
trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1)));
- self.find_constraint_path_between_regions(fr1, |r| {
- // First look for some `r` such that `fr1: r` and `r` is live at `location`
+ self.constraint_path_to(fr1, |r| {
trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r));
self.liveness_constraints.is_live_at(r, location)
- })
- .or_else(|| {
- // If we fail to find that, we may find some `r` such that
- // `fr1: r` and `r` is a placeholder from some universe
- // `fr1` cannot name. This would force `fr1` to be
- // `'static`.
- self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(fr1, r))
- })
- .or_else(|| {
- // If we fail to find THAT, it may be that `fr1` is a
- // placeholder that cannot "fit" into its SCC. In that
- // case, there should be some `r` where `fr1: r` and `fr1` is a
- // placeholder that `r` cannot name. We can blame that
- // edge.
- //
- // Remember that if `R1: R2`, then the universe of R1
- // must be able to name the universe of R2, because R2 will
- // be at least `'empty(Universe(R2))`, and `R1` must be at
- // larger than that.
- self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(r, fr1))
- })
- .map(|(_path, r)| r)
- .unwrap()
+ }, true).unwrap().1
}
/// Get the region outlived by `longer_fr` and live at `element`.
@@ -1619,22 +1550,38 @@ pub(crate) fn universal_regions(&self) -> &UniversalRegions<'tcx> {
/// creating a constraint path that forces `R` to outlive
/// `from_region`, and then finding the best choices within that
/// path to blame.
- #[instrument(level = "debug", skip(self, target_test))]
+ #[instrument(level = "debug", skip(self))]
pub(crate) fn best_blame_constraint(
&self,
from_region: RegionVid,
from_region_origin: NllRegionVariableOrigin,
- target_test: impl Fn(RegionVid) -> bool,
+ to_region: RegionVid,
) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
- // Find all paths
- let (path, target_region) = self
- .find_constraint_path_between_regions(from_region, target_test)
- .or_else(|| {
- self.find_constraint_path_between_regions(from_region, |r| {
- self.cannot_name_placeholder(from_region, r)
- })
- })
- .unwrap();
+ assert!(from_region != to_region, "Trying to blame a region for itself!");
+
+ let path = self.constraint_path_between_regions(from_region, to_region).unwrap();
+
+ // If we are passing through a constraint added because we reached an unnameable placeholder `'unnameable`,
+ // redirect search towards `'unnameable`.
+ let due_to_placeholder_outlives = path.iter().find_map(|c| {
+ if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = c.category {
+ Some(unnameable)
+ } else {
+ None
+ }
+ });
+
+ // Edge case: it's possible that `'from_region` is an unnameable placeholder.
+ let path = if let Some(unnameable) = due_to_placeholder_outlives
+ && unnameable != from_region
+ {
+ // We ignore the extra edges due to unnameable placeholders to get
+ // an explanation that was present in the original constraint graph.
+ self.constraint_path_to(from_region, |r| r == unnameable, false).unwrap().0
+ } else {
+ path
+ };
+
debug!(
"path={:#?}",
path.iter()
@@ -1742,7 +1689,7 @@ pub(crate) fn best_blame_constraint(
ConstraintCategory::Cast {
unsize_to: Some(unsize_ty),
is_implicit_coercion: true,
- } if target_region == self.universal_regions().fr_static
+ } if to_region == self.universal_regions().fr_static
// Mirror the note's condition, to minimize how often this diverts blame.
&& let ty::Adt(_, args) = unsize_ty.kind()
&& args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait()))
@@ -1780,7 +1727,7 @@ pub(crate) fn best_blame_constraint(
// specific, and are not used for relations that would make sense to blame.
ConstraintCategory::BoringNoLocation => 6,
// Do not blame internal constraints.
- ConstraintCategory::IllegalUniverse => 7,
+ ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 7,
ConstraintCategory::Internal => 8,
};
@@ -1817,6 +1764,14 @@ pub(crate) fn best_blame_constraint(
path[best_choice]
};
+ assert!(
+ !matches!(
+ best_constraint.category,
+ ConstraintCategory::OutlivesUnnameablePlaceholder(_)
+ ),
+ "Illegal placeholder constraint blamed; should have redirected to other region relation"
+ );
+
let blame_constraint = BlameConstraint {
category: best_constraint.category,
from_closure: best_constraint.from_closure,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
index 33c4879..bee82e1 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
@@ -17,7 +17,7 @@
use rustc_mir_dataflow::points::DenseLocationMap;
use rustc_span::Span;
use rustc_trait_selection::opaque_types::{
- InvalidOpaqueTypeArgs, check_opaque_type_parameter_valid,
+ NonDefiningUseReason, opaque_type_has_defining_use_args,
};
use rustc_trait_selection::solve::NoSolution;
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
@@ -42,7 +42,7 @@
/// if there are no `RegionErrors`. If there are region errors, it's likely
/// that errors here are caused by them and don't need to be handled separately.
pub(crate) enum DeferredOpaqueTypeError<'tcx> {
- InvalidOpaqueTypeArgs(InvalidOpaqueTypeArgs<'tcx>),
+ InvalidOpaqueTypeArgs(NonDefiningUseReason<'tcx>),
LifetimeMismatchOpaqueParam(LifetimeMismatchOpaqueParam<'tcx>),
UnexpectedHiddenRegion {
/// The opaque type.
@@ -238,7 +238,7 @@ fn collect_defining_uses<'tcx>(
let non_nll_opaque_type_key = opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |r| {
nll_var_to_universal_region(&rcx, r.as_var()).unwrap_or(r)
});
- if let Err(err) = check_opaque_type_parameter_valid(
+ if let Err(err) = opaque_type_has_defining_use_args(
infcx,
non_nll_opaque_type_key,
hidden_type.span,
@@ -248,11 +248,10 @@ fn collect_defining_uses<'tcx>(
// with `TypingMode::Borrowck`.
if infcx.tcx.use_typing_mode_borrowck() {
match err {
- InvalidOpaqueTypeArgs::AlreadyReported(guar) => root_cx
- .add_concrete_opaque_type(
- opaque_type_key.def_id,
- OpaqueHiddenType::new_error(infcx.tcx, guar),
- ),
+ NonDefiningUseReason::Tainted(guar) => root_cx.add_concrete_opaque_type(
+ opaque_type_key.def_id,
+ OpaqueHiddenType::new_error(infcx.tcx, guar),
+ ),
_ => debug!(?non_nll_opaque_type_key, ?err, "ignoring non-defining use"),
}
} else {
@@ -676,8 +675,8 @@ fn infer_opaque_definition_from_instantiation(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: OpaqueHiddenType<'tcx>,
- ) -> Result<Ty<'tcx>, InvalidOpaqueTypeArgs<'tcx>> {
- check_opaque_type_parameter_valid(
+ ) -> Result<Ty<'tcx>, NonDefiningUseReason<'tcx>> {
+ opaque_type_has_defining_use_args(
self,
opaque_type_key,
instantiated_ty.span,
diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs
index 40c0448..4e90ae3 100644
--- a/compiler/rustc_borrowck/src/root_cx.rs
+++ b/compiler/rustc_borrowck/src/root_cx.rs
@@ -38,6 +38,10 @@ pub(super) fn new(
}
}
+ pub(super) fn root_def_id(&self) -> LocalDefId {
+ self.root_def_id
+ }
+
/// Collect all defining uses of opaque types inside of this typeck root. This
/// expects the hidden type to be mapped to the definition parameters of the opaque
/// and errors if we end up with distinct hidden types.
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index a8a4824..2627ed8 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -39,7 +39,7 @@ pub(crate) fn fully_perform_op_raw<'tcx, R: fmt::Debug, Op>(
let old_universe = infcx.universe();
let TypeOpOutput { output, constraints: query_constraints, error_info } =
- op.fully_perform(infcx, locations.span(body))?;
+ op.fully_perform(infcx, infcx.root_def_id, locations.span(body))?;
if cfg!(debug_assertions) {
let data = infcx.take_and_reset_region_constraints();
if !data.is_empty() {
@@ -54,7 +54,6 @@ pub(crate) fn fully_perform_op_raw<'tcx, R: fmt::Debug, Op>(
infcx,
universal_regions,
region_bound_pairs,
- infcx.param_env,
known_type_outlives_obligations,
locations,
locations.span(body),
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 9bb96b9..703223e 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -1,10 +1,10 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::LocalDefId;
+use rustc_infer::infer::SubregionOrigin;
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
-use rustc_infer::infer::{InferCtxt, SubregionOrigin};
use rustc_infer::traits::query::type_op::DeeplyNormalize;
use rustc_middle::bug;
use rustc_middle::ty::{
@@ -18,10 +18,12 @@
use crate::region_infer::TypeTest;
use crate::type_check::{Locations, MirTypeckRegionConstraints};
use crate::universal_regions::UniversalRegions;
-use crate::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
+use crate::{
+ BorrowckInferCtxt, ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory,
+};
pub(crate) struct ConstraintConversion<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
+ infcx: &'a BorrowckInferCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
/// Each RBP `GK: 'a` is assumed to be true. These encode
/// relationships like `T: 'a` that are added via implicit bounds
@@ -34,7 +36,6 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
/// logic expecting to see (e.g.) `ReStatic`, and if we supplied
/// our special inference variable there, we would mess that up.
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
locations: Locations,
span: Span,
@@ -45,10 +46,9 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
pub(crate) fn new(
- infcx: &'a InferCtxt<'tcx>,
+ infcx: &'a BorrowckInferCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
locations: Locations,
span: Span,
@@ -59,7 +59,6 @@ pub(crate) fn new(
infcx,
universal_regions,
region_bound_pairs,
- param_env,
known_type_outlives_obligations,
locations,
span,
@@ -286,8 +285,11 @@ fn normalize_and_add_type_outlives_constraints(
ConstraintCategory<'tcx>,
)>,
) -> Ty<'tcx> {
- match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span)
- {
+ match self.infcx.param_env.and(DeeplyNormalize { value: ty }).fully_perform(
+ self.infcx,
+ self.infcx.root_def_id,
+ self.span,
+ ) {
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
// FIXME(higher_ranked_auto): What should we do with the assumptions here?
if let Some(QueryRegionConstraints { outlives, assumptions: _ }) = constraints {
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index f642d34..7bf2df9 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -2,9 +2,9 @@
use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
use rustc_hir::def::DefKind;
use rustc_infer::infer::canonical::QueryRegionConstraints;
+use rustc_infer::infer::outlives;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::region_constraints::GenericKind;
-use rustc_infer::infer::{InferCtxt, outlives};
use rustc_infer::traits::query::type_op::DeeplyNormalize;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound;
@@ -14,6 +14,7 @@
use tracing::{debug, instrument};
use type_op::TypeOpOutput;
+use crate::BorrowckInferCtxt;
use crate::type_check::{Locations, MirTypeckRegionConstraints, constraint_conversion};
use crate::universal_regions::UniversalRegions;
@@ -47,14 +48,12 @@ pub(crate) struct CreateResult<'tcx> {
}
pub(crate) fn create<'tcx>(
- infcx: &InferCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ infcx: &BorrowckInferCtxt<'tcx>,
universal_regions: UniversalRegions<'tcx>,
constraints: &mut MirTypeckRegionConstraints<'tcx>,
) -> CreateResult<'tcx> {
UniversalRegionRelationsBuilder {
infcx,
- param_env,
constraints,
universal_regions,
region_bound_pairs: Default::default(),
@@ -177,8 +176,7 @@ pub(crate) fn known_outlives(&self) -> impl Iterator<Item = (RegionVid, RegionVi
}
struct UniversalRegionRelationsBuilder<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ infcx: &'a BorrowckInferCtxt<'tcx>,
universal_regions: UniversalRegions<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
@@ -205,7 +203,7 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
// Insert the `'a: 'b` we know from the predicates.
// This does not consider the type-outlives.
- let param_env = self.param_env;
+ let param_env = self.infcx.param_env;
self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
// - outlives is reflexive, so `'r: 'r` for every region `'r`
@@ -263,7 +261,7 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } =
param_env
.and(DeeplyNormalize { value: ty })
- .fully_perform(self.infcx, span)
+ .fully_perform(self.infcx, self.infcx.root_def_id, span)
.unwrap_or_else(|guar| TypeOpOutput {
output: Ty::new_error(self.infcx.tcx, guar),
constraints: None,
@@ -298,8 +296,9 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
// Add implied bounds from impl header.
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
- let result: Result<_, ErrorGuaranteed> =
- param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, span);
+ let result: Result<_, ErrorGuaranteed> = param_env
+ .and(DeeplyNormalize { value: ty })
+ .fully_perform(self.infcx, self.infcx.root_def_id, span);
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
continue;
};
@@ -318,7 +317,6 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
self.infcx,
&self.universal_regions,
&self.region_bound_pairs,
- param_env,
&known_type_outlives_obligations,
Locations::All(span),
span,
@@ -353,10 +351,11 @@ fn normalize_and_push_type_outlives_obligation(
output: normalized_outlives,
constraints: constraints_normalize,
error_info: _,
- }) = self
- .param_env
- .and(DeeplyNormalize { value: outlives })
- .fully_perform(self.infcx, span)
+ }) = self.infcx.param_env.and(DeeplyNormalize { value: outlives }).fully_perform(
+ self.infcx,
+ self.infcx.root_def_id,
+ span,
+ )
else {
self.infcx.dcx().delayed_bug(format!("could not normalize {outlives:?}"));
return;
@@ -381,9 +380,10 @@ fn add_implied_bounds(
span: Span,
) -> Option<&'tcx QueryRegionConstraints<'tcx>> {
let TypeOpOutput { output: bounds, constraints, .. } = self
+ .infcx
.param_env
.and(type_op::ImpliedOutlivesBounds { ty })
- .fully_perform(self.infcx, span)
+ .fully_perform(self.infcx, self.infcx.root_def_id, span)
.map_err(|_: ErrorGuaranteed| debug!("failed to compute implied bounds {:?}", ty))
.ok()?;
debug!(?bounds, ?constraints);
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 5d30fa7..b704d8f 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -640,7 +640,7 @@ fn compute_drop_data(
let op = typeck.infcx.param_env.and(DropckOutlives { dropped_ty });
- match op.fully_perform(typeck.infcx, DUMMY_SP) {
+ match op.fully_perform(typeck.infcx, typeck.root_cx.root_def_id(), DUMMY_SP) {
Ok(TypeOpOutput { output, constraints, .. }) => {
DropData { dropck_result: output, region_constraint_data: constraints }
}
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 0e1dd5c..0d36393 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -34,6 +34,7 @@
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::source_map::Spanned;
use rustc_span::{Span, sym};
+use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
use tracing::{debug, instrument, trace};
@@ -120,7 +121,7 @@ pub(crate) fn type_check<'tcx>(
region_bound_pairs,
normalized_inputs_and_output,
known_type_outlives_obligations,
- } = free_region_relations::create(infcx, infcx.param_env, universal_regions, &mut constraints);
+ } = free_region_relations::create(infcx, universal_regions, &mut constraints);
let pre_obligations = infcx.take_registered_region_obligations();
assert!(
@@ -408,7 +409,6 @@ fn push_region_constraints(
self.infcx,
self.universal_regions,
self.region_bound_pairs,
- self.infcx.param_env,
self.known_type_outlives_obligations,
locations,
locations.span(self.body),
@@ -1455,68 +1455,79 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
}
CastKind::PtrToPtr => {
let ty_from = op.ty(self.body, tcx);
- let cast_ty_from = CastTy::from_ty(ty_from);
- let cast_ty_to = CastTy::from_ty(*ty);
- match (cast_ty_from, cast_ty_to) {
- (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
- let src_tail = self.struct_tail(src.ty, location);
- let dst_tail = self.struct_tail(dst.ty, location);
+ let Some(CastTy::Ptr(src)) = CastTy::from_ty(ty_from) else {
+ unreachable!();
+ };
+ let Some(CastTy::Ptr(dst)) = CastTy::from_ty(*ty) else {
+ unreachable!();
+ };
- // This checks (lifetime part of) vtable validity for pointer casts,
- // which is irrelevant when there are aren't principal traits on
- // both sides (aka only auto traits).
- //
- // Note that other checks (such as denying `dyn Send` -> `dyn
- // Debug`) are in `rustc_hir_typeck`.
- if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) = *src_tail.kind()
- && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) = *dst_tail.kind()
- && src_tty.principal().is_some()
- && dst_tty.principal().is_some()
- {
- // Remove auto traits.
- // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
- let src_obj = Ty::new_dynamic(
- tcx,
- tcx.mk_poly_existential_predicates(
- &src_tty.without_auto_traits().collect::<Vec<_>>(),
- ),
- // FIXME: Once we disallow casting `*const dyn Trait + 'short`
- // to `*const dyn Trait + 'long`, then this can just be `src_lt`.
- dst_lt,
- ty::Dyn,
- );
- let dst_obj = Ty::new_dynamic(
- tcx,
- tcx.mk_poly_existential_predicates(
- &dst_tty.without_auto_traits().collect::<Vec<_>>(),
- ),
- dst_lt,
- ty::Dyn,
- );
+ if self.infcx.type_is_sized_modulo_regions(self.infcx.param_env, dst.ty) {
+ // Wide to thin ptr cast. This may even occur in an env with
+ // impossible predicates, such as `where dyn Trait: Sized`.
+ // In this case, we don't want to fall into the case below,
+ // since the types may not actually be equatable, but it's
+ // fine to perform this operation in an impossible env.
+ let trait_ref = ty::TraitRef::new(
+ tcx,
+ tcx.require_lang_item(LangItem::Sized, self.last_span),
+ [dst.ty],
+ );
+ self.prove_trait_ref(
+ trait_ref,
+ location.to_locations(),
+ ConstraintCategory::Cast {
+ is_implicit_coercion: true,
+ unsize_to: None,
+ },
+ );
+ } else if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) =
+ *self.struct_tail(src.ty, location).kind()
+ && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) =
+ *self.struct_tail(dst.ty, location).kind()
+ && src_tty.principal().is_some()
+ && dst_tty.principal().is_some()
+ {
+ // This checks (lifetime part of) vtable validity for pointer casts,
+ // which is irrelevant when there are aren't principal traits on
+ // both sides (aka only auto traits).
+ //
+ // Note that other checks (such as denying `dyn Send` -> `dyn
+ // Debug`) are in `rustc_hir_typeck`.
- debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
+ // Remove auto traits.
+ // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
+ let src_obj = Ty::new_dynamic(
+ tcx,
+ tcx.mk_poly_existential_predicates(
+ &src_tty.without_auto_traits().collect::<Vec<_>>(),
+ ),
+ // FIXME: Once we disallow casting `*const dyn Trait + 'short`
+ // to `*const dyn Trait + 'long`, then this can just be `src_lt`.
+ dst_lt,
+ ty::Dyn,
+ );
+ let dst_obj = Ty::new_dynamic(
+ tcx,
+ tcx.mk_poly_existential_predicates(
+ &dst_tty.without_auto_traits().collect::<Vec<_>>(),
+ ),
+ dst_lt,
+ ty::Dyn,
+ );
- self.sub_types(
- src_obj,
- dst_obj,
- location.to_locations(),
- ConstraintCategory::Cast {
- is_implicit_coercion: false,
- unsize_to: None,
- },
- )
- .unwrap();
- }
- }
- _ => {
- span_mirbug!(
- self,
- rvalue,
- "Invalid PtrToPtr cast {:?} -> {:?}",
- ty_from,
- ty
- )
- }
+ debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
+
+ self.sub_types(
+ src_obj,
+ dst_obj,
+ location.to_locations(),
+ ConstraintCategory::Cast {
+ is_implicit_coercion: false,
+ unsize_to: None,
+ },
+ )
+ .unwrap();
}
}
CastKind::Transmute => {
@@ -2458,12 +2469,12 @@ fn prove_closure_bounds(
args: GenericArgsRef<'tcx>,
locations: Locations,
) -> ty::InstantiatedPredicates<'tcx> {
+ let root_def_id = self.root_cx.root_def_id();
if let Some(closure_requirements) = &self.root_cx.closure_requirements(def_id) {
constraint_conversion::ConstraintConversion::new(
self.infcx,
self.universal_regions,
self.region_bound_pairs,
- self.infcx.param_env,
self.known_type_outlives_obligations,
locations,
self.body.span, // irrelevant; will be overridden.
@@ -2473,9 +2484,8 @@ fn prove_closure_bounds(
.apply_closure_requirements(closure_requirements, def_id, args);
}
- // Now equate closure args to regions inherited from `typeck_root_def_id`. Fixes #98589.
- let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
- let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
+ // Now equate closure args to regions inherited from `root_def_id`. Fixes #98589.
+ let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, root_def_id);
let parent_args = match tcx.def_kind(def_id) {
// We don't want to dispatch on 3 different kind of closures here, so take
@@ -2550,17 +2560,14 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
fn fully_perform(
mut self,
infcx: &InferCtxt<'tcx>,
+ root_def_id: LocalDefId,
span: Span,
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
- let (mut output, region_constraints) = scrape_region_constraints(
- infcx,
- |ocx| {
+ let (mut output, region_constraints) =
+ scrape_region_constraints(infcx, root_def_id, "InstantiateOpaqueType", span, |ocx| {
ocx.register_obligations(self.obligations.clone());
Ok(())
- },
- "InstantiateOpaqueType",
- span,
- )?;
+ })?;
self.region_constraints = Some(region_constraints);
output.error_info = Some(self);
Ok(output)
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index e56b9e6..9ca44d6 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -30,6 +30,6 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index 3e5a26c..cf563a5 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -416,7 +416,7 @@ macro_rules! move_to {
// Yes, this *is* the parameter.
Some(('$', end2)) => {
state = Flags;
- parameter = Some(at.slice_between(end).unwrap().parse().unwrap());
+ parameter = at.slice_between(end).unwrap().parse().ok();
move_to!(end2);
}
// Wait, no, actually, it's the width.
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
index 759d0d5..e49c62d 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
@@ -82,20 +82,16 @@
- name: Build sample project with target defined as JSON spec
run: |
./y.sh prepare --only-libcore --cross
- ./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
+ ./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
./y.sh clean all
- name: Build
run: |
./y.sh prepare --only-libcore --cross
- ./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu
+ ./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu
./y.sh test --mini-tests --target-triple m68k-unknown-linux-gnu
- # FIXME: since https://github.com/rust-lang/rust/pull/140809, we cannot run programs for architectures not
- # supported by the object crate, since this adds a dependency on symbols.o for the panic runtime.
- # And as such, a wrong order of the object files in the linker command now fails with an undefined reference
- # to some symbols like __rustc::rust_panic.
- #CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
+ CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
./y.sh clean all
- name: Prepare dependencies
@@ -104,23 +100,21 @@
git config --global user.name "User"
./y.sh prepare --cross
- # FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
- #- name: Run tests
- #run: |
- #./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot --sysroot-features compiler-builtins-no-f16-f128 ${{ matrix.commands }}
+ - name: Run tests
+ run: |
+ ./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot ${{ matrix.commands }}
- # FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
- #- name: Run Hello World!
- #run: |
- #./y.sh build --target-triple m68k-unknown-linux-gnu
+ - name: Run Hello World!
+ run: |
+ ./y.sh build --target-triple m68k-unknown-linux-gnu
- #vm_dir=$(pwd)/vm
- #cd tests/hello-world
- #CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
- #sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
- #sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
- #expected_output="40"
- #test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
+ vm_dir=$(pwd)/vm
+ cd tests/hello-world
+ CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
+ sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
+ sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
+ expected_output="40"
+ test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 7f35c1a..a5b972b 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -56,18 +56,18 @@
[[package]]
name = "gccjit"
-version = "2.7.0"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae99a89184220d967dd300139f2d2ae7d52c1a69d632b24aacc57c54625254ce"
+checksum = "4a0e310ef75f396cd11b2443b353d55376656ca92c13cba36f92b7aff346ac1a"
dependencies = [
"gccjit_sys",
]
[[package]]
name = "gccjit_sys"
-version = "0.8.0"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24edb7bfe2b7b27c6d09ed23eebfcab0b359c8fe978433f902943e6f127a0f1b"
+checksum = "95ed7572b30cd32430294dde6fb70822d58e67c6846a548647e8739776a0125b"
dependencies = [
"libc",
]
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index 193348d..6031933 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -24,7 +24,7 @@
[dependencies]
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
tempfile = "3.20"
-gccjit = "2.7"
+gccjit = "2.8"
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
# Local copy.
diff --git a/compiler/rustc_codegen_gcc/build_system/src/fmt.rs b/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
index 7e6594f..91535f2 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
@@ -1,7 +1,7 @@
use std::ffi::OsStr;
use std::path::Path;
-use crate::utils::run_command_with_output;
+use crate::utils::{run_command_with_output, walk_dir};
fn show_usage() {
println!(
@@ -32,5 +32,31 @@ pub fn run() -> Result<(), String> {
if check { &[&"cargo", &"fmt", &"--check"] } else { &[&"cargo", &"fmt"] };
run_command_with_output(cmd, Some(Path::new(".")))?;
- run_command_with_output(cmd, Some(Path::new("build_system")))
+ run_command_with_output(cmd, Some(Path::new("build_system")))?;
+
+ run_rustfmt_recursively("tests/run", check)
+}
+
+fn run_rustfmt_recursively<P>(dir: P, check: bool) -> Result<(), String>
+where
+ P: AsRef<Path>,
+{
+ walk_dir(
+ dir,
+ &mut |dir| run_rustfmt_recursively(dir, check),
+ &mut |file_path| {
+ if file_path.extension().filter(|ext| ext == &OsStr::new("rs")).is_some() {
+ let rustfmt_cmd: &[&dyn AsRef<OsStr>] = if check {
+ &[&"rustfmt", &"--check", &file_path]
+ } else {
+ &[&"rustfmt", &file_path]
+ };
+
+ run_command_with_output(rustfmt_cmd, Some(Path::new(".")))
+ } else {
+ Ok(())
+ }
+ },
+ true,
+ )
}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index 2c8271c..3dd3fce 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -531,7 +531,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
r#"change-id = 115898
[rust]
-codegen-backends = []
+codegen-backends = ["gcc"]
deny-warnings = false
verbose-tests = true
diff --git a/compiler/rustc_codegen_gcc/libgccjit.version b/compiler/rustc_codegen_gcc/libgccjit.version
index f621549..dc9a001 100644
--- a/compiler/rustc_codegen_gcc/libgccjit.version
+++ b/compiler/rustc_codegen_gcc/libgccjit.version
@@ -1 +1 @@
-04ce66d8c918de9273bd7101638ad8724edf5e21
+4e995bd73c4490edfe5080ec6014d63aa9abed5f
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index 058e734..04d33df 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2025-08-03"
+channel = "nightly-2025-08-25"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
index d558dfb..fcee6b6 100644
--- a/compiler/rustc_codegen_gcc/src/back/lto.rs
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -29,7 +29,7 @@
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
use rustc_data_structures::memmap::Mmap;
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct;
use rustc_session::config::Lto;
@@ -51,12 +51,11 @@ fn prepare_lto(
cgcx: &CodegenContext<GccCodegenBackend>,
each_linked_rlib_for_lto: &[PathBuf],
dcx: DiagCtxtHandle<'_>,
-) -> Result<LtoData, FatalError> {
+) -> LtoData {
let tmp_path = match tempdir() {
Ok(tmp_path) => tmp_path,
Err(error) => {
- eprintln!("Cannot create temporary directory: {}", error);
- return Err(FatalError);
+ dcx.fatal(format!("Cannot create temporary directory: {}", error));
}
};
@@ -91,15 +90,14 @@ fn prepare_lto(
upstream_modules.push((module, CString::new(name).unwrap()));
}
Err(e) => {
- dcx.emit_err(e);
- return Err(FatalError);
+ dcx.emit_fatal(e);
}
}
}
}
}
- Ok(LtoData { upstream_modules, tmp_path })
+ LtoData { upstream_modules, tmp_path }
}
fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> {
@@ -114,10 +112,10 @@ pub(crate) fn run_fat(
cgcx: &CodegenContext<GccCodegenBackend>,
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<GccCodegenBackend>>,
-) -> Result<ModuleCodegen<GccContext>, FatalError> {
+) -> ModuleCodegen<GccContext> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
- let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx)?;
+ let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx);
/*let symbols_below_threshold =
lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();*/
fat_lto(
@@ -137,7 +135,7 @@ fn fat_lto(
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
tmp_path: TempDir,
//symbols_below_threshold: &[String],
-) -> Result<ModuleCodegen<GccContext>, FatalError> {
+) -> ModuleCodegen<GccContext> {
let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
info!("going for a fat lto");
@@ -261,7 +259,7 @@ fn fat_lto(
// of now.
module.module_llvm.temp_dir = Some(tmp_path);
- Ok(module)
+ module
}
pub struct ModuleBuffer(PathBuf);
@@ -286,10 +284,10 @@ pub(crate) fn run_thin(
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<(String, ThinBuffer)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
-) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> (Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>) {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
- let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx)?;
+ let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx);
if cgcx.opts.cg.linker_plugin_lto.enabled() {
unreachable!(
"We should never reach this case if the LTO step \
@@ -355,7 +353,7 @@ fn thin_lto(
tmp_path: TempDir,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
//_symbols_below_threshold: &[String],
-) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> (Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>) {
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
info!("going for that thin, thin LTO");
@@ -518,13 +516,13 @@ fn thin_lto(
// TODO: save the directory so that it gets deleted later.
std::mem::forget(tmp_path);
- Ok((opt_jobs, copy_jobs))
+ (opt_jobs, copy_jobs)
}
pub fn optimize_thin_module(
thin_module: ThinModule<GccCodegenBackend>,
_cgcx: &CodegenContext<GccCodegenBackend>,
-) -> Result<ModuleCodegen<GccContext>, FatalError> {
+) -> ModuleCodegen<GccContext> {
//let dcx = cgcx.create_dcx();
//let module_name = &thin_module.shared.module_names[thin_module.idx];
@@ -634,7 +632,8 @@ pub fn optimize_thin_module(
save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
}
}*/
- Ok(module)
+ #[allow(clippy::let_and_return)]
+ module
}
pub struct ThinBuffer {
diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs
index c123114..84bc701 100644
--- a/compiler/rustc_codegen_gcc/src/back/write.rs
+++ b/compiler/rustc_codegen_gcc/src/back/write.rs
@@ -6,7 +6,6 @@
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
use rustc_fs_util::link_or_copy;
use rustc_session::config::OutputType;
-use rustc_span::fatal_error::FatalError;
use rustc_target::spec::SplitDebuginfo;
use crate::base::add_pic_option;
@@ -17,7 +16,7 @@ pub(crate) fn codegen(
cgcx: &CodegenContext<GccCodegenBackend>,
module: ModuleCodegen<GccContext>,
config: &ModuleConfig,
-) -> Result<CompiledModule, FatalError> {
+) -> CompiledModule {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
@@ -246,7 +245,7 @@ pub(crate) fn codegen(
}
}
- Ok(module.into_compiled_module(
+ module.into_compiled_module(
config.emit_obj != EmitObj::None,
cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked,
config.emit_bc,
@@ -254,7 +253,7 @@ pub(crate) fn codegen(
config.emit_ir,
&cgcx.output_filenames,
cgcx.invocation_temp.as_deref(),
- ))
+ )
}
pub(crate) fn save_temp_bitcode(
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index fdc15d5..41363d6 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -1497,7 +1497,6 @@ fn simd_funnel_shift<'a, 'gcc, 'tcx>(
let index = bx.context.new_rvalue_from_int(bx.int_type, i as i32);
let a_val = bx.context.new_vector_access(None, a, index).to_rvalue();
let a_val = bx.context.new_bitcast(None, a_val, unsigned_type);
- // TODO: we probably need to use gcc_int_cast instead.
let a_val = bx.gcc_int_cast(a_val, new_int_type);
let b_val = bx.context.new_vector_access(None, b, index).to_rvalue();
let b_val = bx.context.new_bitcast(None, b_val, unsigned_type);
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 4025aba..2d7df79 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -110,7 +110,6 @@
use rustc_session::Session;
use rustc_session::config::{OptLevel, OutputFilenames};
use rustc_span::Symbol;
-use rustc_span::fatal_error::FatalError;
use rustc_target::spec::RelocModel;
use tempfile::TempDir;
@@ -362,7 +361,7 @@ fn run_and_optimize_fat_lto(
_exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<Self>>,
- ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+ ) -> ModuleCodegen<Self::Module> {
back::lto::run_fat(cgcx, each_linked_rlib_for_lto, modules)
}
@@ -373,7 +372,7 @@ fn run_thin_lto(
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
- ) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
+ ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>) {
back::lto::run_thin(cgcx, each_linked_rlib_for_lto, modules, cached_modules)
}
@@ -390,15 +389,14 @@ fn optimize(
_dcx: DiagCtxtHandle<'_>,
module: &mut ModuleCodegen<Self::Module>,
config: &ModuleConfig,
- ) -> Result<(), FatalError> {
+ ) {
module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
- Ok(())
}
fn optimize_thin(
cgcx: &CodegenContext<Self>,
thin: ThinModule<Self>,
- ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+ ) -> ModuleCodegen<Self::Module> {
back::lto::optimize_thin_module(thin, cgcx)
}
@@ -406,7 +404,7 @@ fn codegen(
cgcx: &CodegenContext<Self>,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
- ) -> Result<CompiledModule, FatalError> {
+ ) -> CompiledModule {
back::write::codegen(cgcx, module, config)
}
diff --git a/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt
index 29032b3..c5e2297 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt
@@ -6,7 +6,6 @@
tests/run-make/doctests-runtool/
tests/run-make/emit-shared-files/
tests/run-make/exit-code/
-tests/run-make/issue-64153/
tests/run-make/llvm-ident/
tests/run-make/native-link-modifier-bundle/
tests/run-make/remap-path-prefix-dwarf/
@@ -34,8 +33,6 @@
tests/run-make/foreign-double-unwind/
tests/run-make/foreign-exceptions/
tests/run-make/glibc-staticlib-args/
-tests/run-make/issue-36710/
-tests/run-make/issue-68794-textrel-on-minimal-lib/
tests/run-make/lto-smoke-c/
tests/run-make/return-non-c-like-enum/
diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
index 41fb472..e2615bc 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
@@ -20,7 +20,7 @@
tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
tests/ui/simd/issue-17170.rs
tests/ui/simd/issue-39720.rs
-tests/ui/issues/issue-14875.rs
+tests/ui/drop/panic-during-drop-14875.rs
tests/ui/issues/issue-29948.rs
tests/ui/process/println-with-broken-pipe.rs
tests/ui/lto/thin-lto-inlines2.rs
@@ -86,3 +86,5 @@
tests/ui/attributes/fn-align-dyn.rs
tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs
tests/ui/explicit-tail-calls/recursion-etc.rs
+tests/ui/explicit-tail-calls/indexer.rs
+tests/ui/explicit-tail-calls/drop-order.rs
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
index e20ecc2..78675ac 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -7,12 +7,10 @@ fn main() {
use std::hint::black_box;
macro_rules! check {
- ($ty:ty, $expr:expr) => {
- {
- const EXPECTED: $ty = $expr;
- assert_eq!($expr, EXPECTED);
- }
- };
+ ($ty:ty, $expr:expr) => {{
+ const EXPECTED: $ty = $expr;
+ assert_eq!($expr, EXPECTED);
+ }};
}
check!(u32, (2220326408_u32 + black_box(1)) >> (32 - 6));
diff --git a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
index 7887215..78e1cac 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
@@ -12,7 +12,7 @@ fn main() {
let arg_count = std::env::args().count();
let int = isize::MAX;
- let _int = int + arg_count as isize; // overflow
+ let _int = int + arg_count as isize; // overflow
// If overflow checking is disabled, we should reach here.
#[cfg(not(debug_assertions))]
diff --git a/compiler/rustc_codegen_gcc/tests/run/structs.rs b/compiler/rustc_codegen_gcc/tests/run/structs.rs
index da73cbe..e08e678 100644
--- a/compiler/rustc_codegen_gcc/tests/run/structs.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/structs.rs
@@ -27,12 +27,8 @@ fn one() -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
- let test = Test {
- field: one(),
- };
- let two = Two {
- two: 2,
- };
+ let test = Test { field: one() };
+ let two = Two { two: 2 };
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, two.two);
diff --git a/compiler/rustc_codegen_gcc/tests/run/volatile.rs b/compiler/rustc_codegen_gcc/tests/run/volatile.rs
index 94a7bdc..dc11fbf 100644
--- a/compiler/rustc_codegen_gcc/tests/run/volatile.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/volatile.rs
@@ -12,15 +12,11 @@ struct Struct {
func: unsafe fn(*const ()),
}
-fn func(_ptr: *const ()) {
-}
+fn func(_ptr: *const ()) {}
fn main() {
let mut x = MaybeUninit::<&Struct>::uninit();
- x.write(&Struct {
- pointer: std::ptr::null(),
- func,
- });
+ x.write(&Struct { pointer: std::ptr::null(), func });
let x = unsafe { x.assume_init() };
let value = unsafe { (x as *const Struct).read_volatile() };
println!("{:?}", value);
diff --git a/compiler/rustc_codegen_gcc/tests/run/volatile2.rs b/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
index bdcb825..ada1126 100644
--- a/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
@@ -7,7 +7,14 @@ mod libc {
#[link(name = "c")]
extern "C" {
pub fn sigaction(signum: i32, act: *const sigaction, oldact: *mut sigaction) -> i32;
- pub fn mmap(addr: *mut (), len: usize, prot: i32, flags: i32, fd: i32, offset: i64) -> *mut ();
+ pub fn mmap(
+ addr: *mut (),
+ len: usize,
+ prot: i32,
+ flags: i32,
+ fd: i32,
+ offset: i64,
+ ) -> *mut ();
pub fn mprotect(addr: *mut (), len: usize, prot: i32) -> i32;
}
@@ -54,7 +61,8 @@ fn main() {
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
- ).cast();
+ )
+ .cast();
if STORAGE == libc::MAP_FAILED {
panic!("error: mmap failed");
}
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 2d11628..b04310f 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -8,15 +8,15 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
# To avoid duplicate dependencies, this should match the version of gimli used
# by `rustc_codegen_ssa` via its `thorin-dwp` dependency.
gimli = "0.31"
-itertools = "0.12"
-libc = "0.2"
-measureme = "12.0.1"
+itertools.workspace = true
+libc.workspace = true
+measureme.workspace = true
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
-rustc-demangle = "0.1.21"
+rustc-demangle.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
@@ -38,9 +38,9 @@
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_target = { path = "../rustc_target" }
serde = { version = "1", features = ["derive"] }
-serde_json = "1"
+serde_json.workspace = true
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 399f8b6..ac7583f 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -44,7 +44,7 @@ fn apply_attrs_to_callsite(
const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 6] = [
(ArgAttribute::NoAlias, llvm::AttributeKind::NoAlias),
- (ArgAttribute::NoCapture, llvm::AttributeKind::NoCapture),
+ (ArgAttribute::CapturesAddress, llvm::AttributeKind::CapturesAddress),
(ArgAttribute::NonNull, llvm::AttributeKind::NonNull),
(ArgAttribute::ReadOnly, llvm::AttributeKind::ReadOnly),
(ArgAttribute::NoUndef, llvm::AttributeKind::NoUndef),
@@ -84,8 +84,10 @@ fn apply_attrs_to_callsite(
}
for (attr, llattr) in OPTIMIZATION_ATTRIBUTES {
if regular.contains(attr) {
- // captures(address, read_provenance) is only available since LLVM 21.
- if attr == ArgAttribute::CapturesReadOnly && llvm_util::get_version() < (21, 0, 0) {
+ // captures(...) is only available since LLVM 21.
+ if (attr == ArgAttribute::CapturesReadOnly || attr == ArgAttribute::CapturesAddress)
+ && llvm_util::get_version() < (21, 0, 0)
+ {
continue;
}
attrs.push(llattr.create_attr(cx.llcx));
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 23610aa..df3e492 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -12,7 +12,7 @@
use crate::builder::SBuilder;
use crate::declare::declare_simple_fn;
-use crate::llvm::{self, False, True, Type, Value};
+use crate::llvm::{self, FALSE, TRUE, Type, Value};
use crate::{SimpleCx, attributes, debuginfo, llvm_util};
pub(crate) unsafe fn codegen(
@@ -80,7 +80,7 @@ pub(crate) unsafe fn codegen(
&cx,
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
&i8,
- &llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, False),
+ &llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, FALSE),
);
// __rust_no_alloc_shim_is_unstable_v2
@@ -201,7 +201,7 @@ fn create_wrapper_function(
.map(|(i, _)| llvm::get_param(llfn, i as c_uint))
.collect::<Vec<_>>();
let ret = bx.call(ty, callee, &args, None);
- llvm::LLVMSetTailCall(ret, True);
+ llvm::LLVMSetTailCall(ret, TRUE);
if output.is_some() {
bx.ret(ret);
} else {
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index a643a91..38c1d3b 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -16,6 +16,7 @@
use crate::builder::Builder;
use crate::common::Funclet;
use crate::context::CodegenCx;
+use crate::llvm::ToLlvmBool;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
@@ -470,10 +471,6 @@ pub(crate) fn inline_asm_call<'ll>(
dest: Option<&'ll llvm::BasicBlock>,
catch_funclet: Option<(&'ll llvm::BasicBlock, Option<&Funclet<'ll>>)>,
) -> Option<&'ll Value> {
- let volatile = if volatile { llvm::True } else { llvm::False };
- let alignstack = if alignstack { llvm::True } else { llvm::False };
- let can_throw = if unwind { llvm::True } else { llvm::False };
-
let argtys = inputs
.iter()
.map(|v| {
@@ -500,10 +497,10 @@ pub(crate) fn inline_asm_call<'ll>(
asm.len(),
cons.as_ptr(),
cons.len(),
- volatile,
- alignstack,
+ volatile.to_llvm_bool(),
+ alignstack.to_llvm_bool(),
dia,
- can_throw,
+ unwind.to_llvm_bool(),
)
};
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 853d029..fc38c4f 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -14,7 +14,8 @@
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::memmap::Mmap;
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
+use rustc_hir::attrs::SanitizerSet;
use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct;
use rustc_session::config::{self, Lto};
@@ -36,12 +37,43 @@ fn prepare_lto(
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
dcx: DiagCtxtHandle<'_>,
-) -> Result<(Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>), FatalError> {
+) -> (Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>) {
let mut symbols_below_threshold = exported_symbols_for_lto
.iter()
.map(|symbol| CString::new(symbol.to_owned()).unwrap())
.collect::<Vec<CString>>();
+ if cgcx.regular_module_config.instrument_coverage
+ || cgcx.regular_module_config.pgo_gen.enabled()
+ {
+ // These are weak symbols that point to the profile version and the
+ // profile name, which need to be treated as exported so LTO doesn't nix
+ // them.
+ const PROFILER_WEAK_SYMBOLS: [&CStr; 2] =
+ [c"__llvm_profile_raw_version", c"__llvm_profile_filename"];
+
+ symbols_below_threshold.extend(PROFILER_WEAK_SYMBOLS.iter().map(|&sym| sym.to_owned()));
+ }
+
+ if cgcx.regular_module_config.sanitizer.contains(SanitizerSet::MEMORY) {
+ let mut msan_weak_symbols = Vec::new();
+
+ // Similar to profiling, preserve weak msan symbol during LTO.
+ if cgcx.regular_module_config.sanitizer_recover.contains(SanitizerSet::MEMORY) {
+ msan_weak_symbols.push(c"__msan_keep_going");
+ }
+
+ if cgcx.regular_module_config.sanitizer_memory_track_origins != 0 {
+ msan_weak_symbols.push(c"__msan_track_origins");
+ }
+
+ symbols_below_threshold.extend(msan_weak_symbols.into_iter().map(|sym| sym.to_owned()));
+ }
+
+ // Preserve LLVM-injected, ASAN-related symbols.
+ // See also https://github.com/rust-lang/rust/issues/113404.
+ symbols_below_threshold.push(c"___asan_globals_registered".to_owned());
+
// __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
// __llvm_profile_runtime, therefore we won't know until link time if this symbol
// should have default visibility.
@@ -79,16 +111,13 @@ fn prepare_lto(
let module = SerializedModule::FromRlib(data.to_vec());
upstream_modules.push((module, CString::new(name).unwrap()));
}
- Err(e) => {
- dcx.emit_err(e);
- return Err(FatalError);
- }
+ Err(e) => dcx.emit_fatal(e),
}
}
}
}
- Ok((symbols_below_threshold, upstream_modules))
+ (symbols_below_threshold, upstream_modules)
}
fn get_bitcode_slice_from_object_data<'a>(
@@ -123,11 +152,11 @@ pub(crate) fn run_fat(
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
-) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
+) -> ModuleCodegen<ModuleLlvm> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let (symbols_below_threshold, upstream_modules) =
- prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx)?;
+ prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx);
let symbols_below_threshold =
symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
fat_lto(cgcx, dcx, modules, upstream_modules, &symbols_below_threshold)
@@ -142,11 +171,11 @@ pub(crate) fn run_thin(
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<(String, ThinBuffer)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
-) -> Result<(Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> (Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>) {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let (symbols_below_threshold, upstream_modules) =
- prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx)?;
+ prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx);
let symbols_below_threshold =
symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
if cgcx.opts.cg.linker_plugin_lto.enabled() {
@@ -173,7 +202,7 @@ fn fat_lto(
modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
symbols_below_threshold: &[*const libc::c_char],
-) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
+) -> ModuleCodegen<ModuleLlvm> {
let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_build_monolithic_module");
info!("going for a fat lto");
@@ -224,7 +253,7 @@ fn fat_lto(
assert!(!serialized_modules.is_empty(), "must have at least one serialized module");
let (buffer, name) = serialized_modules.remove(0);
info!("no in-memory regular modules to choose from, parsing {:?}", name);
- let llvm_module = ModuleLlvm::parse(cgcx, &name, buffer.data(), dcx)?;
+ let llvm_module = ModuleLlvm::parse(cgcx, &name, buffer.data(), dcx);
ModuleCodegen::new_regular(name.into_string().unwrap(), llvm_module)
}
};
@@ -265,7 +294,9 @@ fn fat_lto(
});
info!("linking {:?}", name);
let data = bc_decoded.data();
- linker.add(data).map_err(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name }))?;
+ linker
+ .add(data)
+ .unwrap_or_else(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name }));
}
drop(linker);
save_temp_bitcode(cgcx, &module, "lto.input");
@@ -282,7 +313,7 @@ fn fat_lto(
save_temp_bitcode(cgcx, &module, "lto.after-restriction");
}
- Ok(module)
+ module
}
pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>);
@@ -352,7 +383,7 @@ fn thin_lto(
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
symbols_below_threshold: &[*const libc::c_char],
-) -> Result<(Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> (Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>) {
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
unsafe {
info!("going for that thin, thin LTO");
@@ -422,7 +453,7 @@ fn thin_lto(
symbols_below_threshold.as_ptr(),
symbols_below_threshold.len(),
)
- .ok_or_else(|| write::llvm_err(dcx, LlvmError::PrepareThinLtoContext))?;
+ .unwrap_or_else(|| write::llvm_err(dcx, LlvmError::PrepareThinLtoContext));
let data = ThinData(data);
@@ -492,10 +523,10 @@ fn thin_lto(
if let Some(path) = key_map_path
&& let Err(err) = curr_key_map.save_to_file(&path)
{
- return Err(write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err }));
+ write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err });
}
- Ok((opt_jobs, copy_jobs))
+ (opt_jobs, copy_jobs)
}
}
@@ -550,7 +581,7 @@ pub(crate) fn run_pass_manager(
dcx: DiagCtxtHandle<'_>,
module: &mut ModuleCodegen<ModuleLlvm>,
thin: bool,
-) -> Result<(), FatalError> {
+) {
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_lto_optimize", &*module.name);
let config = cgcx.config(module.kind);
@@ -582,7 +613,7 @@ pub(crate) fn run_pass_manager(
}
unsafe {
- write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
+ write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage);
}
if enable_gpu && !thin {
@@ -596,7 +627,7 @@ pub(crate) fn run_pass_manager(
let stage = write::AutodiffStage::PostAD;
if !config.autodiff.contains(&config::AutoDiff::NoPostopt) {
unsafe {
- write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
+ write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage);
}
}
@@ -608,7 +639,6 @@ pub(crate) fn run_pass_manager(
}
debug!("lto done");
- Ok(())
}
pub struct ModuleBuffer(&'static mut llvm::ModuleBuffer);
@@ -701,7 +731,7 @@ fn drop(&mut self) {
pub(crate) fn optimize_thin_module(
thin_module: ThinModule<LlvmCodegenBackend>,
cgcx: &CodegenContext<LlvmCodegenBackend>,
-) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
+) -> ModuleCodegen<ModuleLlvm> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
@@ -712,7 +742,7 @@ pub(crate) fn optimize_thin_module(
// into that context. One day, however, we may do this for upstream
// crates but for locally codegened modules we may be able to reuse
// that LLVM Context and Module.
- let module_llvm = ModuleLlvm::parse(cgcx, module_name, thin_module.data(), dcx)?;
+ let module_llvm = ModuleLlvm::parse(cgcx, module_name, thin_module.data(), dcx);
let mut module = ModuleCodegen::new_regular(thin_module.name(), module_llvm);
// Given that the newly created module lacks a thinlto buffer for embedding, we need to re-add it here.
if cgcx.config(ModuleKind::Regular).embed_bitcode() {
@@ -746,7 +776,7 @@ pub(crate) fn optimize_thin_module(
.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
if unsafe { !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) }
{
- return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
+ write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
}
@@ -757,7 +787,7 @@ pub(crate) fn optimize_thin_module(
.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
if unsafe { !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) }
{
- return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
+ write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
}
@@ -768,7 +798,7 @@ pub(crate) fn optimize_thin_module(
if unsafe {
!llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target.raw())
} {
- return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
+ write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
}
@@ -780,11 +810,11 @@ pub(crate) fn optimize_thin_module(
// little differently.
{
info!("running thin lto passes over {}", module.name);
- run_pass_manager(cgcx, dcx, &mut module, true)?;
+ run_pass_manager(cgcx, dcx, &mut module, true);
save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
}
}
- Ok(module)
+ module
}
/// Maps LLVM module identifiers to their corresponding LLVM LTO cache keys
@@ -850,9 +880,9 @@ pub(crate) fn parse_module<'a>(
name: &CStr,
data: &[u8],
dcx: DiagCtxtHandle<'_>,
-) -> Result<&'a llvm::Module, FatalError> {
+) -> &'a llvm::Module {
unsafe {
llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr())
- .ok_or_else(|| write::llvm_err(dcx, LlvmError::ParseBitcode))
+ .unwrap_or_else(|| write::llvm_err(dcx, LlvmError::ParseBitcode))
}
}
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 6299800..7ea2ae6 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -20,7 +20,7 @@
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_errors::{DiagCtxtHandle, FatalError, Level};
+use rustc_errors::{DiagCtxtHandle, Level};
use rustc_fs_util::{link_or_copy, path_to_c_string};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
@@ -46,10 +46,10 @@
use crate::type_::Type;
use crate::{LlvmCodegenBackend, ModuleLlvm, base, common, llvm_util};
-pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> FatalError {
+pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> ! {
match llvm::last_error() {
- Some(llvm_err) => dcx.emit_almost_fatal(WithLlvmError(err, llvm_err)),
- None => dcx.emit_almost_fatal(err),
+ Some(llvm_err) => dcx.emit_fatal(WithLlvmError(err, llvm_err)),
+ None => dcx.emit_fatal(err),
}
}
@@ -63,7 +63,7 @@ fn write_output_file<'ll>(
file_type: llvm::FileType,
self_profiler_ref: &SelfProfilerRef,
verify_llvm_ir: bool,
-) -> Result<(), FatalError> {
+) {
debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output);
let output_c = path_to_c_string(output);
let dwo_output_c;
@@ -100,7 +100,7 @@ fn write_output_file<'ll>(
}
}
- result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
+ result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
}
pub(crate) fn create_informational_target_machine(
@@ -112,7 +112,7 @@ pub(crate) fn create_informational_target_machine(
// system/tcx is set up.
let features = llvm_util::global_llvm_features(sess, false, only_base_features);
target_machine_factory(sess, config::OptLevel::No, &features)(config)
- .unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
+ .unwrap_or_else(|err| llvm_err(sess.dcx(), err))
}
pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine {
@@ -139,7 +139,7 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar
tcx.backend_optimization_level(()),
tcx.global_backend_features(()),
)(config)
- .unwrap_or_else(|err| llvm_err(tcx.dcx(), err).raise())
+ .unwrap_or_else(|err| llvm_err(tcx.dcx(), err))
}
fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm::CodeGenOptSize) {
@@ -565,7 +565,7 @@ pub(crate) unsafe fn llvm_optimize(
opt_level: config::OptLevel,
opt_stage: llvm::OptStage,
autodiff_stage: AutodiffStage,
-) -> Result<(), FatalError> {
+) {
// Enzyme:
// The whole point of compiler based AD is to differentiate optimized IR instead of unoptimized
// source code. However, benchmarks show that optimizations increasing the code size
@@ -704,7 +704,7 @@ pub(crate) unsafe fn llvm_optimize(
llvm_plugins.len(),
)
};
- result.into_result().map_err(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
+ result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
}
// Unsafe due to LLVM calls.
@@ -713,7 +713,7 @@ pub(crate) fn optimize(
dcx: DiagCtxtHandle<'_>,
module: &mut ModuleCodegen<ModuleLlvm>,
config: &ModuleConfig,
-) -> Result<(), FatalError> {
+) {
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name);
let llcx = &*module.module_llvm.llcx;
@@ -765,7 +765,7 @@ pub(crate) fn optimize(
opt_stage,
autodiff_stage,
)
- }?;
+ };
if let Some(thin_lto_buffer) = thin_lto_buffer {
let thin_lto_buffer = unsafe { ThinBuffer::from_raw_ptr(thin_lto_buffer) };
module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec());
@@ -793,14 +793,13 @@ pub(crate) fn optimize(
}
}
}
- Ok(())
}
pub(crate) fn codegen(
cgcx: &CodegenContext<LlvmCodegenBackend>,
module: ModuleCodegen<ModuleLlvm>,
config: &ModuleConfig,
-) -> Result<CompiledModule, FatalError> {
+) -> CompiledModule {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
@@ -909,7 +908,9 @@ extern "C" fn demangle_callback(
record_artifact_size(&cgcx.prof, "llvm_ir", &out);
}
- result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteIr { path: &out }))?;
+ result
+ .into_result()
+ .unwrap_or_else(|()| llvm_err(dcx, LlvmError::WriteIr { path: &out }));
}
if config.emit_asm {
@@ -940,7 +941,7 @@ extern "C" fn demangle_callback(
llvm::FileType::AssemblyFile,
&cgcx.prof,
config.verify_llvm_ir,
- )?;
+ );
}
match config.emit_obj {
@@ -976,7 +977,7 @@ extern "C" fn demangle_callback(
llvm::FileType::ObjectFile,
&cgcx.prof,
config.verify_llvm_ir,
- )?;
+ );
}
EmitObj::Bitcode => {
@@ -1009,7 +1010,7 @@ extern "C" fn demangle_callback(
&& cgcx.target_can_use_split_dwarf
&& cgcx.split_debuginfo != SplitDebuginfo::Off
&& cgcx.split_dwarf_kind == SplitDwarfKind::Split;
- Ok(module.into_compiled_module(
+ module.into_compiled_module(
config.emit_obj != EmitObj::None,
dwarf_object_emitted,
config.emit_bc,
@@ -1017,7 +1018,7 @@ extern "C" fn demangle_callback(
config.emit_ir,
&cgcx.output_filenames,
cgcx.invocation_temp.as_deref(),
- ))
+ )
}
fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: &[u8]) -> Vec<u8> {
@@ -1110,7 +1111,7 @@ fn embed_bitcode(
llvm::set_section(llglobal, bitcode_section_name(cgcx));
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
- llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
+ llvm::LLVMSetGlobalConstant(llglobal, llvm::TRUE);
let llconst = common::bytes_in_context(llcx, &[]);
let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 427c75d..3737958 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -35,7 +35,7 @@
use crate::common::Funclet;
use crate::context::{CodegenCx, FullCx, GenericCx, SCx};
use crate::llvm::{
- self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, GEPNoWrapFlags, Metadata, True,
+ self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, GEPNoWrapFlags, Metadata, TRUE, ToLlvmBool,
};
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
@@ -493,8 +493,8 @@ fn unchecked_suadd(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
unsafe {
let add = llvm::LLVMBuildAdd(self.llbuilder, a, b, UNNAMED);
if llvm::LLVMIsAInstruction(add).is_some() {
- llvm::LLVMSetNUW(add, True);
- llvm::LLVMSetNSW(add, True);
+ llvm::LLVMSetNUW(add, TRUE);
+ llvm::LLVMSetNSW(add, TRUE);
}
add
}
@@ -503,8 +503,8 @@ fn unchecked_susub(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
unsafe {
let sub = llvm::LLVMBuildSub(self.llbuilder, a, b, UNNAMED);
if llvm::LLVMIsAInstruction(sub).is_some() {
- llvm::LLVMSetNUW(sub, True);
- llvm::LLVMSetNSW(sub, True);
+ llvm::LLVMSetNUW(sub, TRUE);
+ llvm::LLVMSetNSW(sub, TRUE);
}
sub
}
@@ -513,8 +513,8 @@ fn unchecked_sumul(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
unsafe {
let mul = llvm::LLVMBuildMul(self.llbuilder, a, b, UNNAMED);
if llvm::LLVMIsAInstruction(mul).is_some() {
- llvm::LLVMSetNUW(mul, True);
- llvm::LLVMSetNSW(mul, True);
+ llvm::LLVMSetNUW(mul, TRUE);
+ llvm::LLVMSetNSW(mul, TRUE);
}
mul
}
@@ -528,7 +528,7 @@ fn or_disjoint(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
// an instruction, so we need to check before setting the flag.
// (See also `LLVMBuildNUWNeg` which also needs a check.)
if llvm::LLVMIsAInstruction(or).is_some() {
- llvm::LLVMSetIsDisjoint(or, True);
+ llvm::LLVMSetIsDisjoint(or, TRUE);
}
or
}
@@ -629,7 +629,7 @@ fn load(&mut self, ty: &'ll Type, ptr: &'ll Value, align: Align) -> &'ll Value {
fn volatile_load(&mut self, ty: &'ll Type, ptr: &'ll Value) -> &'ll Value {
unsafe {
let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED);
- llvm::LLVMSetVolatile(load, llvm::True);
+ llvm::LLVMSetVolatile(load, llvm::TRUE);
load
}
}
@@ -717,7 +717,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
let mut const_llval = None;
let llty = place.layout.llvm_type(self);
if let Some(global) = llvm::LLVMIsAGlobalVariable(place.val.llval) {
- if llvm::LLVMIsGlobalConstant(global) == llvm::True {
+ if llvm::LLVMIsGlobalConstant(global).is_true() {
if let Some(init) = llvm::LLVMGetInitializer(global) {
if self.val_ty(init) == llty {
const_llval = Some(init);
@@ -838,7 +838,7 @@ fn store_with_flags(
if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() as c_uint };
llvm::LLVMSetAlignment(store, align);
if flags.contains(MemFlags::VOLATILE) {
- llvm::LLVMSetVolatile(store, llvm::True);
+ llvm::LLVMSetVolatile(store, llvm::TRUE);
}
if flags.contains(MemFlags::NONTEMPORAL) {
// Make sure that the current target architectures supports "sane" non-temporal
@@ -956,7 +956,7 @@ fn unchecked_utrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Valu
let trunc = self.trunc(val, dest_ty);
unsafe {
if llvm::LLVMIsAInstruction(trunc).is_some() {
- llvm::LLVMSetNUW(trunc, True);
+ llvm::LLVMSetNUW(trunc, TRUE);
}
}
trunc
@@ -968,7 +968,7 @@ fn unchecked_strunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Valu
let trunc = self.trunc(val, dest_ty);
unsafe {
if llvm::LLVMIsAInstruction(trunc).is_some() {
- llvm::LLVMSetNSW(trunc, True);
+ llvm::LLVMSetNSW(trunc, TRUE);
}
}
trunc
@@ -1067,13 +1067,7 @@ fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
unsafe {
- llvm::LLVMBuildIntCast2(
- self.llbuilder,
- val,
- dest_ty,
- if is_signed { True } else { False },
- UNNAMED,
- )
+ llvm::LLVMBuildIntCast2(self.llbuilder, val, dest_ty, is_signed.to_llvm_bool(), UNNAMED)
}
}
@@ -1229,7 +1223,7 @@ fn cleanup_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Valu
let ty = self.type_struct(&[self.type_ptr(), self.type_i32()], false);
let landing_pad = self.landing_pad(ty, pers_fn, 0);
unsafe {
- llvm::LLVMSetCleanup(landing_pad, llvm::True);
+ llvm::LLVMSetCleanup(landing_pad, llvm::TRUE);
}
(self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
}
@@ -1317,7 +1311,6 @@ fn atomic_cmpxchg(
failure_order: rustc_middle::ty::AtomicOrdering,
weak: bool,
) -> (&'ll Value, &'ll Value) {
- let weak = if weak { llvm::True } else { llvm::False };
unsafe {
let value = llvm::LLVMBuildAtomicCmpXchg(
self.llbuilder,
@@ -1326,9 +1319,9 @@ fn atomic_cmpxchg(
src,
AtomicOrdering::from_generic(order),
AtomicOrdering::from_generic(failure_order),
- llvm::False, // SingleThreaded
+ llvm::FALSE, // SingleThreaded
);
- llvm::LLVMSetWeak(value, weak);
+ llvm::LLVMSetWeak(value, weak.to_llvm_bool());
let val = self.extract_value(value, 0);
let success = self.extract_value(value, 1);
(val, success)
@@ -1353,7 +1346,7 @@ fn atomic_rmw(
dst,
src,
AtomicOrdering::from_generic(order),
- llvm::False, // SingleThreaded
+ llvm::FALSE, // SingleThreaded
)
};
if ret_ptr && self.val_ty(res) != self.type_ptr() {
@@ -1368,14 +1361,14 @@ fn atomic_fence(
scope: SynchronizationScope,
) {
let single_threaded = match scope {
- SynchronizationScope::SingleThread => llvm::True,
- SynchronizationScope::CrossThread => llvm::False,
+ SynchronizationScope::SingleThread => true,
+ SynchronizationScope::CrossThread => false,
};
unsafe {
llvm::LLVMBuildFence(
self.llbuilder,
AtomicOrdering::from_generic(order),
- single_threaded,
+ single_threaded.to_llvm_bool(),
UNNAMED,
);
}
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index e2df326..6ddf53c 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -11,7 +11,7 @@
use crate::context::SimpleCx;
use crate::declare::declare_simple_fn;
use crate::llvm;
-use crate::llvm::{Metadata, True, Type};
+use crate::llvm::{Metadata, TRUE, Type};
use crate::value::Value;
pub(crate) fn adjust_activity_to_abi<'tcx>(
@@ -293,7 +293,7 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>(
// ret double %0
// }
// ```
- let enzyme_ty = unsafe { llvm::LLVMFunctionType(ret_ty, ptr::null(), 0, True) };
+ let enzyme_ty = unsafe { llvm::LLVMFunctionType(ret_ty, ptr::null(), 0, TRUE) };
// FIXME(ZuseZ4): the CC/Addr/Vis values are best effort guesses, we should look at tests and
// think a bit more about what should go here.
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index f29fefb..11b79a7 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -20,7 +20,7 @@
use crate::consts::const_alloc_to_llvm;
pub(crate) use crate::context::CodegenCx;
use crate::context::{GenericCx, SCx};
-use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, True};
+use crate::llvm::{self, BasicBlock, ConstantInt, FALSE, Metadata, TRUE, ToLlvmBool};
use crate::type_::Type;
use crate::value::Value;
@@ -158,7 +158,7 @@ fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
self.type_kind(t) == TypeKind::Integer,
"only allows integer types in const_int"
);
- unsafe { llvm::LLVMConstInt(t, i as u64, True) }
+ unsafe { llvm::LLVMConstInt(t, i as u64, TRUE) }
}
fn const_u8(&self, i: u8) -> &'ll Value {
@@ -192,7 +192,7 @@ fn const_uint(&self, t: &'ll Type, i: u64) -> &'ll Value {
self.type_kind(t) == TypeKind::Integer,
"only allows integer types in const_uint"
);
- unsafe { llvm::LLVMConstInt(t, i, False) }
+ unsafe { llvm::LLVMConstInt(t, i, FALSE) }
}
fn const_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value {
@@ -377,7 +377,7 @@ pub(crate) fn val_ty(v: &Value) -> &Type {
pub(crate) fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
unsafe {
let ptr = bytes.as_ptr() as *const c_char;
- llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), True)
+ llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), TRUE)
}
}
@@ -392,7 +392,7 @@ fn struct_in_context<'ll>(
packed: bool,
) -> &'ll Value {
let len = c_uint::try_from(elts.len()).expect("LLVMConstStructInContext elements len overflow");
- unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), len, packed as Bool) }
+ unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), len, packed.to_llvm_bool()) }
}
#[inline]
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 4a7de7d..4fd6110 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -701,7 +701,7 @@ pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> &'ll Value {
}
pub(crate) fn get_const_int(&self, ty: &'ll Type, val: u64) -> &'ll Value {
- unsafe { llvm::LLVMConstInt(ty, val, llvm::False) }
+ unsafe { llvm::LLVMConstInt(ty, val, llvm::FALSE) }
}
pub(crate) fn get_const_i64(&self, n: u64) -> &'ll Value {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 6eb7042..7a6dc00 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -72,7 +72,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
.unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
llvm::set_section(section_var, c".debug_gdb_scripts");
llvm::set_initializer(section_var, cx.const_bytes(section_contents));
- llvm::LLVMSetGlobalConstant(section_var, llvm::True);
+ llvm::LLVMSetGlobalConstant(section_var, llvm::TRUE);
llvm::set_unnamed_address(section_var, llvm::UnnamedAddr::Global);
llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
// This should make sure that the whole section is not larger than
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 0e9dbfb..caa3369 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -19,7 +19,9 @@
self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
};
use rustc_session::config::{self, DebugInfo, Lto};
-use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Symbol, hygiene};
+use rustc_span::{
+ DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span, Symbol, hygiene,
+};
use rustc_symbol_mangling::typeid_for_trait_ref;
use rustc_target::spec::DebuginfoKind;
use smallvec::smallvec;
@@ -423,6 +425,14 @@ fn build_slice_type_di_node<'ll, 'tcx>(
/// This function will look up the debuginfo node in the TypeMap. If it can't find it, it
/// will create the node by dispatching to the corresponding `build_*_di_node()` function.
pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
+ spanned_type_di_node(cx, t, DUMMY_SP)
+}
+
+pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
+ cx: &CodegenCx<'ll, 'tcx>,
+ t: Ty<'tcx>,
+ span: Span,
+) -> &'ll DIType {
let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t);
if let Some(existing_di_node) = debug_context(cx).type_map.di_node_for_unique_id(unique_type_id)
@@ -460,7 +470,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
ty::Adt(def, ..) => match def.adt_kind() {
AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id),
AdtKind::Union => build_union_type_di_node(cx, unique_type_id),
- AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id),
+ AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span),
},
ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
_ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t),
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 7c70192..caff358 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -10,7 +10,7 @@
use rustc_middle::mir::CoroutineLayout;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef};
-use rustc_span::Symbol;
+use rustc_span::{Span, Symbol};
use super::type_map::{DINodeCreationResult, UniqueTypeId};
use super::{SmallVec, size_and_align_of};
@@ -30,13 +30,14 @@
pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
unique_type_id: UniqueTypeId<'tcx>,
+ span: Span,
) -> DINodeCreationResult<'ll> {
let enum_type = unique_type_id.expect_ty();
let &ty::Adt(enum_adt_def, _) = enum_type.kind() else {
bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type)
};
- let enum_type_and_layout = cx.layout_of(enum_type);
+ let enum_type_and_layout = cx.spanned_layout_of(enum_type, span);
if wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout) {
return build_c_style_enum_di_node(cx, enum_adt_def, enum_type_and_layout);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 2c3a844..79334f7 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -28,7 +28,9 @@
use smallvec::SmallVec;
use tracing::debug;
-use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, type_di_node};
+use self::metadata::{
+ UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, spanned_type_di_node, type_di_node,
+};
use self::namespace::mangled_name_of_instance;
use self::utils::{DIB, create_DIArray, is_node_local_to_unit};
use crate::builder::Builder;
@@ -626,7 +628,7 @@ fn create_dbg_var(
let loc = self.lookup_debug_loc(span.lo());
let file_metadata = file_metadata(self, &loc.file);
- let type_metadata = type_di_node(self, variable_type);
+ let type_metadata = spanned_type_di_node(self, variable_type, span);
let (argument_index, dwarf_tag) = match variable_kind {
ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
index b4d6393..1dcf4ff 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
@@ -38,7 +38,7 @@ pub(crate) fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'l
parent_scope,
namespace_name_string.as_ptr(),
namespace_name_string.len(),
- llvm::False, // ExportSymbols (only relevant for C++ anonymous namespaces)
+ llvm::FALSE, // ExportSymbols (only relevant for C++ anonymous namespaces)
)
};
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 0fcf31d..628cb34 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -37,7 +37,7 @@
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
@@ -165,15 +165,15 @@ fn run_and_optimize_fat_lto(
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<Self>>,
- ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+ ) -> ModuleCodegen<Self::Module> {
let mut module =
- back::lto::run_fat(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, modules)?;
+ back::lto::run_fat(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, modules);
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
- back::lto::run_pass_manager(cgcx, dcx, &mut module, false)?;
+ back::lto::run_pass_manager(cgcx, dcx, &mut module, false);
- Ok(module)
+ module
}
fn run_thin_lto(
cgcx: &CodegenContext<Self>,
@@ -181,7 +181,7 @@ fn run_thin_lto(
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
- ) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
+ ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>) {
back::lto::run_thin(
cgcx,
exported_symbols_for_lto,
@@ -195,20 +195,20 @@ fn optimize(
dcx: DiagCtxtHandle<'_>,
module: &mut ModuleCodegen<Self::Module>,
config: &ModuleConfig,
- ) -> Result<(), FatalError> {
+ ) {
back::write::optimize(cgcx, dcx, module, config)
}
fn optimize_thin(
cgcx: &CodegenContext<Self>,
thin: ThinModule<Self>,
- ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+ ) -> ModuleCodegen<Self::Module> {
back::lto::optimize_thin_module(thin, cgcx)
}
fn codegen(
cgcx: &CodegenContext<Self>,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
- ) -> Result<CompiledModule, FatalError> {
+ ) -> CompiledModule {
back::write::codegen(cgcx, module, config)
}
fn prepare_thin(
@@ -407,12 +407,12 @@ fn tm_from_cgcx(
cgcx: &CodegenContext<LlvmCodegenBackend>,
name: &str,
dcx: DiagCtxtHandle<'_>,
- ) -> Result<OwnedTargetMachine, FatalError> {
+ ) -> OwnedTargetMachine {
let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, name);
match (cgcx.tm_factory)(tm_factory_config) {
- Ok(m) => Ok(m),
+ Ok(m) => m,
Err(e) => {
- return Err(dcx.emit_almost_fatal(ParseTargetMachineConfig(e)));
+ dcx.emit_fatal(ParseTargetMachineConfig(e));
}
}
}
@@ -422,13 +422,13 @@ fn parse(
name: &CStr,
buffer: &[u8],
dcx: DiagCtxtHandle<'_>,
- ) -> Result<Self, FatalError> {
+ ) -> Self {
unsafe {
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
- let llmod_raw = back::lto::parse_module(llcx, name, buffer, dcx)?;
- let tm = ModuleLlvm::tm_from_cgcx(cgcx, name.to_str().unwrap(), dcx)?;
+ let llmod_raw = back::lto::parse_module(llcx, name, buffer, dcx);
+ let tm = ModuleLlvm::tm_from_cgcx(cgcx, name.to_str().unwrap(), dcx);
- Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
+ ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) }
}
}
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 2461f70..ba59085 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -11,9 +11,8 @@
//! the need for an extra cast from `*const u8` on the Rust side.
#![allow(non_camel_case_types)]
-#![allow(non_upper_case_globals)]
-use std::fmt::Debug;
+use std::fmt::{self, Debug};
use std::marker::PhantomData;
use std::num::NonZero;
use std::ptr;
@@ -33,10 +32,59 @@
/// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`,
/// which has a different ABI from Rust or C++ `bool`.
-pub(crate) type Bool = c_int;
+///
+/// This wrapper does not implement `PartialEq`.
+/// To test the underlying boolean value, use [`Self::is_true`].
+#[derive(Clone, Copy)]
+#[repr(transparent)]
+pub(crate) struct Bool {
+ value: c_int,
+}
-pub(crate) const True: Bool = 1 as Bool;
-pub(crate) const False: Bool = 0 as Bool;
+pub(crate) const TRUE: Bool = Bool::TRUE;
+pub(crate) const FALSE: Bool = Bool::FALSE;
+
+impl Bool {
+ pub(crate) const TRUE: Self = Self { value: 1 };
+ pub(crate) const FALSE: Self = Self { value: 0 };
+
+ pub(crate) const fn from_bool(rust_bool: bool) -> Self {
+ if rust_bool { Self::TRUE } else { Self::FALSE }
+ }
+
+ /// Converts this LLVM-C boolean to a Rust `bool`
+ pub(crate) fn is_true(self) -> bool {
+ // Since we're interacting with a C API, follow the C convention of
+ // treating any nonzero value as true.
+ self.value != Self::FALSE.value
+ }
+}
+
+impl Debug for Bool {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self.value {
+ 0 => f.write_str("FALSE"),
+ 1 => f.write_str("TRUE"),
+ // As with `Self::is_true`, treat any nonzero value as true.
+ v => write!(f, "TRUE ({v})"),
+ }
+ }
+}
+
+/// Convenience trait to convert `bool` to `llvm::Bool` with an explicit method call.
+///
+/// Being able to write `b.to_llvm_bool()` is less noisy than `llvm::Bool::from(b)`,
+/// while being more explicit and less mistake-prone than something like `b.into()`.
+pub(crate) trait ToLlvmBool: Copy {
+ fn to_llvm_bool(self) -> llvm::Bool;
+}
+
+impl ToLlvmBool for bool {
+ #[inline(always)]
+ fn to_llvm_bool(self) -> llvm::Bool {
+ llvm::Bool::from_bool(self)
+ }
+}
/// Wrapper for a raw enum value returned from LLVM's C APIs.
///
@@ -215,7 +263,7 @@ pub(crate) enum AttributeKind {
MinSize = 4,
Naked = 5,
NoAlias = 6,
- NoCapture = 7,
+ CapturesAddress = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,
@@ -1881,11 +1929,17 @@ pub(crate) fn LLVMRustCreateMemoryEffectsAttr(
C: &Context,
effects: MemoryEffects,
) -> &Attribute;
+ /// ## Safety
+ /// - Each of `LowerWords` and `UpperWords` must point to an array that is
+ /// long enough to fully define an integer of size `NumBits`, i.e. each
+ /// pointer must point to `NumBits.div_ceil(64)` elements or more.
+ /// - The implementation will make its own copy of the pointed-to `u64`
+ /// values, so the pointers only need to outlive this function call.
pub(crate) fn LLVMRustCreateRangeAttribute(
C: &Context,
- num_bits: c_uint,
- lower_words: *const u64,
- upper_words: *const u64,
+ NumBits: c_uint,
+ LowerWords: *const u64,
+ UpperWords: *const u64,
) -> &Attribute;
// Operations on functions
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index 7fea7b7..d6974e2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -112,16 +112,26 @@ pub(crate) fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &
pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute {
let lower = range.start;
+ // LLVM treats the upper bound as exclusive, but allows wrapping.
let upper = range.end.wrapping_add(1);
- let lower_words = [lower as u64, (lower >> 64) as u64];
- let upper_words = [upper as u64, (upper >> 64) as u64];
+
+ // Pass each `u128` endpoint value as a `[u64; 2]` array, least-significant part first.
+ let as_u64_array = |x: u128| [x as u64, (x >> 64) as u64];
+ let lower_words: [u64; 2] = as_u64_array(lower);
+ let upper_words: [u64; 2] = as_u64_array(upper);
+
+ // To ensure that LLVM doesn't try to read beyond the `[u64; 2]` arrays,
+ // we must explicitly check that `size_bits` does not exceed 128.
+ let size_bits = size.bits();
+ assert!(size_bits <= 128);
+ // More robust assertions that are redundant with `size_bits <= 128` and
+ // should be optimized away.
+ assert!(size_bits.div_ceil(64) <= u64::try_from(lower_words.len()).unwrap());
+ assert!(size_bits.div_ceil(64) <= u64::try_from(upper_words.len()).unwrap());
+ let size_bits = c_uint::try_from(size_bits).unwrap();
+
unsafe {
- LLVMRustCreateRangeAttribute(
- llcx,
- size.bits().try_into().unwrap(),
- lower_words.as_ptr(),
- upper_words.as_ptr(),
- )
+ LLVMRustCreateRangeAttribute(llcx, size_bits, lower_words.as_ptr(), upper_words.as_ptr())
}
}
@@ -215,7 +225,7 @@ pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) {
}
pub(crate) fn set_global_constant(llglobal: &Value, is_constant: bool) {
- LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
+ LLVMSetGlobalConstant(llglobal, is_constant.to_llvm_bool());
}
pub(crate) fn get_linkage(llglobal: &Value) -> Linkage {
@@ -229,7 +239,7 @@ pub(crate) fn set_linkage(llglobal: &Value, linkage: Linkage) {
}
pub(crate) fn is_declaration(llglobal: &Value) -> bool {
- unsafe { LLVMIsDeclaration(llglobal) == ffi::True }
+ unsafe { LLVMIsDeclaration(llglobal) }.is_true()
}
pub(crate) fn get_visibility(llglobal: &Value) -> Visibility {
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 90f7cd4..d927ffd 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -26,7 +26,7 @@
pub(crate) fn init(sess: &Session) {
unsafe {
// Before we touch LLVM, make sure that multithreading is enabled.
- if llvm::LLVMIsMultithreaded() != 1 {
+ if !llvm::LLVMIsMultithreaded().is_true() {
bug!("LLVM compiled without support for threads");
}
INIT.call_once(|| {
@@ -279,7 +279,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
}
("loongarch32" | "loongarch64", "32s") if get_version().0 < 21 => None,
// Filter out features that are not supported by the current LLVM version
- ("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
+ ("riscv32" | "riscv64", "zacas" | "rva23u64" | "supm") if get_version().0 < 20 => None,
(
"s390x",
"message-security-assist-extension12"
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 5075bef..52eefe2 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -133,7 +133,7 @@ fn should_assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) ->
// Thread-local variables generally don't support copy relocations.
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
- .is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
+ .is_some_and(|v| llvm::LLVMIsThreadLocal(v).is_true());
if is_thread_local_var {
return false;
}
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index f02d16b..9ecaf5f 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -15,7 +15,7 @@
use crate::abi::{FnAbiLlvmExt, LlvmType};
use crate::context::{CodegenCx, GenericCx, SCx};
pub(crate) use crate::llvm::Type;
-use crate::llvm::{Bool, False, Metadata, True};
+use crate::llvm::{FALSE, Metadata, TRUE, ToLlvmBool};
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use crate::{common, llvm};
@@ -53,7 +53,9 @@ pub(crate) fn type_named_struct(&self, name: &str) -> &'ll Type {
}
pub(crate) fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) {
- unsafe { llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed as Bool) }
+ unsafe {
+ llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed.to_llvm_bool())
+ }
}
pub(crate) fn type_void(&self) -> &'ll Type {
unsafe { llvm::LLVMVoidTypeInContext(self.llcx()) }
@@ -139,7 +141,7 @@ pub(crate) fn isize_ty(&self) -> &'ll Type {
}
pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
- unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
+ unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, TRUE) }
}
pub(crate) fn type_i1(&self) -> &'ll Type {
@@ -152,7 +154,7 @@ pub(crate) fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type {
self.llcx(),
els.as_ptr(),
els.len() as c_uint,
- packed as Bool,
+ packed.to_llvm_bool(),
)
}
}
@@ -200,7 +202,7 @@ fn type_f128(&self) -> &'ll Type {
}
fn type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
- unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) }
+ unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, FALSE) }
}
fn type_kind(&self, ty: &'ll Type) -> TypeKind {
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 6a8971d..57e1fee 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -6,12 +6,12 @@
[dependencies]
# tidy-alphabetical-start
ar_archive_writer = "0.4.2"
-bitflags = "2.4.1"
+bitflags.workspace = true
bstr = "1.11.3"
# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version
# per crate", so if you change this, you need to also change it in `rustc_llvm`.
cc = "=1.2.16"
-itertools = "0.12"
+itertools.workspace = true
pathdiff = "0.2.0"
regex = "1.4"
rustc_abi = { path = "../rustc_abi" }
@@ -37,18 +37,18 @@
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-serde_json = "1.0.59"
+serde_json.workspace = true
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tempfile = "3.2"
-thin-vec = "0.2.12"
+tempfile.workspace = true
+thin-vec.workspace = true
thorin-dwp = "0.9"
-tracing = "0.1"
+tracing.workspace = true
wasm-encoder = "0.219"
# tidy-alphabetical-end
[target.'cfg(unix)'.dependencies]
# tidy-alphabetical-start
-libc = "0.2.50"
+libc.workspace = true
# tidy-alphabetical-end
[dependencies.object]
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 42ba015..44b9941 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -171,9 +171,6 @@
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_sanitize = invalid argument for `sanitize`
- .note = expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
-
codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs
index 2274450..b1d646d 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -164,7 +164,7 @@ pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> {
//
// Note that when cross-compiling from e.g. Linux, the `xcrun` binary may sometimes be provided
// as a shim by a cross-compilation helper tool. It usually isn't, but we still try nonetheless.
- match xcrun_show_sdk_path(sdk_name, sess.verbose_internals()) {
+ match xcrun_show_sdk_path(sdk_name, false) {
Ok((path, stderr)) => {
// Emit extra stderr, such as if `-verbose` was passed, or if `xcrun` emitted a warning.
if !stderr.is_empty() {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index c3777f6..19c919c 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -14,11 +14,13 @@
use regex::Regex;
use rustc_arena::TypedArena;
use rustc_ast::CRATE_NODE_ID;
+use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize};
+use rustc_hir::attrs::NativeLibKind;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_macros::LintDiagnostic;
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
@@ -38,7 +40,6 @@
use rustc_session::lint::builtin::LINKER_MESSAGES;
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::search_paths::PathKind;
-use rustc_session::utils::NativeLibKind;
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
use rustc_session::{Session, filesearch};
@@ -3019,7 +3020,9 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
match lib.cfg {
- Some(ref cfg) => rustc_attr_parsing::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
+ Some(ref cfg) => {
+ eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool()
+ }
None => true,
}
}
diff --git a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
index b9e0c95..9f42991 100644
--- a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
@@ -7,9 +7,9 @@
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_hashes::Hash128;
+use rustc_hir::attrs::NativeLibKind;
use rustc_session::Session;
use rustc_session::cstore::DllImport;
-use rustc_session::utils::NativeLibKind;
use rustc_span::Symbol;
use crate::back::archive::ImportLibraryItem;
@@ -307,11 +307,14 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
stub.reserve_section_headers();
stub.reserve_dynsym();
stub.reserve_dynstr();
+ let verdef_count = 1 + vers.len();
+ let mut dynamic_entries = 2; // DT_SONAME, DT_NULL
if !vers.is_empty() {
stub.reserve_gnu_versym();
- stub.reserve_gnu_verdef(1 + vers.len(), 1 + vers.len());
+ stub.reserve_gnu_verdef(verdef_count, verdef_count);
+ dynamic_entries += 1; // DT_VERDEFNUM
}
- stub.reserve_dynamic(2); // DT_SONAME, DT_NULL
+ stub.reserve_dynamic(dynamic_entries);
// First write the ELF header with the arch information.
let e_machine = match (arch, sub_arch) {
@@ -443,9 +446,13 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
// .dynamic
// the DT_SONAME will be used by the linker to populate DT_NEEDED
// which the loader uses to find the library.
- // DT_NULL terminates the .dynamic table.
stub.write_align_dynamic();
stub.write_dynamic_string(elf::DT_SONAME, soname);
+ // LSB section "2.7. Symbol Versioning" requires `DT_VERDEFNUM` to be reliable.
+ if verdef_count > 1 {
+ stub.write_dynamic(elf::DT_VERDEFNUM, verdef_count as u64);
+ }
+ // DT_NULL terminates the .dynamic table.
stub.write_dynamic(elf::DT_NULL, 0);
stub_buf
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index bf38c02..10aaadd 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -329,12 +329,18 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
// Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
let mut e_flags: u32 = 0x0;
- // Check if compressed is enabled
- // `unstable_target_features` is used here because "c" is gated behind riscv_target_feature.
- if sess.unstable_target_features.contains(&sym::c) {
+ // Check if compression is enabled
+ // `unstable_target_features` is used here because "zca" is gated behind riscv_target_feature.
+ if sess.unstable_target_features.contains(&sym::zca) {
e_flags |= elf::EF_RISCV_RVC;
}
+ // Check if RVTSO is enabled
+ // `unstable_target_features` is used here because "ztso" is gated behind riscv_target_feature.
+ if sess.unstable_target_features.contains(&sym::ztso) {
+ e_flags |= elf::EF_RISCV_TSO;
+ }
+
// Set the appropriate flag based on ABI
// This needs to match LLVM `RISCVELFStreamer.cpp`
match &*sess.target.llvm_abiname {
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 7709682..d8a1480 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -15,7 +15,7 @@
use rustc_middle::util::Providers;
use rustc_session::config::{CrateType, OomStrategy};
use rustc_symbol_mangling::mangle_internal_symbol;
-use rustc_target::spec::{SanitizerSet, TlsModel};
+use rustc_target::spec::TlsModel;
use tracing::debug;
use crate::base::allocator_kind_for_codegen;
@@ -242,53 +242,6 @@ fn exported_non_generic_symbols_provider_local<'tcx>(
}
}
- if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
- // These are weak symbols that point to the profile version and the
- // profile name, which need to be treated as exported so LTO doesn't nix
- // them.
- const PROFILER_WEAK_SYMBOLS: [&str; 2] =
- ["__llvm_profile_raw_version", "__llvm_profile_filename"];
-
- symbols.extend(PROFILER_WEAK_SYMBOLS.iter().map(|sym| {
- let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym));
- (
- exported_symbol,
- SymbolExportInfo {
- level: SymbolExportLevel::C,
- kind: SymbolExportKind::Data,
- used: false,
- rustc_std_internal_symbol: false,
- },
- )
- }));
- }
-
- if tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
- let mut msan_weak_symbols = Vec::new();
-
- // Similar to profiling, preserve weak msan symbol during LTO.
- if tcx.sess.opts.unstable_opts.sanitizer_recover.contains(SanitizerSet::MEMORY) {
- msan_weak_symbols.push("__msan_keep_going");
- }
-
- if tcx.sess.opts.unstable_opts.sanitizer_memory_track_origins != 0 {
- msan_weak_symbols.push("__msan_track_origins");
- }
-
- symbols.extend(msan_weak_symbols.into_iter().map(|sym| {
- let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym));
- (
- exported_symbol,
- SymbolExportInfo {
- level: SymbolExportLevel::C,
- kind: SymbolExportKind::Data,
- used: false,
- rustc_std_internal_symbol: false,
- },
- )
- }));
- }
-
// Sort so we get a stable incr. comp. hash.
symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));
@@ -570,7 +523,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
// core/std/allocators/etc. For example symbols used to hook up allocation
// are not considered for export
let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
- let is_extern = codegen_fn_attrs.contains_extern_indicator(tcx, sym_def_id);
+ let is_extern = codegen_fn_attrs.contains_extern_indicator();
let std_internal =
codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 26d089a..92582dc 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1,5 +1,6 @@
use std::assert_matches::assert_matches;
use std::marker::PhantomData;
+use std::panic::AssertUnwindSafe;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender, channel};
@@ -14,7 +15,7 @@
use rustc_errors::emitter::Emitter;
use rustc_errors::translation::Translator;
use rustc_errors::{
- Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, Level, MultiSpan, Style,
+ Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalErrorMarker, Level, MultiSpan, Style,
Suggestions,
};
use rustc_fs_util::link_or_copy;
@@ -137,23 +138,12 @@ macro_rules! if_regular {
let emit_obj = if !should_emit_obj {
EmitObj::None
- } else if sess.target.obj_is_bitcode
- || (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
- {
+ } else if sess.target.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
// This case is selected if the target uses objects as bitcode, or
// if linker plugin LTO is enabled. In the linker plugin LTO case
// the assumption is that the final link-step will read the bitcode
// and convert it to object code. This may be done by either the
// native linker or rustc itself.
- //
- // Note, however, that the linker-plugin-lto requested here is
- // explicitly ignored for `#![no_builtins]` crates. These crates are
- // specifically ignored by rustc's LTO passes and wouldn't work if
- // loaded into the linker. These crates define symbols that LLVM
- // lowers intrinsics to, and these symbol dependencies aren't known
- // until after codegen. As a result any crate marked
- // `#![no_builtins]` is assumed to not participate in LTO and
- // instead goes on to generate object code.
EmitObj::Bitcode
} else if need_bitcode_in_object(tcx) {
EmitObj::ObjectCode(BitcodeSection::Full)
@@ -395,8 +385,7 @@ fn generate_thin_lto_work<B: ExtraBackendMethods>(
each_linked_rlib_for_lto,
needs_thin_lto,
import_only_modules,
- )
- .unwrap_or_else(|e| e.raise());
+ );
lto_modules
.into_iter()
.map(|module| {
@@ -844,11 +833,11 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
mut module: ModuleCodegen<B::Module>,
module_config: &ModuleConfig,
-) -> Result<WorkItemResult<B>, FatalError> {
+) -> WorkItemResult<B> {
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
- B::optimize(cgcx, dcx, &mut module, module_config)?;
+ B::optimize(cgcx, dcx, &mut module, module_config);
// After we've done the initial round of optimizations we need to
// decide whether to synchronously codegen this module or ship it
@@ -868,8 +857,8 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
match lto_type {
ComputedLtoType::No => {
- let module = B::codegen(cgcx, module, module_config)?;
- Ok(WorkItemResult::Finished(module))
+ let module = B::codegen(cgcx, module, module_config);
+ WorkItemResult::Finished(module)
}
ComputedLtoType::Thin => {
let (name, thin_buffer) = B::prepare_thin(module, false);
@@ -878,7 +867,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
});
}
- Ok(WorkItemResult::NeedsThinLto(name, thin_buffer))
+ WorkItemResult::NeedsThinLto(name, thin_buffer)
}
ComputedLtoType::Fat => match bitcode {
Some(path) => {
@@ -886,12 +875,12 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
fs::write(&path, buffer.data()).unwrap_or_else(|e| {
panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
});
- Ok(WorkItemResult::NeedsFatLto(FatLtoInput::Serialized {
+ WorkItemResult::NeedsFatLto(FatLtoInput::Serialized {
name,
buffer: SerializedModule::Local(buffer),
- }))
+ })
}
- None => Ok(WorkItemResult::NeedsFatLto(FatLtoInput::InMemory(module))),
+ None => WorkItemResult::NeedsFatLto(FatLtoInput::InMemory(module)),
},
}
}
@@ -987,7 +976,7 @@ fn execute_fat_lto_work_item<B: ExtraBackendMethods>(
mut needs_fat_lto: Vec<FatLtoInput<B>>,
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
module_config: &ModuleConfig,
-) -> Result<WorkItemResult<B>, FatalError> {
+) -> WorkItemResult<B> {
for (module, wp) in import_only_modules {
needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, buffer: module })
}
@@ -997,19 +986,19 @@ fn execute_fat_lto_work_item<B: ExtraBackendMethods>(
exported_symbols_for_lto,
each_linked_rlib_for_lto,
needs_fat_lto,
- )?;
- let module = B::codegen(cgcx, module, module_config)?;
- Ok(WorkItemResult::Finished(module))
+ );
+ let module = B::codegen(cgcx, module, module_config);
+ WorkItemResult::Finished(module)
}
fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
module: lto::ThinModule<B>,
module_config: &ModuleConfig,
-) -> Result<WorkItemResult<B>, FatalError> {
- let module = B::optimize_thin(cgcx, module)?;
- let module = B::codegen(cgcx, module, module_config)?;
- Ok(WorkItemResult::Finished(module))
+) -> WorkItemResult<B> {
+ let module = B::optimize_thin(cgcx, module);
+ let module = B::codegen(cgcx, module, module_config);
+ WorkItemResult::Finished(module)
}
/// Messages sent to the coordinator.
@@ -1722,37 +1711,10 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
let cgcx = cgcx.clone();
B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || {
- // Set up a destructor which will fire off a message that we're done as
- // we exit.
- struct Bomb<B: ExtraBackendMethods> {
- coordinator_send: Sender<Message<B>>,
- result: Option<Result<WorkItemResult<B>, FatalError>>,
- }
- impl<B: ExtraBackendMethods> Drop for Bomb<B> {
- fn drop(&mut self) {
- let msg = match self.result.take() {
- Some(Ok(result)) => Message::WorkItem::<B> { result: Ok(result) },
- Some(Err(FatalError)) => {
- Message::WorkItem::<B> { result: Err(Some(WorkerFatalError)) }
- }
- None => Message::WorkItem::<B> { result: Err(None) },
- };
- drop(self.coordinator_send.send(msg));
- }
- }
-
- let mut bomb = Bomb::<B> { coordinator_send, result: None };
-
- // Execute the work itself, and if it finishes successfully then flag
- // ourselves as a success as well.
- //
- // Note that we ignore any `FatalError` coming out of `execute_work_item`,
- // as a diagnostic was already sent off to the main thread - just
- // surface that there was an error in this worker.
- bomb.result = {
+ let result = std::panic::catch_unwind(AssertUnwindSafe(|| {
let module_config = cgcx.config(work.module_kind());
- Some(match work {
+ match work {
WorkItem::Optimize(m) => {
let _timer =
cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*m.name);
@@ -1763,7 +1725,7 @@ fn drop(&mut self) {
"codegen_copy_artifacts_from_incr_cache",
&*m.name,
);
- Ok(execute_copy_from_cache_work_item(&cgcx, m, module_config))
+ execute_copy_from_cache_work_item(&cgcx, m, module_config)
}
WorkItem::FatLto {
exported_symbols_for_lto,
@@ -1788,8 +1750,22 @@ fn drop(&mut self) {
cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name());
execute_thin_lto_work_item(&cgcx, m, module_config)
}
- })
+ }
+ }));
+
+ let msg = match result {
+ Ok(result) => Message::WorkItem::<B> { result: Ok(result) },
+
+ // We ignore any `FatalError` coming out of `execute_work_item`, as a
+ // diagnostic was already sent off to the main thread - just surface
+ // that there was an error in this worker.
+ Err(err) if err.is::<FatalErrorMarker>() => {
+ Message::WorkItem::<B> { result: Err(Some(WorkerFatalError)) }
+ }
+
+ Err(_) => Message::WorkItem::<B> { result: Err(None) },
};
+ drop(coordinator_send.send(msg));
})
.expect("failed to spawn work thread");
}
@@ -1970,10 +1946,13 @@ fn drop(&mut self) {
pub struct OngoingCodegen<B: ExtraBackendMethods> {
pub backend: B,
pub crate_info: CrateInfo,
+ pub output_filenames: Arc<OutputFilenames>,
+ // Field order below is intended to terminate the coordinator thread before two fields below
+ // drop and prematurely close channels used by coordinator thread. See `Coordinator`'s
+ // `Drop` implementation for more info.
+ pub coordinator: Coordinator<B>,
pub codegen_worker_receive: Receiver<CguMessage>,
pub shared_emitter_main: SharedEmitterMain,
- pub output_filenames: Arc<OutputFilenames>,
- pub coordinator: Coordinator<B>,
}
impl<B: ExtraBackendMethods> OngoingCodegen<B> {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 23e2abd..961bb78 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -293,6 +293,9 @@ fn process_builtin_attrs(
codegen_fn_attrs.linkage = linkage;
}
}
+ AttributeKind::Sanitize { span, .. } => {
+ interesting_spans.sanitize = Some(*span);
+ }
_ => {}
}
}
@@ -310,7 +313,6 @@ fn process_builtin_attrs(
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
- sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
sym::instruction_set => {
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
}
@@ -383,6 +385,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
// Foreign items by default use no mangling for their symbol name.
if tcx.is_foreign_item(did) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FOREIGN_ITEM;
+
// There's a few exceptions to this rule though:
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
@@ -560,79 +564,9 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
}
}
-/// For an attr that has the `sanitize` attribute, read the list of
-/// disabled sanitizers. `current_attr` holds the information about
-/// previously parsed attributes.
-fn parse_sanitize_attr(
- tcx: TyCtxt<'_>,
- attr: &Attribute,
- current_attr: SanitizerSet,
-) -> SanitizerSet {
- let mut result = current_attr;
- if let Some(list) = attr.meta_item_list() {
- for item in list.iter() {
- let MetaItemInner::MetaItem(set) = item else {
- tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
- break;
- };
- let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
- match segments.as_slice() {
- // Similar to clang, sanitize(address = ..) and
- // sanitize(kernel_address = ..) control both ASan and KASan
- // Source: https://reviews.llvm.org/D44981.
- [sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::off) => {
- result |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
- }
- [sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::on) => {
- result &= !SanitizerSet::ADDRESS;
- result &= !SanitizerSet::KERNELADDRESS;
- }
- [sym::cfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::CFI,
- [sym::cfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::CFI,
- [sym::kcfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::KCFI,
- [sym::kcfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::KCFI,
- [sym::memory] if set.value_str() == Some(sym::off) => {
- result |= SanitizerSet::MEMORY
- }
- [sym::memory] if set.value_str() == Some(sym::on) => {
- result &= !SanitizerSet::MEMORY
- }
- [sym::memtag] if set.value_str() == Some(sym::off) => {
- result |= SanitizerSet::MEMTAG
- }
- [sym::memtag] if set.value_str() == Some(sym::on) => {
- result &= !SanitizerSet::MEMTAG
- }
- [sym::shadow_call_stack] if set.value_str() == Some(sym::off) => {
- result |= SanitizerSet::SHADOWCALLSTACK
- }
- [sym::shadow_call_stack] if set.value_str() == Some(sym::on) => {
- result &= !SanitizerSet::SHADOWCALLSTACK
- }
- [sym::thread] if set.value_str() == Some(sym::off) => {
- result |= SanitizerSet::THREAD
- }
- [sym::thread] if set.value_str() == Some(sym::on) => {
- result &= !SanitizerSet::THREAD
- }
- [sym::hwaddress] if set.value_str() == Some(sym::off) => {
- result |= SanitizerSet::HWADDRESS
- }
- [sym::hwaddress] if set.value_str() == Some(sym::on) => {
- result &= !SanitizerSet::HWADDRESS
- }
- _ => {
- tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
- }
- }
- }
- }
- result
-}
-
fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
// Backtrack to the crate root.
- let disabled = match tcx.opt_local_parent(did) {
+ let mut disabled = match tcx.opt_local_parent(did) {
// Check the parent (recursively).
Some(parent) => tcx.disabled_sanitizers_for(parent),
// We reached the crate root without seeing an attribute, so
@@ -641,8 +575,17 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
};
// Check for a sanitize annotation directly on this def.
- if let Some(attr) = tcx.get_attr(did, sym::sanitize) {
- return parse_sanitize_attr(tcx, attr, disabled);
+ if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set))
+ {
+ // the on set is the set of sanitizers explicitly enabled.
+ // we mask those out since we want the set of disabled sanitizers here
+ disabled &= !*on_set;
+ // the off set is the set of sanitizers explicitly disabled.
+ // we or those in here.
+ disabled |= *off_set;
+ // the on set and off set are distjoint since there's a third option: unset.
+ // a node may not set the sanitizer setting in which case it inherits from parents.
+ // the code above in this function does this backtracking
}
disabled
}
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index a6fd6c7..08e2f35 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -1,10 +1,11 @@
#![allow(non_camel_case_types)]
use rustc_hir::LangItem;
+use rustc_hir::attrs::PeImportNameType;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Instance, TyCtxt};
use rustc_middle::{bug, mir, span_bug};
-use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
+use rustc_session::cstore::{DllCallingConvention, DllImport};
use rustc_span::Span;
use rustc_target::spec::Target;
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 209c78d..fb5a820 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1121,14 +1121,6 @@ fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
}
#[derive(Diagnostic)]
-#[diag(codegen_ssa_invalid_sanitize)]
-#[note]
-pub(crate) struct InvalidSanitize {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(codegen_ssa_target_feature_safe_trait)]
pub(crate) struct TargetFeatureSafeTrait {
#[primary_span]
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 23ed387..fe0500a 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -25,10 +25,10 @@
use std::path::{Path, PathBuf};
use std::sync::Arc;
-use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::UnordMap;
use rustc_hir::CRATE_HIR_ID;
+use rustc_hir::attrs::{CfgEntry, NativeLibKind};
use rustc_hir::def_id::CrateNum;
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_metadata::EncodedMetadata;
@@ -45,7 +45,6 @@
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
use rustc_session::cstore::{self, CrateSource};
use rustc_session::lint::builtin::LINKER_MESSAGES;
-use rustc_session::utils::NativeLibKind;
use rustc_span::Symbol;
pub mod assert_module_sources;
@@ -187,7 +186,7 @@ pub struct NativeLib {
pub kind: NativeLibKind,
pub name: Symbol,
pub filename: Option<Symbol>,
- pub cfg: Option<ast::MetaItemInner>,
+ pub cfg: Option<CfgEntry>,
pub verbatim: bool,
pub dll_imports: Vec<cstore::DllImport>,
}
diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs
index c29ad90..cc7c4e4 100644
--- a/compiler/rustc_codegen_ssa/src/traits/write.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/write.rs
@@ -1,6 +1,6 @@
use std::path::PathBuf;
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
use rustc_middle::dep_graph::WorkProduct;
use crate::back::lto::{SerializedModule, ThinModule};
@@ -22,7 +22,7 @@ fn run_and_optimize_fat_lto(
exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<FatLtoInput<Self>>,
- ) -> Result<ModuleCodegen<Self::Module>, FatalError>;
+ ) -> ModuleCodegen<Self::Module>;
/// Performs thin LTO by performing necessary global analysis and returning two
/// lists, one of the modules that need optimization and another for modules that
/// can simply be copied over from the incr. comp. cache.
@@ -32,7 +32,7 @@ fn run_thin_lto(
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
- ) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError>;
+ ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>);
fn print_pass_timings(&self);
fn print_statistics(&self);
fn optimize(
@@ -40,16 +40,16 @@ fn optimize(
dcx: DiagCtxtHandle<'_>,
module: &mut ModuleCodegen<Self::Module>,
config: &ModuleConfig,
- ) -> Result<(), FatalError>;
+ );
fn optimize_thin(
cgcx: &CodegenContext<Self>,
thin: ThinModule<Self>,
- ) -> Result<ModuleCodegen<Self::Module>, FatalError>;
+ ) -> ModuleCodegen<Self::Module>;
fn codegen(
cgcx: &CodegenContext<Self>,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
- ) -> Result<CompiledModule, FatalError>;
+ ) -> CompiledModule;
fn prepare_thin(
module: ModuleCodegen<Self::Module>,
want_summary: bool,
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
index 51dcee8..acf19b0f 100644
--- a/compiler/rustc_const_eval/Cargo.toml
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -5,9 +5,9 @@
[dependencies]
# tidy-alphabetical-start
-either = "1"
+either.workspace = true
rustc_abi = { path = "../rustc_abi" }
-rustc_apfloat = "0.2.0"
+rustc_apfloat.workspace = true
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
@@ -22,5 +22,5 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index da954cf..fccb6b1 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -280,22 +280,110 @@ fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
interp_ok(match (a, b) {
// Comparisons between integers are always known.
(Scalar::Int(a), Scalar::Int(b)) => (a == b) as u8,
- // Comparisons of null with an arbitrary scalar can be known if `scalar_may_be_null`
- // indicates that the scalar can definitely *not* be null.
- (Scalar::Int(int), ptr) | (ptr, Scalar::Int(int))
- if int.is_null() && !self.scalar_may_be_null(ptr)? =>
- {
- 0
+ // Comparing a pointer `ptr` with an integer `int` is equivalent to comparing
+ // `ptr-int` with null, so we can reduce this case to a `scalar_may_be_null` test.
+ (Scalar::Int(int), Scalar::Ptr(ptr, _)) | (Scalar::Ptr(ptr, _), Scalar::Int(int)) => {
+ let int = int.to_target_usize(*self.tcx);
+ // The `wrapping_neg` here may produce a value that is not
+ // a valid target usize any more... but `wrapping_offset` handles that correctly.
+ let offset_ptr = ptr.wrapping_offset(Size::from_bytes(int.wrapping_neg()), self);
+ if !self.scalar_may_be_null(Scalar::from_pointer(offset_ptr, self))? {
+ // `ptr.wrapping_sub(int)` is definitely not equal to `0`, so `ptr != int`
+ 0
+ } else {
+ // `ptr.wrapping_sub(int)` could be equal to `0`, but might not be,
+ // so we cannot know for sure if `ptr == int` or not
+ 2
+ }
}
- // Other ways of comparing integers and pointers can never be known for sure.
- (Scalar::Int { .. }, Scalar::Ptr(..)) | (Scalar::Ptr(..), Scalar::Int { .. }) => 2,
- // FIXME: return a `1` for when both sides are the same pointer, *except* that
- // some things (like functions and vtables) do not have stable addresses
- // so we need to be careful around them (see e.g. #73722).
- // FIXME: return `0` for at least some comparisons where we can reliably
- // determine the result of runtime inequality tests at compile-time.
- // Examples include comparison of addresses in different static items.
- (Scalar::Ptr(..), Scalar::Ptr(..)) => 2,
+ (Scalar::Ptr(a, _), Scalar::Ptr(b, _)) => {
+ let (a_prov, a_offset) = a.prov_and_relative_offset();
+ let (b_prov, b_offset) = b.prov_and_relative_offset();
+ let a_allocid = a_prov.alloc_id();
+ let b_allocid = b_prov.alloc_id();
+ let a_info = self.get_alloc_info(a_allocid);
+ let b_info = self.get_alloc_info(b_allocid);
+
+ // Check if the pointers cannot be equal due to alignment
+ if a_info.align > Align::ONE && b_info.align > Align::ONE {
+ let min_align = Ord::min(a_info.align.bytes(), b_info.align.bytes());
+ let a_residue = a_offset.bytes() % min_align;
+ let b_residue = b_offset.bytes() % min_align;
+ if a_residue != b_residue {
+ // If the two pointers have a different residue modulo their
+ // common alignment, they cannot be equal.
+ return interp_ok(0);
+ }
+ // The pointers have the same residue modulo their common alignment,
+ // so they could be equal. Try the other checks.
+ }
+
+ if let (Some(GlobalAlloc::Static(a_did)), Some(GlobalAlloc::Static(b_did))) = (
+ self.tcx.try_get_global_alloc(a_allocid),
+ self.tcx.try_get_global_alloc(b_allocid),
+ ) {
+ if a_allocid == b_allocid {
+ debug_assert_eq!(
+ a_did, b_did,
+ "different static item DefIds had same AllocId? {a_allocid:?} == {b_allocid:?}, {a_did:?} != {b_did:?}"
+ );
+ // Comparing two pointers into the same static. As per
+ // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.intro
+ // a static cannot be duplicated, so if two pointers are into the same
+ // static, they are equal if and only if their offsets are equal.
+ (a_offset == b_offset) as u8
+ } else {
+ debug_assert_ne!(
+ a_did, b_did,
+ "same static item DefId had two different AllocIds? {a_allocid:?} != {b_allocid:?}, {a_did:?} == {b_did:?}"
+ );
+ // Comparing two pointers into the different statics.
+ // We can never determine for sure that two pointers into different statics
+ // are *equal*, but we can know that they are *inequal* if they are both
+ // strictly in-bounds (i.e. in-bounds and not one-past-the-end) of
+ // their respective static, as different non-zero-sized statics cannot
+ // overlap or be deduplicated as per
+ // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.intro
+ // (non-deduplication), and
+ // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness
+ // (non-overlapping).
+ if a_offset < a_info.size && b_offset < b_info.size {
+ 0
+ } else {
+ // Otherwise, conservatively say we don't know.
+ // There are some cases we could still return `0` for, e.g.
+ // if the pointers being equal would require their statics to overlap
+ // one or more bytes, but for simplicity we currently only check
+ // strictly in-bounds pointers.
+ 2
+ }
+ }
+ } else {
+ // All other cases we conservatively say we don't know.
+ //
+ // For comparing statics to non-statics, as per https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness
+ // immutable statics can overlap with other kinds of allocations sometimes.
+ //
+ // FIXME: We could be more decisive for (non-zero-sized) mutable statics,
+ // which cannot overlap with other kinds of allocations.
+ //
+ // Functions and vtables can be duplicated and deduplicated, so we
+ // cannot be sure of runtime equality of pointers to the same one, or the
+ // runtime inequality of pointers to different ones (see e.g. #73722),
+ // so comparing those should return 2, whether they are the same allocation
+ // or not.
+ //
+ // `GlobalAlloc::TypeId` exists mostly to prevent consteval from comparing
+ // `TypeId`s, so comparing those should always return 2, whether they are the
+ // same allocation or not.
+ //
+ // FIXME: We could revisit comparing pointers into the same
+ // `GlobalAlloc::Memory` once https://github.com/rust-lang/rust/issues/128775
+ // is fixed (but they can be deduplicated, so comparing pointers into different
+ // ones should return 2).
+ 2
+ }
+ }
})
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 084d45c..23d362d 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -2,6 +2,8 @@
//!
//! The main entry point is the `step` method.
+use std::iter;
+
use either::Either;
use rustc_abi::{FIRST_VARIANT, FieldIdx};
use rustc_data_structures::fx::FxHashSet;
@@ -426,6 +428,7 @@ fn eval_callee_and_args(
terminator: &mir::Terminator<'tcx>,
func: &mir::Operand<'tcx>,
args: &[Spanned<mir::Operand<'tcx>>],
+ dest: &mir::Place<'tcx>,
) -> InterpResult<'tcx, EvaluatedCalleeAndArgs<'tcx, M>> {
let func = self.eval_operand(func, None)?;
@@ -435,14 +438,20 @@ fn eval_callee_and_args(
// protection, but then we'd force *a lot* of arguments into memory. So we do some syntactic
// pre-processing here where if all `move` arguments are syntactically distinct local
// variables (and none is indirect), we can skip the in-memory forcing.
+ // We have to include `dest` in that list so that we can detect aliasing of an in-place
+ // argument with the return place.
let move_definitely_disjoint = 'move_definitely_disjoint: {
let mut previous_locals = FxHashSet::<mir::Local>::default();
- for arg in args {
- let mir::Operand::Move(place) = arg.node else {
- continue; // we can skip non-`Move` arguments.
- };
+ for place in args
+ .iter()
+ .filter_map(|a| {
+ // We only have to care about `Move` arguments.
+ if let mir::Operand::Move(place) = &a.node { Some(place) } else { None }
+ })
+ .chain(iter::once(dest))
+ {
if place.is_indirect_first_projection() {
- // An indirect `Move` argument could alias with anything else...
+ // An indirect in-place argument could alias with anything else...
break 'move_definitely_disjoint false;
}
if !previous_locals.insert(place.local) {
@@ -544,7 +553,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResul
let old_loc = self.frame().loc;
let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
- self.eval_callee_and_args(terminator, func, args)?;
+ self.eval_callee_and_args(terminator, func, args, &destination)?;
let destination = self.eval_place(destination)?;
self.init_fn_call(
@@ -567,7 +576,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResul
let old_frame_idx = self.frame_idx();
let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
- self.eval_callee_and_args(terminator, func, args)?;
+ self.eval_callee_and_args(terminator, func, args, &mir::Place::return_place())?;
self.init_fn_tail_call(callee, (fn_sig.abi, fn_abi), &args, with_caller_location)?;
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 1720488..852fc11 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -6,14 +6,15 @@
[dependencies]
# tidy-alphabetical-start
arrayvec = { version = "0.7", default-features = false }
-bitflags = "2.4.1"
-either = "1.0"
+bitflags.workspace = true
+either.workspace = true
elsa = "1.11.0"
ena = "0.14.3"
-indexmap = "2.4.0"
+indexmap.workspace = true
jobserver_crate = { version = "0.1.28", package = "jobserver" }
-measureme = "12.0.1"
-rustc-hash = "2.0.0"
+measureme.workspace = true
+parking_lot = "0.12"
+rustc-hash.workspace = true
rustc-stable-hash = { version = "0.1.0", features = ["nightly"] }
rustc_arena = { path = "../rustc_arena" }
rustc_graphviz = { path = "../rustc_graphviz" }
@@ -24,9 +25,9 @@
rustc_thread_pool = { path = "../rustc_thread_pool" }
smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
stacker = "0.1.17"
-tempfile = "3.2"
-thin-vec = "0.2.12"
-tracing = "0.1"
+tempfile.workspace = true
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
[dependencies.hashbrown]
@@ -34,9 +35,6 @@
default-features = false
features = ["nightly"] # for may_dangle
-[dependencies.parking_lot]
-version = "0.12"
-
[target.'cfg(windows)'.dependencies.windows]
version = "0.61.0"
features = [
@@ -49,7 +47,7 @@
[target.'cfg(unix)'.dependencies]
# tidy-alphabetical-start
-libc = "0.2"
+libc.workspace = true
# tidy-alphabetical-end
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index ae1dbd2..196c8aa 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -49,14 +49,14 @@
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_ty_utils = { path = "../rustc_ty_utils" }
-serde_json = "1.0.59"
+serde_json.workspace = true
shlex = "1.0"
-tracing = { version = "0.1.35" }
+tracing.workspace = true
# tidy-alphabetical-end
[target.'cfg(all(unix, any(target_env = "gnu", target_os = "macos")))'.dependencies]
# tidy-alphabetical-start
-libc = "0.2"
+libc.workspace = true
# tidy-alphabetical-end
[target.'cfg(windows)'.dependencies.windows]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0458.md b/compiler/rustc_error_codes/src/error_codes/E0458.md
index 1b280cb..651bc37 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0458.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0458.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
An unknown "kind" was specified for a link attribute.
Erroneous code example:
-```compile_fail,E0458
+```ignore (no longer emitted)
#[link(kind = "wonderful_unicorn")] extern "C" {}
// error: unknown kind: `wonderful_unicorn`
```
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index 552ad67..7d2dc20 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -7,9 +7,8 @@
# tidy-alphabetical-start
fluent-bundle = "0.16"
fluent-syntax = "0.12"
-icu_list = "1.2"
-icu_locid = "1.2"
-icu_provider_adapters = "1.2"
+icu_list = { version = "2.0", default-features = false, features = ["alloc"] }
+icu_locale = { version = "2.0", default-features = false }
intl-memoizer = "0.5.1"
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@@ -18,6 +17,6 @@
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
-tracing = "0.1"
+tracing.workspace = true
unic-langid = { version = "0.9.0", features = ["macros"] }
# tidy-alphabetical-end
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index d8bacbe..7b7843f 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -15,7 +15,6 @@
pub use fluent_bundle::types::FluentType;
pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
use fluent_syntax::parser::ParserError;
-use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
use intl_memoizer::concurrent::IntlLangMemoizer;
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
use rustc_macros::{Decodable, Encodable};
@@ -515,8 +514,8 @@ fn from(spans: Vec<Span>) -> MultiSpan {
}
}
-fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locid::Locale> {
- icu_locid::Locale::try_from_bytes(lang.to_string().as_bytes()).ok()
+fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locale::Locale> {
+ icu_locale::Locale::try_from_str(&lang.to_string()).ok()
}
pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
@@ -568,21 +567,15 @@ fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result<Self, Self::
where
Self: Sized,
{
- let baked_data_provider = rustc_baked_icu_data::baked_data_provider();
- let locale_fallbacker =
- LocaleFallbacker::try_new_with_any_provider(&baked_data_provider)
- .expect("Failed to create fallback provider");
- let data_provider =
- LocaleFallbackProvider::new_with_fallbacker(baked_data_provider, locale_fallbacker);
let locale = icu_locale_from_unic_langid(lang)
.unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
- let list_formatter =
- icu_list::ListFormatter::try_new_and_with_length_with_any_provider(
- &data_provider,
- &locale.into(),
- icu_list::ListLength::Wide,
- )
- .expect("Failed to create list formatter");
+ let list_formatter = icu_list::ListFormatter::try_new_and_unstable(
+ &rustc_baked_icu_data::BakedDataProvider,
+ locale.into(),
+ icu_list::options::ListFormatterOptions::default()
+ .with_length(icu_list::options::ListLength::Wide),
+ )
+ .expect("Failed to create list formatter");
Ok(MemoizableListFormatter(list_formatter))
}
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index f37b6fb..67a17ce 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -14,7 +14,6 @@
rustc_error_messages = { path = "../rustc_error_messages" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hashes = { path = "../rustc_hashes" }
-rustc_hir_id = { path = "../rustc_hir_id" }
rustc_index = { path = "../rustc_index" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
@@ -22,10 +21,10 @@
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
serde = { version = "1.0.125", features = ["derive"] }
-serde_json = "1.0.59"
+serde_json.workspace = true
termcolor = "1.2.0"
termize = "0.2"
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[target.'cfg(windows)'.dependencies.windows]
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 43ce886..96a4ed3 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -577,6 +577,29 @@ pub fn downgrade_to_delayed_bug(&mut self) {
self.level = Level::DelayedBug;
}
+ /// Make emitting this diagnostic fatal
+ ///
+ /// Changes the level of this diagnostic to Fatal, and importantly also changes the emission guarantee.
+ /// This is sound for errors that would otherwise be printed, but now simply exit the process instead.
+ /// This function still gives an emission guarantee, the guarantee is now just that it exits fatally.
+ /// For delayed bugs this is different, since those are buffered. If we upgrade one to fatal, another
+ /// might now be ignored.
+ #[rustc_lint_diagnostics]
+ #[track_caller]
+ pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
+ assert!(
+ matches!(self.level, Level::Error),
+ "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
+ self.level
+ );
+ self.level = Level::Fatal;
+
+ // Take is okay since we immediately rewrap it in another diagnostic.
+ // i.e. we do emit it despite defusing the original diagnostic's drop bomb.
+ let diag = self.diag.take();
+ Diag { dcx: self.dcx, diag, _marker: PhantomData }
+ }
+
with_fn! { with_span_label,
/// Appends a labeled span to the diagnostic.
///
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 749bba5..b94370e 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1462,7 +1462,7 @@ fn emit_messages_default_inner(
max_line_num_len: usize,
is_secondary: bool,
is_cont: bool,
- ) -> io::Result<()> {
+ ) -> io::Result<CodeWindowStatus> {
let mut buffer = StyledBuffer::new();
if !msp.has_primary_spans() && !msp.has_span_labels() && is_secondary && !self.short_message
@@ -1575,12 +1575,14 @@ fn emit_messages_default_inner(
}
let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp);
trace!("{annotated_files:#?}");
+ let mut code_window_status = CodeWindowStatus::Open;
// Make sure our primary file comes first
let primary_span = msp.primary_span().unwrap_or_default();
let (Some(sm), false) = (self.sm.as_ref(), primary_span.is_dummy()) else {
// If we don't have span information, emit and exit
- return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message);
+ return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)
+ .map(|_| code_window_status);
};
let primary_lo = sm.lookup_char_pos(primary_span.lo());
if let Ok(pos) =
@@ -1589,6 +1591,9 @@ fn emit_messages_default_inner(
annotated_files.swap(0, pos);
}
+ // An end column separator should be emitted when a file with with a
+ // source, is followed by one without a source
+ let mut col_sep_before_no_show_source = false;
let annotated_files_len = annotated_files.len();
// Print out the annotate source lines that correspond with the error
for (file_idx, annotated_file) in annotated_files.into_iter().enumerate() {
@@ -1599,6 +1604,26 @@ fn emit_messages_default_inner(
&annotated_file.file,
) {
if !self.short_message {
+ // Add an end column separator when a file without a source
+ // comes after one with a source
+ // ╭▸ $DIR/deriving-meta-unknown-trait.rs:1:10
+ // │
+ // LL │ #[derive(Eqr)]
+ // │ ━━━
+ // ╰╴ (<- It prints *this* line)
+ // ╭▸ $SRC_DIR/core/src/cmp.rs:356:0
+ // │
+ // ╰╴note: similarly named derive macro `Eq` defined here
+ if col_sep_before_no_show_source {
+ let buffer_msg_line_offset = buffer.num_lines();
+ self.draw_col_separator_end(
+ &mut buffer,
+ buffer_msg_line_offset,
+ max_line_num_len + 1,
+ );
+ }
+ col_sep_before_no_show_source = false;
+
// We'll just print an unannotated message.
for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
let mut annotations = line.annotations.clone();
@@ -1639,29 +1664,42 @@ fn emit_messages_default_inner(
}
line_idx += 1;
}
- for (label, is_primary) in labels.into_iter() {
+ if is_cont
+ && file_idx == annotated_files_len - 1
+ && annotation_id == annotated_file.lines.len() - 1
+ && !labels.is_empty()
+ {
+ code_window_status = CodeWindowStatus::Closed;
+ }
+ let labels_len = labels.len();
+ for (label_idx, (label, is_primary)) in labels.into_iter().enumerate() {
let style = if is_primary {
Style::LabelPrimary
} else {
Style::LabelSecondary
};
- let pipe = self.col_separator();
- buffer.prepend(line_idx, &format!(" {pipe}"), Style::LineNumber);
- for _ in 0..max_line_num_len {
- buffer.prepend(line_idx, " ", Style::NoStyle);
- }
+ self.draw_col_separator_no_space(
+ &mut buffer,
+ line_idx,
+ max_line_num_len + 1,
+ );
line_idx += 1;
- let chr = self.note_separator();
- buffer.append(line_idx, &format!(" {chr} note: "), style);
- for _ in 0..max_line_num_len {
- buffer.prepend(line_idx, " ", Style::NoStyle);
- }
+ self.draw_note_separator(
+ &mut buffer,
+ line_idx,
+ max_line_num_len + 1,
+ label_idx != labels_len - 1,
+ );
+ buffer.append(line_idx, "note", Style::MainHeaderMsg);
+ buffer.append(line_idx, ": ", Style::NoStyle);
buffer.append(line_idx, label, style);
line_idx += 1;
}
}
}
continue;
+ } else {
+ col_sep_before_no_show_source = true;
}
// print out the span location and spacer before we print the annotated source
@@ -1976,7 +2014,7 @@ fn emit_messages_default_inner(
// final step: take our styled buffer, render it, then output it
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
- Ok(())
+ Ok(code_window_status)
}
fn column_width(&self, code_offset: usize) -> usize {
@@ -2491,7 +2529,7 @@ fn emit_messages_default(
!children.is_empty()
|| suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden),
) {
- Ok(()) => {
+ Ok(code_window_status) => {
if !children.is_empty()
|| suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden)
{
@@ -2502,7 +2540,7 @@ fn emit_messages_default(
{
// We'll continue the vertical bar to point into the next note.
self.draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1);
- } else {
+ } else if matches!(code_window_status, CodeWindowStatus::Open) {
// We'll close the vertical bar to visually end the code window.
self.draw_col_separator_end(&mut buffer, 0, max_line_num_len + 1);
}
@@ -2829,10 +2867,11 @@ fn col_separator(&self) -> char {
}
}
- fn note_separator(&self) -> char {
+ fn note_separator(&self, is_cont: bool) -> &'static str {
match self.theme {
- OutputTheme::Ascii => '=',
- OutputTheme::Unicode => '╰',
+ OutputTheme::Ascii => "= ",
+ OutputTheme::Unicode if is_cont => "├ ",
+ OutputTheme::Unicode => "╰ ",
}
}
@@ -2945,11 +2984,7 @@ fn draw_note_separator(
col: usize,
is_cont: bool,
) {
- let chr = match self.theme {
- OutputTheme::Ascii => "= ",
- OutputTheme::Unicode if is_cont => "├ ",
- OutputTheme::Unicode => "╰ ",
- };
+ let chr = self.note_separator(is_cont);
buffer.puts(line, col, chr, Style::LineNumber);
}
@@ -3050,6 +3085,12 @@ enum DisplaySuggestion {
Add,
}
+#[derive(Clone, Copy, Debug)]
+enum CodeWindowStatus {
+ Closed,
+ Open,
+}
+
impl FileWithAnnotatedLines {
/// Preprocess all the annotations so that they are grouped by file and by line number
/// This helps us quickly iterate over the whole message (including secondary file spans)
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 38c5716..71fc54f 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -61,7 +61,6 @@
fallback_fluent_bundle, fluent_bundle, into_diag_arg_using_display,
};
use rustc_hashes::Hash128;
-use rustc_hir_id::HirId;
pub use rustc_lint_defs::{Applicability, listify, pluralize};
use rustc_lint_defs::{Lint, LintExpectationId};
use rustc_macros::{Decodable, Encodable};
@@ -110,13 +109,14 @@
/// Used to avoid depending on `rustc_middle` in `rustc_attr_parsing`.
/// Always the `TyCtxt`.
pub trait LintEmitter: Copy {
+ type Id: Copy;
#[track_caller]
fn emit_node_span_lint(
self,
lint: &'static Lint,
- hir_id: HirId,
+ hir_id: Self::Id,
span: impl Into<MultiSpan>,
- decorator: impl for<'a> LintDiagnostic<'a, ()>,
+ decorator: impl for<'a> LintDiagnostic<'a, ()> + DynSend + 'static,
);
}
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index f897833..9bb7143 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -29,6 +29,6 @@
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 012bfe2..dbb4a9d 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -7,12 +7,12 @@
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
use rustc_ast::{
- self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, CRATE_NODE_ID,
- DUMMY_NODE_ID, ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle,
- MetaItemInner, MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token,
+ self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, DUMMY_NODE_ID,
+ ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner,
+ MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token,
};
use rustc_ast_pretty::pprust;
-use rustc_attr_parsing::{AttributeParser, EvalConfigResult, ShouldEmit, validate_attr};
+use rustc_attr_parsing::{AttributeParser, Early, EvalConfigResult, ShouldEmit, validate_attr};
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::PResult;
@@ -2165,7 +2165,7 @@ fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
None,
Target::MacroCall,
call.span(),
- CRATE_NODE_ID,
+ self.cx.current_expansion.lint_node_id,
Some(self.cx.ecfg.features),
ShouldEmit::ErrorsAndLints,
);
@@ -2184,7 +2184,9 @@ fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
self.cx.current_expansion.lint_node_id,
BuiltinLintDiag::UnusedDocComment(attr.span),
);
- } else if rustc_attr_parsing::is_builtin_attr(attr) {
+ } else if rustc_attr_parsing::is_builtin_attr(attr)
+ && !AttributeParser::<Early>::is_parsed_attribute(&attr.path())
+ {
let attr_name = attr.ident().unwrap().name;
// `#[cfg]` and `#[cfg_attr]` are special - they are
// eagerly evaluated.
diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml
index a4746ac..b58f237 100644
--- a/compiler/rustc_feature/Cargo.toml
+++ b/compiler/rustc_feature/Cargo.toml
@@ -9,5 +9,5 @@
rustc_hir = { path = "../rustc_hir" }
rustc_span = { path = "../rustc_span" }
serde = { version = "1.0.125", features = ["derive"] }
-serde_json = "1.0.59"
+serde_json.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
index d7ef428..60afd9a 100644
--- a/compiler/rustc_fluent_macro/Cargo.toml
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -11,8 +11,8 @@
annotate-snippets = "0.11"
fluent-bundle = "0.16"
fluent-syntax = "0.12"
-proc-macro2 = "1"
-quote = "1"
+proc-macro2.workspace = true
+quote.workspace = true
syn = { version = "2", features = ["full"] }
unic-langid = { version = "0.9.0", features = ["macros"] }
# tidy-alphabetical-end
diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml
index 90a6aca..37970e8 100644
--- a/compiler/rustc_fs_util/Cargo.toml
+++ b/compiler/rustc_fs_util/Cargo.toml
@@ -5,5 +5,5 @@
[dependencies]
# tidy-alphabetical-start
-tempfile = "3.7.1"
+tempfile.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 1008a3e..e74fcfe 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -5,8 +5,8 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.9.1"
-odht = { version = "0.3.1", features = ["nightly"] }
+bitflags.workspace = true
+odht.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
@@ -21,6 +21,6 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index 2209b18..dd5565d 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -10,6 +10,7 @@
use rustc_span::def_id::DefId;
use rustc_span::hygiene::Transparency;
use rustc_span::{Ident, Span, Symbol};
+pub use rustc_target::spec::SanitizerSet;
use thin_vec::ThinVec;
use crate::attrs::pretty_printing::PrintAttribute;
@@ -247,6 +248,120 @@ fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
}
}
+/// Different ways that the PE Format can decorate a symbol name.
+/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type>
+#[derive(
+ Copy,
+ Clone,
+ Debug,
+ Encodable,
+ Decodable,
+ HashStable_Generic,
+ PartialEq,
+ Eq,
+ PrintAttribute
+)]
+pub enum PeImportNameType {
+ /// IMPORT_ORDINAL
+ /// Uses the ordinal (i.e., a number) rather than the name.
+ Ordinal(u16),
+ /// Same as IMPORT_NAME
+ /// Name is decorated with all prefixes and suffixes.
+ Decorated,
+ /// Same as IMPORT_NAME_NOPREFIX
+ /// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept.
+ NoPrefix,
+ /// Same as IMPORT_NAME_UNDECORATE
+ /// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all
+ /// trailing characters) are skipped.
+ Undecorated,
+}
+
+#[derive(
+ Copy,
+ Clone,
+ Debug,
+ PartialEq,
+ Eq,
+ PartialOrd,
+ Ord,
+ Hash,
+ Encodable,
+ Decodable,
+ PrintAttribute
+)]
+#[derive(HashStable_Generic)]
+pub enum NativeLibKind {
+ /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC)
+ Static {
+ /// Whether to bundle objects from static library into produced rlib
+ bundle: Option<bool>,
+ /// Whether to link static library without throwing any object files away
+ whole_archive: Option<bool>,
+ },
+ /// Dynamic library (e.g. `libfoo.so` on Linux)
+ /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
+ Dylib {
+ /// Whether the dynamic library will be linked only if it satisfies some undefined symbols
+ as_needed: Option<bool>,
+ },
+ /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
+ /// On Linux, it refers to a generated shared library stub.
+ RawDylib,
+ /// A macOS-specific kind of dynamic libraries.
+ Framework {
+ /// Whether the framework will be linked only if it satisfies some undefined symbols
+ as_needed: Option<bool>,
+ },
+ /// Argument which is passed to linker, relative order with libraries and other arguments
+ /// is preserved
+ LinkArg,
+
+ /// Module imported from WebAssembly
+ WasmImportModule,
+
+ /// The library kind wasn't specified, `Dylib` is currently used as a default.
+ Unspecified,
+}
+
+impl NativeLibKind {
+ pub fn has_modifiers(&self) -> bool {
+ match self {
+ NativeLibKind::Static { bundle, whole_archive } => {
+ bundle.is_some() || whole_archive.is_some()
+ }
+ NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
+ as_needed.is_some()
+ }
+ NativeLibKind::RawDylib
+ | NativeLibKind::Unspecified
+ | NativeLibKind::LinkArg
+ | NativeLibKind::WasmImportModule => false,
+ }
+ }
+
+ pub fn is_statically_included(&self) -> bool {
+ matches!(self, NativeLibKind::Static { .. })
+ }
+
+ pub fn is_dllimport(&self) -> bool {
+ matches!(
+ self,
+ NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
+ )
+ }
+}
+
+#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
+pub struct LinkEntry {
+ pub span: Span,
+ pub kind: NativeLibKind,
+ pub name: Symbol,
+ pub cfg: Option<CfgEntry>,
+ pub verbatim: Option<bool>,
+ pub import_name_type: Option<(PeImportNameType, Span)>,
+}
+
/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
@@ -366,6 +481,9 @@ pub enum AttributeKind {
/// Represents `#[coverage(..)]`.
Coverage(Span, CoverageAttrKind),
+ /// Represents `#[crate_name = ...]`
+ CrateName { name: Symbol, name_span: Span, attr_span: Span, style: AttrStyle },
+
/// Represents `#[custom_mir]`.
CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),
@@ -414,6 +532,9 @@ pub enum AttributeKind {
/// Represents `#[inline]` and `#[rustc_force_inline]`.
Inline(InlineAttr, Span),
+ /// Represents `#[link]`.
+ Link(ThinVec<LinkEntry>, Span),
+
/// Represents `#[link_name]`.
LinkName { name: Symbol, span: Span },
@@ -505,6 +626,12 @@ pub enum AttributeKind {
/// Represents `#[rustc_object_lifetime_default]`.
RustcObjectLifetimeDefault,
+ /// Represents `#[sanitize]`
+ ///
+ /// the on set and off set are distjoint since there's a third option: unset.
+ /// a node may not set the sanitizer setting in which case it inherits from parents.
+ Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span },
+
/// Represents `#[should_panic]`
ShouldPanic { reason: Option<Symbol>, span: Span },
diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
index 485ded3..3810bb6 100644
--- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
+++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
@@ -7,6 +7,11 @@ pub enum EncodeCrossCrate {
}
impl AttributeKind {
+ /// Whether this attribute should be encoded in metadata files.
+ ///
+ /// If this is "Yes", then another crate can do `tcx.get_all_attrs(did)` for a did in this crate, and get the attribute.
+ /// When this is No, the attribute is filtered out while encoding and other crate won't be able to observe it.
+ /// This can be unexpectedly good for performance, so unless necessary for cross-crate compilation, prefer No.
pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
use AttributeKind::*;
use EncodeCrossCrate::*;
@@ -31,6 +36,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
ConstTrait(..) => No,
Coroutine(..) => No,
Coverage(..) => No,
+ CrateName { .. } => No,
CustomMir(_, _, _) => Yes,
DenyExplicitImpl(..) => No,
Deprecation { .. } => Yes,
@@ -44,6 +50,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
Fundamental { .. } => Yes,
Ignore { .. } => No,
Inline(..) => No,
+ Link(..) => No,
LinkName { .. } => Yes, // Needed for rustdoc
LinkOrdinal { .. } => No,
LinkSection { .. } => Yes, // Needed for rustdoc
@@ -73,6 +80,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcObjectLifetimeDefault => No,
+ Sanitize { .. } => No,
ShouldPanic { .. } => No,
SkipDuringMethodDispatch { .. } => No,
SpecializationTrait(..) => No,
diff --git a/compiler/rustc_hir/src/attrs/pretty_printing.rs b/compiler/rustc_hir/src/attrs/pretty_printing.rs
index e44b291..e65de25 100644
--- a/compiler/rustc_hir/src/attrs/pretty_printing.rs
+++ b/compiler/rustc_hir/src/attrs/pretty_printing.rs
@@ -6,6 +6,7 @@
use rustc_ast_pretty::pp::Printer;
use rustc_span::hygiene::Transparency;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
+use rustc_target::spec::SanitizerSet;
use thin_vec::ThinVec;
/// This trait is used to print attributes in `rustc_hir_pretty`.
@@ -146,4 +147,14 @@ fn print_attribute(&self, p: &mut Printer) {
print_tup!(A B C D E F G H);
print_skip!(Span, (), ErrorGuaranteed);
print_disp!(u16, bool, NonZero<u32>);
-print_debug!(Symbol, Ident, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
+print_debug!(
+ Symbol,
+ Ident,
+ UintTy,
+ IntTy,
+ Align,
+ AttrStyle,
+ CommentKind,
+ Transparency,
+ SanitizerSet,
+);
diff --git a/compiler/rustc_hir/src/lints.rs b/compiler/rustc_hir/src/lints.rs
index 061ec78..0b24052 100644
--- a/compiler/rustc_hir/src/lints.rs
+++ b/compiler/rustc_hir/src/lints.rs
@@ -35,4 +35,5 @@ pub enum AttributeLintKind {
IllFormedAttributeInput { suggestions: Vec<String> },
EmptyAttribute { first_span: Span },
InvalidTarget { name: AttrPath, target: Target, applied: Vec<String>, only: &'static str },
+ InvalidStyle { name: AttrPath, is_used_as_inner: bool, target: Target, target_span: Span },
}
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index e501779..bb86beb 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -9,7 +9,7 @@
[dependencies]
# tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
@@ -29,5 +29,5 @@
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 2428c1a..06f2ec5 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -509,10 +509,6 @@
hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait
-hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`
- .note = consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
- .opaque = this opaque type is supposed to be constrained
-
hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
hir_analysis_too_large_static = extern static is too large for the target architecture
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index c88c534..e27e68d 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -202,14 +202,10 @@ pub fn structurally_normalize_ty(
Some((normalized_ty, ocx.into_pending_obligations()))
}
- /// Returns the final type we ended up with, which may be an inference
- /// variable (we will resolve it first, if we want).
- pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> {
- if resolve {
- self.infcx.resolve_vars_if_possible(self.state.cur_ty)
- } else {
- self.state.cur_ty
- }
+ /// Returns the final type we ended up with, which may be an unresolved
+ /// inference variable.
+ pub fn final_ty(&self) -> Ty<'tcx> {
+ self.state.cur_ty
}
pub fn step_count(&self) -> usize {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 161a856..eccb88a 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -2053,3 +2053,29 @@ pub(super) fn check_coroutine_obligations(
Ok(())
}
+
+pub(super) fn check_potentially_region_dependent_goals<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+) -> Result<(), ErrorGuaranteed> {
+ if !tcx.next_trait_solver_globally() {
+ return Ok(());
+ }
+ let typeck_results = tcx.typeck(def_id);
+ let param_env = tcx.param_env(def_id);
+
+ // We use `TypingMode::Borrowck` as we want to use the opaque types computed by HIR typeck.
+ let typing_mode = TypingMode::borrowck(tcx, def_id);
+ let infcx = tcx.infer_ctxt().ignoring_regions().build(typing_mode);
+ let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
+ for (predicate, cause) in &typeck_results.potentially_region_dependent_goals {
+ let predicate = fold_regions(tcx, *predicate, |_, _| {
+ infcx.next_region_var(RegionVariableOrigin::Misc(cause.span))
+ });
+ ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
+ }
+
+ let errors = ocx.select_all_or_error();
+ debug!(?errors);
+ if errors.is_empty() { Ok(()) } else { Err(infcx.err_ctxt().report_fulfillment_errors(errors)) }
+}
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 85445cb..2e4b151 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -109,6 +109,7 @@ pub(super) fn provide(providers: &mut Providers) {
collect_return_position_impl_trait_in_trait_tys,
compare_impl_item: compare_impl_item::compare_impl_item,
check_coroutine_obligations: check::check_coroutine_obligations,
+ check_potentially_region_dependent_goals: check::check_potentially_region_dependent_goals,
check_type_wf: wfcheck::check_type_wf,
check_well_formed: wfcheck::check_well_formed,
..*providers
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 50e20a1..b6d8988 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -4,9 +4,10 @@
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, DefiningScopeKind, Ty, TyCtxt, TypeVisitableExt};
+use rustc_trait_selection::opaque_types::report_item_does_not_constrain_error;
use tracing::{debug, instrument, trace};
-use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType};
+use crate::errors::UnconstrainedOpaqueType;
/// Checks "defining uses" of opaque `impl Trait` in associated types.
/// These can only be defined by associated items of the same trait.
@@ -127,14 +128,11 @@ fn insert_found(&mut self, hidden_ty: ty::OpaqueHiddenType<'tcx>) {
}
fn non_defining_use_in_defining_scope(&mut self, item_def_id: LocalDefId) {
- let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 {
- span: self
- .tcx
- .def_ident_span(item_def_id)
- .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
- opaque_type_span: self.tcx.def_span(self.def_id),
- opaque_type: self.tcx.def_path_str(self.def_id),
- });
+ // We make sure that all opaque types get defined while
+ // type checking the defining scope, so this error is unreachable
+ // with the new solver.
+ assert!(!self.tcx.next_trait_solver_globally());
+ let guar = report_item_does_not_constrain_error(self.tcx, item_def_id, self.def_id, None);
self.insert_found(ty::OpaqueHiddenType::new_error(self.tcx, guar));
}
@@ -252,9 +250,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
} else if let Some(hidden_ty) = tables.concrete_opaque_types.get(&def_id) {
hidden_ty.ty
} else {
- // FIXME(-Znext-solver): This should not be necessary and we should
- // instead rely on inference variable fallback inside of typeck itself.
-
+ assert!(!tcx.next_trait_solver_globally());
// We failed to resolve the opaque type or it
// resolves to itself. We interpret this as the
// no values of the hidden type ever being constructed,
@@ -273,6 +269,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
if let Err(guar) = hir_ty.error_reported() {
Ty::new_error(tcx, guar)
} else {
+ assert!(!tcx.next_trait_solver_globally());
hir_ty
}
}
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 26a9872..6565ad7 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -410,17 +410,6 @@ pub(crate) struct UnconstrainedOpaqueType {
pub what: &'static str,
}
-#[derive(Diagnostic)]
-#[diag(hir_analysis_tait_forward_compat2)]
-#[note]
-pub(crate) struct TaitForwardCompat2 {
- #[primary_span]
- pub span: Span,
- #[note(hir_analysis_opaque)]
- pub opaque_type_span: Span,
- pub opaque_type: String,
-}
-
pub(crate) struct MissingTypeParams {
pub span: Span,
pub def_span: Span,
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 3a153ab..44a5cee 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -82,7 +82,7 @@
mod collect;
mod constrained_generic_params;
mod delegation;
-mod errors;
+pub mod errors;
pub mod hir_ty_lowering;
pub mod hir_wf_check;
mod impl_wf_check;
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index f00125c..5af0c61 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
@@ -25,5 +25,5 @@
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs
index 7af2662..4fe7727 100644
--- a/compiler/rustc_hir_typeck/src/autoderef.rs
+++ b/compiler/rustc_hir_typeck/src/autoderef.rs
@@ -42,7 +42,7 @@ pub(crate) fn adjust_steps_as_infer_ok(
let mut obligations = PredicateObligations::new();
let targets =
- steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
+ steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty()));
let steps: Vec<_> = steps
.iter()
.map(|&(source, kind)| {
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 7afc555..c6a4d78 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -86,7 +86,7 @@ pub(crate) fn check_expr_call(
result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
}
- match autoderef.final_ty(false).kind() {
+ match autoderef.final_ty().kind() {
ty::FnDef(def_id, _) => {
let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi;
self.check_call_abi(abi, call_expr.span);
@@ -200,8 +200,7 @@ fn try_overloaded_call_step(
arg_exprs: &'tcx [hir::Expr<'tcx>],
autoderef: &Autoderef<'a, 'tcx>,
) -> Option<CallStep<'tcx>> {
- let adjusted_ty =
- self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
+ let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
// If the callee is a function pointer or a closure, then we're all set.
match *adjusted_ty.kind() {
@@ -511,7 +510,9 @@ fn confirm_builtin_call(
// Untranslatable diagnostics are okay for rustc internals
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
- if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) {
+ if self.has_rustc_attrs
+ && self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses)
+ {
let predicates = self.tcx.predicates_of(def_id);
let predicates = predicates.instantiate(self.tcx, args);
for (predicate, predicate_span) in predicates {
@@ -894,7 +895,7 @@ pub(super) fn enforce_context_effects(
}
// If we have `rustc_do_not_const_check`, do not check `[const]` bounds.
- if self.tcx.has_attr(self.body_id, sym::rustc_do_not_const_check) {
+ if self.has_rustc_attrs && self.tcx.has_attr(self.body_id, sym::rustc_do_not_const_check) {
return;
}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 940f0e3..a652e08 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2918,7 +2918,7 @@ fn check_expr_field(
// Emits an error if we deref an infer variable, like calling `.field` on a base type
// of `&_`. We can also use this to suppress unnecessary "missing field" errors that
// will follow ambiguity errors.
- let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
+ let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
if let ty::Error(_) = final_ty.kind() {
return final_ty;
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 0c6226c..74f27e8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -126,6 +126,10 @@ pub(crate) struct FnCtxt<'a, 'tcx> {
/// These are stored here so we may collect them when canonicalizing user
/// type ascriptions later.
pub(super) trait_ascriptions: RefCell<ItemLocalMap<Vec<ty::Clause<'tcx>>>>,
+
+ /// Whether the current crate enables the `rustc_attrs` feature.
+ /// This allows to skip processing attributes in many places.
+ pub(super) has_rustc_attrs: bool,
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -154,6 +158,7 @@ pub(crate) fn new(
diverging_fallback_behavior,
diverging_block_behavior,
trait_ascriptions: Default::default(),
+ has_rustc_attrs: root_ctxt.tcx.features().rustc_attrs(),
}
}
@@ -525,10 +530,13 @@ fn parse_never_type_options_attr(
let mut fallback = None;
let mut block = None;
- let items = tcx
- .get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
- .map(|attr| attr.meta_item_list().unwrap())
- .unwrap_or_default();
+ let items = if tcx.features().rustc_attrs() {
+ tcx.get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
+ .map(|attr| attr.meta_item_list().unwrap())
+ } else {
+ None
+ };
+ let items = items.unwrap_or_default();
for item in items {
if item.has_name(sym::fallback) && fallback.is_none() {
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index ab4181f..129de32 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -46,14 +46,14 @@
use rustc_errors::codes::*;
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
use rustc_hir as hir;
-use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{HirId, HirIdMap, Node, find_attr};
+use rustc_hir::{HirId, HirIdMap, Node};
use rustc_hir_analysis::check::{check_abi, check_custom_abi};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::config;
use rustc_span::Span;
@@ -174,7 +174,7 @@ fn typeck_with_inspect<'tcx>(
.map(|(idx, ty)| fcx.normalize(arg_span(idx), ty)),
);
- if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Naked(..)) {
+ if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED) {
naked_functions::typeck_naked_fn(tcx, def_id, body);
}
@@ -247,6 +247,13 @@ fn typeck_with_inspect<'tcx>(
debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
+ // We need to handle opaque types before emitting ambiguity errors as applying
+ // defining uses may guide type inference.
+ if fcx.next_trait_solver() {
+ fcx.handle_opaque_type_uses_next();
+ }
+
+ fcx.select_obligations_where_possible(|_| {});
if let None = fcx.infcx.tainted_by_errors() {
fcx.report_ambiguity_errors();
}
@@ -255,21 +262,6 @@ fn typeck_with_inspect<'tcx>(
let typeck_results = fcx.resolve_type_vars_in_body(body);
- // Handle potentially region dependent goals, see `InferCtxt::in_hir_typeck`.
- if let None = fcx.infcx.tainted_by_errors() {
- for obligation in fcx.take_hir_typeck_potentially_region_dependent_goals() {
- let obligation = fcx.resolve_vars_if_possible(obligation);
- if obligation.has_non_region_infer() {
- bug!("unexpected inference variable after writeback: {obligation:?}");
- }
- fcx.register_predicate(obligation);
- }
- fcx.select_obligations_where_possible(|_| {});
- if let None = fcx.infcx.tainted_by_errors() {
- fcx.report_ambiguity_errors();
- }
- }
-
fcx.detect_opaque_types_added_during_writeback();
// Consistency check our TypeckResults instance can hold all ItemLocalIds
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 3ca3b56..ab584eb 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -629,7 +629,7 @@ pub(crate) fn method_autoderef_steps<'tcx>(
.collect();
(steps, autoderef_via_deref.reached_recursion_limit())
};
- let final_ty = autoderef_via_deref.final_ty(true);
+ let final_ty = autoderef_via_deref.final_ty();
let opt_bad_ty = match final_ty.kind() {
ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
reached_raw_pointer,
@@ -777,31 +777,16 @@ fn assemble_probe(
self.assemble_inherent_candidates_from_object(generalized_self_ty);
self.assemble_inherent_impl_candidates_for_type(p.def_id(), receiver_steps);
- if self.tcx.has_attr(p.def_id(), sym::rustc_has_incoherent_inherent_impls) {
- self.assemble_inherent_candidates_for_incoherent_ty(
- raw_self_ty,
- receiver_steps,
- );
- }
+ self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
}
ty::Adt(def, _) => {
let def_id = def.did();
self.assemble_inherent_impl_candidates_for_type(def_id, receiver_steps);
- if self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) {
- self.assemble_inherent_candidates_for_incoherent_ty(
- raw_self_ty,
- receiver_steps,
- );
- }
+ self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
}
ty::Foreign(did) => {
self.assemble_inherent_impl_candidates_for_type(did, receiver_steps);
- if self.tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
- self.assemble_inherent_candidates_for_incoherent_ty(
- raw_self_ty,
- receiver_steps,
- );
- }
+ self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
}
ty::Param(_) => {
self.assemble_inherent_candidates_from_param(raw_self_ty);
@@ -909,6 +894,10 @@ fn assemble_inherent_candidates_from_param(&mut self, param_ty: Ty<'tcx>) {
debug_assert_matches!(param_ty.kind(), ty::Param(_));
let tcx = self.tcx;
+
+ // We use `DeepRejectCtxt` here which may return false positive on where clauses
+ // with alias self types. We need to later on reject these as inherent candidates
+ // in `consider_probe`.
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
@@ -1945,6 +1934,29 @@ fn consider_probe(
);
(xform_self_ty, xform_ret_ty) =
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
+
+ if matches!(probe.kind, WhereClauseCandidate(_)) {
+ // `WhereClauseCandidate` requires that the self type is a param,
+ // because it has special behavior with candidate preference as an
+ // inherent pick.
+ match ocx.structurally_normalize_ty(
+ cause,
+ self.param_env,
+ trait_ref.self_ty(),
+ ) {
+ Ok(ty) => {
+ if !matches!(ty.kind(), ty::Param(_)) {
+ debug!("--> not a param ty: {xform_self_ty:?}");
+ return ProbeResult::NoMatch;
+ }
+ }
+ Err(errors) => {
+ debug!("--> cannot relate self-types {:?}", errors);
+ return ProbeResult::NoMatch;
+ }
+ }
+ }
+
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
match ocx.relate(cause, self.param_env, self.variance(), self_ty, xform_self_ty)
{
@@ -2373,17 +2385,14 @@ fn matches_by_doc_alias(&self, def_id: DefId) -> bool {
if !self.is_relevant_kind_for_mode(x.kind) {
return false;
}
- if self.matches_by_doc_alias(x.def_id) {
- return true;
- }
- match edit_distance_with_substrings(
+ if let Some(d) = edit_distance_with_substrings(
name.as_str(),
x.name().as_str(),
max_dist,
) {
- Some(d) => d > 0,
- None => false,
+ return d > 0;
}
+ self.matches_by_doc_alias(x.def_id)
})
.copied()
.collect()
diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs
index e0224f8..97feac3 100644
--- a/compiler/rustc_hir_typeck/src/opaque_types.rs
+++ b/compiler/rustc_hir_typeck/src/opaque_types.rs
@@ -1,5 +1,218 @@
-use super::FnCtxt;
+use rustc_hir::def::DefKind;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::ty::{
+ self, DefiningScopeKind, EarlyBinder, OpaqueHiddenType, OpaqueTypeKey, TypeVisitableExt,
+ TypingMode,
+};
+use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
+use rustc_trait_selection::opaque_types::{
+ NonDefiningUseReason, opaque_type_has_defining_use_args, report_item_does_not_constrain_error,
+};
+use rustc_trait_selection::solve;
+use tracing::{debug, instrument};
+
+use crate::FnCtxt;
+
impl<'tcx> FnCtxt<'_, 'tcx> {
+ /// This takes all the opaque type uses during HIR typeck. It first computes
+ /// the concrete hidden type by iterating over all defining uses.
+ ///
+ /// A use during HIR typeck is defining if all non-lifetime arguments are
+ /// unique generic parameters and the hidden type does not reference any
+ /// inference variables.
+ ///
+ /// It then uses these defining uses to guide inference for all other uses.
+ #[instrument(level = "debug", skip(self))]
+ pub(super) fn handle_opaque_type_uses_next(&mut self) {
+ // We clone the opaques instead of stealing them here as they are still used for
+ // normalization in the next generation trait solver.
+ let mut opaque_types: Vec<_> = self.infcx.clone_opaque_types();
+ let num_entries = self.inner.borrow_mut().opaque_types().num_entries();
+ let prev = self.checked_opaque_types_storage_entries.replace(Some(num_entries));
+ debug_assert_eq!(prev, None);
+ for entry in &mut opaque_types {
+ *entry = self.resolve_vars_if_possible(*entry);
+ }
+ debug!(?opaque_types);
+
+ self.compute_concrete_opaque_types(&opaque_types);
+ self.apply_computed_concrete_opaque_types(&opaque_types);
+ }
+}
+
+enum UsageKind<'tcx> {
+ None,
+ NonDefiningUse(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>),
+ UnconstrainedHiddenType(OpaqueHiddenType<'tcx>),
+ HasDefiningUse,
+}
+
+impl<'tcx> UsageKind<'tcx> {
+ fn merge(&mut self, other: UsageKind<'tcx>) {
+ match (&*self, &other) {
+ (UsageKind::HasDefiningUse, _) | (_, UsageKind::None) => unreachable!(),
+ (UsageKind::None, _) => *self = other,
+ // When mergining non-defining uses, prefer earlier ones. This means
+ // the error happens as early as possible.
+ (
+ UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
+ UsageKind::NonDefiningUse(..),
+ ) => {}
+ // When merging unconstrained hidden types, we prefer later ones. This is
+ // used as in most cases, the defining use is the final return statement
+ // of our function, and other uses with defining arguments are likely not
+ // intended to be defining.
+ (
+ UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
+ UsageKind::UnconstrainedHiddenType(..) | UsageKind::HasDefiningUse,
+ ) => *self = other,
+ }
+ }
+}
+
+impl<'tcx> FnCtxt<'_, 'tcx> {
+ fn compute_concrete_opaque_types(
+ &mut self,
+ opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
+ ) {
+ let tcx = self.tcx;
+ let TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
+ else {
+ unreachable!();
+ };
+
+ for def_id in defining_opaque_types_and_generators {
+ match tcx.def_kind(def_id) {
+ DefKind::OpaqueTy => {}
+ DefKind::Closure => continue,
+ _ => unreachable!("not opaque or generator: {def_id:?}"),
+ }
+
+ let mut usage_kind = UsageKind::None;
+ for &(opaque_type_key, hidden_type) in opaque_types {
+ if opaque_type_key.def_id != def_id {
+ continue;
+ }
+
+ usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type));
+ if let UsageKind::HasDefiningUse = usage_kind {
+ break;
+ }
+ }
+
+ let guar = match usage_kind {
+ UsageKind::None => {
+ if let Some(guar) = self.tainted_by_errors() {
+ guar
+ } else {
+ report_item_does_not_constrain_error(self.tcx, self.body_id, def_id, None)
+ }
+ }
+ UsageKind::NonDefiningUse(opaque_type_key, hidden_type) => {
+ report_item_does_not_constrain_error(
+ self.tcx,
+ self.body_id,
+ def_id,
+ Some((opaque_type_key, hidden_type.span)),
+ )
+ }
+ UsageKind::UnconstrainedHiddenType(hidden_type) => {
+ let infer_var = hidden_type
+ .ty
+ .walk()
+ .filter_map(ty::GenericArg::as_term)
+ .find(|term| term.is_infer())
+ .unwrap_or_else(|| hidden_type.ty.into());
+ self.err_ctxt()
+ .emit_inference_failure_err(
+ self.body_id,
+ hidden_type.span,
+ infer_var,
+ TypeAnnotationNeeded::E0282,
+ false,
+ )
+ .emit()
+ }
+ UsageKind::HasDefiningUse => continue,
+ };
+
+ self.typeck_results
+ .borrow_mut()
+ .concrete_opaque_types
+ .insert(def_id, OpaqueHiddenType::new_error(tcx, guar));
+ self.set_tainted_by_errors(guar);
+ }
+ }
+
+ fn consider_opaque_type_use(
+ &mut self,
+ opaque_type_key: OpaqueTypeKey<'tcx>,
+ hidden_type: OpaqueHiddenType<'tcx>,
+ ) -> UsageKind<'tcx> {
+ if let Err(err) = opaque_type_has_defining_use_args(
+ &self,
+ opaque_type_key,
+ hidden_type.span,
+ DefiningScopeKind::HirTypeck,
+ ) {
+ match err {
+ NonDefiningUseReason::Tainted(guar) => {
+ self.typeck_results.borrow_mut().concrete_opaque_types.insert(
+ opaque_type_key.def_id,
+ OpaqueHiddenType::new_error(self.tcx, guar),
+ );
+ return UsageKind::HasDefiningUse;
+ }
+ _ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
+ };
+ }
+
+ // We ignore uses of the opaque if they have any inference variables
+ // as this can frequently happen with recursive calls.
+ //
+ // See `tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs`.
+ if hidden_type.ty.has_non_region_infer() {
+ return UsageKind::UnconstrainedHiddenType(hidden_type);
+ }
+
+ let cause = ObligationCause::misc(hidden_type.span, self.body_id);
+ let at = self.at(&cause, self.param_env);
+ let hidden_type = match solve::deeply_normalize(at, hidden_type) {
+ Ok(hidden_type) => hidden_type,
+ Err(errors) => {
+ let guar = self.err_ctxt().report_fulfillment_errors(errors);
+ OpaqueHiddenType::new_error(self.tcx, guar)
+ }
+ };
+ let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
+ opaque_type_key,
+ self.tcx,
+ DefiningScopeKind::HirTypeck,
+ );
+
+ let prev = self
+ .typeck_results
+ .borrow_mut()
+ .concrete_opaque_types
+ .insert(opaque_type_key.def_id, hidden_type);
+ assert!(prev.is_none());
+ UsageKind::HasDefiningUse
+ }
+
+ fn apply_computed_concrete_opaque_types(
+ &mut self,
+ opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
+ ) {
+ let tcx = self.tcx;
+ for &(key, hidden_type) in opaque_types {
+ let expected =
+ *self.typeck_results.borrow_mut().concrete_opaque_types.get(&key.def_id).unwrap();
+
+ let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
+ self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
+ }
+ }
+
/// We may in theory add further uses of an opaque after cloning the opaque
/// types storage during writeback when computing the defining uses.
///
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index fedc75a..1125e98 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -109,8 +109,7 @@ fn try_index_step(
index_ty: Ty<'tcx>,
index_expr: &hir::Expr<'_>,
) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> {
- let adjusted_ty =
- self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
+ let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
debug!(
"try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \
index_ty={:?})",
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 50fa3f2..06acff0 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1747,7 +1747,7 @@ fn place_for_root_variable(
}
fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool {
- self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis)
+ self.has_rustc_attrs && self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis)
}
fn log_capture_analysis_first_pass(
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 42736a0..d75bc9e 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -27,7 +27,7 @@
};
use rustc_span::{Span, sym};
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
-use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
+use rustc_trait_selection::opaque_types::opaque_type_has_defining_use_args;
use rustc_trait_selection::solve;
use tracing::{debug, instrument};
@@ -45,7 +45,8 @@ pub(crate) fn resolve_type_vars_in_body(
// This attribute causes us to dump some writeback information
// in the form of errors, which is used for unit tests.
- let rustc_dump_user_args = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_args);
+ let rustc_dump_user_args =
+ self.has_rustc_attrs && self.tcx.has_attr(item_def_id, sym::rustc_dump_user_args);
let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_args);
for param in body.params {
@@ -76,6 +77,7 @@ pub(crate) fn resolve_type_vars_in_body(
wbcx.visit_coroutine_interior();
wbcx.visit_transmutes();
wbcx.visit_offset_of_container_types();
+ wbcx.visit_potentially_region_dependent_goals();
wbcx.typeck_results.rvalue_scopes =
mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
@@ -545,8 +547,24 @@ fn visit_transmutes(&mut self) {
}
}
+ fn visit_opaque_types_next(&mut self) {
+ let mut fcx_typeck_results = self.fcx.typeck_results.borrow_mut();
+ assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
+ for hidden_ty in fcx_typeck_results.concrete_opaque_types.values() {
+ assert!(!hidden_ty.has_infer());
+ }
+
+ assert_eq!(self.typeck_results.concrete_opaque_types.len(), 0);
+ self.typeck_results.concrete_opaque_types =
+ mem::take(&mut fcx_typeck_results.concrete_opaque_types);
+ }
+
#[instrument(skip(self), level = "debug")]
fn visit_opaque_types(&mut self) {
+ if self.fcx.next_trait_solver() {
+ return self.visit_opaque_types_next();
+ }
+
let tcx = self.tcx();
// We clone the opaques instead of stealing them here as they are still used for
// normalization in the next generation trait solver.
@@ -557,17 +575,14 @@ fn visit_opaque_types(&mut self) {
for (opaque_type_key, hidden_type) in opaque_types {
let hidden_type = self.resolve(hidden_type, &hidden_type.span);
let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);
-
- if !self.fcx.next_trait_solver() {
- if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
- && alias_ty.def_id == opaque_type_key.def_id.to_def_id()
- && alias_ty.args == opaque_type_key.args
- {
- continue;
- }
+ if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
+ && alias_ty.def_id == opaque_type_key.def_id.to_def_id()
+ && alias_ty.args == opaque_type_key.args
+ {
+ continue;
}
- if let Err(err) = check_opaque_type_parameter_valid(
+ if let Err(err) = opaque_type_has_defining_use_args(
&self.fcx,
opaque_type_key,
hidden_type.span,
@@ -775,6 +790,32 @@ fn visit_offset_of_container_types(&mut self) {
}
}
+ fn visit_potentially_region_dependent_goals(&mut self) {
+ let obligations = self.fcx.take_hir_typeck_potentially_region_dependent_goals();
+ if let None = self.fcx.tainted_by_errors() {
+ for obligation in obligations {
+ let (predicate, mut cause) =
+ self.fcx.resolve_vars_if_possible((obligation.predicate, obligation.cause));
+ if predicate.has_non_region_infer() {
+ self.fcx.dcx().span_delayed_bug(
+ cause.span,
+ format!("unexpected inference variable after writeback: {predicate:?}"),
+ );
+ } else {
+ let predicate = self.tcx().erase_regions(predicate);
+ if cause.has_infer() || cause.has_placeholders() {
+ // We can't use the the obligation cause as it references
+ // information local to this query.
+ cause = self.fcx.misc(cause.span);
+ }
+ self.typeck_results
+ .potentially_region_dependent_goals
+ .insert((predicate, cause));
+ }
+ }
+ }
+ }
+
fn resolve<T>(&mut self, value: T, span: &dyn Locatable) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
@@ -896,6 +937,7 @@ fn report_error(&self, p: impl Into<ty::Term<'tcx>>) -> ErrorGuaranteed {
}
}
+ #[instrument(level = "debug", skip(self, outer_exclusive_binder, new_err))]
fn handle_term<T>(
&mut self,
value: T,
diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml
index db0a584..8d7f2eb 100644
--- a/compiler/rustc_incremental/Cargo.toml
+++ b/compiler/rustc_incremental/Cargo.toml
@@ -19,6 +19,6 @@
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 645d95b..684bd34 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -491,19 +491,15 @@ pub struct ChunkedBitSet<T> {
marker: PhantomData<T>,
}
-// Note: the chunk domain size is duplicated in each variant. This is a bit
-// inconvenient, but it allows the type size to be smaller than if we had an
-// outer struct containing a chunk domain size plus the `Chunk`, because the
-// compiler can place the chunk domain size after the tag.
+// NOTE: The chunk size is computed on-the-fly on each manipulation of a chunk.
+// This avoids storing it, as it's almost always CHUNK_BITS except for the last one.
#[derive(Clone, Debug, PartialEq, Eq)]
enum Chunk {
/// A chunk that is all zeros; we don't represent the zeros explicitly.
- /// The `ChunkSize` is always non-zero.
- Zeros(ChunkSize),
+ Zeros,
/// A chunk that is all ones; we don't represent the ones explicitly.
- /// `ChunkSize` is always non-zero.
- Ones(ChunkSize),
+ Ones,
/// A chunk that has a mix of zeros and ones, which are represented
/// explicitly and densely. It never has all zeros or all ones.
@@ -514,16 +510,14 @@ enum Chunk {
/// to store the length, which would make this type larger. These excess
/// words are always zero, as are any excess bits in the final in-use word.
///
- /// The first `ChunkSize` field is always non-zero.
- ///
- /// The second `ChunkSize` field is the count of 1s set in the chunk, and
+ /// The `ChunkSize` field is the count of 1s set in the chunk, and
/// must satisfy `0 < count < chunk_domain_size`.
///
/// The words are within an `Rc` because it's surprisingly common to
/// duplicate an entire chunk, e.g. in `ChunkedBitSet::clone_from()`, or
/// when a `Mixed` chunk is union'd into a `Zeros` chunk. When we do need
/// to modify a chunk we use `Rc::make_mut`.
- Mixed(ChunkSize, ChunkSize, Rc<[Word; CHUNK_WORDS]>),
+ Mixed(ChunkSize, Rc<[Word; CHUNK_WORDS]>),
}
// This type is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -535,6 +529,22 @@ pub fn domain_size(&self) -> usize {
self.domain_size
}
+ #[inline]
+ fn last_chunk_size(&self) -> ChunkSize {
+ let n = self.domain_size % CHUNK_BITS;
+ if n == 0 { CHUNK_BITS as ChunkSize } else { n as ChunkSize }
+ }
+
+ /// All the chunks have a chunk_domain_size of `CHUNK_BITS` except the final one.
+ #[inline]
+ fn chunk_domain_size(&self, chunk: usize) -> ChunkSize {
+ if chunk == self.chunks.len() - 1 {
+ self.last_chunk_size()
+ } else {
+ CHUNK_BITS as ChunkSize
+ }
+ }
+
#[cfg(test)]
fn assert_valid(&self) {
if self.domain_size == 0 {
@@ -544,8 +554,9 @@ fn assert_valid(&self) {
assert!((self.chunks.len() - 1) * CHUNK_BITS <= self.domain_size);
assert!(self.chunks.len() * CHUNK_BITS >= self.domain_size);
- for chunk in self.chunks.iter() {
- chunk.assert_valid();
+ for (chunk_index, chunk) in self.chunks.iter().enumerate() {
+ let chunk_domain_size = self.chunk_domain_size(chunk_index);
+ chunk.assert_valid(chunk_domain_size);
}
}
}
@@ -556,16 +567,7 @@ fn new(domain_size: usize, is_empty: bool) -> Self {
let chunks = if domain_size == 0 {
Box::new([])
} else {
- // All the chunks have a chunk_domain_size of `CHUNK_BITS` except
- // the final one.
- let final_chunk_domain_size = {
- let n = domain_size % CHUNK_BITS;
- if n == 0 { CHUNK_BITS } else { n }
- };
- let mut chunks =
- vec![Chunk::new(CHUNK_BITS, is_empty); num_chunks(domain_size)].into_boxed_slice();
- *chunks.last_mut().unwrap() = Chunk::new(final_chunk_domain_size, is_empty);
- chunks
+ vec![if is_empty { Zeros } else { Ones }; num_chunks(domain_size)].into_boxed_slice()
};
ChunkedBitSet { domain_size, chunks, marker: PhantomData }
}
@@ -594,11 +596,15 @@ fn chunks(&self) -> &[Chunk] {
/// Count the number of bits in the set.
pub fn count(&self) -> usize {
- self.chunks.iter().map(|chunk| chunk.count()).sum()
+ self.chunks
+ .iter()
+ .enumerate()
+ .map(|(index, chunk)| chunk.count(self.chunk_domain_size(index)))
+ .sum()
}
pub fn is_empty(&self) -> bool {
- self.chunks.iter().all(|chunk| matches!(chunk, Zeros(..)))
+ self.chunks.iter().all(|chunk| matches!(chunk, Zeros))
}
/// Returns `true` if `self` contains `elem`.
@@ -607,9 +613,9 @@ pub fn contains(&self, elem: T) -> bool {
assert!(elem.index() < self.domain_size);
let chunk = &self.chunks[chunk_index(elem)];
match &chunk {
- Zeros(_) => false,
- Ones(_) => true,
- Mixed(_, _, words) => {
+ Zeros => false,
+ Ones => true,
+ Mixed(_, words) => {
let (word_index, mask) = chunk_word_index_and_mask(elem);
(words[word_index] & mask) != 0
}
@@ -625,9 +631,10 @@ pub fn iter(&self) -> ChunkedBitIter<'_, T> {
pub fn insert(&mut self, elem: T) -> bool {
assert!(elem.index() < self.domain_size);
let chunk_index = chunk_index(elem);
+ let chunk_domain_size = self.chunk_domain_size(chunk_index);
let chunk = &mut self.chunks[chunk_index];
match *chunk {
- Zeros(chunk_domain_size) => {
+ Zeros => {
if chunk_domain_size > 1 {
#[cfg(feature = "nightly")]
let mut words = {
@@ -649,14 +656,14 @@ pub fn insert(&mut self, elem: T) -> bool {
let (word_index, mask) = chunk_word_index_and_mask(elem);
words_ref[word_index] |= mask;
- *chunk = Mixed(chunk_domain_size, 1, words);
+ *chunk = Mixed(1, words);
} else {
- *chunk = Ones(chunk_domain_size);
+ *chunk = Ones;
}
true
}
- Ones(_) => false,
- Mixed(chunk_domain_size, ref mut count, ref mut words) => {
+ Ones => false,
+ Mixed(ref mut count, ref mut words) => {
// We skip all the work if the bit is already set.
let (word_index, mask) = chunk_word_index_and_mask(elem);
if (words[word_index] & mask) == 0 {
@@ -665,7 +672,7 @@ pub fn insert(&mut self, elem: T) -> bool {
let words = Rc::make_mut(words);
words[word_index] |= mask;
} else {
- *chunk = Ones(chunk_domain_size);
+ *chunk = Ones;
}
true
} else {
@@ -678,11 +685,7 @@ pub fn insert(&mut self, elem: T) -> bool {
/// Sets all bits to true.
pub fn insert_all(&mut self) {
for chunk in self.chunks.iter_mut() {
- *chunk = match *chunk {
- Zeros(chunk_domain_size)
- | Ones(chunk_domain_size)
- | Mixed(chunk_domain_size, ..) => Ones(chunk_domain_size),
- }
+ *chunk = Ones;
}
}
@@ -690,10 +693,11 @@ pub fn insert_all(&mut self) {
pub fn remove(&mut self, elem: T) -> bool {
assert!(elem.index() < self.domain_size);
let chunk_index = chunk_index(elem);
+ let chunk_domain_size = self.chunk_domain_size(chunk_index);
let chunk = &mut self.chunks[chunk_index];
match *chunk {
- Zeros(_) => false,
- Ones(chunk_domain_size) => {
+ Zeros => false,
+ Ones => {
if chunk_domain_size > 1 {
#[cfg(feature = "nightly")]
let mut words = {
@@ -722,13 +726,13 @@ pub fn remove(&mut self, elem: T) -> bool {
);
let (word_index, mask) = chunk_word_index_and_mask(elem);
words_ref[word_index] &= !mask;
- *chunk = Mixed(chunk_domain_size, chunk_domain_size - 1, words);
+ *chunk = Mixed(chunk_domain_size - 1, words);
} else {
- *chunk = Zeros(chunk_domain_size);
+ *chunk = Zeros;
}
true
}
- Mixed(chunk_domain_size, ref mut count, ref mut words) => {
+ Mixed(ref mut count, ref mut words) => {
// We skip all the work if the bit is already clear.
let (word_index, mask) = chunk_word_index_and_mask(elem);
if (words[word_index] & mask) != 0 {
@@ -737,7 +741,7 @@ pub fn remove(&mut self, elem: T) -> bool {
let words = Rc::make_mut(words);
words[word_index] &= !mask;
} else {
- *chunk = Zeros(chunk_domain_size);
+ *chunk = Zeros
}
true
} else {
@@ -748,11 +752,12 @@ pub fn remove(&mut self, elem: T) -> bool {
}
fn chunk_iter(&self, chunk_index: usize) -> ChunkIter<'_> {
+ let chunk_domain_size = self.chunk_domain_size(chunk_index);
match self.chunks.get(chunk_index) {
- Some(Zeros(_chunk_domain_size)) => ChunkIter::Zeros,
- Some(Ones(chunk_domain_size)) => ChunkIter::Ones(0..*chunk_domain_size as usize),
- Some(Mixed(chunk_domain_size, _, words)) => {
- let num_words = num_words(*chunk_domain_size as usize);
+ Some(Zeros) => ChunkIter::Zeros,
+ Some(Ones) => ChunkIter::Ones(0..chunk_domain_size as usize),
+ Some(Mixed(_, words)) => {
+ let num_words = num_words(chunk_domain_size as usize);
ChunkIter::Mixed(BitIter::new(&words[0..num_words]))
}
None => ChunkIter::Finished,
@@ -765,23 +770,33 @@ fn chunk_iter(&self, chunk_index: usize) -> ChunkIter<'_> {
impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size);
- debug_assert_eq!(self.chunks.len(), other.chunks.len());
+
+ let num_chunks = self.chunks.len();
+ debug_assert_eq!(num_chunks, other.chunks.len());
+
+ let last_chunk_size = self.last_chunk_size();
+ debug_assert_eq!(last_chunk_size, other.last_chunk_size());
let mut changed = false;
- for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
+ for (chunk_index, (mut self_chunk, other_chunk)) in
+ self.chunks.iter_mut().zip(other.chunks.iter()).enumerate()
+ {
+ let chunk_domain_size = if chunk_index + 1 == num_chunks {
+ last_chunk_size
+ } else {
+ CHUNK_BITS as ChunkSize
+ };
+
match (&mut self_chunk, &other_chunk) {
- (_, Zeros(_)) | (Ones(_), _) => {}
- (Zeros(self_chunk_domain_size), Ones(other_chunk_domain_size))
- | (Mixed(self_chunk_domain_size, ..), Ones(other_chunk_domain_size))
- | (Zeros(self_chunk_domain_size), Mixed(other_chunk_domain_size, ..)) => {
+ (_, Zeros) | (Ones, _) => {}
+ (Zeros, Ones) | (Mixed(..), Ones) | (Zeros, Mixed(..)) => {
// `other_chunk` fully overwrites `self_chunk`
- debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
*self_chunk = other_chunk.clone();
changed = true;
}
(
- Mixed(self_chunk_domain_size, self_chunk_count, self_chunk_words),
- Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words),
+ Mixed(self_chunk_count, self_chunk_words),
+ Mixed(_other_chunk_count, other_chunk_words),
) => {
// First check if the operation would change
// `self_chunk.words`. If not, we can avoid allocating some
@@ -789,7 +804,7 @@ fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
// performance win. Also, we only need to operate on the
// in-use words, hence the slicing.
let op = |a, b| a | b;
- let num_words = num_words(*self_chunk_domain_size as usize);
+ let num_words = num_words(chunk_domain_size as usize);
if bitwise_changes(
&self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
@@ -806,8 +821,8 @@ fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
.iter()
.map(|w| w.count_ones() as ChunkSize)
.sum();
- if *self_chunk_count == *self_chunk_domain_size {
- *self_chunk = Ones(*self_chunk_domain_size);
+ if *self_chunk_count == chunk_domain_size {
+ *self_chunk = Ones;
}
changed = true;
}
@@ -819,36 +834,41 @@ fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size);
- debug_assert_eq!(self.chunks.len(), other.chunks.len());
+
+ let num_chunks = self.chunks.len();
+ debug_assert_eq!(num_chunks, other.chunks.len());
+
+ let last_chunk_size = self.last_chunk_size();
+ debug_assert_eq!(last_chunk_size, other.last_chunk_size());
let mut changed = false;
- for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
+ for (chunk_index, (mut self_chunk, other_chunk)) in
+ self.chunks.iter_mut().zip(other.chunks.iter()).enumerate()
+ {
+ let chunk_domain_size = if chunk_index + 1 == num_chunks {
+ last_chunk_size
+ } else {
+ CHUNK_BITS as ChunkSize
+ };
+
match (&mut self_chunk, &other_chunk) {
- (Zeros(..), _) | (_, Zeros(..)) => {}
- (
- Ones(self_chunk_domain_size) | Mixed(self_chunk_domain_size, _, _),
- Ones(other_chunk_domain_size),
- ) => {
- debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
+ (Zeros, _) | (_, Zeros) => {}
+ (Ones | Mixed(_, _), Ones) => {
changed = true;
- *self_chunk = Zeros(*self_chunk_domain_size);
+ *self_chunk = Zeros;
}
- (
- Ones(self_chunk_domain_size),
- Mixed(other_chunk_domain_size, other_chunk_count, other_chunk_words),
- ) => {
- debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
+ (Ones, Mixed(other_chunk_count, other_chunk_words)) => {
changed = true;
- let num_words = num_words(*self_chunk_domain_size as usize);
+ let num_words = num_words(chunk_domain_size as usize);
debug_assert!(num_words > 0 && num_words <= CHUNK_WORDS);
let mut tail_mask =
- 1 << (*other_chunk_domain_size - ((num_words - 1) * WORD_BITS) as u16) - 1;
+ 1 << (chunk_domain_size - ((num_words - 1) * WORD_BITS) as u16) - 1;
let mut self_chunk_words = **other_chunk_words;
for word in self_chunk_words[0..num_words].iter_mut().rev() {
*word = !*word & tail_mask;
tail_mask = u64::MAX;
}
- let self_chunk_count = *self_chunk_domain_size - *other_chunk_count;
+ let self_chunk_count = chunk_domain_size - *other_chunk_count;
debug_assert_eq!(
self_chunk_count,
self_chunk_words[0..num_words]
@@ -856,16 +876,15 @@ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
.map(|w| w.count_ones() as ChunkSize)
.sum()
);
- *self_chunk =
- Mixed(*self_chunk_domain_size, self_chunk_count, Rc::new(self_chunk_words));
+ *self_chunk = Mixed(self_chunk_count, Rc::new(self_chunk_words));
}
(
- Mixed(self_chunk_domain_size, self_chunk_count, self_chunk_words),
- Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words),
+ Mixed(self_chunk_count, self_chunk_words),
+ Mixed(_other_chunk_count, other_chunk_words),
) => {
// See [`<Self as BitRelations<ChunkedBitSet<T>>>::union`] for the explanation
let op = |a: u64, b: u64| a & !b;
- let num_words = num_words(*self_chunk_domain_size as usize);
+ let num_words = num_words(chunk_domain_size as usize);
if bitwise_changes(
&self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
@@ -883,7 +902,7 @@ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
.map(|w| w.count_ones() as ChunkSize)
.sum();
if *self_chunk_count == 0 {
- *self_chunk = Zeros(*self_chunk_domain_size);
+ *self_chunk = Zeros;
}
changed = true;
}
@@ -895,28 +914,36 @@ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size);
- debug_assert_eq!(self.chunks.len(), other.chunks.len());
+
+ let num_chunks = self.chunks.len();
+ debug_assert_eq!(num_chunks, other.chunks.len());
+
+ let last_chunk_size = self.last_chunk_size();
+ debug_assert_eq!(last_chunk_size, other.last_chunk_size());
let mut changed = false;
- for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
+ for (chunk_index, (mut self_chunk, other_chunk)) in
+ self.chunks.iter_mut().zip(other.chunks.iter()).enumerate()
+ {
+ let chunk_domain_size = if chunk_index + 1 == num_chunks {
+ last_chunk_size
+ } else {
+ CHUNK_BITS as ChunkSize
+ };
+
match (&mut self_chunk, &other_chunk) {
- (Zeros(..), _) | (_, Ones(..)) => {}
- (
- Ones(self_chunk_domain_size),
- Zeros(other_chunk_domain_size) | Mixed(other_chunk_domain_size, ..),
- )
- | (Mixed(self_chunk_domain_size, ..), Zeros(other_chunk_domain_size)) => {
- debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
+ (Zeros, _) | (_, Ones) => {}
+ (Ones, Zeros | Mixed(..)) | (Mixed(..), Zeros) => {
changed = true;
*self_chunk = other_chunk.clone();
}
(
- Mixed(self_chunk_domain_size, self_chunk_count, self_chunk_words),
- Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words),
+ Mixed(self_chunk_count, self_chunk_words),
+ Mixed(_other_chunk_count, other_chunk_words),
) => {
// See [`<Self as BitRelations<ChunkedBitSet<T>>>::union`] for the explanation
let op = |a, b| a & b;
- let num_words = num_words(*self_chunk_domain_size as usize);
+ let num_words = num_words(chunk_domain_size as usize);
if bitwise_changes(
&self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
@@ -934,7 +961,7 @@ fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
.map(|w| w.count_ones() as ChunkSize)
.sum();
if *self_chunk_count == 0 {
- *self_chunk = Zeros(*self_chunk_domain_size);
+ *self_chunk = Zeros;
}
changed = true;
}
@@ -964,7 +991,7 @@ fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
words = &mut words[..CHUNK_WORDS];
}
match chunk {
- Zeros(..) => {
+ Zeros => {
for word in words {
if *word != 0 {
changed = true;
@@ -972,8 +999,8 @@ fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
}
}
}
- Ones(..) => (),
- Mixed(_, _, data) => {
+ Ones => (),
+ Mixed(_, data) => {
for (i, word) in words.iter_mut().enumerate() {
let new_val = *word & data[i];
if new_val != *word {
@@ -1053,13 +1080,11 @@ fn next(&mut self) -> Option<T> {
impl Chunk {
#[cfg(test)]
- fn assert_valid(&self) {
+ fn assert_valid(&self, chunk_domain_size: ChunkSize) {
+ assert!(chunk_domain_size as usize <= CHUNK_BITS);
match *self {
- Zeros(chunk_domain_size) | Ones(chunk_domain_size) => {
- assert!(chunk_domain_size as usize <= CHUNK_BITS);
- }
- Mixed(chunk_domain_size, count, ref words) => {
- assert!(chunk_domain_size as usize <= CHUNK_BITS);
+ Zeros | Ones => {}
+ Mixed(count, ref words) => {
assert!(0 < count && count < chunk_domain_size);
// Check the number of set bits matches `count`.
@@ -1083,18 +1108,12 @@ fn assert_valid(&self) {
}
}
- fn new(chunk_domain_size: usize, is_empty: bool) -> Self {
- debug_assert!(0 < chunk_domain_size && chunk_domain_size <= CHUNK_BITS);
- let chunk_domain_size = chunk_domain_size as ChunkSize;
- if is_empty { Zeros(chunk_domain_size) } else { Ones(chunk_domain_size) }
- }
-
/// Count the number of 1s in the chunk.
- fn count(&self) -> usize {
+ fn count(&self, chunk_domain_size: ChunkSize) -> usize {
match *self {
- Zeros(_) => 0,
- Ones(chunk_domain_size) => chunk_domain_size as usize,
- Mixed(_, count, _) => count as usize,
+ Zeros => 0,
+ Ones => chunk_domain_size as usize,
+ Mixed(count, _) => count as usize,
}
}
}
diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs
index 9ce4cf4..deddc87 100644
--- a/compiler/rustc_index/src/bit_set/tests.rs
+++ b/compiler/rustc_index/src/bit_set/tests.rs
@@ -120,8 +120,9 @@ fn chunked_bitset() {
let mut b1 = ChunkedBitSet::<usize>::new_empty(1);
assert_eq!(
b1,
- ChunkedBitSet { domain_size: 1, chunks: Box::new([Zeros(1)]), marker: PhantomData }
+ ChunkedBitSet { domain_size: 1, chunks: Box::new([Zeros]), marker: PhantomData }
);
+ assert_eq!(b1.chunk_domain_size(0), 1);
b1.assert_valid();
assert!(!b1.contains(0));
@@ -129,12 +130,12 @@ fn chunked_bitset() {
assert!(b1.insert(0));
assert!(b1.contains(0));
assert_eq!(b1.count(), 1);
- assert_eq!(b1.chunks(), [Ones(1)]);
+ assert_eq!(b1.chunks(), [Ones]);
assert!(!b1.insert(0));
assert!(b1.remove(0));
assert!(!b1.contains(0));
assert_eq!(b1.count(), 0);
- assert_eq!(b1.chunks(), [Zeros(1)]);
+ assert_eq!(b1.chunks(), [Zeros]);
b1.assert_valid();
//-----------------------------------------------------------------------
@@ -142,8 +143,9 @@ fn chunked_bitset() {
let mut b100 = ChunkedBitSet::<usize>::new_filled(100);
assert_eq!(
b100,
- ChunkedBitSet { domain_size: 100, chunks: Box::new([Ones(100)]), marker: PhantomData }
+ ChunkedBitSet { domain_size: 100, chunks: Box::new([Ones]), marker: PhantomData }
);
+ assert_eq!(b100.chunk_domain_size(0), 100);
b100.assert_valid();
for i in 0..100 {
@@ -152,7 +154,7 @@ fn chunked_bitset() {
assert_eq!(b100.count(), 100);
assert!(b100.remove(3));
assert!(b100.insert(3));
- assert_eq!(b100.chunks(), vec![Ones(100)]);
+ assert_eq!(b100.chunks(), vec![Ones]);
assert!(
b100.remove(20) && b100.remove(30) && b100.remove(40) && b100.remove(99) && b100.insert(30)
);
@@ -161,7 +163,6 @@ fn chunked_bitset() {
assert_eq!(
b100.chunks(),
vec![Mixed(
- 100,
97,
#[rustfmt::skip]
Rc::new([
@@ -180,7 +181,7 @@ fn chunked_bitset() {
}
}
assert_eq!(num_removed, 97);
- assert_eq!(b100.chunks(), vec![Zeros(100)]);
+ assert_eq!(b100.chunks(), vec![Zeros]);
b100.assert_valid();
//-----------------------------------------------------------------------
@@ -188,23 +189,21 @@ fn chunked_bitset() {
let mut b2548 = ChunkedBitSet::<usize>::new_empty(2548);
assert_eq!(
b2548,
- ChunkedBitSet {
- domain_size: 2548,
- chunks: Box::new([Zeros(2048), Zeros(500)]),
- marker: PhantomData,
- }
+ ChunkedBitSet { domain_size: 2548, chunks: Box::new([Zeros, Zeros]), marker: PhantomData }
);
+ assert_eq!(b2548.chunk_domain_size(0), 2048);
+ assert_eq!(b2548.chunk_domain_size(1), 500);
b2548.assert_valid();
b2548.insert(14);
b2548.remove(14);
- assert_eq!(b2548.chunks(), vec![Zeros(2048), Zeros(500)]);
+ assert_eq!(b2548.chunks(), vec![Zeros, Zeros]);
b2548.insert_all();
for i in 0..2548 {
assert!(b2548.contains(i));
}
assert_eq!(b2548.count(), 2548);
- assert_eq!(b2548.chunks(), vec![Ones(2048), Ones(500)]);
+ assert_eq!(b2548.chunks(), vec![Ones, Ones]);
b2548.assert_valid();
//-----------------------------------------------------------------------
@@ -212,12 +211,10 @@ fn chunked_bitset() {
let mut b4096 = ChunkedBitSet::<usize>::new_empty(4096);
assert_eq!(
b4096,
- ChunkedBitSet {
- domain_size: 4096,
- chunks: Box::new([Zeros(2048), Zeros(2048)]),
- marker: PhantomData,
- }
+ ChunkedBitSet { domain_size: 4096, chunks: Box::new([Zeros, Zeros]), marker: PhantomData }
);
+ assert_eq!(b4096.chunk_domain_size(0), 2048);
+ assert_eq!(b4096.chunk_domain_size(1), 2048);
b4096.assert_valid();
for i in 0..4096 {
@@ -231,11 +228,11 @@ fn chunked_bitset() {
b4096.chunks(),
#[rustfmt::skip]
vec![
- Mixed(2048, 1, Rc::new([
+ Mixed(1, Rc::new([
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
])),
- Mixed(2048, 1, Rc::new([
+ Mixed(1, Rc::new([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x8000_0000_0000_0000
])),
@@ -251,10 +248,15 @@ fn chunked_bitset() {
b10000,
ChunkedBitSet {
domain_size: 10000,
- chunks: Box::new([Zeros(2048), Zeros(2048), Zeros(2048), Zeros(2048), Zeros(1808),]),
+ chunks: Box::new([Zeros, Zeros, Zeros, Zeros, Zeros,]),
marker: PhantomData,
}
);
+ assert_eq!(b10000.chunk_domain_size(0), 2048);
+ assert_eq!(b10000.chunk_domain_size(1), 2048);
+ assert_eq!(b10000.chunk_domain_size(2), 2048);
+ assert_eq!(b10000.chunk_domain_size(3), 2048);
+ assert_eq!(b10000.chunk_domain_size(4), 1808);
b10000.assert_valid();
assert!(b10000.insert(3000) && b10000.insert(5000));
@@ -262,17 +264,17 @@ fn chunked_bitset() {
b10000.chunks(),
#[rustfmt::skip]
vec![
- Zeros(2048),
- Mixed(2048, 1, Rc::new([
+ Zeros,
+ Mixed(1, Rc::new([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0100_0000_0000_0000, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
])),
- Mixed(2048, 1, Rc::new([
+ Mixed(1, Rc::new([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0100, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
])),
- Zeros(2048),
- Zeros(1808),
+ Zeros,
+ Zeros,
],
);
let mut b10000b = ChunkedBitSet::<usize>::new_empty(10000);
diff --git a/compiler/rustc_index_macros/Cargo.toml b/compiler/rustc_index_macros/Cargo.toml
index 34f3109..8593bde 100644
--- a/compiler/rustc_index_macros/Cargo.toml
+++ b/compiler/rustc_index_macros/Cargo.toml
@@ -8,8 +8,8 @@
[dependencies]
# tidy-alphabetical-start
-proc-macro2 = "1"
-quote = "1"
+proc-macro2.workspace = true
+quote.workspace = true
syn = { version = "2.0.9", features = ["full", "extra-traits"] }
# tidy-alphabetical-end
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 08c0361..6d97fa6 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -18,6 +18,6 @@
rustc_span = { path = "../rustc_span" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index 21e999b..bb9c885 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -22,10 +22,6 @@ fn next_trait_solver(&self) -> bool {
self.next_trait_solver
}
- fn in_hir_typeck(&self) -> bool {
- self.in_hir_typeck
- }
-
fn typing_mode(&self) -> ty::TypingMode<'tcx> {
self.typing_mode()
}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 9ff06bd..d1507f0 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -158,7 +158,8 @@ pub struct InferCtxtInner<'tcx> {
region_assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>,
/// `-Znext-solver`: Successfully proven goals during HIR typeck which
- /// reference inference variables and get reproven after writeback.
+ /// reference inference variables and get reproven in case MIR type check
+ /// fails to prove something.
///
/// See the documentation of `InferCtxt::in_hir_typeck` for more details.
hir_typeck_potentially_region_dependent_goals: Vec<PredicateObligation<'tcx>>,
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index 473ac5e..40152e7 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -46,7 +46,7 @@
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_traits = { path = "../rustc_traits" }
rustc_ty_utils = { path = "../rustc_ty_utils" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[dev-dependencies]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 90f7ae7..bc5ef04 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -6,7 +6,7 @@
use std::{env, fs, iter};
use rustc_ast as ast;
-use rustc_attr_parsing::validate_attr;
+use rustc_attr_parsing::{AttributeParser, ShouldEmit, validate_attr};
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::jobserver::Proxy;
use rustc_data_structures::steal::Steal;
@@ -16,6 +16,7 @@
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
use rustc_feature::Features;
use rustc_fs_util::try_canonicalize;
+use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
use rustc_hir::definitions::Definitions;
use rustc_incremental::setup_dep_graph;
@@ -1244,8 +1245,7 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
// in all code paths that require the crate name very early on, namely before
// macro expansion.
- let attr_crate_name =
- validate_and_find_value_str_builtin_attr(sym::crate_name, sess, krate_attrs);
+ let attr_crate_name = parse_crate_name(sess, krate_attrs, ShouldEmit::EarlyFatal);
let validate = |name, span| {
rustc_session::output::validate_crate_name(sess, name, span);
@@ -1283,6 +1283,28 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
sym::rust_out
}
+pub(crate) fn parse_crate_name(
+ sess: &Session,
+ attrs: &[ast::Attribute],
+ emit_errors: ShouldEmit,
+) -> Option<(Symbol, Span)> {
+ let rustc_hir::Attribute::Parsed(AttributeKind::CrateName { name, name_span, .. }) =
+ AttributeParser::parse_limited_should_emit(
+ sess,
+ &attrs,
+ sym::crate_name,
+ DUMMY_SP,
+ rustc_ast::node_id::CRATE_NODE_ID,
+ None,
+ emit_errors,
+ )?
+ else {
+ unreachable!("crate_name is the only attr we could've parsed here");
+ };
+
+ Some((name, name_span))
+}
+
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
// We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`])
// because that would require expanding this while in the middle of expansion, which needs to
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 4425877..7730bdd 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -8,6 +8,7 @@
use rustc_data_structures::profiling::TimePassesFormat;
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, registry};
+use rustc_hir::attrs::NativeLibKind;
use rustc_session::config::{
AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel,
CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation,
@@ -20,7 +21,7 @@
};
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
-use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
+use rustc_session::utils::{CanonicalizedPath, NativeLib};
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, getopts};
use rustc_span::edition::{DEFAULT_EDITION, Edition};
use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 9a432a6..04006f3 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -5,7 +5,7 @@
use std::{env, thread};
use rustc_ast as ast;
-use rustc_attr_parsing::validate_attr;
+use rustc_attr_parsing::{ShouldEmit, validate_attr};
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::jobserver::Proxy;
use rustc_data_structures::sync;
@@ -24,6 +24,7 @@
use tracing::info;
use crate::errors;
+use crate::passes::parse_crate_name;
/// Function pointer type that constructs a new CodegenBackend.
type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
@@ -520,11 +521,10 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
sess.dcx().emit_fatal(errors::MultipleOutputTypesToStdout);
}
- let crate_name = sess
- .opts
- .crate_name
- .clone()
- .or_else(|| rustc_attr_parsing::find_crate_name(attrs).map(|n| n.to_string()));
+ let crate_name =
+ sess.opts.crate_name.clone().or_else(|| {
+ parse_crate_name(sess, attrs, ShouldEmit::Nothing).map(|i| i.0.to_string())
+ });
match sess.io.output_file {
None => {
diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml
index 448a50f..e0019fb 100644
--- a/compiler/rustc_lexer/Cargo.toml
+++ b/compiler/rustc_lexer/Cargo.toml
@@ -14,13 +14,9 @@
# Note that this crate purposefully does not depend on other rustc crates
[dependencies]
-memchr = "2.7.4"
+memchr.workspace = true
+unicode-properties = { version = "0.1.0", default-features = false, features = ["emoji"] }
unicode-xid = "0.2.0"
-[dependencies.unicode-properties]
-version = "0.1.0"
-default-features = false
-features = ["emoji"]
-
[dev-dependencies]
expect-test = "1.4.0"
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml
index 7718f16..7900e4b 100644
--- a/compiler/rustc_lint/Cargo.toml
+++ b/compiler/rustc_lint/Cargo.toml
@@ -24,6 +24,6 @@
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
unicode-security = "0.1.0"
# tidy-alphabetical-end
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 940a07c..417e5a9 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -462,6 +462,14 @@
lint_invalid_reference_casting_note_ty_has_interior_mutability = even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`
+lint_int_to_ptr_transmutes = transmuting an integer to a pointer creates a pointer without provenance
+ .note = this is dangerous because dereferencing the resulting pointer is undefined behavior
+ .note_exposed_provenance = exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ .help_transmute = for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ .help_exposed_provenance = for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+ .suggestion_with_exposed_provenance = use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance
+ .suggestion_without_provenance_mut = if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+
lint_legacy_derive_helpers = derive helper attribute is used before it is introduced
.label = the attribute is introduced here
diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs
index 464f4fc..413525e 100644
--- a/compiler/rustc_lint/src/lifetime_syntax.rs
+++ b/compiler/rustc_lint/src/lifetime_syntax.rs
@@ -214,9 +214,9 @@ pub fn len(&self) -> LifetimeSyntaxCategories<usize> {
}
}
- pub fn flatten(&self) -> impl Iterator<Item = &T> {
- let Self { hidden, elided, named } = self;
- [hidden.iter(), elided.iter(), named.iter()].into_iter().flatten()
+ pub fn iter_unnamed(&self) -> impl Iterator<Item = &T> {
+ let Self { hidden, elided, named: _ } = self;
+ [hidden.iter(), elided.iter()].into_iter().flatten()
}
}
@@ -495,7 +495,7 @@ fn emit_mismatch_diagnostic<'tcx>(
cx.emit_span_lint(
MISMATCHED_LIFETIME_SYNTAXES,
- inputs.flatten().copied().collect::<Vec<_>>(),
+ inputs.iter_unnamed().chain(outputs.iter_unnamed()).copied().collect::<Vec<_>>(),
lints::MismatchedLifetimeSyntaxes { inputs, outputs, suggestions },
);
}
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 6c50973..56d65ed 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
#![allow(rustc::untranslatable_diagnostic)]
use std::num::NonZero;
@@ -1542,6 +1544,48 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
}
}
+// transmute.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_int_to_ptr_transmutes)]
+#[note]
+#[note(lint_note_exposed_provenance)]
+#[help(lint_suggestion_without_provenance_mut)]
+#[help(lint_help_transmute)]
+#[help(lint_help_exposed_provenance)]
+pub(crate) struct IntegerToPtrTransmutes<'tcx> {
+ #[subdiagnostic]
+ pub suggestion: Option<IntegerToPtrTransmutesSuggestion<'tcx>>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> {
+ #[multipart_suggestion(
+ lint_suggestion_with_exposed_provenance,
+ applicability = "machine-applicable",
+ style = "verbose"
+ )]
+ ToPtr {
+ dst: Ty<'tcx>,
+ suffix: &'static str,
+ #[suggestion_part(code = "std::ptr::with_exposed_provenance{suffix}::<{dst}>(")]
+ start_call: Span,
+ },
+ #[multipart_suggestion(
+ lint_suggestion_with_exposed_provenance,
+ applicability = "machine-applicable",
+ style = "verbose"
+ )]
+ ToRef {
+ dst: Ty<'tcx>,
+ suffix: &'static str,
+ ref_mutbl: &'static str,
+ #[suggestion_part(
+ code = "&{ref_mutbl}*std::ptr::with_exposed_provenance{suffix}::<{dst}>("
+ )]
+ start_call: Span,
+ },
+}
+
// types.rs
#[derive(LintDiagnostic)]
#[diag(lint_range_endpoint_out_of_range)]
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 8fafaa3..65075cf 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -5,7 +5,7 @@
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{FnKind, Visitor};
-use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
+use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
use rustc_middle::hir::nested_filter::All;
use rustc_middle::ty;
use rustc_session::config::CrateType;
@@ -343,35 +343,27 @@ fn check_mod(&mut self, cx: &LateContext<'_>, _: &'tcx hir::Mod<'tcx>, id: hir::
let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
Some(Ident::from_str(name))
} else {
- ast::attr::find_by_name(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), sym::crate_name).and_then(
- |attr| {
- if let Attribute::Unparsed(n) = attr
- && let AttrItem { args: AttrArgs::Eq { eq_span: _, expr: lit }, .. } =
- n.as_ref()
- && let ast::LitKind::Str(name, ..) = lit.kind
- {
- // Discard the double quotes surrounding the literal.
- let sp = cx
- .sess()
- .source_map()
- .span_to_snippet(lit.span)
- .ok()
- .and_then(|snippet| {
- let left = snippet.find('"')?;
- let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
+ find_attr!(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), AttributeKind::CrateName{name, name_span,..} => (name, name_span)).map(
+ |(&name, &span)| {
+ // Discard the double quotes surrounding the literal.
+ let sp = cx
+ .sess()
+ .source_map()
+ .span_to_snippet(span)
+ .ok()
+ .and_then(|snippet| {
+ let left = snippet.find('"')?;
+ let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
- Some(
- lit.span
- .with_lo(lit.span.lo() + BytePos(left as u32 + 1))
- .with_hi(lit.span.hi() - BytePos(right as u32)),
- )
- })
- .unwrap_or(lit.span);
+ Some(
+ span
+ .with_lo(span.lo() + BytePos(left as u32 + 1))
+ .with_hi(span.hi() - BytePos(right as u32)),
+ )
+ })
+ .unwrap_or(span);
- Some(Ident::new(name, sp))
- } else {
- None
- }
+ Ident::new(name, sp)
},
)
};
diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs
index bc1d458..98510eea 100644
--- a/compiler/rustc_lint/src/transmute.rs
+++ b/compiler/rustc_lint/src/transmute.rs
@@ -1,3 +1,4 @@
+use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
@@ -7,6 +8,7 @@
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::sym;
+use crate::lints::{IntegerToPtrTransmutes, IntegerToPtrTransmutesSuggestion};
use crate::{LateContext, LateLintPass};
declare_lint! {
@@ -67,9 +69,44 @@
"detects transmutes that can also be achieved by other operations"
}
+declare_lint! {
+ /// The `integer_to_ptr_transmutes` lint detects integer to pointer
+ /// transmutes where the resulting pointers are undefined behavior to dereference.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// fn foo(a: usize) -> *const u8 {
+ /// unsafe {
+ /// std::mem::transmute::<usize, *const u8>(a)
+ /// }
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Any attempt to use the resulting pointers are undefined behavior as the resulting
+ /// pointers won't have any provenance.
+ ///
+ /// Alternatively, [`std::ptr::with_exposed_provenance`] should be used, as they do not
+ /// carry the provenance requirement. If wanting to create pointers without provenance
+ /// [`std::ptr::without_provenance`] should be used instead.
+ ///
+ /// See [`std::mem::transmute`] in the reference for more details.
+ ///
+ /// [`std::mem::transmute`]: https://doc.rust-lang.org/std/mem/fn.transmute.html
+ /// [`std::ptr::with_exposed_provenance`]: https://doc.rust-lang.org/std/ptr/fn.with_exposed_provenance.html
+ /// [`std::ptr::without_provenance`]: https://doc.rust-lang.org/std/ptr/fn.without_provenance.html
+ pub INTEGER_TO_PTR_TRANSMUTES,
+ Warn,
+ "detects integer to pointer transmutes",
+}
+
pub(crate) struct CheckTransmutes;
-impl_lint_pass!(CheckTransmutes => [PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, UNNECESSARY_TRANSMUTES]);
+impl_lint_pass!(CheckTransmutes => [PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, UNNECESSARY_TRANSMUTES, INTEGER_TO_PTR_TRANSMUTES]);
impl<'tcx> LateLintPass<'tcx> for CheckTransmutes {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
@@ -94,9 +131,68 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
check_ptr_transmute_in_const(cx, expr, body_owner_def_id, const_context, src, dst);
check_unnecessary_transmute(cx, expr, callee, arg, const_context, src, dst);
+ check_int_to_ptr_transmute(cx, expr, arg, src, dst);
}
}
+/// Check for transmutes from integer to pointers (*const/*mut and &/&mut).
+///
+/// Using the resulting pointers would be undefined behavior.
+fn check_int_to_ptr_transmute<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ arg: &'tcx hir::Expr<'tcx>,
+ src: Ty<'tcx>,
+ dst: Ty<'tcx>,
+) {
+ if !matches!(src.kind(), ty::Uint(_) | ty::Int(_)) {
+ return;
+ }
+ let (ty::Ref(_, inner_ty, mutbl) | ty::RawPtr(inner_ty, mutbl)) = dst.kind() else {
+ return;
+ };
+ // bail-out if the argument is literal 0 as we have other lints for those cases
+ if matches!(arg.kind, hir::ExprKind::Lit(hir::Lit { node: LitKind::Int(v, _), .. }) if v == 0) {
+ return;
+ }
+ // bail-out if the inner type is a ZST
+ let Ok(layout_inner_ty) = cx.tcx.layout_of(cx.typing_env().as_query_input(*inner_ty)) else {
+ return;
+ };
+ if layout_inner_ty.is_1zst() {
+ return;
+ }
+
+ let suffix = if mutbl.is_mut() { "_mut" } else { "" };
+ cx.tcx.emit_node_span_lint(
+ INTEGER_TO_PTR_TRANSMUTES,
+ expr.hir_id,
+ expr.span,
+ IntegerToPtrTransmutes {
+ suggestion: if layout_inner_ty.is_sized() {
+ Some(if dst.is_ref() {
+ IntegerToPtrTransmutesSuggestion::ToRef {
+ dst: *inner_ty,
+ suffix,
+ ref_mutbl: mutbl.prefix_str(),
+ start_call: expr.span.shrink_to_lo().until(arg.span),
+ }
+ } else {
+ IntegerToPtrTransmutesSuggestion::ToPtr {
+ dst: *inner_ty,
+ suffix,
+ start_call: expr.span.shrink_to_lo().until(arg.span),
+ }
+ })
+ } else {
+ // We can't suggest using `with_exposed_provenance` for unsized type
+ // so don't suggest anything.
+ None
+ },
+ },
+ );
+}
+
/// Check for transmutes that exhibit undefined behavior.
/// For example, transmuting pointers to integers in a const context.
///
diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml
index cd352ce..e74de45 100644
--- a/compiler/rustc_llvm/Cargo.toml
+++ b/compiler/rustc_llvm/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-libc = "0.2.73"
+libc.workspace = true
# tidy-alphabetical-end
[build-dependencies]
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 8c34052..dd49232 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1226,12 +1226,6 @@
extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
size_t Len) {
auto PreserveFunctions = [=](const GlobalValue &GV) {
- // Preserve LLVM-injected, ASAN-related symbols.
- // See also https://github.com/rust-lang/rust/issues/113404.
- if (GV.getName() == "___asan_globals_registered") {
- return true;
- }
-
// Preserve symbols exported from Rust modules.
for (size_t I = 0; I < Len; I++) {
if (GV.getName() == Symbols[I]) {
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index e699e4b..361a5f7 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -242,7 +242,7 @@
MinSize = 4,
Naked = 5,
NoAlias = 6,
- NoCapture = 7,
+ CapturesAddress = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,
@@ -297,12 +297,6 @@
return Attribute::Naked;
case LLVMRustAttributeKind::NoAlias:
return Attribute::NoAlias;
- case LLVMRustAttributeKind::NoCapture:
-#if LLVM_VERSION_GE(21, 0)
- report_fatal_error("NoCapture doesn't exist in LLVM 21");
-#else
- return Attribute::NoCapture;
-#endif
case LLVMRustAttributeKind::NoCfCheck:
return Attribute::NoCfCheck;
case LLVMRustAttributeKind::NoInline:
@@ -377,6 +371,7 @@
#else
report_fatal_error("DeadOnReturn attribute requires LLVM 21 or later");
#endif
+ case LLVMRustAttributeKind::CapturesAddress:
case LLVMRustAttributeKind::CapturesReadOnly:
report_fatal_error("Should be handled separately");
}
@@ -429,9 +424,9 @@
extern "C" LLVMAttributeRef
LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) {
#if LLVM_VERSION_GE(21, 0)
- // LLVM 21 replaced the NoCapture attribute with Captures(none).
- if (RustAttr == LLVMRustAttributeKind::NoCapture) {
- return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none()));
+ if (RustAttr == LLVMRustAttributeKind::CapturesAddress) {
+ return wrap(Attribute::getWithCaptureInfo(
+ *unwrap(C), CaptureInfo(CaptureComponents::Address)));
}
if (RustAttr == LLVMRustAttributeKind::CapturesReadOnly) {
return wrap(Attribute::getWithCaptureInfo(
@@ -488,6 +483,9 @@
LLVMRustCreateRangeAttribute(LLVMContextRef C, unsigned NumBits,
const uint64_t LowerWords[],
const uint64_t UpperWords[]) {
+ // FIXME(Zalathar): There appears to be no stable guarantee that C++
+ // `AttrKind` values correspond directly to the `unsigned KindID` values
+ // accepted by LLVM-C API functions, though in practice they currently do.
return LLVMCreateConstantRangeAttribute(C, Attribute::Range, NumBits,
LowerWords, UpperWords);
}
diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml
index c673d51..e9d7b47 100644
--- a/compiler/rustc_log/Cargo.toml
+++ b/compiler/rustc_log/Cargo.toml
@@ -5,10 +5,10 @@
[dependencies]
# tidy-alphabetical-start
-tracing = "0.1.28"
tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
tracing-tree = "0.3.1"
+tracing.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml
index f9d3b75..5add269 100644
--- a/compiler/rustc_macros/Cargo.toml
+++ b/compiler/rustc_macros/Cargo.toml
@@ -8,8 +8,8 @@
[dependencies]
# tidy-alphabetical-start
-proc-macro2 = "1"
-quote = "1"
+proc-macro2.workspace = true
+quote.workspace = true
syn = { version = "2.0.9", features = ["full"] }
synstructure = "0.13.0"
# tidy-alphabetical-end
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 1b40d9f..a8f3dd18 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -5,9 +5,9 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
libloading = "0.8.0"
-odht = { version = "0.3.1", features = ["nightly"] }
+odht.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
@@ -30,11 +30,11 @@
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
-tempfile = "3.7.1"
-tracing = "0.1"
+tempfile.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
[target.'cfg(target_os = "aix")'.dependencies]
# tidy-alphabetical-start
-libc = "0.2"
+libc.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 4d3e879..e104be2 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -1,6 +1,3 @@
-metadata_as_needed_compatibility =
- linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
-
metadata_async_drop_types_in_dependency =
found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}`
.help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used
@@ -11,9 +8,6 @@
metadata_binary_output_to_tty =
option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty
-metadata_bundle_needs_static =
- linking modifier `bundle` is only compatible with `static` linking kind
-
metadata_cannot_find_crate =
can't find crate for `{$crate_name}`{$add_info}
@@ -60,10 +54,6 @@
metadata_dl_error =
{$path}{$err}
-metadata_empty_link_name =
- link name must not be empty
- .label = empty link name
-
metadata_empty_renaming_target =
an empty renaming target was specified for library `{$lib_name}`
@@ -108,15 +98,6 @@
metadata_global_alloc_required =
no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
-metadata_import_name_type_form =
- import name type must be of the form `import_name_type = "string"`
-
-metadata_import_name_type_raw =
- import name type can only be used with link kind `raw-dylib`
-
-metadata_import_name_type_x86 =
- import name type is only supported on x86
-
metadata_incompatible_panic_in_drop_strategy =
the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
@@ -143,15 +124,10 @@
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
.note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
-metadata_incompatible_wasm_link =
- `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
metadata_install_missing_components =
maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
-metadata_invalid_link_modifier =
- invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
-
metadata_invalid_meta_files =
found invalid metadata files for crate `{$crate_name}`{$add_info}
@@ -164,67 +140,18 @@
metadata_lib_required =
crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
-metadata_link_arg_unstable =
- link kind `link-arg` is unstable
-
-metadata_link_cfg_form =
- link cfg must be of the form `cfg(/* predicate */)`
-
-metadata_link_cfg_single_predicate =
- link cfg must have a single predicate argument
-
-metadata_link_cfg_unstable =
- link cfg is unstable
-
-metadata_link_framework_apple =
- link kind `framework` is only supported on Apple targets
-
-metadata_link_kind_form =
- link kind must be of the form `kind = "string"`
-
-metadata_link_modifiers_form =
- link modifiers must be of the form `modifiers = "string"`
-
-metadata_link_name_form =
- link name must be of the form `name = "string"`
-
metadata_link_ordinal_raw_dylib =
`#[link_ordinal]` is only supported if link kind is `raw-dylib`
-metadata_link_requires_name =
- `#[link]` attribute requires a `name = "string"` argument
- .label = missing `name` argument
-
metadata_missing_native_library =
could not find native static library `{$libname}`, perhaps an -L flag is missing?
metadata_multiple_candidates =
multiple candidates for `{$flavor}` dependency `{$crate_name}` found
-metadata_multiple_cfgs =
- multiple `cfg` arguments in a single `#[link]` attribute
-
-metadata_multiple_import_name_type =
- multiple `import_name_type` arguments in a single `#[link]` attribute
-
-metadata_multiple_kinds_in_link =
- multiple `kind` arguments in a single `#[link]` attribute
-
-metadata_multiple_link_modifiers =
- multiple `modifiers` arguments in a single `#[link]` attribute
-
-metadata_multiple_modifiers =
- multiple `{$modifier}` modifiers in a single `modifiers` argument
-
-metadata_multiple_names_in_link =
- multiple `name` arguments in a single `#[link]` attribute
-
metadata_multiple_renamings =
multiple renamings were specified for library `{$lib_name}`
-metadata_multiple_wasm_import =
- multiple `wasm_import_module` arguments in a single `#[link]` attribute
-
metadata_newer_crate_version =
found possibly newer version of crate `{$crate_name}`{$add_info}
.note = perhaps that crate needs to be recompiled?
@@ -263,15 +190,6 @@
metadata_prev_global_alloc =
previous global allocator defined here
-metadata_raw_dylib_elf_unstable =
- link kind `raw-dylib` is unstable on ELF platforms
-
-metadata_raw_dylib_no_nul =
- link name must not contain NUL characters if link kind is `raw-dylib`
-
-metadata_raw_dylib_only_windows =
- link kind `raw-dylib` is only supported on Windows targets
-
metadata_raw_dylib_unsupported_abi =
ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
@@ -307,19 +225,6 @@
metadata_two_panic_runtimes =
cannot link together two panic runtimes: {$prev_name} and {$cur_name}
-metadata_unexpected_link_arg =
- unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
-
-metadata_unknown_import_name_type =
- unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
-
-metadata_unknown_link_kind =
- unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib, link-arg
- .label = unknown link kind
-
-metadata_unknown_link_modifier =
- unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
-
metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`
metadata_wasm_c_abi =
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 0332dba..e5a4fd4 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -84,187 +84,6 @@ pub struct IncompatiblePanicInDropStrategy {
}
#[derive(Diagnostic)]
-#[diag(metadata_multiple_names_in_link)]
-pub struct MultipleNamesInLink {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_kinds_in_link)]
-pub struct MultipleKindsInLink {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_name_form)]
-pub struct LinkNameForm {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_kind_form)]
-pub struct LinkKindForm {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_modifiers_form)]
-pub struct LinkModifiersForm {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_cfg_form)]
-pub struct LinkCfgForm {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_wasm_import_form)]
-pub struct WasmImportForm {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_empty_link_name, code = E0454)]
-pub struct EmptyLinkName {
- #[primary_span]
- #[label]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_framework_apple, code = E0455)]
-pub struct LinkFrameworkApple {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_raw_dylib_only_windows, code = E0455)]
-pub struct RawDylibOnlyWindows {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_unknown_link_kind, code = E0458)]
-pub struct UnknownLinkKind<'a> {
- #[primary_span]
- #[label]
- pub span: Span,
- pub kind: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_link_modifiers)]
-pub struct MultipleLinkModifiers {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_cfgs)]
-pub struct MultipleCfgs {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_cfg_single_predicate)]
-pub struct LinkCfgSinglePredicate {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_wasm_import)]
-pub struct MultipleWasmImport {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_unexpected_link_arg)]
-pub struct UnexpectedLinkArg {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_invalid_link_modifier)]
-pub struct InvalidLinkModifier {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_modifiers)]
-pub struct MultipleModifiers<'a> {
- #[primary_span]
- pub span: Span,
- pub modifier: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_bundle_needs_static)]
-pub struct BundleNeedsStatic {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_whole_archive_needs_static)]
-pub struct WholeArchiveNeedsStatic {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_as_needed_compatibility)]
-pub struct AsNeededCompatibility {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_unknown_link_modifier)]
-pub struct UnknownLinkModifier<'a> {
- #[primary_span]
- pub span: Span,
- pub modifier: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_incompatible_wasm_link)]
-pub struct IncompatibleWasmLink {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_requires_name, code = E0459)]
-pub struct LinkRequiresName {
- #[primary_span]
- #[label]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_raw_dylib_no_nul)]
-pub struct RawDylibNoNul {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(metadata_link_ordinal_raw_dylib)]
pub struct LinkOrdinalRawDylib {
#[primary_span]
@@ -707,42 +526,6 @@ pub struct LibFilenameForm<'a> {
}
#[derive(Diagnostic)]
-#[diag(metadata_multiple_import_name_type)]
-pub struct MultipleImportNameType {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_import_name_type_form)]
-pub struct ImportNameTypeForm {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_import_name_type_x86)]
-pub struct ImportNameTypeX86 {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_unknown_import_name_type)]
-pub struct UnknownImportNameType<'a> {
- #[primary_span]
- pub span: Span,
- pub import_name_type: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_import_name_type_raw)]
-pub struct ImportNameTypeRaw {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(metadata_wasm_c_abi)]
pub(crate) struct WasmCAbi {
#[primary_span]
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 63f1b51..82738c6 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -3,25 +3,21 @@
use rustc_abi::ExternAbi;
use rustc_ast::CRATE_NODE_ID;
-use rustc_attr_parsing as attr;
+use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::attrs::AttributeKind;
+use rustc_hir::attrs::{AttributeKind, NativeLibKind, PeImportNameType};
use rustc_hir::find_attr;
use rustc_middle::query::LocalCrate;
use rustc_middle::ty::{self, List, Ty, TyCtxt};
use rustc_session::Session;
use rustc_session::config::CrateType;
-use rustc_session::cstore::{
- DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType,
-};
-use rustc_session::parse::feature_err;
+use rustc_session::cstore::{DllCallingConvention, DllImport, ForeignModule, NativeLib};
use rustc_session::search_paths::PathKind;
-use rustc_session::utils::NativeLibKind;
+use rustc_span::Symbol;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
-use rustc_span::{Symbol, sym};
use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents};
-use crate::{errors, fluent_generated};
+use crate::errors;
/// The fallback directories are passed to linker, but not used when rustc does the search,
/// because in the latter case the set of fallback directories cannot always be determined
@@ -192,7 +188,9 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib>
pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
match lib.cfg {
- Some(ref cfg) => attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
+ Some(ref cfg) => {
+ eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool()
+ }
None => true,
}
}
@@ -213,289 +211,23 @@ fn process_module(&mut self, module: &ForeignModule) {
return;
}
- // Process all of the #[link(..)]-style arguments
- let features = self.tcx.features();
-
- for m in self.tcx.get_attrs(def_id, sym::link) {
- let Some(items) = m.meta_item_list() else {
- continue;
- };
-
- let mut name = None;
- let mut kind = None;
- let mut modifiers = None;
- let mut cfg = None;
- let mut wasm_import_module = None;
- let mut import_name_type = None;
- for item in items.iter() {
- match item.name() {
- Some(sym::name) => {
- if name.is_some() {
- sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() });
- continue;
- }
- let Some(link_name) = item.value_str() else {
- sess.dcx().emit_err(errors::LinkNameForm { span: item.span() });
- continue;
- };
- let span = item.name_value_literal_span().unwrap();
- if link_name.is_empty() {
- sess.dcx().emit_err(errors::EmptyLinkName { span });
- }
- name = Some((link_name, span));
- }
- Some(sym::kind) => {
- if kind.is_some() {
- sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() });
- continue;
- }
- let Some(link_kind) = item.value_str() else {
- sess.dcx().emit_err(errors::LinkKindForm { span: item.span() });
- continue;
- };
-
- let span = item.name_value_literal_span().unwrap();
- let link_kind = match link_kind.as_str() {
- "static" => NativeLibKind::Static { bundle: None, whole_archive: None },
- "dylib" => NativeLibKind::Dylib { as_needed: None },
- "framework" => {
- if !sess.target.is_like_darwin {
- sess.dcx().emit_err(errors::LinkFrameworkApple { span });
- }
- NativeLibKind::Framework { as_needed: None }
- }
- "raw-dylib" => {
- if sess.target.is_like_windows {
- // raw-dylib is stable and working on Windows
- } else if sess.target.binary_format == BinaryFormat::Elf
- && features.raw_dylib_elf()
- {
- // raw-dylib is unstable on ELF, but the user opted in
- } else if sess.target.binary_format == BinaryFormat::Elf
- && sess.is_nightly_build()
- {
- feature_err(
- sess,
- sym::raw_dylib_elf,
- span,
- fluent_generated::metadata_raw_dylib_elf_unstable,
- )
- .emit();
- } else {
- sess.dcx().emit_err(errors::RawDylibOnlyWindows { span });
- }
-
- NativeLibKind::RawDylib
- }
- "link-arg" => {
- if !features.link_arg_attribute() {
- feature_err(
- sess,
- sym::link_arg_attribute,
- span,
- fluent_generated::metadata_link_arg_unstable,
- )
- .emit();
- }
- NativeLibKind::LinkArg
- }
- kind => {
- sess.dcx().emit_err(errors::UnknownLinkKind { span, kind });
- continue;
- }
- };
- kind = Some(link_kind);
- }
- Some(sym::modifiers) => {
- if modifiers.is_some() {
- sess.dcx()
- .emit_err(errors::MultipleLinkModifiers { span: item.span() });
- continue;
- }
- let Some(link_modifiers) = item.value_str() else {
- sess.dcx().emit_err(errors::LinkModifiersForm { span: item.span() });
- continue;
- };
- modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
- }
- Some(sym::cfg) => {
- if cfg.is_some() {
- sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() });
- continue;
- }
- let Some(link_cfg) = item.meta_item_list() else {
- sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() });
- continue;
- };
- let [link_cfg] = link_cfg else {
- sess.dcx()
- .emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
- continue;
- };
- let Some(link_cfg) = link_cfg.meta_item_or_bool() else {
- sess.dcx()
- .emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
- continue;
- };
- if !features.link_cfg() {
- feature_err(
- sess,
- sym::link_cfg,
- item.span(),
- fluent_generated::metadata_link_cfg_unstable,
- )
- .emit();
- }
- cfg = Some(link_cfg.clone());
- }
- Some(sym::wasm_import_module) => {
- if wasm_import_module.is_some() {
- sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() });
- continue;
- }
- let Some(link_wasm_import_module) = item.value_str() else {
- sess.dcx().emit_err(errors::WasmImportForm { span: item.span() });
- continue;
- };
- wasm_import_module = Some((link_wasm_import_module, item.span()));
- }
- Some(sym::import_name_type) => {
- if import_name_type.is_some() {
- sess.dcx()
- .emit_err(errors::MultipleImportNameType { span: item.span() });
- continue;
- }
- let Some(link_import_name_type) = item.value_str() else {
- sess.dcx().emit_err(errors::ImportNameTypeForm { span: item.span() });
- continue;
- };
- if self.tcx.sess.target.arch != "x86" {
- sess.dcx().emit_err(errors::ImportNameTypeX86 { span: item.span() });
- continue;
- }
-
- let link_import_name_type = match link_import_name_type.as_str() {
- "decorated" => PeImportNameType::Decorated,
- "noprefix" => PeImportNameType::NoPrefix,
- "undecorated" => PeImportNameType::Undecorated,
- import_name_type => {
- sess.dcx().emit_err(errors::UnknownImportNameType {
- span: item.span(),
- import_name_type,
- });
- continue;
- }
- };
- import_name_type = Some((link_import_name_type, item.span()));
- }
- _ => {
- sess.dcx().emit_err(errors::UnexpectedLinkArg { span: item.span() });
- }
- }
- }
-
- // Do this outside the above loop so we don't depend on modifiers coming after kinds
- let mut verbatim = None;
- if let Some((modifiers, span)) = modifiers {
- for modifier in modifiers.as_str().split(',') {
- let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
- Some(m) => (m, modifier.starts_with('+')),
- None => {
- sess.dcx().emit_err(errors::InvalidLinkModifier { span });
- continue;
- }
- };
-
- macro report_unstable_modifier($feature: ident) {
- if !features.$feature() {
- // FIXME: make this translatable
- #[expect(rustc::untranslatable_diagnostic)]
- feature_err(
- sess,
- sym::$feature,
- span,
- format!("linking modifier `{modifier}` is unstable"),
- )
- .emit();
- }
- }
- let assign_modifier = |dst: &mut Option<bool>| {
- if dst.is_some() {
- sess.dcx().emit_err(errors::MultipleModifiers { span, modifier });
- } else {
- *dst = Some(value);
- }
- };
- match (modifier, &mut kind) {
- ("bundle", Some(NativeLibKind::Static { bundle, .. })) => {
- assign_modifier(bundle)
- }
- ("bundle", _) => {
- sess.dcx().emit_err(errors::BundleNeedsStatic { span });
- }
-
- ("verbatim", _) => assign_modifier(&mut verbatim),
-
- ("whole-archive", Some(NativeLibKind::Static { whole_archive, .. })) => {
- assign_modifier(whole_archive)
- }
- ("whole-archive", _) => {
- sess.dcx().emit_err(errors::WholeArchiveNeedsStatic { span });
- }
-
- ("as-needed", Some(NativeLibKind::Dylib { as_needed }))
- | ("as-needed", Some(NativeLibKind::Framework { as_needed })) => {
- report_unstable_modifier!(native_link_modifiers_as_needed);
- assign_modifier(as_needed)
- }
- ("as-needed", _) => {
- sess.dcx().emit_err(errors::AsNeededCompatibility { span });
- }
-
- _ => {
- sess.dcx().emit_err(errors::UnknownLinkModifier { span, modifier });
- }
- }
- }
- }
-
- if let Some((_, span)) = wasm_import_module {
- if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
- sess.dcx().emit_err(errors::IncompatibleWasmLink { span });
- }
- }
-
- if wasm_import_module.is_some() {
- (name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
- }
- let Some((name, name_span)) = name else {
- sess.dcx().emit_err(errors::LinkRequiresName { span: m.span() });
- continue;
- };
-
- // Do this outside of the loop so that `import_name_type` can be specified before `kind`.
- if let Some((_, span)) = import_name_type {
- if kind != Some(NativeLibKind::RawDylib) {
- sess.dcx().emit_err(errors::ImportNameTypeRaw { span });
- }
- }
-
- let dll_imports = match kind {
- Some(NativeLibKind::RawDylib) => {
- if name.as_str().contains('\0') {
- sess.dcx().emit_err(errors::RawDylibNoNul { span: name_span });
- }
- foreign_items
- .iter()
- .map(|&child_item| {
- self.build_dll_import(
- abi,
- import_name_type.map(|(import_name_type, _)| import_name_type),
- child_item,
- )
- })
- .collect()
- }
+ for attr in
+ find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::Link(links, _) => links)
+ .iter()
+ .map(|v| v.iter())
+ .flatten()
+ {
+ let dll_imports = match attr.kind {
+ NativeLibKind::RawDylib => foreign_items
+ .iter()
+ .map(|&child_item| {
+ self.build_dll_import(
+ abi,
+ attr.import_name_type.map(|(import_name_type, _)| import_name_type),
+ child_item,
+ )
+ })
+ .collect(),
_ => {
for &child_item in foreign_items {
if let Some(span) = find_attr!(self.tcx.get_all_attrs(child_item), AttributeKind::LinkOrdinal {span, ..} => *span)
@@ -508,15 +240,20 @@ fn process_module(&mut self, module: &ForeignModule) {
}
};
- let kind = kind.unwrap_or(NativeLibKind::Unspecified);
- let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx);
+ let filename = find_bundled_library(
+ attr.name,
+ attr.verbatim,
+ attr.kind,
+ attr.cfg.is_some(),
+ self.tcx,
+ );
self.libs.push(NativeLib {
- name,
+ name: attr.name,
filename,
- kind,
- cfg,
+ kind: attr.kind,
+ cfg: attr.cfg.clone(),
foreign_module: Some(def_id.to_def_id()),
- verbatim,
+ verbatim: attr.verbatim,
dll_imports,
});
}
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index fbcce16..f083240 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -5,12 +5,12 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
-either = "1.5.0"
+bitflags.workspace = true
+either.workspace = true
gsgdt = "0.1.2"
-polonius-engine = "0.13.0"
+polonius-engine.workspace = true
rustc_abi = { path = "../rustc_abi" }
-rustc_apfloat = "0.2.0"
+rustc_apfloat.workspace = true
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_ir = { path = "../rustc_ast_ir" }
@@ -34,8 +34,8 @@
rustc_thread_pool = { path = "../rustc_thread_pool" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index cf0549f..5023b27 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -29,6 +29,7 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::direct_use_of_rustc_type_ir)]
#![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(allocator_api)]
@@ -51,7 +52,6 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(ptr_alignment_type)]
-#![feature(round_char_boundary)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
#![feature(sized_hierarchy)]
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 78cafe8..866736f 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -2,7 +2,6 @@
use rustc_abi::Align;
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
-use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::Symbol;
use rustc_target::spec::SanitizerSet;
@@ -161,6 +160,8 @@ impl CodegenFnAttrFlags: u32 {
const ALLOCATOR_ZEROED = 1 << 14;
/// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
const NO_BUILTINS = 1 << 15;
+ /// Marks foreign items, to make `contains_extern_indicator` cheaper.
+ const FOREIGN_ITEM = 1 << 16;
}
}
rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
@@ -194,8 +195,8 @@ pub const fn new() -> CodegenFnAttrs {
/// * `#[linkage]` is present
///
/// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
- pub fn contains_extern_indicator(&self, tcx: TyCtxt<'_>, did: DefId) -> bool {
- if tcx.is_foreign_item(did) {
+ pub fn contains_extern_indicator(&self) -> bool {
+ if self.flags.contains(CodegenFnAttrFlags::FOREIGN_ITEM) {
return false;
}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index ea8596e..dbbd954 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -120,6 +120,17 @@ pub fn get_byte(&self, offset: Size, cx: &impl HasDataLayout) -> Option<(Prov, u
}
}
+ /// Gets the provenances of all bytes (including from pointers) in a range.
+ pub fn get_range(
+ &self,
+ cx: &impl HasDataLayout,
+ range: AllocRange,
+ ) -> impl Iterator<Item = Prov> {
+ let ptr_provs = self.range_ptrs_get(range, cx).iter().map(|(_, p)| *p);
+ let byte_provs = self.range_bytes_get(range).iter().map(|(_, (p, _))| *p);
+ ptr_provs.chain(byte_provs)
+ }
+
/// Attempt to merge per-byte provenance back into ptr chunks, if the right fragments
/// sit next to each other. Return `false` is that is not possible due to partial pointers.
pub fn merge_bytes(&mut self, cx: &impl HasDataLayout) -> bool {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 533066b..6b45b2d 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -149,7 +149,7 @@ pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
// instantiation:
// We emit an unused_attributes lint for this case, which should be kept in sync if possible.
let codegen_fn_attrs = tcx.codegen_instance_attrs(instance.def);
- if codegen_fn_attrs.contains_extern_indicator(tcx, instance.def.def_id())
+ if codegen_fn_attrs.contains_extern_indicator()
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
{
return InstantiationMode::GloballyShared { may_conflict: false };
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index a8a95c6..466b9c7 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -149,8 +149,15 @@ pub enum ConstraintCategory<'tcx> {
/// A constraint that doesn't correspond to anything the user sees.
Internal,
- /// An internal constraint derived from an illegal universe relation.
- IllegalUniverse,
+ /// An internal constraint added when a region outlives a placeholder
+ /// it cannot name and therefore has to outlive `'static`. The argument
+ /// is the unnameable placeholder and the constraint is always between
+ /// an SCC representative and `'static`.
+ OutlivesUnnameablePlaceholder(
+ #[type_foldable(identity)]
+ #[type_visitable(ignore)]
+ ty::RegionVid,
+ ),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 6039a03..3b8def6 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1371,12 +1371,7 @@ pub enum Rvalue<'tcx> {
/// Creates an array where each element is the value of the operand.
///
- /// This is the cause of a bug in the case where the repetition count is zero because the value
- /// is not dropped, see [#74836].
- ///
/// Corresponds to source code like `[x; 32]`.
- ///
- /// [#74836]: https://github.com/rust-lang/rust/issues/74836
Repeat(Operand<'tcx>, ty::Const<'tcx>),
/// Creates a reference of the indicated kind to the place.
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d4f88c4..7bd8a05 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -696,6 +696,22 @@
return_result_from_ensure_ok
}
+ /// Used in case `mir_borrowck` fails to prove an obligation. We generally assume that
+ /// all goals we prove in MIR type check hold as we've already checked them in HIR typeck.
+ ///
+ /// However, we replace each free region in the MIR body with a unique region inference
+ /// variable. As we may rely on structural identity when proving goals this may cause a
+ /// goal to no longer hold. We store obligations for which this may happen during HIR
+ /// typeck in the `TypeckResults`. We then uniquify and reprove them in case MIR typeck
+ /// encounters an unexpected error. We expect this to result in an error when used and
+ /// delay a bug if it does not.
+ query check_potentially_region_dependent_goals(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
+ desc {
+ |tcx| "reproving potentially region dependent HIR typeck goals for `{}",
+ tcx.def_path_str(key)
+ }
+ }
+
/// MIR after our optimization passes have run. This is MIR that is ready
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 49a4733..5dbbc72 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -33,7 +33,7 @@
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, LintEmitter, MultiSpan,
};
use rustc_hir::attrs::AttributeKind;
-use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState};
use rustc_hir::intravisit::VisitorExt;
@@ -52,7 +52,7 @@
use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
use rustc_type_ir::TyKind::*;
-use rustc_type_ir::lang_items::TraitSolverLangItem;
+use rustc_type_ir::lang_items::{SolverLangItem, SolverTraitLangItem};
pub use rustc_type_ir::lift::Lift;
use rustc_type_ir::{
CollectAndApply, Interner, TypeFlags, TypeFoldable, WithCachedTypeInfo, elaborate, search_graph,
@@ -93,6 +93,7 @@ fn next_trait_solver_globally(self) -> bool {
type DefId = DefId;
type LocalDefId = LocalDefId;
+ type TraitId = DefId;
type Span = Span;
type GenericArgs = ty::GenericArgsRef<'tcx>;
@@ -445,7 +446,10 @@ fn impl_is_const(self, def_id: DefId) -> bool {
}
fn fn_is_const(self, def_id: DefId) -> bool {
- debug_assert_matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
+ debug_assert_matches!(
+ self.def_kind(def_id),
+ DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn)
+ );
self.is_conditionally_const(def_id)
}
@@ -480,20 +484,32 @@ fn has_target_features(self, def_id: DefId) -> bool {
!self.codegen_fn_attrs(def_id).target_features.is_empty()
}
- fn require_lang_item(self, lang_item: TraitSolverLangItem) -> DefId {
- self.require_lang_item(trait_lang_item_to_lang_item(lang_item), DUMMY_SP)
+ fn require_lang_item(self, lang_item: SolverLangItem) -> DefId {
+ self.require_lang_item(solver_lang_item_to_lang_item(lang_item), DUMMY_SP)
}
- fn is_lang_item(self, def_id: DefId, lang_item: TraitSolverLangItem) -> bool {
- self.is_lang_item(def_id, trait_lang_item_to_lang_item(lang_item))
+ fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> DefId {
+ self.require_lang_item(solver_trait_lang_item_to_lang_item(lang_item), DUMMY_SP)
+ }
+
+ fn is_lang_item(self, def_id: DefId, lang_item: SolverLangItem) -> bool {
+ self.is_lang_item(def_id, solver_lang_item_to_lang_item(lang_item))
+ }
+
+ fn is_trait_lang_item(self, def_id: DefId, lang_item: SolverTraitLangItem) -> bool {
+ self.is_lang_item(def_id, solver_trait_lang_item_to_lang_item(lang_item))
}
fn is_default_trait(self, def_id: DefId) -> bool {
self.is_default_trait(def_id)
}
- fn as_lang_item(self, def_id: DefId) -> Option<TraitSolverLangItem> {
- lang_item_to_trait_lang_item(self.lang_items().from_def_id(def_id)?)
+ fn as_lang_item(self, def_id: DefId) -> Option<SolverLangItem> {
+ lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?)
+ }
+
+ fn as_trait_lang_item(self, def_id: DefId) -> Option<SolverTraitLangItem> {
+ lang_item_to_solver_trait_lang_item(self.lang_items().from_def_id(def_id)?)
}
fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator<Item = DefId> {
@@ -724,16 +740,19 @@ fn opaque_types_and_coroutines_defined_by(
}
macro_rules! bidirectional_lang_item_map {
- ($($name:ident),+ $(,)?) => {
- fn trait_lang_item_to_lang_item(lang_item: TraitSolverLangItem) -> LangItem {
+ (
+ $solver_ty:ident, $to_solver:ident, $from_solver:ident;
+ $($name:ident),+ $(,)?
+ ) => {
+ fn $from_solver(lang_item: $solver_ty) -> LangItem {
match lang_item {
- $(TraitSolverLangItem::$name => LangItem::$name,)+
+ $($solver_ty::$name => LangItem::$name,)+
}
}
- fn lang_item_to_trait_lang_item(lang_item: LangItem) -> Option<TraitSolverLangItem> {
+ fn $to_solver(lang_item: LangItem) -> Option<$solver_ty> {
Some(match lang_item {
- $(LangItem::$name => TraitSolverLangItem::$name,)+
+ $(LangItem::$name => $solver_ty::$name,)+
_ => return None,
})
}
@@ -741,40 +760,50 @@ fn lang_item_to_trait_lang_item(lang_item: LangItem) -> Option<TraitSolverLangIt
}
bidirectional_lang_item_map! {
+ SolverLangItem, lang_item_to_solver_lang_item, solver_lang_item_to_lang_item;
+
+// tidy-alphabetical-start
+ AsyncFnKindUpvars,
+ AsyncFnOnceOutput,
+ CallOnceFuture,
+ CallRefFuture,
+ CoroutineReturn,
+ CoroutineYield,
+ DynMetadata,
+ FutureOutput,
+ Metadata,
+ Option,
+ Poll,
+// tidy-alphabetical-end
+}
+
+bidirectional_lang_item_map! {
+ SolverTraitLangItem, lang_item_to_solver_trait_lang_item, solver_trait_lang_item_to_lang_item;
+
// tidy-alphabetical-start
AsyncFn,
AsyncFnKindHelper,
- AsyncFnKindUpvars,
AsyncFnMut,
AsyncFnOnce,
AsyncFnOnceOutput,
AsyncIterator,
BikeshedGuaranteedNoDrop,
- CallOnceFuture,
- CallRefFuture,
Clone,
Copy,
Coroutine,
- CoroutineReturn,
- CoroutineYield,
Destruct,
DiscriminantKind,
Drop,
- DynMetadata,
Fn,
FnMut,
FnOnce,
FnPtrTrait,
FusedIterator,
Future,
- FutureOutput,
Iterator,
MetaSized,
- Metadata,
- Option,
PointeeSized,
PointeeTrait,
- Poll,
Sized,
TransmuteTrait,
Tuple,
@@ -1418,6 +1447,8 @@ pub struct TyCtxt<'tcx> {
}
impl<'tcx> LintEmitter for TyCtxt<'tcx> {
+ type Id = HirId;
+
fn emit_node_span_lint(
self,
lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a7298af..e567ba0 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -829,14 +829,15 @@ pub fn remap_generic_params_to_declaration_params(
// Convert the type from the function into a type valid outside by mapping generic
// parameters to into the context of the opaque.
//
- // We erase regions when doing this during HIR typeck.
+ // We erase regions when doing this during HIR typeck. We manually use `fold_regions`
+ // here as we do not want to anonymize bound variables.
let this = match defining_scope_kind {
- DefiningScopeKind::HirTypeck => tcx.erase_regions(self),
+ DefiningScopeKind::HirTypeck => fold_regions(tcx, self, |_, _| tcx.lifetimes.re_erased),
DefiningScopeKind::MirBorrowck => self,
};
let result = this.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span));
if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) {
- assert_eq!(result.ty, tcx.erase_regions(result.ty));
+ assert_eq!(result.ty, fold_regions(tcx, result.ty, |_, _| tcx.lifetimes.re_erased));
}
result
}
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 59e2b2a..4e38d96 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -6,6 +6,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_macros::{Decodable, Encodable, HashStable};
+use rustc_span::symbol::sym;
use tracing::debug;
use crate::query::LocalCrate;
@@ -239,6 +240,12 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
/// Query provider for `incoherent_impls`.
pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
+ if let Some(def_id) = simp.def()
+ && !tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls)
+ {
+ return &[];
+ }
+
let mut impls = Vec::new();
for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index f42dbbd..8dd80aa 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -206,6 +206,16 @@ pub struct TypeckResults<'tcx> {
/// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
+ /// Goals proven during HIR typeck which may be potentially region dependent.
+ ///
+ /// Borrowck *uniquifies* regions which may cause these goal to be ambiguous in MIR
+ /// type check. We ICE if goals fail in borrowck to detect bugs during MIR building or
+ /// missed checks in HIR typeck. To avoid ICE due to region dependence we store all
+ /// goals which may be region dependent and reprove them in case borrowck encounters
+ /// an error.
+ pub potentially_region_dependent_goals:
+ FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
+
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
/// on closure size.
pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
@@ -245,6 +255,7 @@ pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
closure_fake_reads: Default::default(),
rvalue_scopes: Default::default(),
coroutine_stalled_predicates: Default::default(),
+ potentially_region_dependent_goals: Default::default(),
closure_size_eval: Default::default(),
transmutes_to_check: Default::default(),
offset_of_data: Default::default(),
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index f756f0a..440cb0b 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -5,9 +5,9 @@
[dependencies]
# tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
-rustc_apfloat = "0.2.0"
+rustc_apfloat.workspace = true
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
@@ -23,5 +23,5 @@
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 9621f9f..11713bb 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-polonius-engine = "0.13.0"
+polonius-engine.workspace = true
regex = "1"
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
@@ -18,5 +18,5 @@
rustc_middle = { path = "../rustc_middle" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 08c43a4..99ef67e 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -5,8 +5,8 @@
[dependencies]
# tidy-alphabetical-start
-either = "1"
-itertools = "0.12"
+either.workspace = true
+itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
@@ -26,5 +26,5 @@
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_mir_transform/src/check_enums.rs b/compiler/rustc_mir_transform/src/check_enums.rs
index 33a87cb..12447dc 100644
--- a/compiler/rustc_mir_transform/src/check_enums.rs
+++ b/compiler/rustc_mir_transform/src/check_enums.rs
@@ -48,6 +48,21 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let new_block = split_block(basic_blocks, location);
match check {
+ EnumCheckType::Direct { op_size, .. }
+ | EnumCheckType::WithNiche { op_size, .. }
+ if op_size.bytes() == 0 =>
+ {
+ // It is never valid to use a ZST as a discriminant for an inhabited enum, but that will
+ // have been caught by the type checker. Do nothing but ensure that a bug has been signaled.
+ tcx.dcx().span_delayed_bug(
+ source_info.span,
+ "cannot build enum discriminant from zero-sized type",
+ );
+ basic_blocks[block].terminator = Some(Terminator {
+ source_info,
+ kind: TerminatorKind::Goto { target: new_block },
+ });
+ }
EnumCheckType::Direct { source_op, discr, op_size, valid_discrs } => {
insert_direct_enum_check(
tcx,
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 03fdf9f..b186c2b 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -18,7 +18,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
// If this has an extern indicator, then this function is globally shared and thus will not
// generate cgu-internal copies which would make it cross-crate inlinable.
- if codegen_fn_attrs.contains_extern_indicator(tcx, def_id.into()) {
+ if codegen_fn_attrs.contains_extern_indicator() {
return false;
}
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index 09a55f0..78266d3 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -16,6 +16,6 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
serde = "1"
-serde_json = "1"
-tracing = "0.1"
+serde_json.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index 05bcaba..43db90c 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -5,13 +5,13 @@
[dependencies]
# tidy-alphabetical-start
-derive-where = "1.2.7"
+derive-where.workspace = true
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 3e1f486..da05c49 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -25,12 +25,8 @@ enum CanonicalizeInputKind {
/// trait candidates relies on it when deciding whether a where-bound
/// is trivial.
ParamEnv,
- /// When canonicalizing predicates, we don't keep `'static`. If we're
- /// currently outside of the trait solver and canonicalize the root goal
- /// during HIR typeck, we replace each occurrence of a region with a
- /// unique region variable. See the comment on `InferCtxt::in_hir_typeck`
- /// for more details.
- Predicate { is_hir_typeck_root_goal: bool },
+ /// When canonicalizing predicates, we don't keep `'static`.
+ Predicate,
}
/// Whether we're canonicalizing a query input or the query response.
@@ -191,7 +187,6 @@ fn canonicalize_param_env(
pub fn canonicalize_input<P: TypeFoldable<I>>(
delegate: &'a D,
variables: &'a mut Vec<I::GenericArg>,
- is_hir_typeck_root_goal: bool,
input: QueryInput<I, P>,
) -> ty::Canonical<I, QueryInput<I, P>> {
// First canonicalize the `param_env` while keeping `'static`
@@ -201,9 +196,7 @@ pub fn canonicalize_input<P: TypeFoldable<I>>(
// while *mostly* reusing the canonicalizer from above.
let mut rest_canonicalizer = Canonicalizer {
delegate,
- canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::Predicate {
- is_hir_typeck_root_goal,
- }),
+ canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::Predicate),
variables,
variable_lookup_table,
@@ -481,31 +474,13 @@ fn fold_region(&mut self, r: I::Region) -> I::Region {
}
};
- let var = if let CanonicalizeMode::Input(CanonicalizeInputKind::Predicate {
- is_hir_typeck_root_goal: true,
- }) = self.canonicalize_mode
- {
- let var = ty::BoundVar::from(self.variables.len());
- self.variables.push(r.into());
- self.var_kinds.push(kind);
- var
- } else {
- self.get_or_insert_bound_var(r, kind)
- };
+ let var = self.get_or_insert_bound_var(r, kind);
Region::new_anon_bound(self.cx(), self.binder_index, var)
}
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
- if let CanonicalizeMode::Input(CanonicalizeInputKind::Predicate {
- is_hir_typeck_root_goal: true,
- }) = self.canonicalize_mode
- {
- // If we're canonicalizing a root goal during HIR typeck, we
- // must not use the `cache` as we want to map each occurrence
- // of a region to a unique existential variable.
- self.inner_fold_ty(t)
- } else if let Some(&ty) = self.cache.get(&(self.binder_index, t)) {
+ if let Some(&ty) = self.cache.get(&(self.binder_index, t)) {
ty
} else {
let res = self.inner_fold_ty(t);
diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs
index f8215a2..79219b3 100644
--- a/compiler/rustc_next_trait_solver/src/coherence.rs
+++ b/compiler/rustc_next_trait_solver/src/coherence.rs
@@ -295,7 +295,7 @@ fn found_uncovered_ty_param(&mut self, ty: I::Ty) -> ControlFlow<OrphanCheckEarl
ControlFlow::Break(OrphanCheckEarlyExit::UncoveredTyParam(ty))
}
- fn def_id_is_local(&mut self, def_id: I::DefId) -> bool {
+ fn def_id_is_local(&mut self, def_id: impl DefId<I>) -> bool {
match self.in_crate {
InCrate::Local { .. } => def_id.is_local(),
InCrate::Remote => false,
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index a4a8317..be7e4dd 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -7,7 +7,7 @@
use derive_where::derive_where;
use rustc_type_ir::inherent::*;
-use rustc_type_ir::lang_items::TraitSolverLangItem;
+use rustc_type_ir::lang_items::SolverTraitLangItem;
use rustc_type_ir::search_graph::CandidateHeadUsages;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::{
@@ -54,7 +54,7 @@ pub(super) trait GoalKind<D, I = <D as SolverDelegate>::Interner>:
fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self;
- fn trait_def_id(self, cx: I) -> I::DefId;
+ fn trait_def_id(self, cx: I) -> I::TraitId;
/// Consider a clause, which consists of a "assumption" and some "requirements",
/// to satisfy a goal. If the requirements hold, then attempt to satisfy our
@@ -516,80 +516,80 @@ fn assemble_builtin_impl_candidates<G: GoalKind<D>>(
} else if cx.trait_is_alias(trait_def_id) {
G::consider_trait_alias_candidate(self, goal)
} else {
- match cx.as_lang_item(trait_def_id) {
- Some(TraitSolverLangItem::Sized) => {
+ match cx.as_trait_lang_item(trait_def_id) {
+ Some(SolverTraitLangItem::Sized) => {
G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::Sized)
}
- Some(TraitSolverLangItem::MetaSized) => {
+ Some(SolverTraitLangItem::MetaSized) => {
G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::MetaSized)
}
- Some(TraitSolverLangItem::PointeeSized) => {
+ Some(SolverTraitLangItem::PointeeSized) => {
unreachable!("`PointeeSized` is removed during lowering");
}
- Some(TraitSolverLangItem::Copy | TraitSolverLangItem::Clone) => {
+ Some(SolverTraitLangItem::Copy | SolverTraitLangItem::Clone) => {
G::consider_builtin_copy_clone_candidate(self, goal)
}
- Some(TraitSolverLangItem::Fn) => {
+ Some(SolverTraitLangItem::Fn) => {
G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::Fn)
}
- Some(TraitSolverLangItem::FnMut) => {
+ Some(SolverTraitLangItem::FnMut) => {
G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::FnMut)
}
- Some(TraitSolverLangItem::FnOnce) => {
+ Some(SolverTraitLangItem::FnOnce) => {
G::consider_builtin_fn_trait_candidates(self, goal, ty::ClosureKind::FnOnce)
}
- Some(TraitSolverLangItem::AsyncFn) => {
+ Some(SolverTraitLangItem::AsyncFn) => {
G::consider_builtin_async_fn_trait_candidates(self, goal, ty::ClosureKind::Fn)
}
- Some(TraitSolverLangItem::AsyncFnMut) => {
+ Some(SolverTraitLangItem::AsyncFnMut) => {
G::consider_builtin_async_fn_trait_candidates(
self,
goal,
ty::ClosureKind::FnMut,
)
}
- Some(TraitSolverLangItem::AsyncFnOnce) => {
+ Some(SolverTraitLangItem::AsyncFnOnce) => {
G::consider_builtin_async_fn_trait_candidates(
self,
goal,
ty::ClosureKind::FnOnce,
)
}
- Some(TraitSolverLangItem::FnPtrTrait) => {
+ Some(SolverTraitLangItem::FnPtrTrait) => {
G::consider_builtin_fn_ptr_trait_candidate(self, goal)
}
- Some(TraitSolverLangItem::AsyncFnKindHelper) => {
+ Some(SolverTraitLangItem::AsyncFnKindHelper) => {
G::consider_builtin_async_fn_kind_helper_candidate(self, goal)
}
- Some(TraitSolverLangItem::Tuple) => G::consider_builtin_tuple_candidate(self, goal),
- Some(TraitSolverLangItem::PointeeTrait) => {
+ Some(SolverTraitLangItem::Tuple) => G::consider_builtin_tuple_candidate(self, goal),
+ Some(SolverTraitLangItem::PointeeTrait) => {
G::consider_builtin_pointee_candidate(self, goal)
}
- Some(TraitSolverLangItem::Future) => {
+ Some(SolverTraitLangItem::Future) => {
G::consider_builtin_future_candidate(self, goal)
}
- Some(TraitSolverLangItem::Iterator) => {
+ Some(SolverTraitLangItem::Iterator) => {
G::consider_builtin_iterator_candidate(self, goal)
}
- Some(TraitSolverLangItem::FusedIterator) => {
+ Some(SolverTraitLangItem::FusedIterator) => {
G::consider_builtin_fused_iterator_candidate(self, goal)
}
- Some(TraitSolverLangItem::AsyncIterator) => {
+ Some(SolverTraitLangItem::AsyncIterator) => {
G::consider_builtin_async_iterator_candidate(self, goal)
}
- Some(TraitSolverLangItem::Coroutine) => {
+ Some(SolverTraitLangItem::Coroutine) => {
G::consider_builtin_coroutine_candidate(self, goal)
}
- Some(TraitSolverLangItem::DiscriminantKind) => {
+ Some(SolverTraitLangItem::DiscriminantKind) => {
G::consider_builtin_discriminant_kind_candidate(self, goal)
}
- Some(TraitSolverLangItem::Destruct) => {
+ Some(SolverTraitLangItem::Destruct) => {
G::consider_builtin_destruct_candidate(self, goal)
}
- Some(TraitSolverLangItem::TransmuteTrait) => {
+ Some(SolverTraitLangItem::TransmuteTrait) => {
G::consider_builtin_transmute_candidate(self, goal)
}
- Some(TraitSolverLangItem::BikeshedGuaranteedNoDrop) => {
+ Some(SolverTraitLangItem::BikeshedGuaranteedNoDrop) => {
G::consider_builtin_bikeshed_guaranteed_no_drop_candidate(self, goal)
}
_ => Err(NoSolution),
@@ -600,7 +600,7 @@ fn assemble_builtin_impl_candidates<G: GoalKind<D>>(
// There may be multiple unsize candidates for a trait with several supertraits:
// `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
- if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Unsize) {
+ if cx.is_trait_lang_item(trait_def_id, SolverTraitLangItem::Unsize) {
candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal));
}
}
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index d25e74e..7c59408 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -4,7 +4,7 @@
use derive_where::derive_where;
use rustc_type_ir::data_structures::HashMap;
use rustc_type_ir::inherent::*;
-use rustc_type_ir::lang_items::TraitSolverLangItem;
+use rustc_type_ir::lang_items::{SolverLangItem, SolverTraitLangItem};
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::solve::inspect::ProbeKind;
use rustc_type_ir::{
@@ -454,7 +454,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
nested.push(
ty::TraitRef::new(
cx,
- cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper),
+ cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper),
[kind_ty, Ty::from_closure_kind(cx, goal_kind)],
)
.upcast(cx),
@@ -496,7 +496,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
let args = args.as_closure();
let bound_sig = args.sig();
let sig = bound_sig.skip_binder();
- let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
+ let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
// `Closure`s only implement `AsyncFn*` when their return type
// implements `Future`.
let mut nested = vec![
@@ -514,7 +514,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
}
} else {
let async_fn_kind_trait_def_id =
- cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper);
+ cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper);
// When we don't know the closure kind (and therefore also the closure's upvars,
// which are computed at the same time), we must delay the computation of the
// generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
@@ -532,7 +532,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
);
}
- let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
+ let future_output_def_id = cx.require_lang_item(SolverLangItem::FutureOutput);
let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
Ok((
bound_sig.rebind(AsyncCallableRelevantTypes {
@@ -581,13 +581,13 @@ fn fn_item_to_async_callable<I: Interner>(
bound_sig: ty::Binder<I, ty::FnSig<I>>,
) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
let sig = bound_sig.skip_binder();
- let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
+ let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
// `FnDef` and `FnPtr` only implement `AsyncFn*` when their
// return type implements `Future`.
let nested = vec![
bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
];
- let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
+ let future_output_def_id = cx.require_lang_item(SolverLangItem::FutureOutput);
let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
Ok((
bound_sig.rebind(AsyncCallableRelevantTypes {
@@ -633,7 +633,7 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
args: ty::CoroutineClosureArgs<I>,
sig: ty::CoroutineClosureSignature<I>,
) -> I::Ty {
- let upvars_projection_def_id = cx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars);
+ let upvars_projection_def_id = cx.require_lang_item(SolverLangItem::AsyncFnKindUpvars);
let tupled_upvars_ty = Ty::new_projection(
cx,
upvars_projection_def_id,
@@ -732,7 +732,7 @@ pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
cx: I,
self_ty: I::Ty,
) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
- let destruct_def_id = cx.require_lang_item(TraitSolverLangItem::Destruct);
+ let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct);
match self_ty.kind() {
// `ManuallyDrop` is trivially `[const] Destruct` as we do not run any drop glue on it.
@@ -751,7 +751,7 @@ pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
// `Drop` impl exists, and it's const. Require `Ty: [const] Drop` to hold.
Some(AdtDestructorKind::Const) => {
- let drop_def_id = cx.require_lang_item(TraitSolverLangItem::Drop);
+ let drop_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Drop);
let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
const_conditions.push(drop_trait_ref);
}
@@ -869,7 +869,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
// FIXME(associated_const_equality): Also add associated consts to
// the requirements here.
- for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
+ for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id.into()) {
// associated types that require `Self: Sized` do not show up in the built-in
// implementation of `Trait for dyn Trait`, and can be dropped here.
if cx.generics_require_sized_self(associated_type_def_id) {
diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
index 9a22bf5..2293450 100644
--- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
@@ -3,10 +3,10 @@
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
-use rustc_type_ir::lang_items::TraitSolverLangItem;
+use rustc_type_ir::lang_items::SolverTraitLangItem;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::solve::inspect::ProbeKind;
-use rustc_type_ir::{self as ty, Interner, elaborate};
+use rustc_type_ir::{self as ty, Interner, TypingMode, elaborate};
use tracing::instrument;
use super::assembly::{Candidate, structural_traits};
@@ -33,7 +33,7 @@ fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
self.with_replaced_self_ty(cx, self_ty)
}
- fn trait_def_id(self, _: I) -> I::DefId {
+ fn trait_def_id(self, _: I) -> I::TraitId {
self.def_id()
}
@@ -135,12 +135,16 @@ fn consider_impl_candidate(
}
let impl_polarity = cx.impl_polarity(impl_def_id);
- match impl_polarity {
+ let certainty = match impl_polarity {
ty::ImplPolarity::Negative => return Err(NoSolution),
- ty::ImplPolarity::Reservation => {
- unimplemented!("reservation impl for const trait: {:?}", goal)
- }
- ty::ImplPolarity::Positive => {}
+ ty::ImplPolarity::Reservation => match ecx.typing_mode() {
+ TypingMode::Coherence => Certainty::AMBIGUOUS,
+ TypingMode::Analysis { .. }
+ | TypingMode::Borrowck { .. }
+ | TypingMode::PostBorrowckAnalysis { .. }
+ | TypingMode::PostAnalysis => return Err(NoSolution),
+ },
+ ty::ImplPolarity::Positive => Certainty::Yes,
};
if !cx.impl_is_const(impl_def_id) {
@@ -171,7 +175,7 @@ fn consider_impl_candidate(
});
ecx.add_goals(GoalSource::ImplWhereBound, const_conditions);
- ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ ecx.evaluate_added_goals_and_make_canonical_response(certainty)
})
}
@@ -233,7 +237,7 @@ fn consider_builtin_fn_trait_candidates(
// A built-in `Fn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
let output_is_sized_pred = inputs_and_output.map_bound(|(_, output)| {
- ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
+ ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output])
});
let requirements = cx
.const_conditions(def_id)
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index 74c5b49..4644b14 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -57,7 +57,6 @@ impl<D, I> EvalCtxt<'_, D>
/// This expects `goal` and `opaque_types` to be eager resolved.
pub(super) fn canonicalize_goal(
&self,
- is_hir_typeck_root_goal: bool,
goal: Goal<I, I::Predicate>,
opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>) {
@@ -65,7 +64,6 @@ pub(super) fn canonicalize_goal(
let canonical = Canonicalizer::canonicalize_input(
self.delegate,
&mut orig_values,
- is_hir_typeck_root_goal,
QueryInput {
goal,
predefined_opaques_in_body: self
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index a473830..4f87902 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -4,7 +4,6 @@
#[cfg(feature = "nightly")]
use rustc_macros::HashStable_NoContext;
use rustc_type_ir::data_structures::{HashMap, HashSet};
-use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::relate::Relate;
use rustc_type_ir::relate::solver_relating::RelateExt;
@@ -459,10 +458,7 @@ pub(super) fn evaluate_goal_raw(
let opaque_types = self.delegate.clone_opaque_types_lookup_table();
let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
- let is_hir_typeck_root_goal = matches!(goal_evaluation_kind, GoalEvaluationKind::Root)
- && self.delegate.in_hir_typeck();
- let (orig_values, canonical_goal) =
- self.canonicalize_goal(is_hir_typeck_root_goal, goal, opaque_types);
+ let (orig_values, canonical_goal) = self.canonicalize_goal(goal, opaque_types);
let mut goal_evaluation =
self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
let canonical_result = self.search_graph.evaluate_goal(
@@ -1131,6 +1127,7 @@ pub(super) fn fetch_eligible_assoc_item(
self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
}
+ #[instrument(level = "debug", skip(self), ret)]
pub(super) fn register_hidden_type_in_storage(
&mut self,
opaque_type_key: ty::OpaqueTypeKey<I>,
@@ -1157,29 +1154,6 @@ pub(super) fn add_item_bounds_for_hidden_type(
self.add_goals(GoalSource::AliasWellFormed, goals);
}
- // Do something for each opaque/hidden pair defined with `def_id` in the
- // current inference context.
- pub(super) fn probe_existing_opaque_ty(
- &mut self,
- key: ty::OpaqueTypeKey<I>,
- ) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> {
- // We shouldn't have any duplicate entries when using
- // this function during `TypingMode::Analysis`.
- let duplicate_entries = self.delegate.clone_duplicate_opaque_types();
- assert!(duplicate_entries.is_empty(), "unexpected duplicates: {duplicate_entries:?}");
- let mut matching = self.delegate.clone_opaque_types_lookup_table().into_iter().filter(
- |(candidate_key, _)| {
- candidate_key.def_id == key.def_id
- && DeepRejectCtxt::relate_rigid_rigid(self.cx())
- .args_may_unify(candidate_key.args, key.args)
- },
- );
- let first = matching.next();
- let second = matching.next();
- assert_eq!(second, None);
- first
- }
-
// Try to evaluate a const, or return `None` if the const is too generic.
// This doesn't mean the const isn't evaluatable, though, and should be treated
// as an ambiguity rather than no-solution.
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index c2745c8..710b59f 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -130,7 +130,7 @@ fn compute_subtype_goal(&mut self, goal: Goal<I, ty::SubtypePredicate<I>>) -> Qu
}
}
- fn compute_dyn_compatible_goal(&mut self, trait_def_id: I::DefId) -> QueryResult<I> {
+ fn compute_dyn_compatible_goal(&mut self, trait_def_id: I::TraitId) -> QueryResult<I> {
if self.cx().trait_is_dyn_compatible(trait_def_id) {
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 93434dc..cfdf200 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -5,7 +5,7 @@
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
-use rustc_type_ir::lang_items::TraitSolverLangItem;
+use rustc_type_ir::lang_items::{SolverLangItem, SolverTraitLangItem};
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::{self as ty, Interner, NormalizesTo, PredicateKind, Upcast as _};
use tracing::instrument;
@@ -103,7 +103,7 @@ fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
self.with_replaced_self_ty(cx, self_ty)
}
- fn trait_def_id(self, cx: I) -> I::DefId {
+ fn trait_def_id(self, cx: I) -> I::TraitId {
self.trait_def_id(cx)
}
@@ -456,7 +456,7 @@ fn consider_builtin_fn_trait_candidates(
// A built-in `Fn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
- ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
+ ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output])
});
let pred = tupled_inputs_and_output
@@ -503,7 +503,11 @@ fn consider_builtin_async_fn_trait_candidates(
// (FIXME: technically we only need to check this if the type is a fn ptr...)
let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
|AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
- ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output_ty])
+ ty::TraitRef::new(
+ cx,
+ cx.require_trait_lang_item(SolverTraitLangItem::Sized),
+ [output_ty],
+ )
},
);
@@ -515,7 +519,7 @@ fn consider_builtin_async_fn_trait_candidates(
coroutine_return_ty,
}| {
let (projection_term, term) = if cx
- .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallOnceFuture)
+ .is_lang_item(goal.predicate.def_id(), SolverLangItem::CallOnceFuture)
{
(
ty::AliasTerm::new(
@@ -526,7 +530,7 @@ fn consider_builtin_async_fn_trait_candidates(
output_coroutine_ty.into(),
)
} else if cx
- .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallRefFuture)
+ .is_lang_item(goal.predicate.def_id(), SolverLangItem::CallRefFuture)
{
(
ty::AliasTerm::new(
@@ -540,10 +544,9 @@ fn consider_builtin_async_fn_trait_candidates(
),
output_coroutine_ty.into(),
)
- } else if cx.is_lang_item(
- goal.predicate.def_id(),
- TraitSolverLangItem::AsyncFnOnceOutput,
- ) {
+ } else if cx
+ .is_lang_item(goal.predicate.def_id(), SolverLangItem::AsyncFnOnceOutput)
+ {
(
ty::AliasTerm::new(
cx,
@@ -637,7 +640,7 @@ fn consider_builtin_pointee_candidate(
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
let cx = ecx.cx();
- let metadata_def_id = cx.require_lang_item(TraitSolverLangItem::Metadata);
+ let metadata_def_id = cx.require_lang_item(SolverLangItem::Metadata);
assert_eq!(metadata_def_id, goal.predicate.def_id());
let metadata_ty = match goal.predicate.self_ty().kind() {
ty::Bool
@@ -664,7 +667,7 @@ fn consider_builtin_pointee_candidate(
ty::Str | ty::Slice(_) => Ty::new_usize(cx),
ty::Dynamic(_, _, ty::Dyn) => {
- let dyn_metadata = cx.require_lang_item(TraitSolverLangItem::DynMetadata);
+ let dyn_metadata = cx.require_lang_item(SolverLangItem::DynMetadata);
cx.type_of(dyn_metadata)
.instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
}
@@ -678,7 +681,7 @@ fn consider_builtin_pointee_candidate(
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
let sized_predicate = ty::TraitRef::new(
cx,
- cx.require_lang_item(TraitSolverLangItem::Sized),
+ cx.require_trait_lang_item(SolverTraitLangItem::Sized),
[I::GenericArg::from(goal.predicate.self_ty())],
);
ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
@@ -821,10 +824,10 @@ fn consider_builtin_async_iterator_candidate(
// coroutine yield ty `Poll<Option<I>>`.
let wrapped_expected_ty = Ty::new_adt(
cx,
- cx.adt_def(cx.require_lang_item(TraitSolverLangItem::Poll)),
+ cx.adt_def(cx.require_lang_item(SolverLangItem::Poll)),
cx.mk_args(&[Ty::new_adt(
cx,
- cx.adt_def(cx.require_lang_item(TraitSolverLangItem::Option)),
+ cx.adt_def(cx.require_lang_item(SolverLangItem::Option)),
cx.mk_args(&[expected_ty.into()]),
)
.into()]),
@@ -853,10 +856,9 @@ fn consider_builtin_coroutine_candidate(
let coroutine = args.as_coroutine();
- let term = if cx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineReturn)
- {
+ let term = if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineReturn) {
coroutine.return_ty().into()
- } else if cx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineYield) {
+ } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineYield) {
coroutine.yield_ty().into()
} else {
panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id())
@@ -983,13 +985,13 @@ fn translate_args(
target_container_def_id: I::DefId,
) -> Result<I::GenericArgs, NoSolution> {
let cx = self.cx();
- Ok(if target_container_def_id == impl_trait_ref.def_id {
+ Ok(if target_container_def_id == impl_trait_ref.def_id.into() {
// Default value from the trait definition. No need to rebase.
goal.predicate.alias.args
} else if target_container_def_id == impl_def_id {
// Same impl, no need to fully translate, just a rebase from
// the trait is sufficient.
- goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id, impl_args)
+ goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args)
} else {
let target_args = self.fresh_args_for_item(target_container_def_id);
let target_trait_ref =
@@ -1004,7 +1006,7 @@ fn translate_args(
.iter_instantiated(cx, target_args)
.map(|pred| goal.with(cx, pred)),
);
- goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id, target_args)
+ goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args)
})
}
}
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index df3ad1e..a5f857a 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -1,13 +1,12 @@
//! Computes a normalizes-to (projection) goal for opaque types. This goal
//! behaves differently depending on the current `TypingMode`.
-use rustc_index::bit_set::GrowableBitSet;
use rustc_type_ir::inherent::*;
use rustc_type_ir::solve::GoalSource;
use rustc_type_ir::{self as ty, Interner, TypingMode, fold_regions};
use crate::delegate::SolverDelegate;
-use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect};
+use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};
impl<D, I> EvalCtxt<'_, D>
where
@@ -39,100 +38,68 @@ pub(super) fn normalize_opaque_type(
self.add_goal(GoalSource::Misc, goal.with(cx, ty::PredicateKind::Ambiguous));
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
- TypingMode::Analysis { defining_opaque_types_and_generators } => {
- let Some(def_id) = opaque_ty
- .def_id
- .as_local()
- .filter(|&def_id| defining_opaque_types_and_generators.contains(&def_id))
- else {
- self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
- return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
- };
-
- // FIXME: This may have issues when the args contain aliases...
- match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) {
- Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
- return self.evaluate_added_goals_and_make_canonical_response(
- Certainty::AMBIGUOUS,
- );
- }
- Err(_) => {
- return Err(NoSolution);
- }
- Ok(()) => {}
- }
- // Prefer opaques registered already.
- let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
- // FIXME: This also unifies the previous hidden type with the expected.
- //
- // If that fails, we insert `expected` as a new hidden type instead of
- // eagerly emitting an error.
- let existing = self.probe_existing_opaque_ty(opaque_type_key);
- if let Some((candidate_key, candidate_ty)) = existing {
- return self
- .probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup {
- result: *result,
- })
- .enter(|ecx| {
- for (a, b) in std::iter::zip(
- candidate_key.args.iter(),
- opaque_type_key.args.iter(),
- ) {
- ecx.eq(goal.param_env, a, b)?;
- }
- ecx.eq(goal.param_env, candidate_ty, expected)?;
- ecx.add_item_bounds_for_hidden_type(
- def_id.into(),
- candidate_key.args,
- goal.param_env,
- candidate_ty,
- );
- ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
- });
- }
-
- // Otherwise, define a new opaque type
- let prev = self.register_hidden_type_in_storage(opaque_type_key, expected);
- assert_eq!(prev, None);
- self.add_item_bounds_for_hidden_type(
- def_id.into(),
- opaque_ty.args,
- goal.param_env,
- expected,
- );
- self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ TypingMode::Analysis {
+ defining_opaque_types_and_generators: defining_opaque_types,
}
- // Very similar to `TypingMode::Analysis` with some notably differences:
- // - we accept opaque types even if they have non-universal arguments
- // - we do a structural lookup instead of semantically unifying regions
- // - the hidden type starts out as the type from HIR typeck with fresh region
- // variables instead of a fully unconstrained inference variable
- TypingMode::Borrowck { defining_opaque_types } => {
+ | TypingMode::Borrowck { defining_opaque_types } => {
let Some(def_id) = opaque_ty
.def_id
.as_local()
.filter(|&def_id| defining_opaque_types.contains(&def_id))
else {
+ // If we're not in the defining scope, treat the alias as rigid.
self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
};
- let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
- let actual = self
- .register_hidden_type_in_storage(opaque_type_key, expected)
- .unwrap_or_else(|| {
- let actual =
- cx.type_of_opaque_hir_typeck(def_id).instantiate(cx, opaque_ty.args);
- let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
- ty::ReErased => self.next_region_var(),
- _ => re,
- });
- actual
- });
- self.eq(goal.param_env, expected, actual)?;
+ // We structurally normalize the args so that we're able to detect defining uses
+ // later on.
+ //
+ // This reduces the amount of duplicate definitions in the `opaque_type_storage` and
+ // strengthens inference. This causes us to subtly depend on the normalization behavior
+ // when inferring the hidden type of opaques.
+ //
+ // E.g. it's observable that we don't normalize nested aliases with bound vars in
+ // `structurally_normalize` and because we use structural lookup, we also don't
+ // reuse an entry for `Tait<for<'a> fn(&'a ())>` for `Tait<for<'b> fn(&'b ())>`.
+ let normalized_args =
+ cx.mk_args_from_iter(opaque_ty.args.iter().map(|arg| match arg.kind() {
+ ty::GenericArgKind::Lifetime(lt) => Ok(lt.into()),
+ ty::GenericArgKind::Type(ty) => {
+ self.structurally_normalize_ty(goal.param_env, ty).map(Into::into)
+ }
+ ty::GenericArgKind::Const(ct) => {
+ self.structurally_normalize_const(goal.param_env, ct).map(Into::into)
+ }
+ }))?;
+
+ let opaque_type_key = ty::OpaqueTypeKey { def_id, args: normalized_args };
+ if let Some(prev) = self.register_hidden_type_in_storage(opaque_type_key, expected)
+ {
+ self.eq(goal.param_env, expected, prev)?;
+ } else {
+ // During HIR typeck, opaque types start out as unconstrained
+ // inference variables. In borrowck we instead use the type
+ // computed in HIR typeck as the initial value.
+ match self.typing_mode() {
+ TypingMode::Analysis { .. } => {}
+ TypingMode::Borrowck { .. } => {
+ let actual = cx
+ .type_of_opaque_hir_typeck(def_id)
+ .instantiate(cx, opaque_ty.args);
+ let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
+ ty::ReErased => self.next_region_var(),
+ _ => re,
+ });
+ self.eq(goal.param_env, expected, actual)?;
+ }
+ _ => unreachable!(),
+ }
+ }
+
self.add_item_bounds_for_hidden_type(
def_id.into(),
- opaque_ty.args,
+ normalized_args,
goal.param_env,
expected,
);
@@ -168,44 +135,3 @@ pub(super) fn normalize_opaque_type(
}
}
}
-
-/// Checks whether each generic argument is simply a unique generic placeholder.
-///
-/// FIXME: Interner argument is needed to constrain the `I` parameter.
-fn uses_unique_placeholders_ignoring_regions<I: Interner>(
- _cx: I,
- args: I::GenericArgs,
-) -> Result<(), NotUniqueParam<I>> {
- let mut seen = GrowableBitSet::default();
- for arg in args.iter() {
- match arg.kind() {
- // Ignore regions, since we can't resolve those in a canonicalized
- // query in the trait solver.
- ty::GenericArgKind::Lifetime(_) => {}
- ty::GenericArgKind::Type(t) => match t.kind() {
- ty::Placeholder(p) => {
- if !seen.insert(p.var()) {
- return Err(NotUniqueParam::DuplicateParam(t.into()));
- }
- }
- _ => return Err(NotUniqueParam::NotParam(t.into())),
- },
- ty::GenericArgKind::Const(c) => match c.kind() {
- ty::ConstKind::Placeholder(p) => {
- if !seen.insert(p.var()) {
- return Err(NotUniqueParam::DuplicateParam(c.into()));
- }
- }
- _ => return Err(NotUniqueParam::NotParam(c.into())),
- },
- }
- }
-
- Ok(())
-}
-
-// FIXME: This should check for dupes and non-params first, then infer vars.
-enum NotUniqueParam<I: Interner> {
- DuplicateParam(I::GenericArg),
- NotParam(I::GenericArg),
-}
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 891ecab..cdcfebf 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -3,7 +3,7 @@
use rustc_type_ir::data_structures::IndexSet;
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
-use rustc_type_ir::lang_items::TraitSolverLangItem;
+use rustc_type_ir::lang_items::SolverTraitLangItem;
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
use rustc_type_ir::{
self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef,
@@ -39,7 +39,7 @@ fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
self.with_replaced_self_ty(cx, self_ty)
}
- fn trait_def_id(self, _: I) -> I::DefId {
+ fn trait_def_id(self, _: I) -> I::TraitId {
self.def_id()
}
@@ -131,8 +131,8 @@ fn fast_reject_assumption(
) -> Result<(), NoSolution> {
fn trait_def_id_matches<I: Interner>(
cx: I,
- clause_def_id: I::DefId,
- goal_def_id: I::DefId,
+ clause_def_id: I::TraitId,
+ goal_def_id: I::TraitId,
polarity: PredicatePolarity,
) -> bool {
clause_def_id == goal_def_id
@@ -141,8 +141,8 @@ fn trait_def_id_matches<I: Interner>(
//
// `PointeeSized` bounds are syntactic sugar for a lack of bounds so don't need this.
|| (polarity == PredicatePolarity::Positive
- && cx.is_lang_item(clause_def_id, TraitSolverLangItem::Sized)
- && cx.is_lang_item(goal_def_id, TraitSolverLangItem::MetaSized))
+ && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized)
+ && cx.is_trait_lang_item(goal_def_id, SolverTraitLangItem::MetaSized))
}
if let Some(trait_clause) = assumption.as_trait_clause()
@@ -177,8 +177,8 @@ fn match_assumption(
// are syntactic sugar for a lack of bounds so don't need this.
// We don't need to check polarity, `fast_reject_assumption` already rejected non-`Positive`
// polarity `Sized` assumptions as matching non-`Positive` `MetaSized` goals.
- if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized)
- && ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized)
+ if ecx.cx().is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::MetaSized)
+ && ecx.cx().is_trait_lang_item(trait_clause.def_id(), SolverTraitLangItem::Sized)
{
let meta_sized_clause =
trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
@@ -263,7 +263,7 @@ fn consider_trait_alias_candidate(
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
let nested_obligations = cx
- .predicates_of(goal.predicate.def_id())
+ .predicates_of(goal.predicate.def_id().into())
.iter_instantiated(cx, goal.predicate.trait_ref.args)
.map(|p| goal.with(cx, p));
// While you could think of trait aliases to have a single builtin impl
@@ -372,7 +372,7 @@ fn consider_builtin_fn_trait_candidates(
// A built-in `Fn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
- ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
+ ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output])
});
let pred = tupled_inputs_and_output
@@ -414,7 +414,7 @@ fn consider_builtin_async_fn_trait_candidates(
|AsyncCallableRelevantTypes { output_coroutine_ty, .. }| {
ty::TraitRef::new(
cx,
- cx.require_lang_item(TraitSolverLangItem::Sized),
+ cx.require_trait_lang_item(SolverTraitLangItem::Sized),
[output_coroutine_ty],
)
},
@@ -757,7 +757,7 @@ fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
cx,
ty::TraitRef::new(
cx,
- cx.require_lang_item(TraitSolverLangItem::Copy),
+ cx.require_trait_lang_item(SolverTraitLangItem::Copy),
[ty],
),
),
@@ -857,7 +857,7 @@ fn consider_structural_builtin_unsize_candidates(
fn trait_predicate_with_def_id<I: Interner>(
cx: I,
clause: ty::Binder<I, ty::TraitPredicate<I>>,
- did: I::DefId,
+ did: I::TraitId,
) -> I::Clause {
clause
.map_bound(|c| TraitPredicate {
@@ -956,7 +956,11 @@ fn consider_builtin_unsize_to_dyn_candidate(
GoalSource::ImplWhereBound,
goal.with(
cx,
- ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [a_ty]),
+ ty::TraitRef::new(
+ cx,
+ cx.require_trait_lang_item(SolverTraitLangItem::Sized),
+ [a_ty],
+ ),
),
);
@@ -981,7 +985,7 @@ fn consider_builtin_upcast_to_principal(
// We may upcast to auto traits that are either explicitly listed in
// the object type's bounds, or implied by the principal trait ref's
// supertraits.
- let a_auto_traits: IndexSet<I::DefId> = a_data
+ let a_auto_traits: IndexSet<I::TraitId> = a_data
.auto_traits()
.into_iter()
.chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
@@ -1143,7 +1147,7 @@ fn consider_builtin_struct_unsize(
cx,
ty::TraitRef::new(
cx,
- cx.require_lang_item(TraitSolverLangItem::Unsize),
+ cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
[a_tail_ty, b_tail_ty],
),
),
@@ -1208,7 +1212,9 @@ fn disqualify_auto_trait_candidate_due_to_possible_impl(
// takes precedence over the structural auto trait candidate being
// assembled.
ty::Coroutine(def_id, _)
- if self.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::Unpin) =>
+ if self
+ .cx()
+ .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
{
match self.cx().coroutine_movability(def_id) {
Movability::Static => Some(Err(NoSolution)),
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index 6d738a1..7cb4ae7 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -5,8 +5,8 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
-rustc-literal-escaper = "0.0.5"
+bitflags.workspace = true
+rustc-literal-escaper.workspace = true
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" }
@@ -18,8 +18,8 @@
rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
unicode-normalization = "0.1.11"
unicode-width = "0.2.0"
# tidy-alphabetical-end
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 220e4ac..a28af78 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -463,8 +463,8 @@ pub(super) fn is_lit_bad_ident(&mut self) -> Option<(usize, Symbol)> {
pub(super) fn expected_one_of_not_found(
&mut self,
- edible: &[ExpTokenPair<'_>],
- inedible: &[ExpTokenPair<'_>],
+ edible: &[ExpTokenPair],
+ inedible: &[ExpTokenPair],
) -> PResult<'a, ErrorGuaranteed> {
debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible);
fn tokens_to_string(tokens: &[TokenType]) -> String {
@@ -1092,7 +1092,7 @@ pub(super) fn recover_closure_body(
/// Eats and discards tokens until one of `closes` is encountered. Respects token trees,
/// passes through any errors encountered. Used for error recovery.
- pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair<'_>]) {
+ pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair]) {
if let Err(err) = self
.parse_seq_to_before_tokens(closes, &[], SeqSep::none(), |p| Ok(p.parse_token_tree()))
{
@@ -1113,7 +1113,7 @@ pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair<'_>]) {
pub(super) fn check_trailing_angle_brackets(
&mut self,
segment: &PathSegment,
- end: &[ExpTokenPair<'_>],
+ end: &[ExpTokenPair],
) -> Option<ErrorGuaranteed> {
if !self.may_recover() {
return None;
@@ -1196,7 +1196,7 @@ pub(super) fn check_trailing_angle_brackets(
// second case.
if self.look_ahead(position, |t| {
trace!("check_trailing_angle_brackets: t={:?}", t);
- end.iter().any(|exp| exp.tok == &t.kind)
+ end.iter().any(|exp| exp.tok == t.kind)
}) {
// Eat from where we started until the end token so that parsing can continue
// as if we didn't have those extra angle brackets.
@@ -2120,8 +2120,8 @@ pub(super) fn expect_gt_or_maybe_suggest_closing_generics(
pub(super) fn recover_seq_parse_error(
&mut self,
- open: ExpTokenPair<'_>,
- close: ExpTokenPair<'_>,
+ open: ExpTokenPair,
+ close: ExpTokenPair,
lo: Span,
err: Diag<'a>,
) -> Box<Expr> {
@@ -2386,8 +2386,8 @@ pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a,
pub(super) fn consume_block(
&mut self,
- open: ExpTokenPair<'_>,
- close: ExpTokenPair<'_>,
+ open: ExpTokenPair,
+ close: ExpTokenPair,
consume_close: ConsumeClosingDelim,
) {
let mut brace_depth = 0;
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 1499808..7de4f6e 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1598,7 +1598,7 @@ fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a,
self.maybe_recover_from_bad_qpath(expr)
}
- fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair<'_>) -> PResult<'a, Box<Expr>> {
+ fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair) -> PResult<'a, Box<Expr>> {
let lo = self.token.span;
self.bump(); // `[` or other open delim
@@ -2077,7 +2077,7 @@ pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span)
(token::Lit { symbol: name, suffix: None, kind: token::Char }, span)
}
- pub fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
+ fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
ast::MetaItemLit {
symbol: name,
suffix: None,
@@ -2086,7 +2086,7 @@ pub fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
}
}
- pub fn handle_missing_lit<L>(
+ fn handle_missing_lit<L>(
&mut self,
mk_lit_char: impl FnOnce(Symbol, Span) -> L,
) -> PResult<'a, L> {
@@ -3661,7 +3661,7 @@ pub(super) fn parse_struct_fields(
&mut self,
pth: ast::Path,
recover: bool,
- close: ExpTokenPair<'_>,
+ close: ExpTokenPair,
) -> PResult<
'a,
(
@@ -3680,8 +3680,8 @@ pub(super) fn parse_struct_fields(
errors::HelpUseLatestEdition::new().add_to_diag(e);
};
- while self.token != *close.tok {
- if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(close.tok) {
+ while self.token != close.tok {
+ if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(&close.tok) {
let exp_span = self.prev_token.span;
// We permit `.. }` on the left-hand side of a destructuring assignment.
if self.check(close) {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index fd9fb65..eb264f5 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -54,7 +54,7 @@ fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
/// - `}` for mod items
pub fn parse_mod(
&mut self,
- term: ExpTokenPair<'_>,
+ term: ExpTokenPair,
) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
let lo = self.token.span;
let attrs = self.parse_inner_attributes()?;
@@ -1201,7 +1201,7 @@ fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
}?;
let dash = exp!(Minus);
- if self.token != *dash.tok {
+ if self.token != dash.tok {
return Ok(ident);
}
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index d19114d..15598f3 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -261,19 +261,19 @@ struct CaptureState {
/// A sequence separator.
#[derive(Debug)]
-struct SeqSep<'a> {
+struct SeqSep {
/// The separator token.
- sep: Option<ExpTokenPair<'a>>,
+ sep: Option<ExpTokenPair>,
/// `true` if a trailing separator is allowed.
trailing_sep_allowed: bool,
}
-impl<'a> SeqSep<'a> {
- fn trailing_allowed(sep: ExpTokenPair<'a>) -> SeqSep<'a> {
+impl SeqSep {
+ fn trailing_allowed(sep: ExpTokenPair) -> SeqSep {
SeqSep { sep: Some(sep), trailing_sep_allowed: true }
}
- fn none() -> SeqSep<'a> {
+ fn none() -> SeqSep {
SeqSep { sep: None, trailing_sep_allowed: false }
}
}
@@ -425,13 +425,13 @@ pub fn unexpected(&mut self) -> PResult<'a, ()> {
}
/// Expects and consumes the token `t`. Signals an error if the next token is not `t`.
- pub fn expect(&mut self, exp: ExpTokenPair<'_>) -> PResult<'a, Recovered> {
+ pub fn expect(&mut self, exp: ExpTokenPair) -> PResult<'a, Recovered> {
if self.expected_token_types.is_empty() {
- if self.token == *exp.tok {
+ if self.token == exp.tok {
self.bump();
Ok(Recovered::No)
} else {
- self.unexpected_try_recover(exp.tok)
+ self.unexpected_try_recover(&exp.tok)
}
} else {
self.expect_one_of(slice::from_ref(&exp), &[])
@@ -443,13 +443,13 @@ pub fn expect(&mut self, exp: ExpTokenPair<'_>) -> PResult<'a, Recovered> {
/// anything. Signal a fatal error if next token is unexpected.
fn expect_one_of(
&mut self,
- edible: &[ExpTokenPair<'_>],
- inedible: &[ExpTokenPair<'_>],
+ edible: &[ExpTokenPair],
+ inedible: &[ExpTokenPair],
) -> PResult<'a, Recovered> {
- if edible.iter().any(|exp| exp.tok == &self.token.kind) {
+ if edible.iter().any(|exp| exp.tok == self.token.kind) {
self.bump();
Ok(Recovered::No)
- } else if inedible.iter().any(|exp| exp.tok == &self.token.kind) {
+ } else if inedible.iter().any(|exp| exp.tok == self.token.kind) {
// leave it in the input
Ok(Recovered::No)
} else if self.token != token::Eof
@@ -494,8 +494,8 @@ fn ident_or_err(&mut self, recover: bool) -> PResult<'a, (Ident, IdentIsRaw)> {
/// This method will automatically add `tok` to `expected_token_types` if `tok` is not
/// encountered.
#[inline]
- pub fn check(&mut self, exp: ExpTokenPair<'_>) -> bool {
- let is_present = self.token == *exp.tok;
+ pub fn check(&mut self, exp: ExpTokenPair) -> bool {
+ let is_present = self.token == exp.tok;
if !is_present {
self.expected_token_types.insert(exp.token_type);
}
@@ -542,7 +542,7 @@ fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
/// Consumes a token 'tok' if it exists. Returns whether the given token was present.
#[inline]
#[must_use]
- pub fn eat(&mut self, exp: ExpTokenPair<'_>) -> bool {
+ pub fn eat(&mut self, exp: ExpTokenPair) -> bool {
let is_present = self.check(exp);
if is_present {
self.bump()
@@ -745,13 +745,13 @@ fn check_plus(&mut self) -> bool {
/// Eats the expected token if it's present possibly breaking
/// compound tokens like multi-character operators in process.
/// Returns `true` if the token was eaten.
- fn break_and_eat(&mut self, exp: ExpTokenPair<'_>) -> bool {
- if self.token == *exp.tok {
+ fn break_and_eat(&mut self, exp: ExpTokenPair) -> bool {
+ if self.token == exp.tok {
self.bump();
return true;
}
match self.token.kind.break_two_token_op(1) {
- Some((first, second)) if first == *exp.tok => {
+ Some((first, second)) if first == exp.tok => {
let first_span = self.psess.source_map().start_point(self.token.span);
let second_span = self.token.span.with_lo(first_span.hi());
self.token = Token::new(first, first_span);
@@ -826,7 +826,7 @@ fn expect_gt(&mut self) -> PResult<'a, ()> {
/// Checks if the next token is contained within `closes`, and returns `true` if so.
fn expect_any_with_type(
&mut self,
- closes_expected: &[ExpTokenPair<'_>],
+ closes_expected: &[ExpTokenPair],
closes_not_expected: &[&TokenKind],
) -> bool {
closes_expected.iter().any(|&close| self.check(close))
@@ -838,9 +838,9 @@ fn expect_any_with_type(
/// closing bracket.
fn parse_seq_to_before_tokens<T>(
&mut self,
- closes_expected: &[ExpTokenPair<'_>],
+ closes_expected: &[ExpTokenPair],
closes_not_expected: &[&TokenKind],
- sep: SeqSep<'_>,
+ sep: SeqSep,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
let mut first = true;
@@ -869,7 +869,7 @@ fn parse_seq_to_before_tokens<T>(
}
Err(mut expect_err) => {
let sp = self.prev_token.span.shrink_to_hi();
- let token_str = pprust::token_kind_to_string(exp.tok);
+ let token_str = pprust::token_kind_to_string(&exp.tok);
match self.current_closure.take() {
Some(closure_spans) if self.token == TokenKind::Semi => {
@@ -1039,8 +1039,8 @@ fn recover_missing_braces_around_closure_body(
/// closing bracket.
fn parse_seq_to_before_end<T>(
&mut self,
- close: ExpTokenPair<'_>,
- sep: SeqSep<'_>,
+ close: ExpTokenPair,
+ sep: SeqSep,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
self.parse_seq_to_before_tokens(&[close], &[], sep, f)
@@ -1051,8 +1051,8 @@ fn parse_seq_to_before_end<T>(
/// closing bracket.
fn parse_seq_to_end<T>(
&mut self,
- close: ExpTokenPair<'_>,
- sep: SeqSep<'_>,
+ close: ExpTokenPair,
+ sep: SeqSep,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing)> {
let (val, trailing, recovered) = self.parse_seq_to_before_end(close, sep, f)?;
@@ -1070,9 +1070,9 @@ fn parse_seq_to_end<T>(
/// closing bracket.
fn parse_unspanned_seq<T>(
&mut self,
- open: ExpTokenPair<'_>,
- close: ExpTokenPair<'_>,
- sep: SeqSep<'_>,
+ open: ExpTokenPair,
+ close: ExpTokenPair,
+ sep: SeqSep,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing)> {
self.expect(open)?;
@@ -1084,8 +1084,8 @@ fn parse_unspanned_seq<T>(
/// closing bracket.
fn parse_delim_comma_seq<T>(
&mut self,
- open: ExpTokenPair<'_>,
- close: ExpTokenPair<'_>,
+ open: ExpTokenPair,
+ close: ExpTokenPair,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing)> {
self.parse_unspanned_seq(open, close, SeqSep::trailing_allowed(exp!(Comma)), f)
diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs
index b915481..bd4bb36 100644
--- a/compiler/rustc_parse/src/parser/token_type.rs
+++ b/compiler/rustc_parse/src/parser/token_type.rs
@@ -416,8 +416,8 @@ pub(super) fn to_string(&self) -> String {
/// is always by used those methods. The second field is only used when the
/// first field doesn't match.
#[derive(Clone, Copy, Debug)]
-pub struct ExpTokenPair<'a> {
- pub tok: &'a TokenKind,
+pub struct ExpTokenPair {
+ pub tok: TokenKind,
pub token_type: TokenType,
}
@@ -444,7 +444,7 @@ macro_rules! exp {
// `ExpTokenPair` helper rules.
(@tok, $tok:ident) => {
$crate::parser::token_type::ExpTokenPair {
- tok: &rustc_ast::token::$tok,
+ tok: rustc_ast::token::$tok,
token_type: $crate::parser::token_type::TokenType::$tok
}
};
diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml
index d178fcd..645e34b 100644
--- a/compiler/rustc_parse_format/Cargo.toml
+++ b/compiler/rustc_parse_format/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-rustc-literal-escaper = "0.0.5"
+rustc-literal-escaper.workspace = true
rustc_lexer = { path = "../rustc_lexer" }
# tidy-alphabetical-end
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index ba81ef3..c74608a 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -24,5 +24,5 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 00a41e3..498d9a4 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -145,6 +145,10 @@
passes_doc_attr_not_crate_level =
`#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
+passes_doc_attribute_not_attribute =
+ nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]`
+ .help = only existing builtin attributes are allowed in core/std
+
passes_doc_cfg_hide_takes_list =
`#[doc(cfg_hide(...))]` takes a list of attributes
@@ -173,16 +177,16 @@
passes_doc_invalid =
invalid `doc` attribute
-passes_doc_keyword_empty_mod =
- `#[doc(keyword = "...")]` should be used on empty modules
+passes_doc_keyword_attribute_empty_mod =
+ `#[doc({$attr_name} = "...")]` should be used on empty modules
+
+passes_doc_keyword_attribute_not_mod =
+ `#[doc({$attr_name} = "...")]` should be used on modules
passes_doc_keyword_not_keyword =
nonexistent keyword `{$keyword}` used in `#[doc(keyword = "...")]`
.help = only existing keywords are allowed in core/std
-passes_doc_keyword_not_mod =
- `#[doc(keyword = "...")]` should be used on modules
-
passes_doc_keyword_only_impl =
`#[doc(keyword = "...")]` should be used on impl blocks
@@ -462,8 +466,10 @@
{$repr}
passes_outer_crate_level_attr =
- crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+ crate-level attribute should be an inner attribute
+passes_outer_crate_level_attr_suggestion =
+ add a `!`
passes_panic_unwind_without_std =
unwinding panics are not supported without std
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 077afd6..2cd4830 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -18,7 +18,7 @@
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
BuiltinAttribute,
};
-use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr};
+use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr, SanitizerSet};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalModDefId;
use rustc_hir::intravisit::{self, Visitor};
@@ -99,6 +99,21 @@ fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::Diag
}
}
+#[derive(Clone, Copy)]
+enum DocFakeItemKind {
+ Attribute,
+ Keyword,
+}
+
+impl DocFakeItemKind {
+ fn name(self) -> &'static str {
+ match self {
+ Self::Attribute => "attribute",
+ Self::Keyword => "keyword",
+ }
+ }
+}
+
struct CheckAttrVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
@@ -197,6 +212,12 @@ fn check_attributes(
&Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => {
self.check_custom_mir(dialect, phase, attr_span)
}
+ &Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, span: attr_span}) => {
+ self.check_sanitize(attr_span, on_set | off_set, span, target);
+ },
+ Attribute::Parsed(AttributeKind::Link(_, attr_span)) => {
+ self.check_link(hir_id, *attr_span, span, target)
+ }
Attribute::Parsed(
AttributeKind::BodyStability { .. }
| AttributeKind::ConstStabilityIndirect
@@ -247,7 +268,8 @@ fn check_attributes(
| AttributeKind::ShouldPanic { .. }
| AttributeKind::Coroutine(..)
| AttributeKind::Linkage(..)
- | AttributeKind::MustUse { .. },
+ | AttributeKind::MustUse { .. }
+ | AttributeKind::CrateName { .. }
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
@@ -258,9 +280,6 @@ fn check_attributes(
[sym::diagnostic, sym::on_unimplemented, ..] => {
self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
}
- [sym::sanitize, ..] => {
- self.check_sanitize(attr, span, target)
- }
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
[sym::doc, ..] => self.check_doc_attrs(
attr,
@@ -304,7 +323,6 @@ fn check_attributes(
[sym::rustc_has_incoherent_inherent_impls, ..] => {
self.check_has_incoherent_inherent_impls(attr, span, target)
}
- [sym::link, ..] => self.check_link(hir_id, attr, span, target),
[sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
self.check_autodiff(hir_id, attr, span, target)
@@ -367,22 +385,46 @@ fn check_attributes(
let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
if hir_id != CRATE_HIR_ID {
- if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) =
- attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
- {
- match style {
- Some(ast::AttrStyle::Outer) => self.tcx.emit_node_span_lint(
- UNUSED_ATTRIBUTES,
- hir_id,
- attr.span(),
- errors::OuterCrateLevelAttr,
- ),
- Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
- UNUSED_ATTRIBUTES,
- hir_id,
- attr.span(),
- errors::InnerCrateLevelAttr,
- ),
+ match attr {
+ Attribute::Parsed(_) => { /* Already validated. */ }
+ Attribute::Unparsed(attr) => {
+ // FIXME(jdonszelmann): remove once all crate-level attrs are parsed and caught by
+ // the above
+ if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) =
+ attr.path
+ .segments
+ .first()
+ .and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
+ {
+ match attr.style {
+ ast::AttrStyle::Outer => {
+ let attr_span = attr.span;
+ let bang_position = self
+ .tcx
+ .sess
+ .source_map()
+ .span_until_char(attr_span, '[')
+ .shrink_to_hi();
+
+ self.tcx.emit_node_span_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ errors::OuterCrateLevelAttr {
+ suggestion: errors::OuterCrateLevelAttrSuggestion {
+ bang_position,
+ },
+ },
+ )
+ }
+ ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ errors::InnerCrateLevelAttr,
+ ),
+ }
+ }
}
}
}
@@ -467,7 +509,7 @@ fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target
{
let attrs = self.tcx.codegen_fn_attrs(did);
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
- if attrs.contains_extern_indicator(self.tcx, did.into()) {
+ if attrs.contains_extern_indicator() {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
@@ -483,42 +525,48 @@ fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target
/// Checks that the `#[sanitize(..)]` attribute is applied to a
/// function/closure/method, or to an impl block or module.
- fn check_sanitize(&self, attr: &Attribute, target_span: Span, target: Target) {
+ fn check_sanitize(
+ &self,
+ attr_span: Span,
+ set: SanitizerSet,
+ target_span: Span,
+ target: Target,
+ ) {
let mut not_fn_impl_mod = None;
let mut no_body = None;
- if let Some(list) = attr.meta_item_list() {
- for item in list.iter() {
- let MetaItemInner::MetaItem(set) = item else {
- return;
- };
- let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
- match target {
- Target::Fn
- | Target::Closure
- | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
- | Target::Impl { .. }
- | Target::Mod => return,
- Target::Static if matches!(segments.as_slice(), [sym::address]) => return,
-
- // These are "functions", but they aren't allowed because they don't
- // have a body, so the usual explanation would be confusing.
- Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
- no_body = Some(target_span);
- }
-
- _ => {
- not_fn_impl_mod = Some(target_span);
- }
- }
+ match target {
+ Target::Fn
+ | Target::Closure
+ | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
+ | Target::Impl { .. }
+ | Target::Mod => return,
+ Target::Static
+ // if we mask out the address bits, i.e. *only* address was set,
+ // we allow it
+ if set & !(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
+ == SanitizerSet::empty() =>
+ {
+ return;
}
- self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
- attr_span: attr.span(),
- not_fn_impl_mod,
- no_body,
- help: (),
- });
+
+ // These are "functions", but they aren't allowed because they don't
+ // have a body, so the usual explanation would be confusing.
+ Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
+ no_body = Some(target_span);
+ }
+
+ _ => {
+ not_fn_impl_mod = Some(target_span);
+ }
}
+
+ self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
+ attr_span,
+ not_fn_impl_mod,
+ no_body,
+ help: (),
+ });
}
/// Checks if `#[naked]` is applied to a function definition.
@@ -820,7 +868,12 @@ fn check_doc_alias(
}
}
- fn check_doc_keyword(&self, meta: &MetaItemInner, hir_id: HirId) {
+ fn check_doc_keyword_and_attribute(
+ &self,
+ meta: &MetaItemInner,
+ hir_id: HirId,
+ attr_kind: DocFakeItemKind,
+ ) {
fn is_doc_keyword(s: Symbol) -> bool {
// FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we
// can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the
@@ -828,9 +881,14 @@ fn is_doc_keyword(s: Symbol) -> bool {
s.is_reserved(|| edition::LATEST_STABLE_EDITION) || s.is_weak() || s == sym::SelfTy
}
- let doc_keyword = match meta.value_str() {
+ // FIXME: This should support attributes with namespace like `diagnostic::do_not_recommend`.
+ fn is_builtin_attr(s: Symbol) -> bool {
+ rustc_feature::BUILTIN_ATTRIBUTE_MAP.contains_key(&s)
+ }
+
+ let value = match meta.value_str() {
Some(value) if value != sym::empty => value,
- _ => return self.doc_attr_str_error(meta, "keyword"),
+ _ => return self.doc_attr_str_error(meta, attr_kind.name()),
};
let item_kind = match self.tcx.hir_node(hir_id) {
@@ -840,20 +898,38 @@ fn is_doc_keyword(s: Symbol) -> bool {
match item_kind {
Some(ItemKind::Mod(_, module)) => {
if !module.item_ids.is_empty() {
- self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() });
+ self.dcx().emit_err(errors::DocKeywordAttributeEmptyMod {
+ span: meta.span(),
+ attr_name: attr_kind.name(),
+ });
return;
}
}
_ => {
- self.dcx().emit_err(errors::DocKeywordNotMod { span: meta.span() });
+ self.dcx().emit_err(errors::DocKeywordAttributeNotMod {
+ span: meta.span(),
+ attr_name: attr_kind.name(),
+ });
return;
}
}
- if !is_doc_keyword(doc_keyword) {
- self.dcx().emit_err(errors::DocKeywordNotKeyword {
- span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
- keyword: doc_keyword,
- });
+ match attr_kind {
+ DocFakeItemKind::Keyword => {
+ if !is_doc_keyword(value) {
+ self.dcx().emit_err(errors::DocKeywordNotKeyword {
+ span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
+ keyword: value,
+ });
+ }
+ }
+ DocFakeItemKind::Attribute => {
+ if !is_builtin_attr(value) {
+ self.dcx().emit_err(errors::DocAttributeNotAttribute {
+ span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
+ attribute: value,
+ });
+ }
+ }
}
}
@@ -1113,7 +1189,21 @@ fn check_doc_attrs(
Some(sym::keyword) => {
if self.check_attr_not_crate_level(meta, hir_id, "keyword") {
- self.check_doc_keyword(meta, hir_id);
+ self.check_doc_keyword_and_attribute(
+ meta,
+ hir_id,
+ DocFakeItemKind::Keyword,
+ );
+ }
+ }
+
+ Some(sym::attribute) => {
+ if self.check_attr_not_crate_level(meta, hir_id, "attribute") {
+ self.check_doc_keyword_and_attribute(
+ meta,
+ hir_id,
+ DocFakeItemKind::Attribute,
+ );
}
}
@@ -1293,7 +1383,7 @@ fn check_may_dangle(&self, hir_id: HirId, attr_span: Span) {
}
/// Checks if `#[link]` is applied to an item other than a foreign module.
- fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
+ fn check_link(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
if target == Target::ForeignMod
&& let hir::Node::Item(item) = self.tcx.hir_node(hir_id)
&& let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item
@@ -1305,7 +1395,7 @@ fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
- attr.span(),
+ attr_span,
errors::Link { span: (target != Target::ForeignMod).then_some(span) },
);
}
@@ -1817,12 +1907,24 @@ fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute, style: Option<
{
if hir_id != CRATE_HIR_ID {
match style {
- Some(ast::AttrStyle::Outer) => self.tcx.emit_node_span_lint(
- UNUSED_ATTRIBUTES,
- hir_id,
- attr.span(),
- errors::OuterCrateLevelAttr,
- ),
+ Some(ast::AttrStyle::Outer) => {
+ let attr_span = attr.span();
+ let bang_position = self
+ .tcx
+ .sess
+ .source_map()
+ .span_until_char(attr_span, '[')
+ .shrink_to_hi();
+
+ self.tcx.emit_node_span_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr_span,
+ errors::OuterCrateLevelAttr {
+ suggestion: errors::OuterCrateLevelAttrSuggestion { bang_position },
+ },
+ )
+ }
Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 10cd9df..fc33405 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -706,7 +706,7 @@ fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
// forcefully, e.g., for placing it in a specific section.
- cg_attrs.contains_extern_indicator(tcx, def_id.into())
+ cg_attrs.contains_extern_indicator()
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
}
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 4fec6b0..680e2a2 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -64,7 +64,17 @@ pub(crate) struct MixedExportNameAndNoMangle {
#[derive(LintDiagnostic)]
#[diag(passes_outer_crate_level_attr)]
-pub(crate) struct OuterCrateLevelAttr;
+pub(crate) struct OuterCrateLevelAttr {
+ #[subdiagnostic]
+ pub suggestion: OuterCrateLevelAttrSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(passes_outer_crate_level_attr_suggestion, style = "verbose")]
+pub(crate) struct OuterCrateLevelAttrSuggestion {
+ #[suggestion_part(code = "!")]
+ pub bang_position: Span,
+}
#[derive(LintDiagnostic)]
#[diag(passes_inner_crate_level_attr)]
@@ -185,10 +195,11 @@ pub(crate) struct DocAliasMalformed {
}
#[derive(Diagnostic)]
-#[diag(passes_doc_keyword_empty_mod)]
-pub(crate) struct DocKeywordEmptyMod {
+#[diag(passes_doc_keyword_attribute_empty_mod)]
+pub(crate) struct DocKeywordAttributeEmptyMod {
#[primary_span]
pub span: Span,
+ pub attr_name: &'static str,
}
#[derive(Diagnostic)]
@@ -201,10 +212,20 @@ pub(crate) struct DocKeywordNotKeyword {
}
#[derive(Diagnostic)]
-#[diag(passes_doc_keyword_not_mod)]
-pub(crate) struct DocKeywordNotMod {
+#[diag(passes_doc_attribute_not_attribute)]
+#[help]
+pub(crate) struct DocAttributeNotAttribute {
#[primary_span]
pub span: Span,
+ pub attribute: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_attribute_not_mod)]
+pub(crate) struct DocKeywordAttributeNotMod {
+ #[primary_span]
+ pub span: Span,
+ pub attr_name: &'static str,
}
#[derive(Diagnostic)]
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 6cd8a54..d1a703f 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -183,7 +183,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
} else {
CodegenFnAttrs::EMPTY
};
- let is_extern = codegen_attrs.contains_extern_indicator(self.tcx, search_item.into());
+ let is_extern = codegen_attrs.contains_extern_indicator();
if is_extern {
self.reachable_symbols.insert(search_item);
}
@@ -425,7 +425,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
}
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
- codegen_attrs.contains_extern_indicator(tcx, def_id.into())
+ codegen_attrs.contains_extern_indicator()
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml
index a59f7bb..e4909ab 100644
--- a/compiler/rustc_pattern_analysis/Cargo.toml
+++ b/compiler/rustc_pattern_analysis/Cargo.toml
@@ -5,9 +5,9 @@
[dependencies]
# tidy-alphabetical-start
-rustc-hash = "2.0.0"
+rustc-hash.workspace = true
rustc_abi = { path = "../rustc_abi", optional = true }
-rustc_apfloat = "0.2.0"
+rustc_apfloat.workspace = true
rustc_arena = { path = "../rustc_arena", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_errors = { path = "../rustc_errors", optional = true }
@@ -19,7 +19,7 @@
rustc_session = { path = "../rustc_session", optional = true }
rustc_span = { path = "../rustc_span", optional = true }
smallvec = { version = "1.8.1", features = ["union"] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[dev-dependencies]
diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs
index 7649f72..cdf62c2 100644
--- a/compiler/rustc_pattern_analysis/src/rustc/print.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs
@@ -101,23 +101,11 @@ pub(crate) fn write_struct_like<'tcx>(
let num_fields = variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
if num_fields != 0 || variant_and_name.is_none() {
write!(f, "(")?;
- for i in 0..num_fields {
- write!(f, "{}", start_or_comma())?;
-
- // Common case: the field is where we expect it.
- if let Some(p) = subpatterns.get(i) {
- if p.field.index() == i {
- write!(f, "{}", p.pattern)?;
- continue;
- }
- }
-
- // Otherwise, we have to go looking for it.
- if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
- write!(f, "{}", p.pattern)?;
- } else {
- write!(f, "_")?;
- }
+ for FieldPat { pattern, .. } in subpatterns {
+ write!(f, "{}{pattern}", start_or_comma())?;
+ }
+ if matches!(ty.kind(), ty::Tuple(..)) && num_fields == 1 {
+ write!(f, ",")?;
}
write!(f, ")")?;
}
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index c8bfdb9..7de5813 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -15,5 +15,5 @@
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_ty_utils = { path = "../rustc_ty_utils" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_proc_macro/Cargo.toml b/compiler/rustc_proc_macro/Cargo.toml
index beb95aa..99e7fc7 100644
--- a/compiler/rustc_proc_macro/Cargo.toml
+++ b/compiler/rustc_proc_macro/Cargo.toml
@@ -16,7 +16,7 @@
[dependencies]
# tidy-alphabetical-start
-rustc-literal-escaper = "0.0.5"
+rustc-literal-escaper.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_public/Cargo.toml b/compiler/rustc_public/Cargo.toml
index 70af30c..e67e4fe 100644
--- a/compiler/rustc_public/Cargo.toml
+++ b/compiler/rustc_public/Cargo.toml
@@ -12,9 +12,9 @@
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
-scoped-tls = "1.0"
+scoped-tls.workspace = true
serde = { version = "1.0.125", features = [ "derive" ] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index e5cceac..3d5cf0e 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-measureme = "12.0.1"
+measureme.workspace = true
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hashes = { path = "../rustc_hashes" }
rustc_hir = { path = "../rustc_hir" }
@@ -15,5 +15,5 @@
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 7480ba0..0df933b 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -21,7 +21,7 @@
rustc_span = { path = "../rustc_span" }
rustc_thread_pool = { path = "../rustc_thread_pool" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[dependencies.hashbrown]
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index eb98a6e..4da4c08 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -5,9 +5,9 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
-indexmap = "2.4.0"
-itertools = "0.12"
+bitflags.workspace = true
+indexmap.workspace = true
+itertools.workspace = true
pulldown-cmark = { version = "0.11", features = ["html"], default-features = false }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
@@ -27,6 +27,6 @@
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 679e663..d4f7fb2 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -5016,7 +5016,7 @@ fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExport
}
ResolveDocLinks::Exported
if !maybe_exported.eval(self.r)
- && !rustdoc::has_primitive_or_keyword_docs(attrs) =>
+ && !rustdoc::has_primitive_or_keyword_or_attribute_docs(attrs) =>
{
return;
}
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 6450f63..804792c 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -207,8 +207,10 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
attrs: impl Iterator<Item = (&'a A, Option<DefId>)>,
doc_only: bool,
) -> (Vec<DocFragment>, ThinVec<A>) {
- let mut doc_fragments = Vec::new();
- let mut other_attrs = ThinVec::<A>::new();
+ let (min_size, max_size) = attrs.size_hint();
+ let size_hint = max_size.unwrap_or(min_size);
+ let mut doc_fragments = Vec::with_capacity(size_hint);
+ let mut other_attrs = ThinVec::<A>::with_capacity(if doc_only { 0 } else { size_hint });
for (attr, item_id) in attrs {
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
let doc = beautify_doc_string(doc_str, comment_kind);
@@ -230,6 +232,9 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
}
}
+ doc_fragments.shrink_to_fit();
+ other_attrs.shrink_to_fit();
+
unindent_doc_fragments(&mut doc_fragments);
(doc_fragments, other_attrs)
@@ -368,8 +373,8 @@ pub fn inner_docs(attrs: &[impl AttributeExt]) -> bool {
true
}
-/// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]`.
-pub fn has_primitive_or_keyword_docs(attrs: &[impl AttributeExt]) -> bool {
+/// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]` or `#[doc(attribute)]`.
+pub fn has_primitive_or_keyword_or_attribute_docs(attrs: &[impl AttributeExt]) -> bool {
for attr in attrs {
if attr.has_name(sym::rustc_doc_primitive) {
return true;
@@ -377,7 +382,7 @@ pub fn has_primitive_or_keyword_docs(attrs: &[impl AttributeExt]) -> bool {
&& let Some(items) = attr.meta_item_list()
{
for item in items {
- if item.has_name(sym::keyword) {
+ if item.has_name(sym::keyword) || item.has_name(sym::attribute) {
return true;
}
}
diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml
index 9069d2c..3dbeaa4 100644
--- a/compiler/rustc_sanitizers/Cargo.toml
+++ b/compiler/rustc_sanitizers/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.5.0"
+bitflags.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hir = { path = "../rustc_hir" }
@@ -13,6 +13,6 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
twox-hash = "1.6.3"
# tidy-alphabetical-end
diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml
index 9482423..853f87e 100644
--- a/compiler/rustc_serialize/Cargo.toml
+++ b/compiler/rustc_serialize/Cargo.toml
@@ -5,14 +5,14 @@
[dependencies]
# tidy-alphabetical-start
-indexmap = "2.0.0"
+indexmap.workspace = true
rustc_hashes = { path = "../rustc_hashes" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
+thin-vec.workspace = true
# tidy-alphabetical-end
[dev-dependencies]
# tidy-alphabetical-start
rustc_macros = { path = "../rustc_macros" }
-tempfile = "3.2"
+tempfile.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 0516982..5870fb2 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
getopts = "0.2"
rand = "0.9.0"
rustc_abi = { path = "../rustc_abi" }
@@ -23,12 +23,12 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
termize = "0.2"
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[target.'cfg(unix)'.dependencies]
# tidy-alphabetical-start
-libc = "0.2"
+libc.workspace = true
# tidy-alphabetical-end
[target.'cfg(windows)'.dependencies.windows]
diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs
index f1f0aeb..50a0593 100644
--- a/compiler/rustc_session/src/config/native_libs.rs
+++ b/compiler/rustc_session/src/config/native_libs.rs
@@ -5,10 +5,11 @@
//! which have their own parser in `rustc_metadata`.)
use rustc_feature::UnstableFeatures;
+use rustc_hir::attrs::NativeLibKind;
use crate::EarlyDiagCtxt;
use crate::config::UnstableOptions;
-use crate::utils::{NativeLib, NativeLibKind};
+use crate::utils::NativeLib;
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 4cfc745..30f6256 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,8 +6,8 @@
use std::path::PathBuf;
use rustc_abi::ExternAbi;
-use rustc_ast as ast;
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock};
+use rustc_hir::attrs::{CfgEntry, NativeLibKind, PeImportNameType};
use rustc_hir::def_id::{
CrateNum, DefId, LOCAL_CRATE, LocalDefId, StableCrateId, StableCrateIdMap,
};
@@ -16,7 +16,6 @@
use rustc_span::{Span, Symbol};
use crate::search_paths::PathKind;
-use crate::utils::NativeLibKind;
// lonely orphan structs and enums looking for a better home
@@ -72,7 +71,7 @@ pub struct NativeLib {
pub name: Symbol,
/// If packed_bundled_libs enabled, actual filename of library is stored.
pub filename: Option<Symbol>,
- pub cfg: Option<ast::MetaItemInner>,
+ pub cfg: Option<CfgEntry>,
pub foreign_module: Option<DefId>,
pub verbatim: Option<bool>,
pub dll_imports: Vec<DllImport>,
@@ -88,25 +87,6 @@ pub fn wasm_import_module(&self) -> Option<Symbol> {
}
}
-/// Different ways that the PE Format can decorate a symbol name.
-/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type>
-#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic, PartialEq, Eq)]
-pub enum PeImportNameType {
- /// IMPORT_ORDINAL
- /// Uses the ordinal (i.e., a number) rather than the name.
- Ordinal(u16),
- /// Same as IMPORT_NAME
- /// Name is decorated with all prefixes and suffixes.
- Decorated,
- /// Same as IMPORT_NAME_NOPREFIX
- /// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept.
- NoPrefix,
- /// Same as IMPORT_NAME_UNDECORATE
- /// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all
- /// trailing characters) are skipped.
- Undecorated,
-}
-
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
pub struct DllImport {
pub name: Symbol,
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 34da54a..50bc734 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -384,6 +384,10 @@ pub fn report_lit_error(
lit: token::Lit,
span: Span,
) -> ErrorGuaranteed {
+ create_lit_error(psess, err, lit, span).emit()
+}
+
+pub fn create_lit_error(psess: &ParseSess, err: LitError, lit: token::Lit, span: Span) -> Diag<'_> {
// Checks if `s` looks like i32 or u1234 etc.
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
@@ -414,32 +418,32 @@ fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
let dcx = psess.dcx();
match err {
LitError::InvalidSuffix(suffix) => {
- dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix })
+ dcx.create_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix })
}
LitError::InvalidIntSuffix(suffix) => {
let suf = suffix.as_str();
if looks_like_width_suffix(&['i', 'u'], suf) {
// If it looks like a width, try to be helpful.
- dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() })
+ dcx.create_err(InvalidIntLiteralWidth { span, width: suf[1..].into() })
} else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) {
- dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed })
+ dcx.create_err(InvalidNumLiteralBasePrefix { span, fixed })
} else {
- dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() })
+ dcx.create_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() })
}
}
LitError::InvalidFloatSuffix(suffix) => {
let suf = suffix.as_str();
if looks_like_width_suffix(&['f'], suf) {
// If it looks like a width, try to be helpful.
- dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() })
+ dcx.create_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() })
} else {
- dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() })
+ dcx.create_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() })
}
}
LitError::NonDecimalFloat(base) => match base {
- 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }),
- 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }),
- 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }),
+ 16 => dcx.create_err(HexadecimalFloatLiteralNotSupported { span }),
+ 8 => dcx.create_err(OctalFloatLiteralNotSupported { span }),
+ 2 => dcx.create_err(BinaryFloatLiteralNotSupported { span }),
_ => unreachable!(),
},
LitError::IntTooLarge(base) => {
@@ -450,7 +454,7 @@ fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
16 => format!("{max:#x}"),
_ => format!("{max}"),
};
- dcx.emit_err(IntLiteralTooLarge { span, limit })
+ dcx.create_err(IntLiteralTooLarge { span, limit })
}
}
}
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index bb7ffa2..96767d0 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -7,6 +7,7 @@
use std::{env, fmt, io};
use rand::{RngCore, rng};
+use rustc_ast::NodeId;
use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
@@ -22,7 +23,7 @@
use rustc_errors::translation::Translator;
use rustc_errors::{
Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort,
- TerminalUrl, fallback_fluent_bundle,
+ LintEmitter, TerminalUrl, fallback_fluent_bundle,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
@@ -223,6 +224,20 @@ pub struct Session {
pub invocation_temp: Option<String>,
}
+impl LintEmitter for &'_ Session {
+ type Id = NodeId;
+
+ fn emit_node_span_lint(
+ self,
+ lint: &'static rustc_lint_defs::Lint,
+ node_id: Self::Id,
+ span: impl Into<rustc_errors::MultiSpan>,
+ decorator: impl for<'a> rustc_errors::LintDiagnostic<'a, ()> + DynSend + 'static,
+ ) {
+ self.psess.buffer_lint(lint, span, node_id, decorator);
+ }
+}
+
#[derive(Clone, Copy)]
pub enum CodegenUnits {
/// Specified by the user. In this case we try fairly hard to produce the
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index e9ddd66..c64d9bc 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -3,6 +3,7 @@
use rustc_data_structures::profiling::VerboseTimingGuard;
use rustc_fs_util::try_canonicalize;
+use rustc_hir::attrs::NativeLibKind;
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use crate::session::Session;
@@ -17,69 +18,6 @@ pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
-#[derive(HashStable_Generic)]
-pub enum NativeLibKind {
- /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC)
- Static {
- /// Whether to bundle objects from static library into produced rlib
- bundle: Option<bool>,
- /// Whether to link static library without throwing any object files away
- whole_archive: Option<bool>,
- },
- /// Dynamic library (e.g. `libfoo.so` on Linux)
- /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
- Dylib {
- /// Whether the dynamic library will be linked only if it satisfies some undefined symbols
- as_needed: Option<bool>,
- },
- /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
- /// On Linux, it refers to a generated shared library stub.
- RawDylib,
- /// A macOS-specific kind of dynamic libraries.
- Framework {
- /// Whether the framework will be linked only if it satisfies some undefined symbols
- as_needed: Option<bool>,
- },
- /// Argument which is passed to linker, relative order with libraries and other arguments
- /// is preserved
- LinkArg,
-
- /// Module imported from WebAssembly
- WasmImportModule,
-
- /// The library kind wasn't specified, `Dylib` is currently used as a default.
- Unspecified,
-}
-
-impl NativeLibKind {
- pub fn has_modifiers(&self) -> bool {
- match self {
- NativeLibKind::Static { bundle, whole_archive } => {
- bundle.is_some() || whole_archive.is_some()
- }
- NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
- as_needed.is_some()
- }
- NativeLibKind::RawDylib
- | NativeLibKind::Unspecified
- | NativeLibKind::LinkArg
- | NativeLibKind::WasmImportModule => false,
- }
- }
-
- pub fn is_statically_included(&self) -> bool {
- matches!(self, NativeLibKind::Static { .. })
- }
-
- pub fn is_dllimport(&self) -> bool {
- matches!(
- self,
- NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
- )
- }
-}
-
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
#[derive(HashStable_Generic)]
pub struct NativeLib {
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index 43a2d69..da6f210 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -6,8 +6,8 @@
[dependencies]
# tidy-alphabetical-start
blake3 = "1.5.2"
-derive-where = "1.2.7"
-indexmap = { version = "2.0.0" }
+derive-where.workspace = true
+indexmap.workspace = true
itoa = "1.0"
md5 = { package = "md-5", version = "0.10.0" }
rustc_arena = { path = "../rustc_arena" }
@@ -16,9 +16,9 @@
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
-scoped-tls = "1.0"
+scoped-tls.workspace = true
sha1 = "0.10.0"
sha2 = "0.10.1"
-tracing = "0.1"
+tracing.workspace = true
unicode-width = "0.2.0"
# tidy-alphabetical-end
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index d647ec2..ae6755f 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -17,6 +17,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(array_windows)]
@@ -26,7 +27,6 @@
#![feature(map_try_insert)]
#![feature(negative_impls)]
#![feature(read_buf)]
-#![feature(round_char_boundary)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 8270de1..166842e 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -9,6 +9,7 @@
//! within the `SourceMap`, which upon request can be converted to line and column
//! information, source code snippets, etc.
+use std::fs::File;
use std::io::{self, BorrowedBuf, Read};
use std::{fs, path};
@@ -115,13 +116,18 @@ fn file_exists(&self, path: &Path) -> bool {
}
fn read_file(&self, path: &Path) -> io::Result<String> {
- if path.metadata().is_ok_and(|metadata| metadata.len() > SourceFile::MAX_FILE_SIZE.into()) {
+ let mut file = File::open(path)?;
+ let size = file.metadata().map(|metadata| metadata.len()).ok().unwrap_or(0);
+
+ if size > SourceFile::MAX_FILE_SIZE.into() {
return Err(io::Error::other(format!(
"text files larger than {} bytes are unsupported",
SourceFile::MAX_FILE_SIZE
)));
}
- fs::read_to_string(path)
+ let mut contents = String::new();
+ file.read_to_string(&mut contents)?;
+ Ok(contents)
}
fn read_binary_file(&self, path: &Path) -> io::Result<Arc<[u8]>> {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5d140cc..77260d0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -466,6 +466,7 @@
arm,
arm_target_feature,
array,
+ as_dash_needed: "as-needed",
as_ptr,
as_ref,
as_str,
@@ -540,6 +541,7 @@
att_syntax,
attr,
attr_literals,
+ attribute,
attributes,
audit_that,
augmented_assignments,
@@ -592,6 +594,7 @@
btreeset_iter,
built,
builtin_syntax,
+ bundle,
c,
c_dash_variadic,
c_str,
@@ -817,6 +820,7 @@
decl_macro,
declare_lint_pass,
decode,
+ decorated,
default_alloc_error_handler,
default_field_values,
default_fn,
@@ -1075,6 +1079,7 @@
format_macro,
format_placeholder,
format_unsafe_arg,
+ framework,
freeze,
freeze_impls,
freg,
@@ -1295,6 +1300,7 @@
link_arg_attribute,
link_args,
link_cfg,
+ link_dash_arg: "link-arg",
link_llvm_intrinsics,
link_name,
link_ordinal,
@@ -1528,6 +1534,7 @@
noop_method_borrow,
noop_method_clone,
noop_method_deref,
+ noprefix,
noreturn,
nostack,
not,
@@ -1741,6 +1748,7 @@
quote,
range_inclusive_new,
range_step,
+ raw_dash_dylib: "raw-dylib",
raw_dylib,
raw_dylib_elf,
raw_eq,
@@ -2277,6 +2285,7 @@
unchecked_shl,
unchecked_shr,
unchecked_sub,
+ undecorated,
underscore_const_names,
underscore_imports,
underscore_lifetimes,
@@ -2365,6 +2374,7 @@
vecdeque_iter,
vecdeque_reserve,
vector,
+ verbatim,
version,
vfp2,
vis,
@@ -2389,6 +2399,7 @@
weak_odr,
where_clause_attrs,
while_let,
+ whole_dash_archive: "whole-archive",
width,
windows,
windows_subsystem,
@@ -2419,9 +2430,11 @@
yield_expr,
ymm_reg,
yreg,
+ zca,
zfh,
zfhmin,
zmm_reg,
+ ztso,
// tidy-alphabetical-end
}
}
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index 0df9c76..0ceac4b 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -6,7 +6,7 @@
[dependencies]
# tidy-alphabetical-start
punycode = "0.4.0"
-rustc-demangle = "0.1.21"
+rustc-demangle.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
@@ -15,5 +15,5 @@
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index 57c90a7..ed59ee2 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -5,7 +5,8 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
+object = { version = "0.37.0", default-features = false, features = ["elf", "macho"] }
rustc_abi = { path = "../rustc_abi" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_error_messages = { path = "../rustc_error_messages" }
@@ -15,14 +16,8 @@
rustc_span = { path = "../rustc_span" }
serde = "1.0.219"
serde_derive = "1.0.219"
-serde_json = "1.0.59"
+serde_json.workspace = true
serde_path_to_error = "0.1.17"
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
-[dependencies.object]
-# tidy-alphabetical-start
-default-features = false
-features = ["elf", "macho"]
-version = "0.37.0"
-# tidy-alphabetical-end
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 5f2a6f7..7a7c63c 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -114,7 +114,7 @@ mod attr_impl {
bitflags::bitflags! {
impl ArgAttribute: u8 {
const NoAlias = 1 << 1;
- const NoCapture = 1 << 2;
+ const CapturesAddress = 1 << 2;
const NonNull = 1 << 3;
const ReadOnly = 1 << 4;
const InReg = 1 << 5;
@@ -400,11 +400,11 @@ fn indirect_pass_mode(layout: &TyAndLayout<'a, Ty>) -> PassMode {
let mut attrs = ArgAttributes::new();
// For non-immediate arguments the callee gets its own copy of
- // the value on the stack, so there are no aliases. It's also
- // program-invisible so can't possibly capture
+ // the value on the stack, so there are no aliases. The function
+ // can capture the address of the argument, but not the provenance.
attrs
.set(ArgAttribute::NoAlias)
- .set(ArgAttribute::NoCapture)
+ .set(ArgAttribute::CapturesAddress)
.set(ArgAttribute::NonNull)
.set(ArgAttribute::NoUndef);
attrs.pointee_size = layout.size;
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index a67795e..c53d92b 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1954,6 +1954,7 @@ fn $module() {
("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
+ ("aarch64_be-unknown-linux-musl", aarch64_be_unknown_linux_musl),
("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
("i686-unknown-linux-musl", i686_unknown_linux_musl),
("i586-unknown-linux-musl", i586_unknown_linux_musl),
@@ -2149,6 +2150,7 @@ fn $module() {
("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
+ ("riscv64a23-unknown-linux-gnu", riscv64a23_unknown_linux_gnu),
("sparc-unknown-none-elf", sparc_unknown_none_elf),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_musl.rs
new file mode 100644
index 0000000..be5ac4a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_musl.rs
@@ -0,0 +1,40 @@
+use rustc_abi::Endian;
+
+use crate::spec::{
+ FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
+
+pub(crate) fn target() -> Target {
+ let mut base = base::linux_musl::opts();
+ base.max_atomic_width = Some(128);
+ base.supports_xray = true;
+ base.features = "+v8a,+outline-atomics".into();
+ base.stack_probes = StackProbeType::Inline;
+ base.supported_sanitizers = SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::THREAD;
+
+ Target {
+ llvm_target: "aarch64_be-unknown-linux-musl".into(),
+ metadata: TargetMetadata {
+ description: Some("ARM64 Linux (big-endian) with musl-libc 1.2.5".into()),
+ tier: Some(3),
+ host_tools: Some(false),
+ std: Some(true),
+ },
+ pointer_width: 64,
+ data_layout: "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ // the AAPCS64 expects use of non-leaf frame pointers per
+ // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+ // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+ frame_pointer: FramePointer::NonLeaf,
+ mcount: "\u{1}_mcount".into(),
+ endian: Endian::Big,
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs
new file mode 100644
index 0000000..60f2e7d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs
@@ -0,0 +1,27 @@
+use std::borrow::Cow;
+
+use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
+
+pub(crate) fn target() -> Target {
+ Target {
+ llvm_target: "riscv64-unknown-linux-gnu".into(),
+ metadata: TargetMetadata {
+ description: Some("RISC-V Linux (kernel 6.8.0, glibc 2.39)".into()),
+ tier: Some(3),
+ host_tools: Some(true),
+ std: Some(true),
+ },
+ pointer_width: 64,
+ data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
+ arch: "riscv64".into(),
+ options: TargetOptions {
+ code_model: Some(CodeModel::Medium),
+ cpu: "generic-rv64".into(),
+ features: "+rva23u64".into(),
+ llvm_abiname: "lp64d".into(),
+ max_atomic_width: Some(64),
+ supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
+ ..base::linux_gnu::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index e45300b..4c1b8c9 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -601,6 +601,49 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
),
("m", Stable, &[]),
("relax", Unstable(sym::riscv_target_feature), &[]),
+ (
+ "rva23u64",
+ Unstable(sym::riscv_target_feature),
+ &[
+ "m",
+ "a",
+ "f",
+ "d",
+ "c",
+ "b",
+ "v",
+ "zicsr",
+ "zicntr",
+ "zihpm",
+ "ziccif",
+ "ziccrse",
+ "ziccamoa",
+ "zicclsm",
+ "zic64b",
+ "za64rs",
+ "zihintpause",
+ "zba",
+ "zbb",
+ "zbs",
+ "zicbom",
+ "zicbop",
+ "zicboz",
+ "zfhmin",
+ "zkt",
+ "zvfhmin",
+ "zvbb",
+ "zvkt",
+ "zihintntl",
+ "zicond",
+ "zimop",
+ "zcmop",
+ "zcb",
+ "zfa",
+ "zawrs",
+ "supm",
+ ],
+ ),
+ ("supm", Unstable(sym::riscv_target_feature), &[]),
("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]),
("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]),
diff --git a/compiler/rustc_thread_pool/Cargo.toml b/compiler/rustc_thread_pool/Cargo.toml
index c929844..8e8c646 100644
--- a/compiler/rustc_thread_pool/Cargo.toml
+++ b/compiler/rustc_thread_pool/Cargo.toml
@@ -20,10 +20,10 @@
[dev-dependencies]
rand = "0.9"
rand_xorshift = "0.4"
-scoped-tls = "1.0"
+scoped-tls.workspace = true
[target.'cfg(unix)'.dev-dependencies]
-libc = "0.2"
+libc.workspace = true
[[test]]
name = "stack_overflow_crash"
diff --git a/compiler/rustc_thread_pool/src/lib.rs b/compiler/rustc_thread_pool/src/lib.rs
index 34252d9..7ce7fbc 100644
--- a/compiler/rustc_thread_pool/src/lib.rs
+++ b/compiler/rustc_thread_pool/src/lib.rs
@@ -787,18 +787,7 @@ fn is_unsupported(&self) -> bool {
}
}
-const GLOBAL_POOL_ALREADY_INITIALIZED: &str =
- "The global thread pool has already been initialized.";
-
impl Error for ThreadPoolBuildError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- match self.kind {
- ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED,
- ErrorKind::IOError(ref e) => e.description(),
- }
- }
-
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.kind {
ErrorKind::GlobalPoolAlreadyInitialized => None,
@@ -810,7 +799,9 @@ fn source(&self) -> Option<&(dyn Error + 'static)> {
impl fmt::Display for ThreadPoolBuildError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
- ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED.fmt(f),
+ ErrorKind::GlobalPoolAlreadyInitialized => {
+ "The global thread pool has already been initialized.".fmt(f)
+ }
ErrorKind::IOError(e) => e.fmt(f),
}
}
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 1071105..6b79b98 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
@@ -21,6 +21,6 @@
rustc_span = { path = "../rustc_span" }
rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index e31ff8b..aa153d3 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -820,16 +820,20 @@ pub(super) fn suggest_fn_call(
if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. })
&& obligation.cause.span.can_be_used_for_suggestions()
{
+ let (span, sugg) = if let Some(snippet) =
+ self.tcx.sess.source_map().span_to_snippet(obligation.cause.span).ok()
+ && snippet.starts_with("|")
+ {
+ (obligation.cause.span, format!("({snippet})({args})"))
+ } else {
+ (obligation.cause.span.shrink_to_hi(), format!("({args})"))
+ };
+
// When the obligation error has been ensured to have been caused by
// an argument, the `obligation.cause.span` points at the expression
// of the argument, so we can provide a suggestion. Otherwise, we give
// a more general note.
- err.span_suggestion_verbose(
- obligation.cause.span.shrink_to_hi(),
- msg,
- format!("({args})"),
- Applicability::HasPlaceholders,
- );
+ err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders);
} else if let DefIdOrName::DefId(def_id) = def_id_or_name {
let name = match self.tcx.hir_get_if_local(def_id) {
Some(hir::Node::Expr(hir::Expr {
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index 70a08f3..bc7bdd3 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -4,8 +4,8 @@
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::ty::{
- self, DefiningScopeKind, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt,
- TypingMode, fold_regions,
+ self, DefiningScopeKind, GenericArgKind, GenericArgs, OpaqueTypeKey, Ty, TyCtxt,
+ TypeVisitableExt, TypingMode, fold_regions,
};
use rustc_span::{ErrorGuaranteed, Span};
@@ -14,22 +14,22 @@
use crate::traits::ObligationCtxt;
#[derive(Debug)]
-pub enum InvalidOpaqueTypeArgs<'tcx> {
- AlreadyReported(ErrorGuaranteed),
+pub enum NonDefiningUseReason<'tcx> {
+ Tainted(ErrorGuaranteed),
NotAParam { opaque_type_key: OpaqueTypeKey<'tcx>, param_index: usize, span: Span },
DuplicateParam { opaque_type_key: OpaqueTypeKey<'tcx>, param_indices: Vec<usize>, span: Span },
}
-impl From<ErrorGuaranteed> for InvalidOpaqueTypeArgs<'_> {
+impl From<ErrorGuaranteed> for NonDefiningUseReason<'_> {
fn from(guar: ErrorGuaranteed) -> Self {
- InvalidOpaqueTypeArgs::AlreadyReported(guar)
+ NonDefiningUseReason::Tainted(guar)
}
}
-impl<'tcx> InvalidOpaqueTypeArgs<'tcx> {
+impl<'tcx> NonDefiningUseReason<'tcx> {
pub fn report(self, infcx: &InferCtxt<'tcx>) -> ErrorGuaranteed {
let tcx = infcx.tcx;
match self {
- InvalidOpaqueTypeArgs::AlreadyReported(guar) => guar,
- InvalidOpaqueTypeArgs::NotAParam { opaque_type_key, param_index, span } => {
+ NonDefiningUseReason::Tainted(guar) => guar,
+ NonDefiningUseReason::NotAParam { opaque_type_key, param_index, span } => {
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
let opaque_param = opaque_generics.param_at(param_index, tcx);
let kind = opaque_param.kind.descr();
@@ -40,7 +40,7 @@ pub fn report(self, infcx: &InferCtxt<'tcx>) -> ErrorGuaranteed {
param_span: tcx.def_span(opaque_param.def_id),
})
}
- InvalidOpaqueTypeArgs::DuplicateParam { opaque_type_key, param_indices, span } => {
+ NonDefiningUseReason::DuplicateParam { opaque_type_key, param_indices, span } => {
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
let descr = opaque_generics.param_at(param_indices[0], tcx).kind.descr();
let spans: Vec<_> = param_indices
@@ -58,15 +58,17 @@ pub fn report(self, infcx: &InferCtxt<'tcx>) -> ErrorGuaranteed {
}
/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
+/// With the new solver, uses which fail this check are simply treated as non-defining
+/// and we only emit an error if no defining use exists.
///
/// [rustc-dev-guide chapter]:
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
-pub fn check_opaque_type_parameter_valid<'tcx>(
+pub fn opaque_type_has_defining_use_args<'tcx>(
infcx: &InferCtxt<'tcx>,
opaque_type_key: OpaqueTypeKey<'tcx>,
span: Span,
defining_scope_kind: DefiningScopeKind,
-) -> Result<(), InvalidOpaqueTypeArgs<'tcx>> {
+) -> Result<(), NonDefiningUseReason<'tcx>> {
let tcx = infcx.tcx;
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
@@ -105,13 +107,13 @@ pub fn check_opaque_type_parameter_valid<'tcx>(
} else {
// Prevent `fn foo() -> Foo<u32>` from being defining.
opaque_env.param_is_error(i)?;
- return Err(InvalidOpaqueTypeArgs::NotAParam { opaque_type_key, param_index: i, span });
+ return Err(NonDefiningUseReason::NotAParam { opaque_type_key, param_index: i, span });
}
}
for (_, param_indices) in seen_params {
if param_indices.len() > 1 {
- return Err(InvalidOpaqueTypeArgs::DuplicateParam {
+ return Err(NonDefiningUseReason::DuplicateParam {
opaque_type_key,
param_indices,
span,
@@ -206,3 +208,27 @@ fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
canonical_args
}
}
+
+pub fn report_item_does_not_constrain_error<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ item_def_id: LocalDefId,
+ def_id: LocalDefId,
+ non_defining_use: Option<(OpaqueTypeKey<'tcx>, Span)>,
+) -> ErrorGuaranteed {
+ let span = tcx.def_ident_span(item_def_id).unwrap_or_else(|| tcx.def_span(item_def_id));
+ let opaque_type_span = tcx.def_span(def_id);
+ let opaque_type_name = tcx.def_path_str(def_id);
+
+ let mut err =
+ tcx.dcx().struct_span_err(span, format!("item does not constrain `{opaque_type_name}`"));
+ err.note("consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`");
+ err.span_note(opaque_type_span, "this opaque type is supposed to be constrained");
+ if let Some((key, span)) = non_defining_use {
+ let opaque_ty = Ty::new_opaque(tcx, key.def_id.into(), key.args);
+ err.span_note(
+ span,
+ format!("this use of `{opaque_ty}` does not have unique universal generic arguments"),
+ );
+ }
+ err.emit()
+}
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 3f628d8..575e047 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -252,7 +252,9 @@ fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
// inside of an opaque type, e.g. if there's `Opaque = (?x, ?x)` in the
// storage, we can also rely on structural identity of `?x` even if we
// later uniquify it in MIR borrowck.
- if infcx.in_hir_typeck && obligation.has_non_region_infer() {
+ if infcx.in_hir_typeck
+ && (obligation.has_non_region_infer() || obligation.has_free_regions())
+ {
infcx.push_hir_typeck_potentially_region_dependent_goal(obligation);
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 0ca2d21..6ce6850 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -1,6 +1,7 @@
use std::fmt;
use rustc_errors::ErrorGuaranteed;
+use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{TyCtxt, TypeFoldable};
@@ -42,13 +43,14 @@ impl<'tcx, F, R> super::TypeOp<'tcx> for CustomTypeOp<F>
fn fully_perform(
self,
infcx: &InferCtxt<'tcx>,
+ root_def_id: LocalDefId,
span: Span,
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
if cfg!(debug_assertions) {
info!("fully_perform({:?})", self);
}
- Ok(scrape_region_constraints(infcx, self.closure, self.description, span)?.0)
+ Ok(scrape_region_constraints(infcx, root_def_id, self.description, span, self.closure)?.0)
}
}
@@ -62,9 +64,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// constraints that result, creating query-region-constraints.
pub fn scrape_region_constraints<'tcx, Op, R>(
infcx: &InferCtxt<'tcx>,
- op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
+ root_def_id: LocalDefId,
name: &'static str,
span: Span,
+ op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
) -> Result<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>), ErrorGuaranteed>
where
R: TypeFoldable<TyCtxt<'tcx>>,
@@ -94,6 +97,8 @@ pub fn scrape_region_constraints<'tcx, Op, R>(
let errors = ocx.select_all_or_error();
if errors.is_empty() {
Ok(value)
+ } else if let Err(guar) = infcx.tcx.check_potentially_region_dependent_goals(root_def_id) {
+ Err(guar)
} else {
Err(infcx
.dcx()
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 018e974..4b8bf86 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -1,6 +1,7 @@
use std::fmt;
use rustc_errors::ErrorGuaranteed;
+use rustc_hir::def_id::LocalDefId;
use rustc_infer::traits::PredicateObligations;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt, TypeFoldable};
@@ -37,6 +38,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
fn fully_perform(
self,
infcx: &InferCtxt<'tcx>,
+ root_def_id: LocalDefId,
span: Span,
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>;
}
@@ -140,6 +142,7 @@ impl<'tcx, Q> TypeOp<'tcx> for ParamEnvAnd<'tcx, Q>
fn fully_perform(
self,
infcx: &InferCtxt<'tcx>,
+ root_def_id: LocalDefId,
span: Span,
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
// In the new trait solver, query type ops are performed locally. This
@@ -152,9 +155,10 @@ fn fully_perform(
if infcx.next_trait_solver() {
return Ok(scrape_region_constraints(
infcx,
- |ocx| QueryTypeOp::perform_locally_with_next_solver(ocx, self, span),
+ root_def_id,
"query type op",
span,
+ |ocx| QueryTypeOp::perform_locally_with_next_solver(ocx, self, span),
)?
.0);
}
@@ -166,19 +170,15 @@ fn fully_perform(
// we sometimes end up with `Opaque<'a> = Opaque<'b>` instead of an actual hidden type. In that case we don't register a
// hidden type but just equate the lifetimes. Thus we need to scrape the region constraints even though we're also manually
// collecting region constraints via `region_constraints`.
- let (mut output, _) = scrape_region_constraints(
- infcx,
- |ocx| {
+ let (mut output, _) =
+ scrape_region_constraints(infcx, root_def_id, "fully_perform", span, |ocx| {
let (output, ei, obligations, _) =
Q::fully_perform_into(self, infcx, &mut region_constraints, span)?;
error_info = ei;
ocx.register_obligations(obligations);
Ok(output)
- },
- "fully_perform",
- span,
- )?;
+ })?;
output.error_info = error_info;
if let Some(QueryRegionConstraints { outlives, assumptions }) = output.constraints {
region_constraints.outlives.extend(outlives.iter().cloned());
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 3565c11..7e8a414 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -153,7 +153,12 @@ fn prepare_vtable_segments_inner<'tcx, T>(
// emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() {
- let has_entries = has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id);
+ // We don't need to emit a vptr for "truly-empty" supertraits, but we *do* need to emit a
+ // vptr for supertraits that have no methods, but that themselves have supertraits
+ // with methods, so we check if any transitive supertrait has entries here (this includes
+ // the trait itself).
+ let has_entries = ty::elaborate::supertrait_def_ids(tcx, inner_most_trait_ref.def_id)
+ .any(|def_id| has_own_existential_vtable_entries(tcx, def_id));
segment_visitor(VtblSegment::TraitOwnEntries {
trait_ref: inner_most_trait_ref,
diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml
index 9f40f4d..24360a9 100644
--- a/compiler/rustc_traits/Cargo.toml
+++ b/compiler/rustc_traits/Cargo.toml
@@ -10,5 +10,5 @@
rustc_middle = { path = "../rustc_middle" }
rustc_span = { path = "../rustc_span" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index e61717e..2ac2b46 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -11,12 +11,12 @@
rustc_middle = { path = "../rustc_middle", optional = true }
rustc_span = { path = "../rustc_span", optional = true }
smallvec = "1.8.1"
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
[dev-dependencies]
# tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index ce08b30..394cde5 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
@@ -20,5 +20,5 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
# tidy-alphabetical-end
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index d55e9b3..42860fa 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -5,11 +5,11 @@
[dependencies]
# tidy-alphabetical-start
-bitflags = "2.4.1"
-derive-where = "1.2.7"
+bitflags.workspace = true
+derive-where.workspace = true
ena = "0.14.3"
-indexmap = "2.0.0"
-rustc-hash = "2.0.0"
+indexmap.workspace = true
+rustc-hash.workspace = true
rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_error_messages = { path = "../rustc_error_messages", optional = true }
@@ -19,8 +19,8 @@
rustc_span = { path = "../rustc_span", optional = true }
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
smallvec = { version = "1.8.1", default-features = false, features = ["const_generics"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
# tidy-alphabetical-end
[features]
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index dc15cc3..2f7c78d 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -4,7 +4,7 @@
use crate::data_structures::HashSet;
use crate::inherent::*;
-use crate::lang_items::TraitSolverLangItem;
+use crate::lang_items::SolverTraitLangItem;
use crate::outlives::{Component, push_outlives_components};
use crate::{self as ty, Interner, Upcast as _};
@@ -140,7 +140,7 @@ fn elaborate(&mut self, elaboratable: &O) {
// is present.
if self.elaborate_sized == ElaborateSized::No
&& let Some(did) = clause.as_trait_clause().map(|c| c.def_id())
- && self.cx.is_lang_item(did, TraitSolverLangItem::Sized)
+ && self.cx.is_trait_lang_item(did, SolverTraitLangItem::Sized)
{
return;
}
@@ -166,7 +166,7 @@ fn elaborate(&mut self, elaboratable: &O) {
// Get predicates implied by the trait, or only super predicates if we only care about self predicates.
match self.mode {
Filter::All => self.extend_deduped(
- cx.explicit_implied_predicates_of(data.def_id())
+ cx.explicit_implied_predicates_of(data.def_id().into())
.iter_identity()
.enumerate()
.map(map_to_child_clause),
@@ -181,13 +181,15 @@ fn elaborate(&mut self, elaboratable: &O) {
}
// `T: [const] Trait` implies `T: [const] Supertrait`.
ty::ClauseKind::HostEffect(data) => self.extend_deduped(
- cx.explicit_implied_const_bounds(data.def_id()).iter_identity().map(|trait_ref| {
- elaboratable.child(
- trait_ref
- .to_host_effect_clause(cx, data.constness)
- .instantiate_supertrait(cx, bound_clause.rebind(data.trait_ref)),
- )
- }),
+ cx.explicit_implied_const_bounds(data.def_id().into()).iter_identity().map(
+ |trait_ref| {
+ elaboratable.child(
+ trait_ref
+ .to_host_effect_clause(cx, data.constness)
+ .instantiate_supertrait(cx, bound_clause.rebind(data.trait_ref)),
+ )
+ },
+ ),
),
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
// We know that `T: 'a` for some type `T`. We can
@@ -312,8 +314,8 @@ fn next(&mut self) -> Option<Self::Item> {
/// and to make size estimates for vtable layout computation.
pub fn supertrait_def_ids<I: Interner>(
cx: I,
- trait_def_id: I::DefId,
-) -> impl Iterator<Item = I::DefId> {
+ trait_def_id: I::TraitId,
+) -> impl Iterator<Item = I::TraitId> {
let mut set = HashSet::default();
let mut stack = vec![trait_def_id];
diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs
index e8840bc..eb5b6b4 100644
--- a/compiler/rustc_type_ir/src/error.rs
+++ b/compiler/rustc_type_ir/src/error.rs
@@ -38,7 +38,7 @@ pub enum TypeError<I: Interner> {
Sorts(ExpectedFound<I::Ty>),
ArgumentSorts(ExpectedFound<I::Ty>, usize),
- Traits(ExpectedFound<I::DefId>),
+ Traits(ExpectedFound<I::TraitId>),
VariadicMismatch(ExpectedFound<bool>),
/// Instantiating a type variable with the given type would have
diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs
index d88c88f..5a05630 100644
--- a/compiler/rustc_type_ir/src/fast_reject.rs
+++ b/compiler/rustc_type_ir/src/fast_reject.rs
@@ -130,7 +130,7 @@ pub fn simplify_type<I: Interner>(
ty::RawPtr(_, mutbl) => Some(SimplifiedType::Ptr(mutbl)),
ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() {
Some(principal_def_id) if !cx.trait_is_auto(principal_def_id) => {
- Some(SimplifiedType::Trait(principal_def_id))
+ Some(SimplifiedType::Trait(principal_def_id.into()))
}
_ => Some(SimplifiedType::MarkerTraitObject),
},
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index e39b99e..b446229 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -148,10 +148,6 @@ fn next_trait_solver(&self) -> bool {
true
}
- fn in_hir_typeck(&self) -> bool {
- false
- }
-
fn typing_mode(&self) -> TypingMode<Self::Interner>;
fn universe(&self) -> ty::UniverseIndex;
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 569570b..64063b1 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -649,11 +649,11 @@ pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
pub trait BoundExistentialPredicates<I: Interner>:
Copy + Debug + Hash + Eq + Relate<I> + SliceLike<Item = ty::Binder<I, ty::ExistentialPredicate<I>>>
{
- fn principal_def_id(self) -> Option<I::DefId>;
+ fn principal_def_id(self) -> Option<I::TraitId>;
fn principal(self) -> Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>;
- fn auto_traits(self) -> impl IntoIterator<Item = I::DefId>;
+ fn auto_traits(self) -> impl IntoIterator<Item = I::TraitId>;
fn projection_bounds(
self,
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index e323124..21fe787 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -8,7 +8,7 @@
use crate::fold::TypeFoldable;
use crate::inherent::*;
use crate::ir_print::IrPrint;
-use crate::lang_items::TraitSolverLangItem;
+use crate::lang_items::{SolverLangItem, SolverTraitLangItem};
use crate::relate::Relate;
use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult};
use crate::visit::{Flags, TypeVisitable};
@@ -38,6 +38,13 @@ fn next_trait_solver_globally(self) -> bool {
type DefId: DefId<Self>;
type LocalDefId: Copy + Debug + Hash + Eq + Into<Self::DefId> + TypeFoldable<Self>;
+ /// A `DefId` of a trait.
+ ///
+ /// In rustc this is just a `DefId`, but rust-analyzer uses different types for different items.
+ ///
+ /// Note: The `TryFrom<DefId>` always succeeds (in rustc), so don't use it to check if some `DefId`
+ /// is a trait!
+ type TraitId: DefId<Self> + Into<Self::DefId> + TryFrom<Self::DefId, Error: std::fmt::Debug>;
type Span: Span<Self>;
type GenericArgs: GenericArgs<Self>;
@@ -271,7 +278,7 @@ fn own_predicates_of(
fn explicit_super_predicates_of(
self,
- def_id: Self::DefId,
+ def_id: Self::TraitId,
) -> ty::EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>>;
fn explicit_implied_predicates_of(
@@ -302,19 +309,25 @@ fn explicit_implied_const_bounds(
fn has_target_features(self, def_id: Self::DefId) -> bool;
- fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId;
+ fn require_lang_item(self, lang_item: SolverLangItem) -> Self::DefId;
- fn is_lang_item(self, def_id: Self::DefId, lang_item: TraitSolverLangItem) -> bool;
+ fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> Self::TraitId;
- fn is_default_trait(self, def_id: Self::DefId) -> bool;
+ fn is_lang_item(self, def_id: Self::DefId, lang_item: SolverLangItem) -> bool;
- fn as_lang_item(self, def_id: Self::DefId) -> Option<TraitSolverLangItem>;
+ fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool;
+
+ fn is_default_trait(self, def_id: Self::TraitId) -> bool;
+
+ fn as_lang_item(self, def_id: Self::DefId) -> Option<SolverLangItem>;
+
+ fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem>;
fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator<Item = Self::DefId>;
fn for_each_relevant_impl(
self,
- trait_def_id: Self::DefId,
+ trait_def_id: Self::TraitId,
self_ty: Self::Ty,
f: impl FnMut(Self::DefId),
);
@@ -329,20 +342,20 @@ fn for_each_relevant_impl(
fn impl_polarity(self, impl_def_id: Self::DefId) -> ty::ImplPolarity;
- fn trait_is_auto(self, trait_def_id: Self::DefId) -> bool;
+ fn trait_is_auto(self, trait_def_id: Self::TraitId) -> bool;
- fn trait_is_coinductive(self, trait_def_id: Self::DefId) -> bool;
+ fn trait_is_coinductive(self, trait_def_id: Self::TraitId) -> bool;
- fn trait_is_alias(self, trait_def_id: Self::DefId) -> bool;
+ fn trait_is_alias(self, trait_def_id: Self::TraitId) -> bool;
- fn trait_is_dyn_compatible(self, trait_def_id: Self::DefId) -> bool;
+ fn trait_is_dyn_compatible(self, trait_def_id: Self::TraitId) -> bool;
- fn trait_is_fundamental(self, def_id: Self::DefId) -> bool;
+ fn trait_is_fundamental(self, def_id: Self::TraitId) -> bool;
- fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;
+ fn trait_may_be_implemented_via_object(self, trait_def_id: Self::TraitId) -> bool;
/// Returns `true` if this is an `unsafe trait`.
- fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool;
+ fn trait_is_unsafe(self, trait_def_id: Self::TraitId) -> bool;
fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs
index f999444..31f8f5b 100644
--- a/compiler/rustc_type_ir/src/lang_items.rs
+++ b/compiler/rustc_type_ir/src/lang_items.rs
@@ -1,40 +1,46 @@
/// Lang items used by the new trait solver. This can be mapped to whatever internal
/// representation of `LangItem`s used in the underlying compiler implementation.
-pub enum TraitSolverLangItem {
+pub enum SolverLangItem {
+ // tidy-alphabetical-start
+ AsyncFnKindUpvars,
+ AsyncFnOnceOutput,
+ CallOnceFuture,
+ CallRefFuture,
+ CoroutineReturn,
+ CoroutineYield,
+ DynMetadata,
+ FutureOutput,
+ Metadata,
+ Option,
+ Poll,
+ // tidy-alphabetical-end
+}
+
+pub enum SolverTraitLangItem {
// tidy-alphabetical-start
AsyncFn,
AsyncFnKindHelper,
- AsyncFnKindUpvars,
AsyncFnMut,
AsyncFnOnce,
AsyncFnOnceOutput,
AsyncIterator,
BikeshedGuaranteedNoDrop,
- CallOnceFuture,
- CallRefFuture,
Clone,
Copy,
Coroutine,
- CoroutineReturn,
- CoroutineYield,
Destruct,
DiscriminantKind,
Drop,
- DynMetadata,
Fn,
FnMut,
FnOnce,
FnPtrTrait,
FusedIterator,
Future,
- FutureOutput,
Iterator,
MetaSized,
- Metadata,
- Option,
PointeeSized,
PointeeTrait,
- Poll,
Sized,
TransmuteTrait,
Tuple,
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index b53eb09..a3300b8 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -58,7 +58,7 @@ fn lift_to_interner(self, cx: U) -> Option<Self::Lifted> {
derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
)]
pub struct TraitRef<I: Interner> {
- pub def_id: I::DefId,
+ pub def_id: I::TraitId,
pub args: I::GenericArgs,
/// This field exists to prevent the creation of `TraitRef` without
/// calling [`TraitRef::new_from_args`].
@@ -68,32 +68,32 @@ pub struct TraitRef<I: Interner> {
impl<I: Interner> Eq for TraitRef<I> {}
impl<I: Interner> TraitRef<I> {
- pub fn new_from_args(interner: I, trait_def_id: I::DefId, args: I::GenericArgs) -> Self {
- interner.debug_assert_args_compatible(trait_def_id, args);
+ pub fn new_from_args(interner: I, trait_def_id: I::TraitId, args: I::GenericArgs) -> Self {
+ interner.debug_assert_args_compatible(trait_def_id.into(), args);
Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
}
pub fn new(
interner: I,
- trait_def_id: I::DefId,
+ trait_def_id: I::TraitId,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
) -> Self {
let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
Self::new_from_args(interner, trait_def_id, args)
}
- pub fn from_assoc(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
- let generics = interner.generics_of(trait_id);
+ pub fn from_assoc(interner: I, trait_id: I::TraitId, args: I::GenericArgs) -> TraitRef<I> {
+ let generics = interner.generics_of(trait_id.into());
TraitRef::new(interner, trait_id, args.iter().take(generics.count()))
}
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
/// are the parameters defined on trait.
- pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
+ pub fn identity(interner: I, def_id: I::TraitId) -> TraitRef<I> {
TraitRef::new_from_args(
interner,
def_id,
- I::GenericArgs::identity_for_item(interner, def_id),
+ I::GenericArgs::identity_for_item(interner, def_id.into()),
)
}
@@ -116,7 +116,7 @@ pub fn self_ty(&self) -> ty::Binder<I, I::Ty> {
self.map_bound_ref(|tr| tr.self_ty())
}
- pub fn def_id(&self) -> I::DefId {
+ pub fn def_id(&self) -> I::TraitId {
self.skip_binder().def_id
}
@@ -155,7 +155,7 @@ pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
}
}
- pub fn def_id(self) -> I::DefId {
+ pub fn def_id(self) -> I::TraitId {
self.trait_ref.def_id
}
@@ -165,7 +165,7 @@ pub fn self_ty(self) -> I::Ty {
}
impl<I: Interner> ty::Binder<I, TraitPredicate<I>> {
- pub fn def_id(self) -> I::DefId {
+ pub fn def_id(self) -> I::TraitId {
// Ok to skip binder since trait `DefId` does not care about regions.
self.skip_binder().def_id()
}
@@ -285,7 +285,7 @@ pub enum ExistentialPredicate<I: Interner> {
/// E.g., `Iterator::Item = T`.
Projection(ExistentialProjection<I>),
/// E.g., `Send`.
- AutoTrait(I::DefId),
+ AutoTrait(I::TraitId),
}
impl<I: Interner> Eq for ExistentialPredicate<I> {}
@@ -301,13 +301,14 @@ pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause {
self.rebind(p.with_self_ty(cx, self_ty)).upcast(cx)
}
ExistentialPredicate::AutoTrait(did) => {
- let generics = cx.generics_of(did);
+ let generics = cx.generics_of(did.into());
let trait_ref = if generics.count() == 1 {
ty::TraitRef::new(cx, did, [self_ty])
} else {
// If this is an ill-formed auto trait, then synthesize
// new error args for the missing generics.
- let err_args = GenericArgs::extend_with_error(cx, did, &[self_ty.into()]);
+ let err_args =
+ GenericArgs::extend_with_error(cx, did.into(), &[self_ty.into()]);
ty::TraitRef::new_from_args(cx, did, err_args)
};
self.rebind(trait_ref).upcast(cx)
@@ -330,7 +331,7 @@ pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause {
derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
)]
pub struct ExistentialTraitRef<I: Interner> {
- pub def_id: I::DefId,
+ pub def_id: I::TraitId,
pub args: I::GenericArgs,
/// This field exists to prevent the creation of `ExistentialTraitRef` without
/// calling [`ExistentialTraitRef::new_from_args`].
@@ -340,14 +341,14 @@ pub struct ExistentialTraitRef<I: Interner> {
impl<I: Interner> Eq for ExistentialTraitRef<I> {}
impl<I: Interner> ExistentialTraitRef<I> {
- pub fn new_from_args(interner: I, trait_def_id: I::DefId, args: I::GenericArgs) -> Self {
- interner.debug_assert_existential_args_compatible(trait_def_id, args);
+ pub fn new_from_args(interner: I, trait_def_id: I::TraitId, args: I::GenericArgs) -> Self {
+ interner.debug_assert_existential_args_compatible(trait_def_id.into(), args);
Self { def_id: trait_def_id, args, _use_existential_trait_ref_new_instead: () }
}
pub fn new(
interner: I,
- trait_def_id: I::DefId,
+ trait_def_id: I::TraitId,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
) -> Self {
let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
@@ -378,7 +379,7 @@ pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef<I> {
}
impl<I: Interner> ty::Binder<I, ExistentialTraitRef<I>> {
- pub fn def_id(&self) -> I::DefId {
+ pub fn def_id(&self) -> I::TraitId {
self.skip_binder().def_id
}
@@ -439,7 +440,7 @@ pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef<I> {
let def_id = interner.parent(self.def_id);
let args_count = interner.generics_of(def_id).count() - 1;
let args = interner.mk_args(&self.args.as_slice()[..args_count]);
- ExistentialTraitRef { def_id, args, _use_existential_trait_ref_new_instead: () }
+ ExistentialTraitRef::new_from_args(interner, def_id.try_into().unwrap(), args)
}
pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
@@ -675,7 +676,7 @@ pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
)
}
- pub fn trait_def_id(self, interner: I) -> I::DefId {
+ pub fn trait_def_id(self, interner: I) -> I::TraitId {
assert!(
matches!(
self.kind(interner),
@@ -683,7 +684,7 @@ pub fn trait_def_id(self, interner: I) -> I::DefId {
),
"expected a projection"
);
- interner.parent(self.def_id)
+ interner.parent(self.def_id).try_into().unwrap()
}
/// Extracts the underlying trait reference and own args from this projection.
@@ -787,7 +788,7 @@ pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPre
}
}
- pub fn trait_def_id(self, interner: I) -> I::DefId {
+ pub fn trait_def_id(self, interner: I) -> I::TraitId {
self.projection_term.trait_def_id(interner)
}
@@ -799,7 +800,7 @@ pub fn def_id(self) -> I::DefId {
impl<I: Interner> ty::Binder<I, ProjectionPredicate<I>> {
/// Returns the `DefId` of the trait of the associated item being projected.
#[inline]
- pub fn trait_def_id(&self, cx: I) -> I::DefId {
+ pub fn trait_def_id(&self, cx: I) -> I::TraitId {
self.skip_binder().projection_term.trait_def_id(cx)
}
@@ -847,7 +848,7 @@ pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo<
Self { alias: self.alias.with_replaced_self_ty(interner, self_ty), ..self }
}
- pub fn trait_def_id(self, interner: I) -> I::DefId {
+ pub fn trait_def_id(self, interner: I) -> I::TraitId {
self.alias.trait_def_id(interner)
}
@@ -884,13 +885,13 @@ pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), ..self }
}
- pub fn def_id(self) -> I::DefId {
+ pub fn def_id(self) -> I::TraitId {
self.trait_ref.def_id
}
}
impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
- pub fn def_id(self) -> I::DefId {
+ pub fn def_id(self) -> I::TraitId {
// Ok to skip binder since trait `DefId` does not care about regions.
self.skip_binder().def_id()
}
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index ff92a00..785d419 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -68,7 +68,7 @@ pub enum PredicateKind<I: Interner> {
Clause(ClauseKind<I>),
/// Trait must be dyn-compatible.
- DynCompatible(I::DefId),
+ DynCompatible(I::TraitId),
/// `T1 <: T2`
///
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index 1497236..b6d362d 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -7,7 +7,7 @@
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
-use crate::lang_items::TraitSolverLangItem;
+use crate::lang_items::SolverTraitLangItem;
use crate::search_graph::PathKind;
use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast};
@@ -386,10 +386,10 @@ pub enum SizedTraitKind {
impl SizedTraitKind {
/// Returns `DefId` of corresponding language item.
- pub fn require_lang_item<I: Interner>(self, cx: I) -> I::DefId {
- cx.require_lang_item(match self {
- SizedTraitKind::Sized => TraitSolverLangItem::Sized,
- SizedTraitKind::MetaSized => TraitSolverLangItem::MetaSized,
+ pub fn require_lang_item<I: Interner>(self, cx: I) -> I::TraitId {
+ cx.require_trait_lang_item(match self {
+ SizedTraitKind::Sized => SolverTraitLangItem::Sized,
+ SizedTraitKind::MetaSized => SolverTraitLangItem::MetaSized,
})
}
}
diff --git a/compiler/rustc_type_ir_macros/Cargo.toml b/compiler/rustc_type_ir_macros/Cargo.toml
index 15a5557..29a2cc8 100644
--- a/compiler/rustc_type_ir_macros/Cargo.toml
+++ b/compiler/rustc_type_ir_macros/Cargo.toml
@@ -8,8 +8,8 @@
[dependencies]
# tidy-alphabetical-start
-proc-macro2 = "1"
-quote = "1"
+proc-macro2.workspace = true
+quote.workspace = true
syn = { version = "2.0.9", features = ["full"] }
synstructure = "0.13.0"
# tidy-alphabetical-end
diff --git a/library/Cargo.lock b/library/Cargo.lock
index f0ac9d2..8b860f6 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -140,9 +140,9 @@
[[package]]
name = "libc"
-version = "0.2.174"
+version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
+checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
dependencies = [
"rustc-std-workspace-core",
]
@@ -169,9 +169,9 @@
[[package]]
name = "object"
-version = "0.37.2"
+version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3e3d0a7419f081f4a808147e845310313a39f322d7ae1f996b7f001d6cbed04"
+checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
"memchr",
"rustc-std-workspace-alloc",
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index fa12d37..98c9f6b5 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -2128,11 +2128,6 @@ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
#[stable(feature = "box_error", since = "1.8.0")]
impl<E: Error> Error for Box<E> {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- Error::description(&**self)
- }
-
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn Error> {
Error::cause(&**self)
diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs
index 8062658..45c46fb 100644
--- a/library/alloc/src/boxed/convert.rs
+++ b/library/alloc/src/boxed/convert.rs
@@ -608,12 +608,7 @@ impl<'a> From<String> for Box<dyn Error + Send + Sync + 'a> {
fn from(err: String) -> Box<dyn Error + Send + Sync + 'a> {
struct StringError(String);
- impl Error for StringError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- &self.0
- }
- }
+ impl Error for StringError {}
impl fmt::Display for StringError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index c4e5992..8b6d86a 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -40,30 +40,15 @@
/// An ordered map based on a [B-Tree].
///
-/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
-/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
-/// choice for a sorted map, as a perfectly balanced BST performs the theoretical minimum amount of
-/// comparisons necessary to find an element (log<sub>2</sub>n). However, in practice the way this
-/// is done is *very* inefficient for modern computer architectures. In particular, every element
-/// is stored in its own individually heap-allocated node. This means that every single insertion
-/// triggers a heap-allocation, and every single comparison should be a cache-miss. Since these
-/// are both notably expensive things to do in practice, we are forced to, at the very least,
-/// reconsider the BST strategy.
+/// Given a key type with a [total order], an ordered map stores its entries in key order.
+/// That means that keys must be of a type that implements the [`Ord`] trait,
+/// such that two keys can always be compared to determine their [`Ordering`].
+/// Examples of keys with a total order are strings with lexicographical order,
+/// and numbers with their natural order.
///
-/// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing
-/// this, we reduce the number of allocations by a factor of B, and improve cache efficiency in
-/// searches. However, this does mean that searches will have to do *more* comparisons on average.
-/// The precise number of comparisons depends on the node search strategy used. For optimal cache
-/// efficiency, one could search the nodes linearly. For optimal comparisons, one could search
-/// the node using binary search. As a compromise, one could also perform a linear search
-/// that initially only checks every i<sup>th</sup> element for some choice of i.
-///
-/// Currently, our implementation simply performs naive linear search. This provides excellent
-/// performance on *small* nodes of elements which are cheap to compare. However in the future we
-/// would like to further explore choosing the optimal search strategy based on the choice of B,
-/// and possibly other factors. Using linear search, searching for a random element is expected
-/// to take B * log(n) comparisons, which is generally worse than a BST. In practice,
-/// however, performance is excellent.
+/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::into_iter`], [`BTreeMap::values`], or
+/// [`BTreeMap::keys`] produce their items in key order, and take worst-case logarithmic and
+/// amortized constant time per item returned.
///
/// It is a logic error for a key to be modified in such a way that the key's ordering relative to
/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
@@ -72,14 +57,6 @@
/// `BTreeMap` that observed the logic error and not result in undefined behavior. This could
/// include panics, incorrect results, aborts, memory leaks, and non-termination.
///
-/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::into_iter`], [`BTreeMap::values`], or
-/// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and
-/// amortized constant time per item returned.
-///
-/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree
-/// [`Cell`]: core::cell::Cell
-/// [`RefCell`]: core::cell::RefCell
-///
/// # Examples
///
/// ```
@@ -169,6 +146,43 @@
/// // modify an entry before an insert with in-place mutation
/// player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100);
/// ```
+///
+/// # Background
+///
+/// A B-tree is (like) a [binary search tree], but adapted to the natural granularity that modern
+/// machines like to consume data at. This means that each node contains an entire array of elements,
+/// instead of just a single element.
+///
+/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
+/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
+/// choice for a sorted map, as a perfectly balanced BST performs the theoretical minimum number of
+/// comparisons necessary to find an element (log<sub>2</sub>n). However, in practice the way this
+/// is done is *very* inefficient for modern computer architectures. In particular, every element
+/// is stored in its own individually heap-allocated node. This means that every single insertion
+/// triggers a heap-allocation, and every comparison is a potential cache-miss due to the indirection.
+/// Since both heap-allocations and cache-misses are notably expensive in practice, we are forced to,
+/// at the very least, reconsider the BST strategy.
+///
+/// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing
+/// this, we reduce the number of allocations by a factor of B, and improve cache efficiency in
+/// searches. However, this does mean that searches will have to do *more* comparisons on average.
+/// The precise number of comparisons depends on the node search strategy used. For optimal cache
+/// efficiency, one could search the nodes linearly. For optimal comparisons, one could search
+/// the node using binary search. As a compromise, one could also perform a linear search
+/// that initially only checks every i<sup>th</sup> element for some choice of i.
+///
+/// Currently, our implementation simply performs naive linear search. This provides excellent
+/// performance on *small* nodes of elements which are cheap to compare. However in the future we
+/// would like to further explore choosing the optimal search strategy based on the choice of B,
+/// and possibly other factors. Using linear search, searching for a random element is expected
+/// to take B * log(n) comparisons, which is generally worse than a BST. In practice,
+/// however, performance is excellent.
+///
+/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree
+/// [binary search tree]: https://en.wikipedia.org/wiki/Binary_search_tree
+/// [total order]: https://en.wikipedia.org/wiki/Total_order
+/// [`Cell`]: core::cell::Cell
+/// [`RefCell`]: core::cell::RefCell
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeMap")]
#[rustc_insignificant_dtor]
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index ea8fa363..ec9b774 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -136,10 +136,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl<'a, K: core::fmt::Debug + Ord, V: core::fmt::Debug> core::error::Error
for crate::collections::btree_map::OccupiedError<'a, K, V>
{
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "key already exists"
- }
}
impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> {
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index fe6c89a..b0c8c4b 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -1061,17 +1061,10 @@ pub fn utf8_error(&self) -> Utf8Error {
}
}
-impl IntoStringError {
- fn description(&self) -> &str {
- "C string contained non-utf8 bytes"
- }
-}
-
#[stable(feature = "cstring_into", since = "1.7.0")]
impl fmt::Display for IntoStringError {
- #[allow(deprecated, deprecated_in_future)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.description().fmt(f)
+ "C string contained non-utf8 bytes".fmt(f)
}
}
@@ -1291,23 +1284,13 @@ fn ne(&self, other: &CString) -> bool {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl core::error::Error for NulError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "nul byte found in data"
- }
-}
+impl core::error::Error for NulError {}
#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
impl core::error::Error for FromVecWithNulError {}
#[stable(feature = "cstring_into", since = "1.7.0")]
impl core::error::Error for IntoStringError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "C string contained non-utf8 bytes"
- }
-
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
Some(&self.error)
}
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 639c5d4..711092a 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -159,6 +159,7 @@
#![feature(unicode_internals)]
#![feature(unsize)]
#![feature(unwrap_infallible)]
+#![feature(wtf8_internals)]
// tidy-alphabetical-end
//
// Language features:
@@ -232,6 +233,8 @@
#[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))]
pub mod task;
pub mod vec;
+#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))]
+pub mod wtf8;
#[doc(hidden)]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs
index 4071675..fd05f9c 100644
--- a/library/alloc/src/raw_vec/mod.rs
+++ b/library/alloc/src/raw_vec/mod.rs
@@ -155,7 +155,7 @@ fn with_capacity(capacity: usize, elem_layout: Layout) -> Self {
}
// Tiny Vecs are dumb. Skip to:
-// - 8 if the element size is 1, because any heap allocators is likely
+// - 8 if the element size is 1, because any heap allocator is likely
// to round up a request of less than 8 bytes to at least 8 bytes.
// - 4 if elements are moderate-sized (<= 1 KiB).
// - 1 otherwise, to avoid wasting too much space for very short Vecs.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 9eacbf0..1d0dd4b 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2285,20 +2285,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for FromUtf8Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "invalid utf-8"
- }
-}
+impl Error for FromUtf8Error {}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for FromUtf16Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "invalid utf-16"
- }
-}
+impl Error for FromUtf16Error {}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2949,68 +2939,41 @@ fn spec_to_string(&self) -> String {
}
}
-// Generic/generated code can sometimes have multiple, nested references
-// for strings, including `&&&str`s that would never be written
-// by hand. This macro generates twelve layers of nested `&`-impl
-// for primitive strings.
-#[cfg(not(no_global_oom_handling))]
-macro_rules! to_string_str_wrap_in_ref {
- {x $($x:ident)*} => {
- &to_string_str_wrap_in_ref! { $($x)* }
- };
- {} => { str };
-}
-#[cfg(not(no_global_oom_handling))]
-macro_rules! to_string_expr_wrap_in_deref {
- {$self:expr ; x $($x:ident)*} => {
- *(to_string_expr_wrap_in_deref! { $self ; $($x)* })
- };
- {$self:expr ;} => { $self };
-}
#[cfg(not(no_global_oom_handling))]
macro_rules! to_string_str {
- {$($($x:ident)*),+} => {
+ {$($type:ty,)*} => {
$(
- impl SpecToString for to_string_str_wrap_in_ref!($($x)*) {
+ impl SpecToString for $type {
#[inline]
fn spec_to_string(&self) -> String {
- String::from(to_string_expr_wrap_in_deref!(self ; $($x)*))
+ let s: &str = self;
+ String::from(s)
}
}
- )+
+ )*
};
}
#[cfg(not(no_global_oom_handling))]
to_string_str! {
- x x x x x x x x x x x x,
- x x x x x x x x x x x,
- x x x x x x x x x x,
- x x x x x x x x x,
- x x x x x x x x,
- x x x x x x x,
- x x x x x x,
- x x x x x,
- x x x x,
- x x x,
- x x,
- x,
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl SpecToString for Cow<'_, str> {
- #[inline]
- fn spec_to_string(&self) -> String {
- self[..].to_owned()
- }
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl SpecToString for String {
- #[inline]
- fn spec_to_string(&self) -> String {
- self.to_owned()
- }
+ Cow<'_, str>,
+ String,
+ // Generic/generated code can sometimes have multiple, nested references
+ // for strings, including `&&&str`s that would never be written
+ // by hand.
+ &&&&&&&&&&&&str,
+ &&&&&&&&&&&str,
+ &&&&&&&&&&str,
+ &&&&&&&&&str,
+ &&&&&&&&str,
+ &&&&&&&str,
+ &&&&&&str,
+ &&&&&str,
+ &&&&str,
+ &&&str,
+ &&str,
+ &str,
+ str,
}
#[cfg(not(no_global_oom_handling))]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 29caa7b..a21b688 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -4113,11 +4113,6 @@ fn drop(&mut self) {
#[stable(feature = "arc_error", since = "1.52.0")]
impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- core::error::Error::description(&**self)
- }
-
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn core::error::Error> {
core::error::Error::cause(&**self)
diff --git a/library/alloc/src/wtf8/mod.rs b/library/alloc/src/wtf8/mod.rs
new file mode 100644
index 0000000..047994a
--- /dev/null
+++ b/library/alloc/src/wtf8/mod.rs
@@ -0,0 +1,562 @@
+//! Heap-allocated counterpart to core `wtf8` module.
+#![unstable(
+ feature = "wtf8_internals",
+ issue = "none",
+ reason = "this is internal code for representing OsStr on some platforms and not a public API"
+)]
+// rustdoc bug: doc(hidden) on the module won't stop types in the module from showing up in trait
+// implementations, so, we'll have to add more doc(hidden)s anyway
+#![doc(hidden)]
+
+// Note: This module is also included in the alloctests crate using #[path] to
+// run the tests. See the comment there for an explanation why this is the case.
+
+#[cfg(test)]
+mod tests;
+
+use core::char::{MAX_LEN_UTF8, encode_utf8_raw};
+use core::hash::{Hash, Hasher};
+pub use core::wtf8::{CodePoint, Wtf8};
+#[cfg(not(test))]
+pub use core::wtf8::{EncodeWide, Wtf8CodePoints};
+use core::{fmt, mem, ops, str};
+
+use crate::borrow::{Cow, ToOwned};
+use crate::boxed::Box;
+use crate::collections::TryReserveError;
+#[cfg(not(test))]
+use crate::rc::Rc;
+use crate::string::String;
+#[cfg(all(not(test), target_has_atomic = "ptr"))]
+use crate::sync::Arc;
+use crate::vec::Vec;
+
+/// An owned, growable string of well-formed WTF-8 data.
+///
+/// Similar to `String`, but can additionally contain surrogate code points
+/// if they’re not in a surrogate pair.
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
+#[doc(hidden)]
+pub struct Wtf8Buf {
+ bytes: Vec<u8>,
+
+ /// Do we know that `bytes` holds a valid UTF-8 encoding? We can easily
+ /// know this if we're constructed from a `String` or `&str`.
+ ///
+ /// It is possible for `bytes` to have valid UTF-8 without this being
+ /// set, such as when we're concatenating `&Wtf8`'s and surrogates become
+ /// paired, as we don't bother to rescan the entire string.
+ is_known_utf8: bool,
+}
+
+impl ops::Deref for Wtf8Buf {
+ type Target = Wtf8;
+
+ fn deref(&self) -> &Wtf8 {
+ self.as_slice()
+ }
+}
+
+impl ops::DerefMut for Wtf8Buf {
+ fn deref_mut(&mut self) -> &mut Wtf8 {
+ self.as_mut_slice()
+ }
+}
+
+/// Formats the string in double quotes, with characters escaped according to
+/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
+/// where each `x` is a hexadecimal digit.
+///
+/// For example, the code units [U+0061, U+D800, U+000A] are formatted as
+/// `"a\u{D800}\n"`.
+impl fmt::Debug for Wtf8Buf {
+ #[inline]
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&**self, formatter)
+ }
+}
+
+/// Formats the string with unpaired surrogates substituted with the replacement
+/// character, U+FFFD.
+impl fmt::Display for Wtf8Buf {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(s) = self.as_known_utf8() {
+ fmt::Display::fmt(s, formatter)
+ } else {
+ fmt::Display::fmt(&**self, formatter)
+ }
+ }
+}
+
+#[cfg_attr(test, allow(dead_code))]
+impl Wtf8Buf {
+ /// Creates a new, empty WTF-8 string.
+ #[inline]
+ pub fn new() -> Wtf8Buf {
+ Wtf8Buf { bytes: Vec::new(), is_known_utf8: true }
+ }
+
+ /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes.
+ #[inline]
+ pub fn with_capacity(capacity: usize) -> Wtf8Buf {
+ Wtf8Buf { bytes: Vec::with_capacity(capacity), is_known_utf8: true }
+ }
+
+ /// Creates a WTF-8 string from a WTF-8 byte vec.
+ ///
+ /// Since the byte vec is not checked for valid WTF-8, this function is
+ /// marked unsafe.
+ #[inline]
+ pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf {
+ Wtf8Buf { bytes: value, is_known_utf8: false }
+ }
+
+ /// Creates a WTF-8 string from a UTF-8 `String`.
+ ///
+ /// This takes ownership of the `String` and does not copy.
+ ///
+ /// Since WTF-8 is a superset of UTF-8, this always succeeds.
+ #[inline]
+ pub const fn from_string(string: String) -> Wtf8Buf {
+ Wtf8Buf { bytes: string.into_bytes(), is_known_utf8: true }
+ }
+
+ /// Creates a WTF-8 string from a UTF-8 `&str` slice.
+ ///
+ /// This copies the content of the slice.
+ ///
+ /// Since WTF-8 is a superset of UTF-8, this always succeeds.
+ #[inline]
+ pub fn from_str(s: &str) -> Wtf8Buf {
+ Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true }
+ }
+
+ pub fn clear(&mut self) {
+ self.bytes.clear();
+ self.is_known_utf8 = true;
+ }
+
+ /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units.
+ ///
+ /// This is lossless: calling `.encode_wide()` on the resulting string
+ /// will always return the original code units.
+ pub fn from_wide(v: &[u16]) -> Wtf8Buf {
+ let mut string = Wtf8Buf::with_capacity(v.len());
+ for item in char::decode_utf16(v.iter().cloned()) {
+ match item {
+ Ok(ch) => string.push_char(ch),
+ Err(surrogate) => {
+ let surrogate = surrogate.unpaired_surrogate();
+ // Surrogates are known to be in the code point range.
+ let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) };
+ // The string will now contain an unpaired surrogate.
+ string.is_known_utf8 = false;
+ // Skip the WTF-8 concatenation check,
+ // surrogate pairs are already decoded by decode_utf16
+ unsafe {
+ string.push_code_point_unchecked(code_point);
+ }
+ }
+ }
+ }
+ string
+ }
+
+ /// Appends the given `char` to the end of this string.
+ /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check.
+ /// Copied from String::push.
+ unsafe fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
+ let mut bytes = [0; MAX_LEN_UTF8];
+ let bytes = encode_utf8_raw(code_point.to_u32(), &mut bytes);
+ self.bytes.extend_from_slice(bytes)
+ }
+
+ #[inline]
+ pub fn as_slice(&self) -> &Wtf8 {
+ unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
+ }
+
+ #[inline]
+ pub fn as_mut_slice(&mut self) -> &mut Wtf8 {
+ // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would
+ // cause them to change from well-formed UTF-8 to ill-formed UTF-8,
+ // which would break the assumptions of the `is_known_utf8` field.
+ unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) }
+ }
+
+ /// Converts the string to UTF-8 without validation, if it was created from
+ /// valid UTF-8.
+ #[inline]
+ fn as_known_utf8(&self) -> Option<&str> {
+ if self.is_known_utf8 {
+ // SAFETY: The buffer is known to be valid UTF-8.
+ Some(unsafe { str::from_utf8_unchecked(self.as_bytes()) })
+ } else {
+ None
+ }
+ }
+
+ /// Reserves capacity for at least `additional` more bytes to be inserted
+ /// in the given `Wtf8Buf`.
+ /// The collection may reserve more space to avoid frequent reallocations.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity exceeds `isize::MAX` bytes.
+ #[inline]
+ pub fn reserve(&mut self, additional: usize) {
+ self.bytes.reserve(additional)
+ }
+
+ /// Tries to reserve capacity for at least `additional` more bytes to be
+ /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to
+ /// avoid frequent reallocations. After calling `try_reserve`, capacity will
+ /// be greater than or equal to `self.len() + additional`. Does nothing if
+ /// capacity is already sufficient. This method preserves the contents even
+ /// if an error occurs.
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ #[inline]
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.bytes.try_reserve(additional)
+ }
+
+ #[inline]
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.bytes.reserve_exact(additional)
+ }
+
+ /// Tries to reserve the minimum capacity for exactly `additional` more
+ /// bytes to be inserted in the given `Wtf8Buf`. After calling
+ /// `try_reserve_exact`, capacity will be greater than or equal to
+ /// `self.len() + additional` if it returns `Ok(())`.
+ /// Does nothing if the capacity is already sufficient.
+ ///
+ /// Note that the allocator may give the `Wtf8Buf` more space than it
+ /// requests. Therefore, capacity can not be relied upon to be precisely
+ /// minimal. Prefer [`try_reserve`] if future insertions are expected.
+ ///
+ /// [`try_reserve`]: Wtf8Buf::try_reserve
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ #[inline]
+ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.bytes.try_reserve_exact(additional)
+ }
+
+ #[inline]
+ pub fn shrink_to_fit(&mut self) {
+ self.bytes.shrink_to_fit()
+ }
+
+ #[inline]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ self.bytes.shrink_to(min_capacity)
+ }
+
+ #[inline]
+ pub fn leak<'a>(self) -> &'a mut Wtf8 {
+ unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) }
+ }
+
+ /// Returns the number of bytes that this string buffer can hold without reallocating.
+ #[inline]
+ pub fn capacity(&self) -> usize {
+ self.bytes.capacity()
+ }
+
+ /// Append a UTF-8 slice at the end of the string.
+ #[inline]
+ pub fn push_str(&mut self, other: &str) {
+ self.bytes.extend_from_slice(other.as_bytes())
+ }
+
+ /// Append a WTF-8 slice at the end of the string.
+ ///
+ /// This replaces newly paired surrogates at the boundary
+ /// with a supplementary code point,
+ /// like concatenating ill-formed UTF-16 strings effectively would.
+ #[inline]
+ pub fn push_wtf8(&mut self, other: &Wtf8) {
+ match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) {
+ // Replace newly paired surrogates by a supplementary code point.
+ (Some(lead), Some(trail)) => {
+ let len_without_lead_surrogate = self.len() - 3;
+ self.bytes.truncate(len_without_lead_surrogate);
+ let other_without_trail_surrogate = &other.as_bytes()[3..];
+ // 4 bytes for the supplementary code point
+ self.bytes.reserve(4 + other_without_trail_surrogate.len());
+ self.push_char(decode_surrogate_pair(lead, trail));
+ self.bytes.extend_from_slice(other_without_trail_surrogate);
+ }
+ _ => {
+ // If we'll be pushing a string containing a surrogate, we may
+ // no longer have UTF-8.
+ if self.is_known_utf8 && other.next_surrogate(0).is_some() {
+ self.is_known_utf8 = false;
+ }
+
+ self.bytes.extend_from_slice(other.as_bytes());
+ }
+ }
+ }
+
+ /// Append a Unicode scalar value at the end of the string.
+ #[inline]
+ pub fn push_char(&mut self, c: char) {
+ // SAFETY: It's always safe to push a char.
+ unsafe { self.push_code_point_unchecked(CodePoint::from_char(c)) }
+ }
+
+ /// Append a code point at the end of the string.
+ ///
+ /// This replaces newly paired surrogates at the boundary
+ /// with a supplementary code point,
+ /// like concatenating ill-formed UTF-16 strings effectively would.
+ #[inline]
+ pub fn push(&mut self, code_point: CodePoint) {
+ if let Some(trail) = code_point.to_trail_surrogate() {
+ if let Some(lead) = (&*self).final_lead_surrogate() {
+ let len_without_lead_surrogate = self.len() - 3;
+ self.bytes.truncate(len_without_lead_surrogate);
+ self.push_char(decode_surrogate_pair(lead, trail));
+ return;
+ }
+
+ // We're pushing a trailing surrogate.
+ self.is_known_utf8 = false;
+ } else if code_point.to_lead_surrogate().is_some() {
+ // We're pushing a leading surrogate.
+ self.is_known_utf8 = false;
+ }
+
+ // No newly paired surrogates at the boundary.
+ unsafe { self.push_code_point_unchecked(code_point) }
+ }
+
+ /// Shortens a string to the specified length.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `new_len` > current length,
+ /// or if `new_len` is not a code point boundary.
+ #[inline]
+ pub fn truncate(&mut self, new_len: usize) {
+ assert!(self.is_code_point_boundary(new_len));
+ self.bytes.truncate(new_len)
+ }
+
+ /// Consumes the WTF-8 string and tries to convert it to a vec of bytes.
+ #[inline]
+ pub fn into_bytes(self) -> Vec<u8> {
+ self.bytes
+ }
+
+ /// Consumes the WTF-8 string and tries to convert it to UTF-8.
+ ///
+ /// This does not copy the data.
+ ///
+ /// If the contents are not well-formed UTF-8
+ /// (that is, if the string contains surrogates),
+ /// the original WTF-8 string is returned instead.
+ pub fn into_string(self) -> Result<String, Wtf8Buf> {
+ if self.is_known_utf8 || self.next_surrogate(0).is_none() {
+ Ok(unsafe { String::from_utf8_unchecked(self.bytes) })
+ } else {
+ Err(self)
+ }
+ }
+
+ /// Consumes the WTF-8 string and converts it lossily to UTF-8.
+ ///
+ /// This does not copy the data (but may overwrite parts of it in place).
+ ///
+ /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”)
+ pub fn into_string_lossy(mut self) -> String {
+ if !self.is_known_utf8 {
+ let mut pos = 0;
+ while let Some((surrogate_pos, _)) = self.next_surrogate(pos) {
+ pos = surrogate_pos + 3;
+ // Surrogates and the replacement character are all 3 bytes, so
+ // they can substituted in-place.
+ self.bytes[surrogate_pos..pos].copy_from_slice("\u{FFFD}".as_bytes());
+ }
+ }
+ unsafe { String::from_utf8_unchecked(self.bytes) }
+ }
+
+ /// Converts this `Wtf8Buf` into a boxed `Wtf8`.
+ #[inline]
+ pub fn into_box(self) -> Box<Wtf8> {
+ // SAFETY: relies on `Wtf8` being `repr(transparent)`.
+ unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
+ }
+
+ /// Converts a `Box<Wtf8>` into a `Wtf8Buf`.
+ pub fn from_box(boxed: Box<Wtf8>) -> Wtf8Buf {
+ let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) };
+ Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false }
+ }
+
+ /// Provides plumbing to core `Vec::extend_from_slice`.
+ /// More well behaving alternative to allowing outer types
+ /// full mutable access to the core `Vec`.
+ #[inline]
+ pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
+ self.bytes.extend_from_slice(other);
+ self.is_known_utf8 = false;
+ }
+}
+
+/// Creates a new WTF-8 string from an iterator of code points.
+///
+/// This replaces surrogate code point pairs with supplementary code points,
+/// like concatenating ill-formed UTF-16 strings effectively would.
+impl FromIterator<CodePoint> for Wtf8Buf {
+ fn from_iter<T: IntoIterator<Item = CodePoint>>(iter: T) -> Wtf8Buf {
+ let mut string = Wtf8Buf::new();
+ string.extend(iter);
+ string
+ }
+}
+
+/// Append code points from an iterator to the string.
+///
+/// This replaces surrogate code point pairs with supplementary code points,
+/// like concatenating ill-formed UTF-16 strings effectively would.
+impl Extend<CodePoint> for Wtf8Buf {
+ fn extend<T: IntoIterator<Item = CodePoint>>(&mut self, iter: T) {
+ let iterator = iter.into_iter();
+ let (low, _high) = iterator.size_hint();
+ // Lower bound of one byte per code point (ASCII only)
+ self.bytes.reserve(low);
+ iterator.for_each(move |code_point| self.push(code_point));
+ }
+
+ #[inline]
+ fn extend_one(&mut self, code_point: CodePoint) {
+ self.push(code_point);
+ }
+
+ #[inline]
+ fn extend_reserve(&mut self, additional: usize) {
+ // Lower bound of one byte per code point (ASCII only)
+ self.bytes.reserve(additional);
+ }
+}
+
+/// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`.
+pub(super) fn to_owned(slice: &Wtf8) -> Wtf8Buf {
+ Wtf8Buf { bytes: slice.as_bytes().to_vec(), is_known_utf8: false }
+}
+
+/// Lossily converts the string to UTF-8.
+/// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8.
+///
+/// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”).
+///
+/// This only copies the data if necessary (if it contains any surrogate).
+pub(super) fn to_string_lossy(slice: &Wtf8) -> Cow<'_, str> {
+ let Some((surrogate_pos, _)) = slice.next_surrogate(0) else {
+ return Cow::Borrowed(unsafe { str::from_utf8_unchecked(slice.as_bytes()) });
+ };
+ let wtf8_bytes = slice.as_bytes();
+ let mut utf8_bytes = Vec::with_capacity(slice.len());
+ utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]);
+ utf8_bytes.extend_from_slice("\u{FFFD}".as_bytes());
+ let mut pos = surrogate_pos + 3;
+ loop {
+ match slice.next_surrogate(pos) {
+ Some((surrogate_pos, _)) => {
+ utf8_bytes.extend_from_slice(&wtf8_bytes[pos..surrogate_pos]);
+ utf8_bytes.extend_from_slice("\u{FFFD}".as_bytes());
+ pos = surrogate_pos + 3;
+ }
+ None => {
+ utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]);
+ return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) });
+ }
+ }
+ }
+}
+
+#[inline]
+pub(super) fn clone_into(slice: &Wtf8, buf: &mut Wtf8Buf) {
+ buf.is_known_utf8 = false;
+ slice.as_bytes().clone_into(&mut buf.bytes);
+}
+
+#[cfg(not(test))]
+impl Wtf8 {
+ #[rustc_allow_incoherent_impl]
+ pub fn to_owned(&self) -> Wtf8Buf {
+ to_owned(self)
+ }
+
+ #[rustc_allow_incoherent_impl]
+ pub fn clone_into(&self, buf: &mut Wtf8Buf) {
+ clone_into(self, buf)
+ }
+
+ #[rustc_allow_incoherent_impl]
+ pub fn to_string_lossy(&self) -> Cow<'_, str> {
+ to_string_lossy(self)
+ }
+
+ #[rustc_allow_incoherent_impl]
+ pub fn into_box(&self) -> Box<Wtf8> {
+ let boxed: Box<[u8]> = self.as_bytes().into();
+ unsafe { mem::transmute(boxed) }
+ }
+
+ #[rustc_allow_incoherent_impl]
+ pub fn empty_box() -> Box<Wtf8> {
+ let boxed: Box<[u8]> = Default::default();
+ unsafe { mem::transmute(boxed) }
+ }
+
+ #[cfg(target_has_atomic = "ptr")]
+ #[rustc_allow_incoherent_impl]
+ pub fn into_arc(&self) -> Arc<Wtf8> {
+ let arc: Arc<[u8]> = Arc::from(self.as_bytes());
+ unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) }
+ }
+
+ #[rustc_allow_incoherent_impl]
+ pub fn into_rc(&self) -> Rc<Wtf8> {
+ let rc: Rc<[u8]> = Rc::from(self.as_bytes());
+ unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) }
+ }
+
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
+ Wtf8Buf { bytes: self.as_bytes().to_ascii_lowercase(), is_known_utf8: false }
+ }
+
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
+ Wtf8Buf { bytes: self.as_bytes().to_ascii_uppercase(), is_known_utf8: false }
+ }
+}
+
+#[inline]
+fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
+ let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32);
+ unsafe { char::from_u32_unchecked(code_point) }
+}
+
+impl Hash for Wtf8Buf {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write(&self.bytes);
+ 0xfeu8.hash(state)
+ }
+}
diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/alloc/src/wtf8/tests.rs
similarity index 75%
rename from library/std/src/sys_common/wtf8/tests.rs
rename to library/alloc/src/wtf8/tests.rs
index b57c99a..291f63f 100644
--- a/library/std/src/sys_common/wtf8/tests.rs
+++ b/library/alloc/src/wtf8/tests.rs
@@ -1,3 +1,5 @@
+use realalloc::string::ToString;
+
use super::*;
#[test]
@@ -82,82 +84,85 @@ fn c(value: u32) -> CodePoint {
#[test]
fn wtf8buf_new() {
- assert_eq!(Wtf8Buf::new().bytes, b"");
+ assert_eq!(Wtf8Buf::new().as_bytes(), b"");
}
#[test]
fn wtf8buf_from_str() {
- assert_eq!(Wtf8Buf::from_str("").bytes, b"");
- assert_eq!(Wtf8Buf::from_str("aé 💩").bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(Wtf8Buf::from_str("").as_bytes(), b"");
+ assert_eq!(Wtf8Buf::from_str("aé 💩").as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
}
#[test]
fn wtf8buf_from_string() {
- assert_eq!(Wtf8Buf::from_string(String::from("")).bytes, b"");
- assert_eq!(Wtf8Buf::from_string(String::from("aé 💩")).bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(Wtf8Buf::from_string(String::from("")).as_bytes(), b"");
+ assert_eq!(
+ Wtf8Buf::from_string(String::from("aé 💩")).as_bytes(),
+ b"a\xC3\xA9 \xF0\x9F\x92\xA9"
+ );
}
#[test]
fn wtf8buf_from_wide() {
let buf = Wtf8Buf::from_wide(&[]);
- assert_eq!(buf.bytes, b"");
+ assert_eq!(buf.as_bytes(), b"");
assert!(buf.is_known_utf8);
let buf = Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xDCA9]);
- assert_eq!(buf.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(buf.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
assert!(buf.is_known_utf8);
let buf = Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]);
- assert_eq!(buf.bytes, b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9");
+ assert_eq!(buf.as_bytes(), b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9");
assert!(!buf.is_known_utf8);
let buf = Wtf8Buf::from_wide(&[0xD800]);
- assert_eq!(buf.bytes, b"\xED\xA0\x80");
+ assert_eq!(buf.as_bytes(), b"\xED\xA0\x80");
assert!(!buf.is_known_utf8);
let buf = Wtf8Buf::from_wide(&[0xDBFF]);
- assert_eq!(buf.bytes, b"\xED\xAF\xBF");
+ assert_eq!(buf.as_bytes(), b"\xED\xAF\xBF");
assert!(!buf.is_known_utf8);
let buf = Wtf8Buf::from_wide(&[0xDC00]);
- assert_eq!(buf.bytes, b"\xED\xB0\x80");
+ assert_eq!(buf.as_bytes(), b"\xED\xB0\x80");
assert!(!buf.is_known_utf8);
let buf = Wtf8Buf::from_wide(&[0xDFFF]);
- assert_eq!(buf.bytes, b"\xED\xBF\xBF");
+ assert_eq!(buf.as_bytes(), b"\xED\xBF\xBF");
assert!(!buf.is_known_utf8);
}
#[test]
fn wtf8buf_push_str() {
let mut string = Wtf8Buf::new();
- assert_eq!(string.bytes, b"");
+ assert_eq!(string.as_bytes(), b"");
assert!(string.is_known_utf8);
string.push_str("aé 💩");
- assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
assert!(string.is_known_utf8);
}
#[test]
fn wtf8buf_push_char() {
let mut string = Wtf8Buf::from_str("aé ");
- assert_eq!(string.bytes, b"a\xC3\xA9 ");
+ assert_eq!(string.as_bytes(), b"a\xC3\xA9 ");
assert!(string.is_known_utf8);
string.push_char('💩');
- assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
assert!(string.is_known_utf8);
}
#[test]
fn wtf8buf_push() {
let mut string = Wtf8Buf::from_str("aé ");
- assert_eq!(string.bytes, b"a\xC3\xA9 ");
+ assert_eq!(string.as_bytes(), b"a\xC3\xA9 ");
assert!(string.is_known_utf8);
string.push(CodePoint::from_char('💩'));
- assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
assert!(string.is_known_utf8);
fn c(value: u32) -> CodePoint {
@@ -168,53 +173,53 @@ fn c(value: u32) -> CodePoint {
string.push(c(0xD83D)); // lead
assert!(!string.is_known_utf8);
string.push(c(0xDCA9)); // trail
- assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic!
+ assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic!
let mut string = Wtf8Buf::new();
string.push(c(0xD83D)); // lead
assert!(!string.is_known_utf8);
string.push(c(0x20)); // not surrogate
string.push(c(0xDCA9)); // trail
- assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
+ assert_eq!(string.as_bytes(), b"\xED\xA0\xBD \xED\xB2\xA9");
let mut string = Wtf8Buf::new();
string.push(c(0xD800)); // lead
assert!(!string.is_known_utf8);
string.push(c(0xDBFF)); // lead
- assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF");
+ assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xED\xAF\xBF");
let mut string = Wtf8Buf::new();
string.push(c(0xD800)); // lead
assert!(!string.is_known_utf8);
string.push(c(0xE000)); // not surrogate
- assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80");
+ assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xEE\x80\x80");
let mut string = Wtf8Buf::new();
string.push(c(0xD7FF)); // not surrogate
assert!(string.is_known_utf8);
string.push(c(0xDC00)); // trail
assert!(!string.is_known_utf8);
- assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80");
+ assert_eq!(string.as_bytes(), b"\xED\x9F\xBF\xED\xB0\x80");
let mut string = Wtf8Buf::new();
string.push(c(0x61)); // not surrogate, < 3 bytes
assert!(string.is_known_utf8);
string.push(c(0xDC00)); // trail
assert!(!string.is_known_utf8);
- assert_eq!(string.bytes, b"\x61\xED\xB0\x80");
+ assert_eq!(string.as_bytes(), b"\x61\xED\xB0\x80");
let mut string = Wtf8Buf::new();
string.push(c(0xDC00)); // trail
assert!(!string.is_known_utf8);
- assert_eq!(string.bytes, b"\xED\xB0\x80");
+ assert_eq!(string.as_bytes(), b"\xED\xB0\x80");
}
#[test]
fn wtf8buf_push_wtf8() {
let mut string = Wtf8Buf::from_str("aé");
- assert_eq!(string.bytes, b"a\xC3\xA9");
+ assert_eq!(string.as_bytes(), b"a\xC3\xA9");
string.push_wtf8(Wtf8::from_str(" 💩"));
- assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
assert!(string.is_known_utf8);
fn w(v: &[u8]) -> &Wtf8 {
@@ -224,42 +229,42 @@ fn w(v: &[u8]) -> &Wtf8 {
let mut string = Wtf8Buf::new();
string.push_wtf8(w(b"\xED\xA0\xBD")); // lead
string.push_wtf8(w(b"\xED\xB2\xA9")); // trail
- assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic!
+ assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic!
let mut string = Wtf8Buf::new();
string.push_wtf8(w(b"\xED\xA0\xBD")); // lead
string.push_wtf8(w(b" ")); // not surrogate
string.push_wtf8(w(b"\xED\xB2\xA9")); // trail
- assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
+ assert_eq!(string.as_bytes(), b"\xED\xA0\xBD \xED\xB2\xA9");
assert!(!string.is_known_utf8);
let mut string = Wtf8Buf::new();
string.push_wtf8(w(b"\xED\xA0\x80")); // lead
string.push_wtf8(w(b"\xED\xAF\xBF")); // lead
- assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF");
+ assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xED\xAF\xBF");
assert!(!string.is_known_utf8);
let mut string = Wtf8Buf::new();
string.push_wtf8(w(b"\xED\xA0\x80")); // lead
string.push_wtf8(w(b"\xEE\x80\x80")); // not surrogate
- assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80");
+ assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xEE\x80\x80");
assert!(!string.is_known_utf8);
let mut string = Wtf8Buf::new();
string.push_wtf8(w(b"\xED\x9F\xBF")); // not surrogate
string.push_wtf8(w(b"\xED\xB0\x80")); // trail
- assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80");
+ assert_eq!(string.as_bytes(), b"\xED\x9F\xBF\xED\xB0\x80");
assert!(!string.is_known_utf8);
let mut string = Wtf8Buf::new();
string.push_wtf8(w(b"a")); // not surrogate, < 3 bytes
string.push_wtf8(w(b"\xED\xB0\x80")); // trail
- assert_eq!(string.bytes, b"\x61\xED\xB0\x80");
+ assert_eq!(string.as_bytes(), b"\x61\xED\xB0\x80");
assert!(!string.is_known_utf8);
let mut string = Wtf8Buf::new();
string.push_wtf8(w(b"\xED\xB0\x80")); // trail
- assert_eq!(string.bytes, b"\xED\xB0\x80");
+ assert_eq!(string.as_bytes(), b"\xED\xB0\x80");
assert!(!string.is_known_utf8);
}
@@ -269,15 +274,15 @@ fn wtf8buf_truncate() {
assert!(string.is_known_utf8);
string.truncate(3);
- assert_eq!(string.bytes, b"a\xC3\xA9");
+ assert_eq!(string.as_bytes(), b"a\xC3\xA9");
assert!(string.is_known_utf8);
string.truncate(1);
- assert_eq!(string.bytes, b"a");
+ assert_eq!(string.as_bytes(), b"a");
assert!(string.is_known_utf8);
string.truncate(0);
- assert_eq!(string.bytes, b"");
+ assert_eq!(string.as_bytes(), b"");
assert!(string.is_known_utf8);
}
@@ -287,11 +292,11 @@ fn wtf8buf_truncate_around_non_bmp() {
assert!(string.is_known_utf8);
string.truncate(4);
- assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9");
+ assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9");
assert!(string.is_known_utf8);
string.truncate(0);
- assert_eq!(string.bytes, b"");
+ assert_eq!(string.as_bytes(), b"");
assert!(string.is_known_utf8);
}
@@ -361,7 +366,7 @@ fn f(values: &[u32]) -> Wtf8Buf {
Wtf8Buf { bytes: b"a\xC3\xA9 \xF0\x9F\x92\xA9".to_vec(), is_known_utf8: true }
);
- assert_eq!(f(&[0xD83D, 0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic!
+ assert_eq!(f(&[0xD83D, 0xDCA9]).as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic!
assert_eq!(
f(&[0xD83D, 0x20, 0xDCA9]),
Wtf8Buf { bytes: b"\xED\xA0\xBD \xED\xB2\xA9".to_vec(), is_known_utf8: false }
@@ -401,7 +406,7 @@ fn c(value: &u32) -> CodePoint {
Wtf8Buf { bytes: b"a\xC3\xA9 \xF0\x9F\x92\xA9".to_vec(), is_known_utf8: true }
);
- assert_eq!(e(&[0xD83D], &[0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic!
+ assert_eq!(e(&[0xD83D], &[0xDCA9]).as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic!
assert_eq!(
e(&[0xD83D, 0x20], &[0xDCA9]),
Wtf8Buf { bytes: b"\xED\xA0\xBD \xED\xB2\xA9".to_vec(), is_known_utf8: false }
@@ -449,8 +454,8 @@ fn wtf8buf_show_str() {
#[test]
fn wtf8_from_str() {
- assert_eq!(&Wtf8::from_str("").bytes, b"");
- assert_eq!(&Wtf8::from_str("aé 💩").bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(&Wtf8::from_str("").as_bytes(), b"");
+ assert_eq!(&Wtf8::from_str("aé 💩").as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
}
#[test]
@@ -461,7 +466,7 @@ fn wtf8_len() {
#[test]
fn wtf8_slice() {
- assert_eq!(&Wtf8::from_str("aé 💩")[1..4].bytes, b"\xC3\xA9 ");
+ assert_eq!(&Wtf8::from_str("aé 💩")[1..4].as_bytes(), b"\xC3\xA9 ");
}
#[test]
@@ -472,7 +477,7 @@ fn wtf8_slice_not_code_point_boundary() {
#[test]
fn wtf8_slice_from() {
- assert_eq!(&Wtf8::from_str("aé 💩")[1..].bytes, b"\xC3\xA9 \xF0\x9F\x92\xA9");
+ assert_eq!(&Wtf8::from_str("aé 💩")[1..].as_bytes(), b"\xC3\xA9 \xF0\x9F\x92\xA9");
}
#[test]
@@ -483,7 +488,7 @@ fn wtf8_slice_from_not_code_point_boundary() {
#[test]
fn wtf8_slice_to() {
- assert_eq!(&Wtf8::from_str("aé 💩")[..4].bytes, b"a\xC3\xA9 ");
+ assert_eq!(&Wtf8::from_str("aé 💩")[..4].as_bytes(), b"a\xC3\xA9 ");
}
#[test]
@@ -529,12 +534,12 @@ fn wtf8_as_str() {
#[test]
fn wtf8_to_string_lossy() {
- assert_eq!(Wtf8::from_str("").to_string_lossy(), Cow::Borrowed(""));
- assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(), Cow::Borrowed("aé 💩"));
+ assert_eq!(to_string_lossy(Wtf8::from_str("")), Cow::Borrowed(""));
+ assert_eq!(to_string_lossy(Wtf8::from_str("aé 💩")), Cow::Borrowed("aé 💩"));
let mut string = Wtf8Buf::from_str("aé 💩");
string.push(CodePoint::from_u32(0xD800).unwrap());
let expected: Cow<'_, str> = Cow::Owned(String::from("aé 💩�"));
- assert_eq!(string.to_string_lossy(), expected);
+ assert_eq!(to_string_lossy(&string), expected);
}
#[test]
@@ -548,7 +553,7 @@ fn d(b: &[u8]) -> String {
let mut string = Wtf8Buf::from_str("aé 💩");
string.push(CodePoint::from_u32(0xD800).unwrap());
- assert_eq!("aé 💩�", d(string.as_inner()));
+ assert_eq!("aé 💩�", d(string.as_ref()));
}
#[test]
@@ -577,67 +582,41 @@ fn wtf8_encode_wide_size_hint() {
#[test]
fn wtf8_clone_into() {
let mut string = Wtf8Buf::new();
- Wtf8::from_str("green").clone_into(&mut string);
- assert_eq!(string.bytes, b"green");
+ clone_into(Wtf8::from_str("green"), &mut string);
+ assert_eq!(string.as_bytes(), b"green");
let mut string = Wtf8Buf::from_str("green");
- Wtf8::from_str("").clone_into(&mut string);
- assert_eq!(string.bytes, b"");
+ clone_into(Wtf8::from_str(""), &mut string);
+ assert_eq!(string.as_bytes(), b"");
let mut string = Wtf8Buf::from_str("red");
- Wtf8::from_str("green").clone_into(&mut string);
- assert_eq!(string.bytes, b"green");
+ clone_into(Wtf8::from_str("green"), &mut string);
+ assert_eq!(string.as_bytes(), b"green");
let mut string = Wtf8Buf::from_str("green");
- Wtf8::from_str("red").clone_into(&mut string);
- assert_eq!(string.bytes, b"red");
+ clone_into(Wtf8::from_str("red"), &mut string);
+ assert_eq!(string.as_bytes(), b"red");
let mut string = Wtf8Buf::from_str("green");
assert!(string.is_known_utf8);
- unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").clone_into(&mut string) };
- assert_eq!(string.bytes, b"\xED\xA0\x80");
+ clone_into(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") }, &mut string);
+ assert_eq!(string.as_bytes(), b"\xED\xA0\x80");
assert!(!string.is_known_utf8);
}
#[test]
-fn wtf8_to_ascii_lowercase() {
- let lowercase = Wtf8::from_str("").to_ascii_lowercase();
- assert_eq!(lowercase.bytes, b"");
-
- let lowercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_lowercase();
- assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87");
-
- let lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_lowercase() };
- assert_eq!(lowercase.bytes, b"\xED\xA0\x80");
- assert!(!lowercase.is_known_utf8);
-}
-
-#[test]
-fn wtf8_to_ascii_uppercase() {
- let uppercase = Wtf8::from_str("").to_ascii_uppercase();
- assert_eq!(uppercase.bytes, b"");
-
- let uppercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_uppercase();
- assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87");
-
- let uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_uppercase() };
- assert_eq!(uppercase.bytes, b"\xED\xA0\x80");
- assert!(!uppercase.is_known_utf8);
-}
-
-#[test]
fn wtf8_make_ascii_lowercase() {
let mut lowercase = Wtf8Buf::from_str("");
lowercase.make_ascii_lowercase();
- assert_eq!(lowercase.bytes, b"");
+ assert_eq!(lowercase.as_bytes(), b"");
let mut lowercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇");
lowercase.make_ascii_lowercase();
- assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87");
+ assert_eq!(lowercase.as_bytes(), b"green grapes! \xf0\x9f\x8d\x87");
- let mut lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
+ let mut lowercase = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
lowercase.make_ascii_lowercase();
- assert_eq!(lowercase.bytes, b"\xED\xA0\x80");
+ assert_eq!(lowercase.as_bytes(), b"\xED\xA0\x80");
assert!(!lowercase.is_known_utf8);
}
@@ -645,22 +624,22 @@ fn wtf8_make_ascii_lowercase() {
fn wtf8_make_ascii_uppercase() {
let mut uppercase = Wtf8Buf::from_str("");
uppercase.make_ascii_uppercase();
- assert_eq!(uppercase.bytes, b"");
+ assert_eq!(uppercase.as_bytes(), b"");
let mut uppercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇");
uppercase.make_ascii_uppercase();
- assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87");
+ assert_eq!(uppercase.as_bytes(), b"GREEN GRAPES! \xf0\x9f\x8d\x87");
- let mut uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
+ let mut uppercase = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
uppercase.make_ascii_uppercase();
- assert_eq!(uppercase.bytes, b"\xED\xA0\x80");
+ assert_eq!(uppercase.as_bytes(), b"\xED\xA0\x80");
assert!(!uppercase.is_known_utf8);
}
#[test]
fn wtf8_to_owned() {
- let string = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
- assert_eq!(string.bytes, b"\xED\xA0\x80");
+ let string = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
+ assert_eq!(string.as_bytes(), b"\xED\xA0\x80");
assert!(!string.is_known_utf8);
}
@@ -669,44 +648,44 @@ fn wtf8_valid_utf8_boundaries() {
let mut string = Wtf8Buf::from_str("aé 💩");
string.push(CodePoint::from_u32(0xD800).unwrap());
string.push(CodePoint::from_u32(0xD800).unwrap());
- check_utf8_boundary(&string, 0);
- check_utf8_boundary(&string, 1);
- check_utf8_boundary(&string, 3);
- check_utf8_boundary(&string, 4);
- check_utf8_boundary(&string, 8);
- check_utf8_boundary(&string, 14);
+ string.check_utf8_boundary(0);
+ string.check_utf8_boundary(1);
+ string.check_utf8_boundary(3);
+ string.check_utf8_boundary(4);
+ string.check_utf8_boundary(8);
+ string.check_utf8_boundary(14);
assert_eq!(string.len(), 14);
string.push_char('a');
- check_utf8_boundary(&string, 14);
- check_utf8_boundary(&string, 15);
+ string.check_utf8_boundary(14);
+ string.check_utf8_boundary(15);
let mut string = Wtf8Buf::from_str("a");
string.push(CodePoint::from_u32(0xD800).unwrap());
- check_utf8_boundary(&string, 1);
+ string.check_utf8_boundary(1);
let mut string = Wtf8Buf::from_str("\u{D7FF}");
string.push(CodePoint::from_u32(0xD800).unwrap());
- check_utf8_boundary(&string, 3);
+ string.check_utf8_boundary(3);
let mut string = Wtf8Buf::new();
string.push(CodePoint::from_u32(0xD800).unwrap());
string.push_char('\u{D7FF}');
- check_utf8_boundary(&string, 3);
+ string.check_utf8_boundary(3);
}
#[test]
#[should_panic(expected = "byte index 4 is out of bounds")]
fn wtf8_utf8_boundary_out_of_bounds() {
let string = Wtf8::from_str("aé");
- check_utf8_boundary(&string, 4);
+ string.check_utf8_boundary(4);
}
#[test]
#[should_panic(expected = "byte index 1 is not a codepoint boundary")]
fn wtf8_utf8_boundary_inside_codepoint() {
let string = Wtf8::from_str("é");
- check_utf8_boundary(&string, 1);
+ string.check_utf8_boundary(1);
}
#[test]
@@ -714,7 +693,7 @@ fn wtf8_utf8_boundary_inside_codepoint() {
fn wtf8_utf8_boundary_inside_surrogate() {
let mut string = Wtf8Buf::new();
string.push(CodePoint::from_u32(0xD800).unwrap());
- check_utf8_boundary(&string, 1);
+ string.check_utf8_boundary(1);
}
#[test]
@@ -723,20 +702,22 @@ fn wtf8_utf8_boundary_between_surrogates() {
let mut string = Wtf8Buf::new();
string.push(CodePoint::from_u32(0xD800).unwrap());
string.push(CodePoint::from_u32(0xD800).unwrap());
- check_utf8_boundary(&string, 3);
+ string.check_utf8_boundary(3);
}
#[test]
fn wobbled_wtf8_plus_bytes_isnt_utf8() {
- let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
+ let mut string: Wtf8Buf = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
assert!(!string.is_known_utf8);
- string.extend_from_slice(b"some utf-8");
+ unsafe {
+ string.extend_from_slice_unchecked(b"some utf-8");
+ }
assert!(!string.is_known_utf8);
}
#[test]
fn wobbled_wtf8_plus_str_isnt_utf8() {
- let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
+ let mut string: Wtf8Buf = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
assert!(!string.is_known_utf8);
string.push_str("some utf-8");
assert!(!string.is_known_utf8);
diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs
index 3241b4b..97de7d6 100644
--- a/library/alloctests/lib.rs
+++ b/library/alloctests/lib.rs
@@ -18,6 +18,8 @@
#![feature(allocator_api)]
#![feature(array_into_iter_constructors)]
#![feature(assert_matches)]
+#![feature(char_internals)]
+#![feature(char_max_len)]
#![feature(core_intrinsics)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
@@ -41,6 +43,7 @@
#![feature(trusted_random_access)]
#![feature(try_reserve_kind)]
#![feature(try_trait_v2)]
+#![feature(wtf8_internals)]
// tidy-alphabetical-end
//
// Language features:
@@ -68,15 +71,18 @@
mod testing;
use realalloc::*;
-// We are directly including collections and raw_vec here as both use non-public
-// methods and fields in tests and as such need to have the types to test in the
-// same crate as the tests themself.
+// We are directly including collections, raw_vec, and wtf8 here as they use non-public
+// methods and fields in tests and as such need to have the types to test in the same
+// crate as the tests themself.
#[path = "../alloc/src/collections/mod.rs"]
mod collections;
#[path = "../alloc/src/raw_vec/mod.rs"]
mod raw_vec;
+#[path = "../alloc/src/wtf8/mod.rs"]
+mod wtf8;
+
#[allow(dead_code)] // Not used in all configurations
pub(crate) mod test_helpers {
/// Copied from `std::test_helpers::test_rng`, since these tests rely on the
diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs
index fcfc7f8..bf446ae 100644
--- a/library/alloctests/tests/lib.rs
+++ b/library/alloctests/tests/lib.rs
@@ -3,6 +3,7 @@
#![feature(iter_array_chunks)]
#![feature(assert_matches)]
#![feature(btree_extract_if)]
+#![feature(wtf8_internals)]
#![feature(char_max_len)]
#![feature(cow_is_borrowed)]
#![feature(core_intrinsics)]
@@ -23,7 +24,6 @@
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_next_chunk)]
-#![feature(round_char_boundary)]
#![feature(slice_partition_dedup)]
#![feature(string_from_utf8_lossy_owned)]
#![feature(string_remove_matches)]
diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml
index c54df2e..3afadbf 100644
--- a/library/compiler-builtins/.github/workflows/main.yaml
+++ b/library/compiler-builtins/.github/workflows/main.yaml
@@ -51,8 +51,7 @@
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04-arm
- target: aarch64-pc-windows-msvc
- os: windows-2025
- build_only: 1
+ os: windows-11-arm
- target: arm-unknown-linux-gnueabi
os: ubuntu-24.04
- target: arm-unknown-linux-gnueabihf
diff --git a/library/compiler-builtins/builtins-test/benches/float_conv.rs b/library/compiler-builtins/builtins-test/benches/float_conv.rs
index e0f488e..40c13d2 100644
--- a/library/compiler-builtins/builtins-test/benches/float_conv.rs
+++ b/library/compiler-builtins/builtins-test/benches/float_conv.rs
@@ -1,4 +1,3 @@
-#![allow(improper_ctypes)]
#![cfg_attr(f128_enabled, feature(f128))]
use builtins_test::float_bench;
diff --git a/library/compiler-builtins/builtins-test/tests/addsub.rs b/library/compiler-builtins/builtins-test/tests/addsub.rs
index abe7dde..f3334bd 100644
--- a/library/compiler-builtins/builtins-test/tests/addsub.rs
+++ b/library/compiler-builtins/builtins-test/tests/addsub.rs
@@ -1,4 +1,5 @@
#![allow(unused_macros)]
+#![cfg_attr(f16_enabled, feature(f16))]
#![cfg_attr(f128_enabled, feature(f128))]
use builtins_test::*;
@@ -115,28 +116,25 @@ fn $fn_add() {
mod float_addsub {
use super::*;
+ #[cfg(f16_enabled)]
+ float_sum! {
+ f16, __addhf3, __subhf3, Half, all();
+ }
+
float_sum! {
f32, __addsf3, __subsf3, Single, all();
f64, __adddf3, __subdf3, Double, all();
}
-}
-#[cfg(f128_enabled)]
-#[cfg(not(x86_no_sse))]
-#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
-mod float_addsub_f128 {
- use super::*;
-
+ #[cfg(f128_enabled)]
+ #[cfg(not(x86_no_sse))]
+ #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
float_sum! {
f128, __addtf3, __subtf3, Quad, not(feature = "no-sys-f128");
}
-}
-#[cfg(f128_enabled)]
-#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
-mod float_addsub_f128_ppc {
- use super::*;
-
+ #[cfg(f128_enabled)]
+ #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
float_sum! {
f128, __addkf3, __subkf3, Quad, not(feature = "no-sys-f128");
}
diff --git a/library/compiler-builtins/builtins-test/tests/cmp.rs b/library/compiler-builtins/builtins-test/tests/cmp.rs
index a904dc5..4b01b6c 100644
--- a/library/compiler-builtins/builtins-test/tests/cmp.rs
+++ b/library/compiler-builtins/builtins-test/tests/cmp.rs
@@ -1,5 +1,6 @@
#![allow(unused_macros)]
#![allow(unreachable_code)]
+#![cfg_attr(f16_enabled, feature(f16))]
#![cfg_attr(f128_enabled, feature(f128))]
use builtins_test::*;
@@ -52,6 +53,26 @@ macro_rules! cmp {
}
#[test]
+ #[cfg(f16_enabled)]
+ fn cmp_f16() {
+ use compiler_builtins::float::cmp::{
+ __eqhf2, __gehf2, __gthf2, __lehf2, __lthf2, __nehf2, __unordhf2,
+ };
+
+ fuzz_float_2(N, |x: f16, y: f16| {
+ assert_eq!(__unordhf2(x, y) != 0, x.is_nan() || y.is_nan());
+ cmp!(f16, x, y, Half, all(),
+ 1, __lthf2;
+ 1, __lehf2;
+ 1, __eqhf2;
+ -1, __gehf2;
+ -1, __gthf2;
+ 1, __nehf2;
+ );
+ });
+ }
+
+ #[test]
fn cmp_f32() {
use compiler_builtins::float::cmp::{
__eqsf2, __gesf2, __gtsf2, __lesf2, __ltsf2, __nesf2, __unordsf2,
diff --git a/library/compiler-builtins/builtins-test/tests/mul.rs b/library/compiler-builtins/builtins-test/tests/mul.rs
index 3072b45..bbf1157 100644
--- a/library/compiler-builtins/builtins-test/tests/mul.rs
+++ b/library/compiler-builtins/builtins-test/tests/mul.rs
@@ -1,5 +1,6 @@
-#![allow(unused_macros)]
+#![cfg_attr(f16_enabled, feature(f16))]
#![cfg_attr(f128_enabled, feature(f128))]
+#![allow(unused_macros)]
use builtins_test::*;
@@ -117,6 +118,11 @@ fn $fn() {
mod float_mul {
use super::*;
+ #[cfg(f16_enabled)]
+ float_mul! {
+ f16, __mulhf3, Half, all();
+ }
+
// FIXME(#616): Stop ignoring arches that don't have native support once fix for builtins is in
// nightly.
float_mul! {
diff --git a/library/compiler-builtins/compiler-builtins/README.md b/library/compiler-builtins/compiler-builtins/README.md
index 387b70c..2d92b76 100644
--- a/library/compiler-builtins/compiler-builtins/README.md
+++ b/library/compiler-builtins/compiler-builtins/README.md
@@ -10,6 +10,16 @@
[`compiler-rt`]: https://github.com/llvm/llvm-project/tree/1b1dc505057322f4fa1110ef4f53c44347f52986/compiler-rt
+## Configuration
+
+`compiler-builtins` can be configured with the following environment variables when the `c` feature
+is enabled:
+
+- `LLVM_COMPILER_RT_LIB`
+- `RUST_COMPILER_RT_ROOT`
+
+See `build.rs` for details.
+
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).
diff --git a/library/compiler-builtins/compiler-builtins/build.rs b/library/compiler-builtins/compiler-builtins/build.rs
index 43b9786..6e1d230 100644
--- a/library/compiler-builtins/compiler-builtins/build.rs
+++ b/library/compiler-builtins/compiler-builtins/build.rs
@@ -540,12 +540,20 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
sources.extend(&[("__emutls_get_address", "emutls.c")]);
}
+ // Optionally, link against a prebuilt llvm compiler-rt containing the builtins
+ // library. Only the builtins library is required. On many platforms, this is
+ // available as a library named libclang_rt.builtins.a.
+ let link_against_prebuilt_rt = env::var_os("LLVM_COMPILER_RT_LIB").is_some();
+
// When compiling the C code we require the user to tell us where the
// source code is, and this is largely done so when we're compiling as
// part of rust-lang/rust we can use the same llvm-project repository as
// rust-lang/rust.
let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
Some(s) => PathBuf::from(s),
+ // If a prebuild libcompiler-rt is provided, set a valid
+ // path to simplify later logic. Nothing should be compiled.
+ None if link_against_prebuilt_rt => PathBuf::new(),
None => {
panic!(
"RUST_COMPILER_RT_ROOT is not set. You may need to run \
@@ -553,7 +561,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
);
}
};
- if !root.exists() {
+ if !link_against_prebuilt_rt && !root.exists() {
panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
}
@@ -569,7 +577,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
let src_dir = root.join("lib/builtins");
if target.arch == "aarch64" && target.env != "msvc" && target.os != "uefi" {
// See below for why we're building these as separate libraries.
- build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
+ build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg, link_against_prebuilt_rt);
// Some run-time CPU feature detection is necessary, as well.
let cpu_model_src = if src_dir.join("cpu_model.c").exists() {
@@ -583,20 +591,45 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
let mut added_sources = HashSet::new();
for (sym, src) in sources.map.iter() {
let src = src_dir.join(src);
- if added_sources.insert(src.clone()) {
+ if !link_against_prebuilt_rt && added_sources.insert(src.clone()) {
cfg.file(&src);
println!("cargo:rerun-if-changed={}", src.display());
}
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
}
- cfg.compile("libcompiler-rt.a");
+ if link_against_prebuilt_rt {
+ let rt_builtins_ext = PathBuf::from(env::var_os("LLVM_COMPILER_RT_LIB").unwrap());
+ if !rt_builtins_ext.exists() {
+ panic!(
+ "LLVM_COMPILER_RT_LIB={} does not exist",
+ rt_builtins_ext.display()
+ );
+ }
+ if let Some(dir) = rt_builtins_ext.parent() {
+ println!("cargo::rustc-link-search=native={}", dir.display());
+ }
+ if let Some(lib) = rt_builtins_ext.file_name() {
+ println!(
+ "cargo::rustc-link-lib=static:+verbatim={}",
+ lib.to_str().unwrap()
+ );
+ }
+ } else {
+ cfg.compile("libcompiler-rt.a");
+ }
}
- fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc::Build) {
+ fn build_aarch64_out_of_line_atomics_libraries(
+ builtins_dir: &Path,
+ cfg: &mut cc::Build,
+ link_against_prebuilt_rt: bool,
+ ) {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let outlined_atomics_file = builtins_dir.join("aarch64").join("lse.S");
- println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
+ if !link_against_prebuilt_rt {
+ println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
+ }
cfg.include(&builtins_dir);
@@ -609,6 +642,13 @@ fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc
for (model_number, model_name) in
&[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
{
+ let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
+ println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
+
+ if link_against_prebuilt_rt {
+ continue;
+ }
+
// The original compiler-rt build system compiles the same
// source file multiple times with different compiler
// options. Here we do something slightly different: we
@@ -632,9 +672,6 @@ fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc
.unwrap();
drop(file);
cfg.file(path);
-
- let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
- println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
}
}
}
diff --git a/library/compiler-builtins/compiler-builtins/src/float/add.rs b/library/compiler-builtins/compiler-builtins/src/float/add.rs
index 0cc362f..acdcd2e 100644
--- a/library/compiler-builtins/compiler-builtins/src/float/add.rs
+++ b/library/compiler-builtins/compiler-builtins/src/float/add.rs
@@ -130,7 +130,7 @@ fn add<F: Float>(a: F, b: F) -> F
return F::from_bits(MinInt::ZERO);
}
- // If partial cancellation occured, we need to left-shift the result
+ // If partial cancellation occurred, we need to left-shift the result
// and adjust the exponent:
if a_significand < implicit_bit << 3 {
let shift = a_significand.leading_zeros() as i32
@@ -191,6 +191,11 @@ fn add<F: Float>(a: F, b: F) -> F
}
intrinsics! {
+ #[cfg(f16_enabled)]
+ pub extern "C" fn __addhf3(a: f16, b: f16) -> f16 {
+ add(a, b)
+ }
+
#[aapcs_on_arm]
#[arm_aeabi_alias = __aeabi_fadd]
pub extern "C" fn __addsf3(a: f32, b: f32) -> f32 {
diff --git a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs
index f1e54dc..8ab39c2 100644
--- a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs
+++ b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs
@@ -115,6 +115,37 @@ fn unord<F: Float>(a: F, b: F) -> bool {
a_abs > inf_rep || b_abs > inf_rep
}
+#[cfg(f16_enabled)]
+intrinsics! {
+ pub extern "C" fn __lehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
+ cmp(a, b).to_le_abi()
+ }
+
+ pub extern "C" fn __gehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
+ cmp(a, b).to_ge_abi()
+ }
+
+ pub extern "C" fn __unordhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
+ unord(a, b) as crate::float::cmp::CmpResult
+ }
+
+ pub extern "C" fn __eqhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
+ cmp(a, b).to_le_abi()
+ }
+
+ pub extern "C" fn __lthf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
+ cmp(a, b).to_le_abi()
+ }
+
+ pub extern "C" fn __nehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
+ cmp(a, b).to_le_abi()
+ }
+
+ pub extern "C" fn __gthf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
+ cmp(a, b).to_ge_abi()
+ }
+}
+
intrinsics! {
pub extern "C" fn __lesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
diff --git a/library/compiler-builtins/compiler-builtins/src/float/mul.rs b/library/compiler-builtins/compiler-builtins/src/float/mul.rs
index dbed309..49a2414 100644
--- a/library/compiler-builtins/compiler-builtins/src/float/mul.rs
+++ b/library/compiler-builtins/compiler-builtins/src/float/mul.rs
@@ -180,6 +180,11 @@ fn mul<F: Float>(a: F, b: F) -> F
}
intrinsics! {
+ #[cfg(f16_enabled)]
+ pub extern "C" fn __mulhf3(a: f16, b: f16) -> f16 {
+ mul(a, b)
+ }
+
#[aapcs_on_arm]
#[arm_aeabi_alias = __aeabi_fmul]
pub extern "C" fn __mulsf3(a: f32, b: f32) -> f32 {
diff --git a/library/compiler-builtins/compiler-builtins/src/float/sub.rs b/library/compiler-builtins/compiler-builtins/src/float/sub.rs
index a0fd9df..48ef33b 100644
--- a/library/compiler-builtins/compiler-builtins/src/float/sub.rs
+++ b/library/compiler-builtins/compiler-builtins/src/float/sub.rs
@@ -1,6 +1,11 @@
use crate::float::Float;
intrinsics! {
+ #[cfg(f16_enabled)]
+ pub extern "C" fn __subhf3(a: f16, b: f16) -> f16 {
+ crate::float::add::__addhf3(a, f16::from_bits(b.to_bits() ^ f16::SIGN_MASK))
+ }
+
#[arm_aeabi_alias = __aeabi_fsub]
pub extern "C" fn __subsf3(a: f32, b: f32) -> f32 {
crate::float::add::__addsf3(a, f32::from_bits(b.to_bits() ^ f32::SIGN_MASK))
diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs
index ca75f44..b111dc0 100644
--- a/library/compiler-builtins/compiler-builtins/src/lib.rs
+++ b/library/compiler-builtins/compiler-builtins/src/lib.rs
@@ -18,10 +18,6 @@
#![no_std]
#![allow(unused_features)]
#![allow(internal_features)]
-// We use `u128` in a whole bunch of places which we currently agree with the
-// compiler on ABIs and such, so we should be "good enough" for now and changes
-// to the `u128` ABI will be reflected here.
-#![allow(improper_ctypes, improper_ctypes_definitions)]
// `mem::swap` cannot be used because it may generate references to memcpy in unoptimized code.
#![allow(clippy::manual_swap)]
// Support compiling on both stage0 and stage1 which may differ in supported stable features.
diff --git a/library/compiler-builtins/compiler-builtins/src/probestack.rs b/library/compiler-builtins/compiler-builtins/src/probestack.rs
index 9a18216..7297548 100644
--- a/library/compiler-builtins/compiler-builtins/src/probestack.rs
+++ b/library/compiler-builtins/compiler-builtins/src/probestack.rs
@@ -73,7 +73,7 @@
// page needed.
//
// Note that we're also testing against `8(%rsp)` to account for the 8
- // bytes pushed on the stack orginally with our return address. Using
+ // bytes pushed on the stack originally with our return address. Using
// `8(%rsp)` simulates us testing the stack pointer in the caller's
// context.
diff --git a/library/compiler-builtins/crates/symbol-check/src/main.rs b/library/compiler-builtins/crates/symbol-check/src/main.rs
index 1312a71..4e94552 100644
--- a/library/compiler-builtins/crates/symbol-check/src/main.rs
+++ b/library/compiler-builtins/crates/symbol-check/src/main.rs
@@ -9,7 +9,7 @@
use object::read::archive::{ArchiveFile, ArchiveMember};
use object::{
- File as ObjFile, Object, ObjectSymbol, Symbol, SymbolKind, SymbolScope, SymbolSection,
+ File as ObjFile, Object, ObjectSection, ObjectSymbol, Symbol, SymbolKind, SymbolScope,
};
use serde_json::Value;
@@ -154,7 +154,7 @@ struct SymInfo {
name: String,
kind: SymbolKind,
scope: SymbolScope,
- section: SymbolSection,
+ section: String,
is_undefined: bool,
is_global: bool,
is_local: bool,
@@ -165,12 +165,22 @@ struct SymInfo {
}
impl SymInfo {
- fn new(sym: &Symbol, member: &ArchiveMember) -> Self {
+ fn new(sym: &Symbol, obj: &ObjFile, member: &ArchiveMember) -> Self {
+ // Include the section name if possible. Fall back to the `Section` debug impl if not.
+ let section = sym.section();
+ let section_name = sym
+ .section()
+ .index()
+ .and_then(|idx| obj.section_by_index(idx).ok())
+ .and_then(|sec| sec.name().ok())
+ .map(ToString::to_string)
+ .unwrap_or_else(|| format!("{section:?}"));
+
Self {
name: sym.name().expect("missing name").to_owned(),
kind: sym.kind(),
scope: sym.scope(),
- section: sym.section(),
+ section: section_name,
is_undefined: sym.is_undefined(),
is_global: sym.is_global(),
is_local: sym.is_local(),
@@ -192,22 +202,27 @@ fn verify_no_duplicates(archive: &Archive) {
let mut dups = Vec::new();
let mut found_any = false;
- archive.for_each_symbol(|symbol, member| {
+ archive.for_each_symbol(|symbol, obj, member| {
// Only check defined globals
if !symbol.is_global() || symbol.is_undefined() {
return;
}
- let sym = SymInfo::new(&symbol, member);
+ let sym = SymInfo::new(&symbol, obj, member);
// x86-32 includes multiple copies of thunk symbols
if sym.name.starts_with("__x86.get_pc_thunk") {
return;
}
+ // GDB pretty printing symbols may show up more than once but are weak.
+ if sym.section == ".debug_gdb_scripts" && sym.is_weak {
+ return;
+ }
+
// Windows has symbols for literal numeric constants, string literals, and MinGW pseudo-
// relocations. These are allowed to have repeated definitions.
- let win_allowed_dup_pfx = ["__real@", "__xmm@", "??_C@_", ".refptr"];
+ let win_allowed_dup_pfx = ["__real@", "__xmm@", "__ymm@", "??_C@_", ".refptr"];
if win_allowed_dup_pfx
.iter()
.any(|pfx| sym.name.starts_with(pfx))
@@ -244,7 +259,7 @@ fn verify_core_symbols(archive: &Archive) {
let mut undefined = Vec::new();
let mut has_symbols = false;
- archive.for_each_symbol(|symbol, member| {
+ archive.for_each_symbol(|symbol, obj, member| {
has_symbols = true;
// Find only symbols from `core`
@@ -252,7 +267,7 @@ fn verify_core_symbols(archive: &Archive) {
return;
}
- let sym = SymInfo::new(&symbol, member);
+ let sym = SymInfo::new(&symbol, obj, member);
if sym.is_undefined {
undefined.push(sym);
} else {
@@ -304,9 +319,9 @@ fn for_each_object(&self, mut f: impl FnMut(ObjFile, &ArchiveMember)) {
}
/// For a given archive, do something with each symbol.
- fn for_each_symbol(&self, mut f: impl FnMut(Symbol, &ArchiveMember)) {
+ fn for_each_symbol(&self, mut f: impl FnMut(Symbol, &ObjFile, &ArchiveMember)) {
self.for_each_object(|obj, member| {
- obj.symbols().for_each(|sym| f(sym, member));
+ obj.symbols().for_each(|sym| f(sym, &obj, member));
});
}
}
diff --git a/library/compiler-builtins/etc/update-api-list.py b/library/compiler-builtins/etc/update-api-list.py
index 28ff22f..76c75cb 100755
--- a/library/compiler-builtins/etc/update-api-list.py
+++ b/library/compiler-builtins/etc/update-api-list.py
@@ -34,7 +34,7 @@
@dataclass
class Crate:
- """Representation of public interfaces and function defintion locations in
+ """Representation of public interfaces and function definition locations in
`libm`.
"""
diff --git a/library/compiler-builtins/libm/src/math/rem_pio2_large.rs b/library/compiler-builtins/libm/src/math/rem_pio2_large.rs
index f1fdf36..bb2c532 100644
--- a/library/compiler-builtins/libm/src/math/rem_pio2_large.rs
+++ b/library/compiler-builtins/libm/src/math/rem_pio2_large.rs
@@ -146,7 +146,7 @@
// x[i] = floor(z)
// z = (z-x[i])*2**24
//
-// y[] ouput result in an array of double precision numbers.
+// y[] output result in an array of double precision numbers.
// The dimension of y[] is:
// 24-bit precision 1
// 53-bit precision 2
diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version
index a4db05a..8489eac 100644
--- a/library/compiler-builtins/rust-version
+++ b/library/compiler-builtins/rust-version
@@ -1 +1 @@
-82310651b93a594a3fd69015e1562186a080d94c
+d36f964125163c2e698de5559efefb8217b8b7f0
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index bb75ec7..835ee57 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -184,18 +184,12 @@
impl fmt::Display for TryFromSliceError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[allow(deprecated)]
- self.description().fmt(f)
+ "could not convert slice to array".fmt(f)
}
}
#[stable(feature = "try_from", since = "1.34.0")]
-impl Error for TryFromSliceError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "could not convert slice to array"
- }
-}
+impl Error for TryFromSliceError {}
#[stable(feature = "try_from_slice_error", since = "1.36.0")]
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index 23061cb..cf5a91b 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -193,21 +193,16 @@ enum CharErrorKind {
}
#[stable(feature = "char_from_str", since = "1.20.0")]
-impl Error for ParseCharError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- match self.kind {
- CharErrorKind::EmptyString => "cannot parse char from empty string",
- CharErrorKind::TooManyChars => "too many characters in string",
- }
- }
-}
+impl Error for ParseCharError {}
#[stable(feature = "char_from_str", since = "1.20.0")]
impl fmt::Display for ParseCharError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[allow(deprecated)]
- self.description().fmt(f)
+ match self.kind {
+ CharErrorKind::EmptyString => "cannot parse char from empty string",
+ CharErrorKind::TooManyChars => "too many characters in string",
+ }
+ .fmt(f)
}
}
diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs
index 23319fb..d7c5f45 100644
--- a/library/core/src/char/decode.rs
+++ b/library/core/src/char/decode.rs
@@ -126,9 +126,4 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "decode_utf16", since = "1.9.0")]
-impl Error for DecodeUtf16Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "unpaired surrogate found"
- }
-}
+impl Error for DecodeUtf16Error {}
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 7ee0962..985e669 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1872,28 +1872,33 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
// SAFETY: The caller must guarantee that the buffer pointed to by `dst`
// is at least `len` bytes long.
unsafe {
- match len {
- 1 => {
- *dst = code as u8;
- }
- 2 => {
- *dst = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
- *dst.add(1) = (code & 0x3F) as u8 | TAG_CONT;
- }
- 3 => {
- *dst = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
- *dst.add(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
- *dst.add(2) = (code & 0x3F) as u8 | TAG_CONT;
- }
- 4 => {
- *dst = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
- *dst.add(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
- *dst.add(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
- *dst.add(3) = (code & 0x3F) as u8 | TAG_CONT;
- }
- // SAFETY: `char` always takes between 1 and 4 bytes to encode in UTF-8.
- _ => crate::hint::unreachable_unchecked(),
+ if len == 1 {
+ *dst = code as u8;
+ return;
}
+
+ let last1 = (code >> 0 & 0x3F) as u8 | TAG_CONT;
+ let last2 = (code >> 6 & 0x3F) as u8 | TAG_CONT;
+ let last3 = (code >> 12 & 0x3F) as u8 | TAG_CONT;
+ let last4 = (code >> 18 & 0x3F) as u8 | TAG_FOUR_B;
+
+ if len == 2 {
+ *dst = last2 | TAG_TWO_B;
+ *dst.add(1) = last1;
+ return;
+ }
+
+ if len == 3 {
+ *dst = last3 | TAG_THREE_B;
+ *dst.add(1) = last2;
+ *dst.add(2) = last1;
+ return;
+ }
+
+ *dst = last4;
+ *dst.add(1) = last3;
+ *dst.add(2) = last2;
+ *dst.add(3) = last1;
}
}
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 0c3034c..a0a7b79 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -958,11 +958,7 @@ fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "str_parse_error2", since = "1.8.0")]
-impl Error for Infallible {
- fn description(&self) -> &str {
- match *self {}
- }
-}
+impl Error for Infallible {}
#[stable(feature = "convert_infallible", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 88e633c..92b3c83 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -1042,11 +1042,6 @@ impl<'a> crate::iter::FusedIterator for Source<'a> {}
#[stable(feature = "error_by_ref", since = "1.51.0")]
impl<'a, T: Error + ?Sized> Error for &'a T {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- Error::description(&**self)
- }
-
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn Error> {
Error::cause(&**self)
@@ -1062,36 +1057,16 @@ fn provide<'b>(&'b self, request: &mut Request<'b>) {
}
#[stable(feature = "fmt_error", since = "1.11.0")]
-impl Error for crate::fmt::Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "an error occurred when formatting an argument"
- }
-}
+impl Error for crate::fmt::Error {}
#[stable(feature = "try_borrow", since = "1.13.0")]
-impl Error for crate::cell::BorrowError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "already mutably borrowed"
- }
-}
+impl Error for crate::cell::BorrowError {}
#[stable(feature = "try_borrow", since = "1.13.0")]
-impl Error for crate::cell::BorrowMutError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "already borrowed"
- }
-}
+impl Error for crate::cell::BorrowMutError {}
#[stable(feature = "try_from", since = "1.34.0")]
-impl Error for crate::char::CharTryFromError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "converted integer out of range for `char`"
- }
-}
+impl Error for crate::char::CharTryFromError {}
#[stable(feature = "duration_checked_float", since = "1.66.0")]
impl Error for crate::time::TryFromFloatSecsError {}
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 8ac29e5..b6de892 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -359,7 +359,7 @@ pub const fn new() -> Self {
/// always be printed.
/// - `-`: Currently not used
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
+ pub const fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
let sign = match sign {
None => 0,
Some(Sign::Plus) => flags::SIGN_PLUS_FLAG,
@@ -372,7 +372,7 @@ pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
///
/// This is used to indicate for integer formats that the padding to width should both be done with a 0 character as well as be sign-aware
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
+ pub const fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
if sign_aware_zero_pad {
self.flags |= flags::SIGN_AWARE_ZERO_PAD_FLAG;
} else {
@@ -389,7 +389,7 @@ pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
/// - [`Octal`] - precedes the argument with a `0b`
/// - [`Binary`] - precedes the argument with a `0o`
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn alternate(&mut self, alternate: bool) -> &mut Self {
+ pub const fn alternate(&mut self, alternate: bool) -> &mut Self {
if alternate {
self.flags |= flags::ALTERNATE_FLAG;
} else {
@@ -404,7 +404,7 @@ pub fn alternate(&mut self, alternate: bool) -> &mut Self {
/// being formatted is smaller than width some extra characters will be
/// printed around it.
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn fill(&mut self, fill: char) -> &mut Self {
+ pub const fn fill(&mut self, fill: char) -> &mut Self {
self.flags = self.flags & (u32::MAX << 21) | fill as u32;
self
}
@@ -413,7 +413,7 @@ pub fn fill(&mut self, fill: char) -> &mut Self {
/// The alignment specifies how the value being formatted should be
/// positioned if it is smaller than the width of the formatter.
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn align(&mut self, align: Option<Alignment>) -> &mut Self {
+ pub const fn align(&mut self, align: Option<Alignment>) -> &mut Self {
let align: u32 = match align {
Some(Alignment::Left) => flags::ALIGN_LEFT,
Some(Alignment::Right) => flags::ALIGN_RIGHT,
@@ -430,7 +430,7 @@ pub fn align(&mut self, align: Option<Alignment>) -> &mut Self {
/// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
/// will be used to take up the required space.
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn width(&mut self, width: Option<u16>) -> &mut Self {
+ pub const fn width(&mut self, width: Option<u16>) -> &mut Self {
if let Some(width) = width {
self.flags |= flags::WIDTH_FLAG;
self.width = width;
@@ -450,7 +450,7 @@ pub fn width(&mut self, width: Option<u16>) -> &mut Self {
/// - For floating-point types, this indicates how many digits after the
/// decimal point should be printed.
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
+ pub const fn precision(&mut self, precision: Option<u16>) -> &mut Self {
if let Some(precision) = precision {
self.flags |= flags::PRECISION_FLAG;
self.precision = precision;
@@ -463,7 +463,7 @@ pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
/// Specifies whether the [`Debug`] trait should use lower-/upper-case
/// hexadecimal or normal integers
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self {
+ pub const fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self {
let debug_as_hex = match debug_as_hex {
None => 0,
Some(DebugAsHex::Lower) => flags::DEBUG_LOWER_HEX_FLAG,
@@ -537,7 +537,7 @@ pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> {
///
/// You may alternatively use [`Formatter::new()`].
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
+ pub const fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
Formatter { options: self, buf: write }
}
}
@@ -578,13 +578,13 @@ impl<'a> Formatter<'a> {
///
/// You may alternatively use [`FormattingOptions::create_formatter()`].
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self {
+ pub const fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self {
Formatter { options, buf: write }
}
/// Creates a new formatter based on this one with given [`FormattingOptions`].
#[unstable(feature = "formatting_options", issue = "118117")]
- pub fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b> {
+ pub const fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b> {
Formatter { options, buf: self.buf }
}
}
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index c72eeb9..535c5a8 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -267,39 +267,29 @@
#[inline(always)]
#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
pub fn spin_loop() {
- #[cfg(target_arch = "x86")]
- {
- // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
- unsafe { crate::arch::x86::_mm_pause() };
- }
-
- #[cfg(target_arch = "x86_64")]
- {
- // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
- unsafe { crate::arch::x86_64::_mm_pause() };
- }
-
- #[cfg(target_arch = "riscv32")]
- {
- crate::arch::riscv32::pause();
- }
-
- #[cfg(target_arch = "riscv64")]
- {
- crate::arch::riscv64::pause();
- }
-
- #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
- {
- // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
- unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
- }
-
- #[cfg(all(target_arch = "arm", target_feature = "v6"))]
- {
- // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
- // with support for the v6 feature.
- unsafe { crate::arch::arm::__yield() };
+ crate::cfg_select! {
+ target_arch = "x86" => {
+ // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
+ unsafe { crate::arch::x86::_mm_pause() }
+ }
+ target_arch = "x86_64" => {
+ // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
+ unsafe { crate::arch::x86_64::_mm_pause() }
+ }
+ target_arch = "riscv32" => crate::arch::riscv32::pause(),
+ target_arch = "riscv64" => crate::arch::riscv64::pause(),
+ any(target_arch = "aarch64", target_arch = "arm64ec") => {
+ // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
+ unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }
+ }
+ all(target_arch = "arm", target_feature = "v6") => {
+ // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
+ // with support for the v6 feature.
+ unsafe { crate::arch::arm::__yield() }
+ }
+ target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(),
+ target_arch = "loongarch64" => crate::arch::loongarch64::ibar::<0>(),
+ _ => { /* do nothing */ }
}
}
diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs
index 12e2b8b..7312236 100644
--- a/library/core/src/iter/traits/accum.rs
+++ b/library/core/src/iter/traits/accum.rs
@@ -1,5 +1,5 @@
use crate::iter;
-use crate::num::Wrapping;
+use crate::num::{Saturating, Wrapping};
/// Trait to represent types that can be created by summing up an iterator.
///
@@ -98,6 +98,61 @@ fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
);
}
+macro_rules! saturating_integer_sum_product {
+ (@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($(
+ #[$attr]
+ #[doc = $doc]
+ impl Sum for $a {
+ fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
+ iter.fold(
+ $zero,
+ |a, b| a + b,
+ )
+ }
+ }
+
+ #[$attr]
+ #[doc = $doc]
+ impl Product for $a {
+ fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
+ iter.fold(
+ $one,
+ |a, b| a * b,
+ )
+ }
+ }
+
+ #[$attr]
+ #[doc = $doc]
+ impl<'a> Sum<&'a $a> for $a {
+ fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
+ iter.fold(
+ $zero,
+ |a, b| a + b,
+ )
+ }
+ }
+
+ #[$attr]
+ #[doc = $doc]
+ impl<'a> Product<&'a $a> for $a {
+ fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
+ iter.fold(
+ $one,
+ |a, b| a * b,
+ )
+ }
+ }
+ )*);
+ ($($a:ty)*) => (
+ saturating_integer_sum_product!(@impls Saturating(0), Saturating(1),
+ "The short-circuiting behavior of this implementation is unspecified. If you care about \
+ short-circuiting, use [`Iterator::fold`] directly.",
+ #[stable(feature = "saturating_iter_arith", since = "CURRENT_RUSTC_VERSION")],
+ $(Saturating<$a>)*);
+ );
+}
+
macro_rules! float_sum_product {
($($a:ident)*) => ($(
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
@@ -147,6 +202,7 @@ fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
}
integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
+saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize }
float_sum_product! { f32 f64 }
#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index f69d6a9..8250637 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -363,6 +363,8 @@ pub mod autodiff {
pub mod str;
pub mod time;
+pub mod wtf8;
+
pub mod unicode;
/* Async */
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 8ad5859..73aad27 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -1049,7 +1049,7 @@ impl !UnsafeUnpin for PhantomPinned {}
/// A marker for types that can be dropped.
///
-/// This should be used for `~const` bounds,
+/// This should be used for `[const]` bounds,
/// as non-const bounds will always hold for every type.
#[unstable(feature = "const_destruct", issue = "133214")]
#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs
index 73230f6..3aab24a 100644
--- a/library/core/src/net/parser.rs
+++ b/library/core/src/net/parser.rs
@@ -497,16 +497,7 @@ enum AddrKind {
#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
impl fmt::Display for AddrParseError {
- #[allow(deprecated, deprecated_in_future)]
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt.write_str(self.description())
- }
-}
-
-#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
-impl Error for AddrParseError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
AddrKind::Ip => "invalid IP address syntax",
AddrKind::Ipv4 => "invalid IPv4 address syntax",
@@ -515,5 +506,9 @@ fn description(&self) -> &str {
AddrKind::SocketV4 => "invalid IPv4 socket address syntax",
AddrKind::SocketV6 => "invalid IPv6 socket address syntax",
}
+ .fmt(f)
}
}
+
+#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
+impl Error for AddrParseError {}
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index 3118a6e..dd4eccd 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -219,21 +219,16 @@ enum FloatErrorKind {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseFloatError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- match self.kind {
- FloatErrorKind::Empty => "cannot parse float from empty string",
- FloatErrorKind::Invalid => "invalid float literal",
- }
- }
-}
+impl Error for ParseFloatError {}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseFloatError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[allow(deprecated)]
- self.description().fmt(f)
+ match self.kind {
+ FloatErrorKind::Empty => "cannot parse float from empty string",
+ FloatErrorKind::Invalid => "invalid float literal",
+ }
+ .fmt(f)
}
}
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index cfedd46..faa5232 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -11,19 +11,13 @@
#[stable(feature = "try_from", since = "1.34.0")]
impl fmt::Display for TryFromIntError {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[allow(deprecated)]
- self.description().fmt(fmt)
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ "out of range integral type conversion attempted".fmt(f)
}
}
#[stable(feature = "try_from", since = "1.34.0")]
-impl Error for TryFromIntError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "out of range integral type conversion attempted"
- }
-}
+impl Error for TryFromIntError {}
#[stable(feature = "try_from", since = "1.34.0")]
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
@@ -128,15 +122,6 @@ pub const fn kind(&self) -> &IntErrorKind {
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseIntError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[allow(deprecated)]
- self.description().fmt(f)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseIntError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
match self.kind {
IntErrorKind::Empty => "cannot parse integer from empty string",
IntErrorKind::InvalidDigit => "invalid digit found in string",
@@ -144,5 +129,9 @@ fn description(&self) -> &str {
IntErrorKind::NegOverflow => "number too small to fit in target type",
IntErrorKind::Zero => "number would be zero for non-zero type",
}
+ .fmt(f)
}
}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for ParseIntError {}
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 69e6c10..4282b1a 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -630,6 +630,13 @@ pub const fn recip(self) -> Self {
/// Converts radians to degrees.
///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
@@ -645,13 +652,22 @@ pub const fn recip(self) -> Self {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_degrees(self) -> Self {
- // Use a literal for better precision.
- const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128;
+ // The division here is correctly rounded with respect to the true value of 180/π.
+ // Although π is irrational and already rounded, the double rounding happens
+ // to produce correct result for f128.
+ const PIS_IN_180: f128 = 180.0 / consts::PI;
self * PIS_IN_180
}
/// Converts degrees to radians.
///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
@@ -668,7 +684,8 @@ pub const fn to_degrees(self) -> Self {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_radians(self) -> f128 {
- // Use a literal for better precision.
+ // Use a literal to avoid double rounding, consts::PI is already rounded,
+ // and dividing would round again.
const RADS_PER_DEG: f128 =
0.0174532925199432957692369076848861271344287188854172545609719_f128;
self * RADS_PER_DEG
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index b66cef0..23a8661 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -625,6 +625,13 @@ pub const fn recip(self) -> Self {
/// Converts radians to degrees.
///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
/// ```
/// #![feature(f16)]
/// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
@@ -640,13 +647,21 @@ pub const fn recip(self) -> Self {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_degrees(self) -> Self {
- // Use a literal for better precision.
+ // Use a literal to avoid double rounding, consts::PI is already rounded,
+ // and dividing would round again.
const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
self * PIS_IN_180
}
/// Converts degrees to radians.
///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
/// ```
/// #![feature(f16)]
/// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
@@ -663,7 +678,8 @@ pub const fn to_degrees(self) -> Self {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_radians(self) -> f16 {
- // Use a literal for better precision.
+ // Use a literal to avoid double rounding, consts::PI is already rounded,
+ // and dividing would round again.
const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
self * RADS_PER_DEG
}
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index f8344da..da08bfc 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -839,6 +839,13 @@ pub const fn recip(self) -> f32 {
/// Converts radians to degrees.
///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
/// ```
/// let angle = std::f32::consts::PI;
///
@@ -852,13 +859,21 @@ pub const fn recip(self) -> f32 {
#[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")]
#[inline]
pub const fn to_degrees(self) -> f32 {
- // Use a constant for better precision.
+ // Use a literal to avoid double rounding, consts::PI is already rounded,
+ // and dividing would round again.
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
self * PIS_IN_180
}
/// Converts degrees to radians.
///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
/// ```
/// let angle = 180.0f32;
///
@@ -872,6 +887,9 @@ pub const fn to_degrees(self) -> f32 {
#[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")]
#[inline]
pub const fn to_radians(self) -> f32 {
+ // The division here is correctly rounded with respect to the true value of π/180.
+ // Although π is irrational and already rounded, the double rounding happens
+ // to produce correct result for f32.
const RADS_PER_DEG: f32 = consts::PI / 180.0;
self * RADS_PER_DEG
}
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 93da63c..dc0977c 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -856,6 +856,13 @@ pub const fn recip(self) -> f64 {
/// Converts radians to degrees.
///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
/// ```
/// let angle = std::f64::consts::PI;
///
@@ -869,14 +876,22 @@ pub const fn recip(self) -> f64 {
#[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")]
#[inline]
pub const fn to_degrees(self) -> f64 {
- // The division here is correctly rounded with respect to the true
- // value of 180/π. (This differs from f32, where a constant must be
- // used to ensure a correctly rounded result.)
- self * (180.0f64 / consts::PI)
+ // The division here is correctly rounded with respect to the true value of 180/π.
+ // Although π is irrational and already rounded, the double rounding happens
+ // to produce correct result for f64.
+ const PIS_IN_180: f64 = 180.0 / consts::PI;
+ self * PIS_IN_180
}
/// Converts degrees to radians.
///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
/// ```
/// let angle = 180.0_f64;
///
@@ -890,6 +905,9 @@ pub const fn to_degrees(self) -> f64 {
#[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")]
#[inline]
pub const fn to_radians(self) -> f64 {
+ // The division here is correctly rounded with respect to the true value of π/180.
+ // Although π is irrational and already rounded, the double rounding happens
+ // to produce correct result for f64.
const RADS_PER_DEG: f64 = consts::PI / 180.0;
self * RADS_PER_DEG
}
diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs
index d57b1d4..610d9d8 100644
--- a/library/core/src/num/niche_types.rs
+++ b/library/core/src/num/niche_types.rs
@@ -178,3 +178,18 @@ impl NotAllOnesHelper for u64 {
impl NotAllOnesHelper for i64 {
type Type = I64NotAllOnes;
}
+
+define_valid_range_type! {
+ pub struct CodePointInner(u32 as u32 in 0..=0x10ffff);
+}
+
+impl CodePointInner {
+ pub const ZERO: Self = CodePointInner::new(0).unwrap();
+}
+
+impl Default for CodePointInner {
+ #[inline]
+ fn default() -> Self {
+ Self::ZERO
+ }
+}
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 10d9498..c556d95 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2447,7 +2447,7 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
}
/// Calculates `self` + `rhs` + `carry` and returns a tuple containing
- /// the sum and the output carry.
+ /// the sum and the output carry (in that order).
///
/// Performs "ternary addition" of two integer operands and a carry-in
/// bit, and returns an output integer and a carry-out bit. This allows
@@ -2465,8 +2465,6 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
/// # Examples
///
/// ```
- /// #![feature(bigint_helper_methods)]
- ///
#[doc = concat!("// 3 MAX (a = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
#[doc = concat!("// + 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")]
/// // ---------
@@ -2483,7 +2481,7 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
///
/// assert_eq!((sum1, sum0), (9, 6));
/// ```
- #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+ #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
@@ -2559,8 +2557,6 @@ pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
/// # Examples
///
/// ```
- /// #![feature(bigint_helper_methods)]
- ///
#[doc = concat!("// 9 6 (a = 9 × 2^", stringify!($BITS), " + 6)")]
#[doc = concat!("// - 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")]
/// // ---------
@@ -2577,7 +2573,7 @@ pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
///
#[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")]
/// ```
- #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+ #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
@@ -2651,10 +2647,12 @@ pub const fn abs_diff(self, other: Self) -> Self {
/// indicating whether an arithmetic overflow would occur. If an
/// overflow would have occurred then the wrapped value is returned.
///
+ /// If you want the *value* of the overflow, rather than just *whether*
+ /// an overflow occurred, see [`Self::carrying_mul`].
+ ///
/// # Examples
///
- /// Please note that this example is shared among integer types, which is why why `u32`
- /// is used.
+ /// Please note that this example is shared among integer types, which is why `u32` is used.
///
/// ```
/// assert_eq!(5u32.overflowing_mul(2), (10, false));
@@ -2670,16 +2668,38 @@ pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
(a as Self, b)
}
- /// Calculates the complete product `self * rhs` without the possibility to overflow.
+ /// Calculates the complete double-width product `self * rhs`.
///
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
- /// of the result as two separate values, in that order.
+ /// of the result as two separate values, in that order. As such,
+ /// `a.widening_mul(b).0` produces the same result as `a.wrapping_mul(b)`.
+ ///
+ /// If you also need to add a value and carry to the wide result, then you want
+ /// [`Self::carrying_mul_add`] instead.
///
/// If you also need to add a carry to the wide result, then you want
/// [`Self::carrying_mul`] instead.
///
+ /// If you just want to know *whether* the multiplication overflowed, then you
+ /// want [`Self::overflowing_mul`] instead.
+ ///
/// # Examples
///
+ /// ```
+ /// #![feature(bigint_helper_methods)]
+ #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".widening_mul(7), (35, 0));")]
+ #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), (1, ", stringify!($SelfT), "::MAX - 1));")]
+ /// ```
+ ///
+ /// Compared to other `*_mul` methods:
+ /// ```
+ /// #![feature(bigint_helper_methods)]
+ #[doc = concat!("assert_eq!(", stringify!($SelfT), "::widening_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, 3));")]
+ #[doc = concat!("assert_eq!(", stringify!($SelfT), "::overflowing_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, true));")]
+ #[doc = concat!("assert_eq!(", stringify!($SelfT), "::wrapping_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), 0);")]
+ #[doc = concat!("assert_eq!(", stringify!($SelfT), "::checked_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), None);")]
+ /// ```
+ ///
/// Please note that this example is shared among integer types, which is why `u32` is used.
///
/// ```
@@ -2706,14 +2726,13 @@ pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
/// additional amount of overflow. This allows for chaining together multiple
/// multiplications to create "big integers" which represent larger values.
///
- /// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead.
+ /// If you also need to add a value, then use [`Self::carrying_mul_add`].
///
/// # Examples
///
/// Please note that this example is shared among integer types, which is why `u32` is used.
///
/// ```
- /// #![feature(bigint_helper_methods)]
/// assert_eq!(5u32.carrying_mul(2, 0), (10, 0));
/// assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
/// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
@@ -2771,7 +2790,7 @@ pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
/// 789_u16.wrapping_mul(456).wrapping_add(123),
/// );
/// ```
- #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+ #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
@@ -2780,18 +2799,20 @@ pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
Self::carrying_mul_add(self, rhs, carry, 0)
}
- /// Calculates the "full multiplication" `self * rhs + carry1 + carry2`
- /// without the possibility to overflow.
+ /// Calculates the "full multiplication" `self * rhs + carry1 + carry2`.
///
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
/// of the result as two separate values, in that order.
///
+ /// This cannot overflow, as the double-width result has exactly enough
+ /// space for the largest possible result. This is equivalent to how, in
+ /// decimal, 9 × 9 + 9 + 9 = 81 + 18 = 99 = 9×10⁰ + 9×10¹ = 10² - 1.
+ ///
/// Performs "long multiplication" which takes in an extra amount to add, and may return an
/// additional amount of overflow. This allows for chaining together multiple
/// multiplications to create "big integers" which represent larger values.
///
- /// If you don't need either `carry`, then you can use [`Self::widening_mul`] instead,
- /// and if you only need one `carry`, then you can use [`Self::carrying_mul`] instead.
+ /// If you don't need the `add` part, then you can use [`Self::carrying_mul`] instead.
///
/// # Examples
///
@@ -2799,7 +2820,6 @@ pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
/// which explains why `u32` is used here.
///
/// ```
- /// #![feature(bigint_helper_methods)]
/// assert_eq!(5u32.carrying_mul_add(2, 0, 0), (10, 0));
/// assert_eq!(5u32.carrying_mul_add(2, 10, 10), (30, 0));
/// assert_eq!(1_000_000_000u32.carrying_mul_add(10, 0, 0), (1410065408, 2));
@@ -2816,8 +2836,6 @@ pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
/// using `u8` for simplicity of the demonstration.
///
/// ```
- /// #![feature(bigint_helper_methods)]
- ///
/// fn quadratic_mul<const N: usize>(a: [u8; N], b: [u8; N]) -> [u8; N] {
/// let mut out = [0; N];
/// for j in 0..N {
@@ -2832,13 +2850,13 @@ pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
/// // -1 * -1 == 1
/// assert_eq!(quadratic_mul([0xFF; 3], [0xFF; 3]), [1, 0, 0]);
///
- /// assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xCFFC982D);
+ /// assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xcffc982d);
/// assert_eq!(
/// quadratic_mul(u32::to_le_bytes(0x9e3779b9), u32::to_le_bytes(0x7f4a7c15)),
- /// u32::to_le_bytes(0xCFFC982D)
+ /// u32::to_le_bytes(0xcffc982d)
/// );
/// ```
- #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+ #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index e83e773..fa09409 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1961,6 +1961,42 @@ pub const fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R>
_ => None,
}
}
+
+ /// Reduces two options into one, using the provided function if both are `Some`.
+ ///
+ /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`.
+ /// Otherwise, if only one of `self` and `other` is `Some`, that one is returned.
+ /// If both `self` and `other` are `None`, `None` is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(option_reduce)]
+ ///
+ /// let s12 = Some(12);
+ /// let s17 = Some(17);
+ /// let n = None;
+ /// let f = |a, b| a + b;
+ ///
+ /// assert_eq!(s12.reduce(s17, f), Some(29));
+ /// assert_eq!(s12.reduce(n, f), Some(12));
+ /// assert_eq!(n.reduce(s17, f), Some(17));
+ /// assert_eq!(n.reduce(n, f), None);
+ /// ```
+ #[unstable(feature = "option_reduce", issue = "144273")]
+ pub fn reduce<U, R, F>(self, other: Option<U>, f: F) -> Option<R>
+ where
+ T: Into<R>,
+ U: Into<R>,
+ F: FnOnce(T, U) -> R,
+ {
+ match (self, other) {
+ (Some(a), Some(b)) => Some(f(a, b)),
+ (Some(a), _) => Some(a.into()),
+ (_, Some(b)) => Some(b.into()),
+ _ => None,
+ }
+ }
}
impl<T, U> Option<(T, U)> {
diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs
index cafdcfa..7a68d39 100644
--- a/library/core/src/panic/location.rs
+++ b/library/core/src/panic/location.rs
@@ -39,7 +39,7 @@
pub struct Location<'a> {
// A raw pointer is used rather than a reference because the pointer is valid for one more byte
// than the length stored in this pointer; the additional byte is the NUL-terminator used by
- // `Location::file_with_nul`.
+ // `Location::file_as_c_str`.
filename: NonNull<str>,
line: u32,
col: u32,
@@ -195,7 +195,7 @@ pub const fn file(&self) -> &'a str {
#[must_use]
#[unstable(feature = "file_with_nul", issue = "141727")]
#[inline]
- pub const fn file_with_nul(&self) -> &'a CStr {
+ pub const fn file_as_c_str(&self) -> &'a CStr {
let filename = self.filename.as_ptr();
// SAFETY: The filename is valid for `filename_len+1` bytes, so this addition can't
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index 0deac36..dc3ec3f 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -106,6 +106,9 @@ pub const fn metadata<T: PointeeSized>(ptr: *const T) -> <T as Pointee>::Metadat
/// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements.
/// For trait objects, the metadata must come from a pointer to the same underlying erased type.
///
+/// If you are attempting to deconstruct a DST in a generic context to be reconstructed later,
+/// a thin pointer can always be obtained by casting `*const T` to `*const ()`.
+///
/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
#[unstable(feature = "ptr_metadata", issue = "81513")]
#[inline]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index f5c490c..6fc85a8 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -914,6 +914,7 @@ pub const fn dangling<T>() -> *const T {
#[must_use]
#[stable(feature = "strict_provenance", since = "1.84.0")]
#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
+#[allow(integer_to_ptr_transmutes)] // Expected semantics here.
pub const fn without_provenance_mut<T>(addr: usize) -> *mut T {
// An int-to-pointer transmute currently has exactly the intended semantics: it creates a
// pointer without provenance. Note that this is *not* a stable guarantee about transmute
diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs
index 4c8231a..1677c84 100644
--- a/library/core/src/str/error.rs
+++ b/library/core/src/str/error.rs
@@ -124,12 +124,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for Utf8Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "invalid utf-8: corrupt contents"
- }
-}
+impl Error for Utf8Error {}
/// An error returned when parsing a `bool` using [`from_str`] fails
///
@@ -147,9 +142,4 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseBoolError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "failed to parse bool"
- }
-}
+impl Error for ParseBoolError {}
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 1b6e841..f1db385 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -396,7 +396,6 @@ pub const fn is_char_boundary(&self, index: usize) -> bool {
/// # Examples
///
/// ```
- /// #![feature(round_char_boundary)]
/// let s = "❤️🧡💛💚💙💜";
/// assert_eq!(s.len(), 26);
/// assert!(!s.is_char_boundary(13));
@@ -405,7 +404,8 @@ pub const fn is_char_boundary(&self, index: usize) -> bool {
/// assert_eq!(closest, 10);
/// assert_eq!(&s[..closest], "❤️🧡");
/// ```
- #[unstable(feature = "round_char_boundary", issue = "93743")]
+ #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn floor_char_boundary(&self, index: usize) -> usize {
if index >= self.len() {
@@ -439,7 +439,6 @@ pub const fn floor_char_boundary(&self, index: usize) -> usize {
/// # Examples
///
/// ```
- /// #![feature(round_char_boundary)]
/// let s = "❤️🧡💛💚💙💜";
/// assert_eq!(s.len(), 26);
/// assert!(!s.is_char_boundary(13));
@@ -448,7 +447,8 @@ pub const fn floor_char_boundary(&self, index: usize) -> usize {
/// assert_eq!(closest, 14);
/// assert_eq!(&s[..closest], "❤️🧡💛");
/// ```
- #[unstable(feature = "round_char_boundary", issue = "93743")]
+ #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn ceil_char_boundary(&self, index: usize) -> usize {
if index >= self.len() {
@@ -3072,7 +3072,7 @@ pub fn substr_range(&self, substr: &str) -> Option<Range<usize>> {
/// for example references to `Box<str>` or `Arc<str>`.
#[inline]
#[unstable(feature = "str_as_str", issue = "130366")]
- pub fn as_str(&self) -> &str {
+ pub const fn as_str(&self) -> &str {
self
}
}
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 44a6895..7bd68bc 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2199,7 +2199,6 @@ pub fn update(
/// # Examples
///
/// ```
- /// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
@@ -2209,7 +2208,7 @@ pub fn update(
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
- #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
+ #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T {
self.fetch_byte_add(val.wrapping_mul(size_of::<T>()), order)
@@ -2240,7 +2239,6 @@ pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T {
/// # Examples
///
/// ```
- /// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let array = [1i32, 2i32];
@@ -2254,7 +2252,7 @@ pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
- #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
+ #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
self.fetch_byte_sub(val.wrapping_mul(size_of::<T>()), order)
@@ -2279,7 +2277,6 @@ pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
/// # Examples
///
/// ```
- /// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
@@ -2289,7 +2286,7 @@ pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
- #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
+ #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
@@ -2315,7 +2312,6 @@ pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
/// # Examples
///
/// ```
- /// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let mut arr = [0i64, 1];
@@ -2325,7 +2321,7 @@ pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
- #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
+ #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
@@ -2361,7 +2357,6 @@ pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
/// # Examples
///
/// ```
- /// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let pointer = &mut 3i64 as *mut i64;
@@ -2376,7 +2371,7 @@ pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
- #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
+ #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
@@ -2412,7 +2407,6 @@ pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
/// # Examples
///
/// ```
- /// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let pointer = &mut 3i64 as *mut i64;
@@ -2426,7 +2420,7 @@ pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
- #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
+ #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
@@ -2462,7 +2456,6 @@ pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
/// # Examples
///
/// ```
- /// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let pointer = &mut 3i64 as *mut i64;
@@ -2474,7 +2467,7 @@ pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
- #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
+ #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 0cc570f..f37e47f 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -927,7 +927,7 @@ pub const fn as_millis_f32(&self) -> f32 {
pub fn from_secs_f64(secs: f64) -> Duration {
match Duration::try_from_secs_f64(secs) {
Ok(v) => v,
- Err(e) => panic!("{}", e.description()),
+ Err(e) => panic!("{e}"),
}
}
@@ -964,7 +964,7 @@ pub fn from_secs_f64(secs: f64) -> Duration {
pub fn from_secs_f32(secs: f32) -> Duration {
match Duration::try_from_secs_f32(secs) {
Ok(v) => v,
- Err(e) => panic!("{}", e.description()),
+ Err(e) => panic!("{e}"),
}
}
@@ -1445,8 +1445,9 @@ pub struct TryFromFloatSecsError {
kind: TryFromFloatSecsErrorKind,
}
-impl TryFromFloatSecsError {
- const fn description(&self) -> &'static str {
+#[stable(feature = "duration_checked_float", since = "1.66.0")]
+impl fmt::Display for TryFromFloatSecsError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
TryFromFloatSecsErrorKind::Negative => {
"cannot convert float seconds to Duration: value is negative"
@@ -1455,13 +1456,7 @@ const fn description(&self) -> &'static str {
"cannot convert float seconds to Duration: value is either too big or NaN"
}
}
- }
-}
-
-#[stable(feature = "duration_checked_float", since = "1.66.0")]
-impl fmt::Display for TryFromFloatSecsError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.description().fmt(f)
+ .fmt(f)
}
}
diff --git a/library/core/src/wtf8.rs b/library/core/src/wtf8.rs
new file mode 100644
index 0000000..de0dfa5
--- /dev/null
+++ b/library/core/src/wtf8.rs
@@ -0,0 +1,597 @@
+//! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/).
+//!
+//! This library uses Rust’s type system to maintain
+//! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed),
+//! like the `String` and `&str` types do for UTF-8.
+//!
+//! Since [WTF-8 must not be used
+//! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience),
+//! this library deliberately does not provide access to the underlying bytes
+//! of WTF-8 strings,
+//! nor can it decode WTF-8 from arbitrary bytes.
+//! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points.
+#![unstable(
+ feature = "wtf8_internals",
+ issue = "none",
+ reason = "this is internal code for representing OsStr on some platforms and not a public API"
+)]
+// rustdoc bug: doc(hidden) on the module won't stop types in the module from showing up in trait
+// implementations, so, we'll have to add more doc(hidden)s anyway
+#![doc(hidden)]
+
+use crate::char::{MAX_LEN_UTF16, encode_utf16_raw};
+use crate::clone::CloneToUninit;
+use crate::fmt::{self, Write};
+use crate::hash::{Hash, Hasher};
+use crate::iter::FusedIterator;
+use crate::num::niche_types::CodePointInner;
+use crate::str::next_code_point;
+use crate::{ops, slice, str};
+
+/// A Unicode code point: from U+0000 to U+10FFFF.
+///
+/// Compares with the `char` type,
+/// which represents a Unicode scalar value:
+/// a code point that is not a surrogate (U+D800 to U+DFFF).
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
+#[doc(hidden)]
+pub struct CodePoint(CodePointInner);
+
+/// Format the code point as `U+` followed by four to six hexadecimal digits.
+/// Example: `U+1F4A9`
+impl fmt::Debug for CodePoint {
+ #[inline]
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(formatter, "U+{:04X}", self.0.as_inner())
+ }
+}
+
+impl CodePoint {
+ /// Unsafely creates a new `CodePoint` without checking the value.
+ ///
+ /// Only use when `value` is known to be less than or equal to 0x10FFFF.
+ #[inline]
+ pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint {
+ // SAFETY: Guaranteed by caller.
+ CodePoint(unsafe { CodePointInner::new_unchecked(value) })
+ }
+
+ /// Creates a new `CodePoint` if the value is a valid code point.
+ ///
+ /// Returns `None` if `value` is above 0x10FFFF.
+ #[inline]
+ pub fn from_u32(value: u32) -> Option<CodePoint> {
+ Some(CodePoint(CodePointInner::new(value)?))
+ }
+
+ /// Creates a new `CodePoint` from a `char`.
+ ///
+ /// Since all Unicode scalar values are code points, this always succeeds.
+ #[inline]
+ pub fn from_char(value: char) -> CodePoint {
+ // SAFETY: All char are valid for this type.
+ unsafe { CodePoint::from_u32_unchecked(value as u32) }
+ }
+
+ /// Returns the numeric value of the code point.
+ #[inline]
+ pub fn to_u32(&self) -> u32 {
+ self.0.as_inner()
+ }
+
+ /// Returns the numeric value of the code point if it is a leading surrogate.
+ #[inline]
+ pub fn to_lead_surrogate(&self) -> Option<u16> {
+ match self.to_u32() {
+ lead @ 0xD800..=0xDBFF => Some(lead as u16),
+ _ => None,
+ }
+ }
+
+ /// Returns the numeric value of the code point if it is a trailing surrogate.
+ #[inline]
+ pub fn to_trail_surrogate(&self) -> Option<u16> {
+ match self.to_u32() {
+ trail @ 0xDC00..=0xDFFF => Some(trail as u16),
+ _ => None,
+ }
+ }
+
+ /// Optionally returns a Unicode scalar value for the code point.
+ ///
+ /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF).
+ #[inline]
+ pub fn to_char(&self) -> Option<char> {
+ match self.to_u32() {
+ 0xD800..=0xDFFF => None,
+ // SAFETY: We explicitly check that the char is valid.
+ valid => Some(unsafe { char::from_u32_unchecked(valid) }),
+ }
+ }
+
+ /// Returns a Unicode scalar value for the code point.
+ ///
+ /// Returns `'\u{FFFD}'` (the replacement character “�”)
+ /// if the code point is a surrogate (from U+D800 to U+DFFF).
+ #[inline]
+ pub fn to_char_lossy(&self) -> char {
+ self.to_char().unwrap_or(char::REPLACEMENT_CHARACTER)
+ }
+}
+
+/// A borrowed slice of well-formed WTF-8 data.
+///
+/// Similar to `&str`, but can additionally contain surrogate code points
+/// if they’re not in a surrogate pair.
+#[derive(Eq, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
+#[rustc_has_incoherent_inherent_impls]
+#[doc(hidden)]
+pub struct Wtf8 {
+ bytes: [u8],
+}
+
+impl AsRef<[u8]> for Wtf8 {
+ #[inline]
+ fn as_ref(&self) -> &[u8] {
+ &self.bytes
+ }
+}
+
+/// Formats the string in double quotes, with characters escaped according to
+/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
+/// where each `x` is a hexadecimal digit.
+impl fmt::Debug for Wtf8 {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result {
+ use crate::fmt::Write;
+ for c in s.chars().flat_map(|c| c.escape_debug()) {
+ f.write_char(c)?
+ }
+ Ok(())
+ }
+
+ formatter.write_str("\"")?;
+ let mut pos = 0;
+ while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
+ // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes.
+ write_str_escaped(formatter, unsafe {
+ str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos])
+ })?;
+ write!(formatter, "\\u{{{:x}}}", surrogate)?;
+ pos = surrogate_pos + 3;
+ }
+
+ // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8.
+ write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?;
+ formatter.write_str("\"")
+ }
+}
+
+/// Formats the string with unpaired surrogates substituted with the replacement
+/// character, U+FFFD.
+impl fmt::Display for Wtf8 {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let wtf8_bytes = &self.bytes;
+ let mut pos = 0;
+ loop {
+ match self.next_surrogate(pos) {
+ Some((surrogate_pos, _)) => {
+ // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes.
+ formatter.write_str(unsafe {
+ str::from_utf8_unchecked(&wtf8_bytes[pos..surrogate_pos])
+ })?;
+ formatter.write_char(char::REPLACEMENT_CHARACTER)?;
+ pos = surrogate_pos + 3;
+ }
+ None => {
+ // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8.
+ let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) };
+ if pos == 0 { return s.fmt(formatter) } else { return formatter.write_str(s) }
+ }
+ }
+ }
+ }
+}
+
+impl Wtf8 {
+ /// Creates a WTF-8 slice from a UTF-8 `&str` slice.
+ #[inline]
+ pub fn from_str(value: &str) -> &Wtf8 {
+ // SAFETY: Since WTF-8 is a superset of UTF-8, this always is valid.
+ unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
+ }
+
+ /// Creates a WTF-8 slice from a WTF-8 byte slice.
+ ///
+ /// Since the byte slice is not checked for valid WTF-8, this functions is
+ /// marked unsafe.
+ #[inline]
+ pub unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
+ // SAFETY: start with &[u8], end with fancy &[u8]
+ unsafe { &*(value as *const [u8] as *const Wtf8) }
+ }
+
+ /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice.
+ ///
+ /// Since the byte slice is not checked for valid WTF-8, this functions is
+ /// marked unsafe.
+ #[inline]
+ pub unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 {
+ // SAFETY: start with &mut [u8], end with fancy &mut [u8]
+ unsafe { &mut *(value as *mut [u8] as *mut Wtf8) }
+ }
+
+ /// Returns the length, in WTF-8 bytes.
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.bytes.len()
+ }
+
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.bytes.is_empty()
+ }
+
+ /// Returns the code point at `position` if it is in the ASCII range,
+ /// or `b'\xFF'` otherwise.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `position` is beyond the end of the string.
+ #[inline]
+ pub fn ascii_byte_at(&self, position: usize) -> u8 {
+ match self.bytes[position] {
+ ascii_byte @ 0x00..=0x7F => ascii_byte,
+ _ => 0xFF,
+ }
+ }
+
+ /// Returns an iterator for the string’s code points.
+ #[inline]
+ pub fn code_points(&self) -> Wtf8CodePoints<'_> {
+ Wtf8CodePoints { bytes: self.bytes.iter() }
+ }
+
+ /// Access raw bytes of WTF-8 data
+ #[inline]
+ pub fn as_bytes(&self) -> &[u8] {
+ &self.bytes
+ }
+
+ /// Tries to convert the string to UTF-8 and return a `&str` slice.
+ ///
+ /// Returns `None` if the string contains surrogates.
+ ///
+ /// This does not copy the data.
+ #[inline]
+ pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
+ str::from_utf8(&self.bytes)
+ }
+
+ /// Converts the WTF-8 string to potentially ill-formed UTF-16
+ /// and return an iterator of 16-bit code units.
+ ///
+ /// This is lossless:
+ /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units
+ /// would always return the original WTF-8 string.
+ #[inline]
+ pub fn encode_wide(&self) -> EncodeWide<'_> {
+ EncodeWide { code_points: self.code_points(), extra: 0 }
+ }
+
+ #[inline]
+ pub fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> {
+ let mut iter = self.bytes[pos..].iter();
+ loop {
+ let b = *iter.next()?;
+ if b < 0x80 {
+ pos += 1;
+ } else if b < 0xE0 {
+ iter.next();
+ pos += 2;
+ } else if b == 0xED {
+ match (iter.next(), iter.next()) {
+ (Some(&b2), Some(&b3)) if b2 >= 0xA0 => {
+ return Some((pos, decode_surrogate(b2, b3)));
+ }
+ _ => pos += 3,
+ }
+ } else if b < 0xF0 {
+ iter.next();
+ iter.next();
+ pos += 3;
+ } else {
+ iter.next();
+ iter.next();
+ iter.next();
+ pos += 4;
+ }
+ }
+ }
+
+ #[inline]
+ pub fn final_lead_surrogate(&self) -> Option<u16> {
+ match self.bytes {
+ [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub fn initial_trail_surrogate(&self) -> Option<u16> {
+ match self.bytes {
+ [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub fn make_ascii_lowercase(&mut self) {
+ self.bytes.make_ascii_lowercase()
+ }
+
+ #[inline]
+ pub fn make_ascii_uppercase(&mut self) {
+ self.bytes.make_ascii_uppercase()
+ }
+
+ #[inline]
+ pub fn is_ascii(&self) -> bool {
+ self.bytes.is_ascii()
+ }
+
+ #[inline]
+ pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
+ self.bytes.eq_ignore_ascii_case(&other.bytes)
+ }
+}
+
+/// Returns a slice of the given string for the byte range \[`begin`..`end`).
+///
+/// # Panics
+///
+/// Panics when `begin` and `end` do not point to code point boundaries,
+/// or point beyond the end of the string.
+impl ops::Index<ops::Range<usize>> for Wtf8 {
+ type Output = Wtf8;
+
+ #[inline]
+ fn index(&self, range: ops::Range<usize>) -> &Wtf8 {
+ if range.start <= range.end
+ && self.is_code_point_boundary(range.start)
+ && self.is_code_point_boundary(range.end)
+ {
+ // SAFETY: is_code_point_boundary checks that the index is valid
+ unsafe { slice_unchecked(self, range.start, range.end) }
+ } else {
+ slice_error_fail(self, range.start, range.end)
+ }
+ }
+}
+
+/// Returns a slice of the given string from byte `begin` to its end.
+///
+/// # Panics
+///
+/// Panics when `begin` is not at a code point boundary,
+/// or is beyond the end of the string.
+impl ops::Index<ops::RangeFrom<usize>> for Wtf8 {
+ type Output = Wtf8;
+
+ #[inline]
+ fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 {
+ if self.is_code_point_boundary(range.start) {
+ // SAFETY: is_code_point_boundary checks that the index is valid
+ unsafe { slice_unchecked(self, range.start, self.len()) }
+ } else {
+ slice_error_fail(self, range.start, self.len())
+ }
+ }
+}
+
+/// Returns a slice of the given string from its beginning to byte `end`.
+///
+/// # Panics
+///
+/// Panics when `end` is not at a code point boundary,
+/// or is beyond the end of the string.
+impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
+ type Output = Wtf8;
+
+ #[inline]
+ fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 {
+ if self.is_code_point_boundary(range.end) {
+ // SAFETY: is_code_point_boundary checks that the index is valid
+ unsafe { slice_unchecked(self, 0, range.end) }
+ } else {
+ slice_error_fail(self, 0, range.end)
+ }
+ }
+}
+
+impl ops::Index<ops::RangeFull> for Wtf8 {
+ type Output = Wtf8;
+
+ #[inline]
+ fn index(&self, _range: ops::RangeFull) -> &Wtf8 {
+ self
+ }
+}
+
+#[inline]
+fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
+ // The first byte is assumed to be 0xED
+ 0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F
+}
+
+impl Wtf8 {
+ /// Copied from str::is_char_boundary
+ #[inline]
+ pub fn is_code_point_boundary(&self, index: usize) -> bool {
+ if index == 0 {
+ return true;
+ }
+ match self.bytes.get(index) {
+ None => index == self.len(),
+ Some(&b) => (b as i8) >= -0x40,
+ }
+ }
+
+ /// Verify that `index` is at the edge of either a valid UTF-8 codepoint
+ /// (i.e. a codepoint that's not a surrogate) or of the whole string.
+ ///
+ /// These are the cases currently permitted by `OsStr::self_encoded_bytes`.
+ /// Splitting between surrogates is valid as far as WTF-8 is concerned, but
+ /// we do not permit it in the public API because WTF-8 is considered an
+ /// implementation detail.
+ #[track_caller]
+ #[inline]
+ pub fn check_utf8_boundary(&self, index: usize) {
+ if index == 0 {
+ return;
+ }
+ match self.bytes.get(index) {
+ Some(0xED) => (), // Might be a surrogate
+ Some(&b) if (b as i8) >= -0x40 => return,
+ Some(_) => panic!("byte index {index} is not a codepoint boundary"),
+ None if index == self.len() => return,
+ None => panic!("byte index {index} is out of bounds"),
+ }
+ if self.bytes[index + 1] >= 0xA0 {
+ // There's a surrogate after index. Now check before index.
+ if index >= 3 && self.bytes[index - 3] == 0xED && self.bytes[index - 2] >= 0xA0 {
+ panic!("byte index {index} lies between surrogate codepoints");
+ }
+ }
+ }
+}
+
+/// Copied from core::str::raw::slice_unchecked
+#[inline]
+unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
+ // SAFETY: memory layout of a &[u8] and &Wtf8 are the same
+ unsafe {
+ let len = end - begin;
+ let start = s.as_bytes().as_ptr().add(begin);
+ Wtf8::from_bytes_unchecked(slice::from_raw_parts(start, len))
+ }
+}
+
+/// Copied from core::str::raw::slice_error_fail
+#[inline(never)]
+fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! {
+ assert!(begin <= end);
+ panic!("index {begin} and/or {end} in `{s:?}` do not lie on character boundary");
+}
+
+/// Iterator for the code points of a WTF-8 string.
+///
+/// Created with the method `.code_points()`.
+#[derive(Clone)]
+#[doc(hidden)]
+pub struct Wtf8CodePoints<'a> {
+ bytes: slice::Iter<'a, u8>,
+}
+
+impl Iterator for Wtf8CodePoints<'_> {
+ type Item = CodePoint;
+
+ #[inline]
+ fn next(&mut self) -> Option<CodePoint> {
+ // SAFETY: `self.bytes` has been created from a WTF-8 string
+ unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint::from_u32_unchecked(c)) }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.bytes.len();
+ (len.saturating_add(3) / 4, Some(len))
+ }
+}
+
+impl fmt::Debug for Wtf8CodePoints<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("Wtf8CodePoints")
+ // SAFETY: We always leave the string in a valid state after each iteration.
+ .field(&unsafe { Wtf8::from_bytes_unchecked(self.bytes.as_slice()) })
+ .finish()
+ }
+}
+
+/// Generates a wide character sequence for potentially ill-formed UTF-16.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+#[doc(hidden)]
+pub struct EncodeWide<'a> {
+ code_points: Wtf8CodePoints<'a>,
+ extra: u16,
+}
+
+// Copied from libunicode/u_str.rs
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EncodeWide<'_> {
+ type Item = u16;
+
+ #[inline]
+ fn next(&mut self) -> Option<u16> {
+ if self.extra != 0 {
+ let tmp = self.extra;
+ self.extra = 0;
+ return Some(tmp);
+ }
+
+ let mut buf = [0; MAX_LEN_UTF16];
+ self.code_points.next().map(|code_point| {
+ let n = encode_utf16_raw(code_point.to_u32(), &mut buf).len();
+ if n == 2 {
+ self.extra = buf[1];
+ }
+ buf[0]
+ })
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (low, high) = self.code_points.size_hint();
+ let ext = (self.extra != 0) as usize;
+ // every code point gets either one u16 or two u16,
+ // so this iterator is between 1 or 2 times as
+ // long as the underlying iterator.
+ (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext)))
+ }
+}
+
+impl fmt::Debug for EncodeWide<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("EncodeWide").finish_non_exhaustive()
+ }
+}
+
+#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
+impl FusedIterator for EncodeWide<'_> {}
+
+impl Hash for CodePoint {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.0.hash(state)
+ }
+}
+
+impl Hash for Wtf8 {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write(&self.bytes);
+ 0xfeu8.hash(state)
+ }
+}
+
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for Wtf8 {
+ #[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ // SAFETY: we're just a transparent wrapper around [u8]
+ unsafe { self.bytes.clone_to_uninit(dst) }
+ }
+}
diff --git a/library/coretests/tests/iter/traits/accum.rs b/library/coretests/tests/iter/traits/accum.rs
index f3eeb31..95f299d 100644
--- a/library/coretests/tests/iter/traits/accum.rs
+++ b/library/coretests/tests/iter/traits/accum.rs
@@ -1,4 +1,5 @@
use core::iter::*;
+use std::num::Saturating;
#[test]
fn test_iterator_sum() {
@@ -64,3 +65,38 @@ fn test_iterator_product_option() {
let v: &[Option<i32>] = &[Some(1), None, Some(3), Some(4)];
assert_eq!(v.iter().cloned().product::<Option<i32>>(), None);
}
+
+#[test]
+fn test_saturating_sum_product() {
+ let v = (1u32..=10).map(|i| Saturating(i));
+ assert_eq!(v.sum::<Saturating<u32>>(), Saturating(55));
+ let v = (1u32..=10).map(|i| Saturating(i));
+ assert_eq!(v.product::<Saturating<u32>>(), Saturating(3628800));
+ let v = [Saturating(usize::MAX), Saturating(2)];
+ assert_eq!(v.iter().copied().sum::<Saturating<usize>>(), Saturating(usize::MAX));
+ assert_eq!(v.iter().copied().product::<Saturating<usize>>(), Saturating(usize::MAX));
+
+ let mut cnt = 0;
+ let v = 250..=u8::MAX;
+ assert_eq!(
+ v.map(|i| {
+ cnt += 1;
+ Saturating(i)
+ })
+ .sum::<Saturating<u8>>(),
+ Saturating(u8::MAX)
+ );
+ assert_eq!(cnt, 6); // no short-circuiting
+
+ let mut cnt = 0;
+ let v = (250..=u8::MAX).chain(0..5);
+ assert_eq!(
+ v.map(|i| {
+ cnt += 1;
+ Saturating(i)
+ })
+ .product::<Saturating<u8>>(),
+ Saturating(0)
+ );
+ assert_eq!(cnt, 11); // no short-circuiting
+}
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index d2281b1..a260c47 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -80,6 +80,7 @@
#![feature(next_index)]
#![feature(non_exhaustive_omitted_patterns_lint)]
#![feature(numfmt)]
+#![feature(option_reduce)]
#![feature(pattern)]
#![feature(pointer_is_aligned_to)]
#![feature(portable_simd)]
@@ -94,7 +95,6 @@
#![feature(std_internals)]
#![feature(step_trait)]
#![feature(str_internals)]
-#![feature(strict_provenance_atomic_ptr)]
#![feature(strict_provenance_lints)]
#![feature(test)]
#![feature(trusted_len)]
@@ -194,6 +194,7 @@ fn $test() $block
mod tuple;
mod unicode;
mod waker;
+mod wtf8;
/// Copied from `std::test_helpers::test_rng`, see that function for rationale.
#[track_caller]
diff --git a/library/coretests/tests/wtf8.rs b/library/coretests/tests/wtf8.rs
new file mode 100644
index 0000000..9f187e7
--- /dev/null
+++ b/library/coretests/tests/wtf8.rs
@@ -0,0 +1 @@
+// All `wtf8` tests live in library/alloctests/tests/wtf8.rs
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 15a7a77..fc0fef6 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1875,12 +1875,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[unstable(feature = "map_try_insert", issue = "82766")]
-impl<'a, K: fmt::Debug, V: fmt::Debug> Error for OccupiedError<'a, K, V> {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "key already exists"
- }
-}
+impl<'a, K: Debug, V: Debug> Error for OccupiedError<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 9f17ff7..e457cd6 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -296,15 +296,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "env", since = "1.0.0")]
-impl Error for VarError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- match *self {
- VarError::NotPresent => "environment variable not found",
- VarError::NotUnicode(..) => "environment variable was not valid unicode",
- }
- }
-}
+impl Error for VarError {}
/// Sets the environment variable `key` to the value `value` for the currently running
/// process.
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 1ed4f2f..73d7068 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -304,7 +304,7 @@ pub struct DirBuilder {
pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
fn inner(path: &Path) -> io::Result<Vec<u8>> {
let mut file = File::open(path)?;
- let size = file.metadata().map(|m| m.len() as usize).ok();
+ let size = file.metadata().map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX)).ok();
let mut bytes = Vec::try_with_capacity(size.unwrap_or(0))?;
io::default_read_to_end(&mut file, &mut bytes, size)?;
Ok(bytes)
@@ -346,7 +346,7 @@ fn inner(path: &Path) -> io::Result<Vec<u8>> {
pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
fn inner(path: &Path) -> io::Result<String> {
let mut file = File::open(path)?;
- let size = file.metadata().map(|m| m.len() as usize).ok();
+ let size = file.metadata().map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX)).ok();
let mut string = String::new();
string.try_reserve_exact(size.unwrap_or(0))?;
io::default_read_to_string(&mut file, &mut string, size)?;
@@ -3036,6 +3036,9 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
/// Entries for the current and parent directories (typically `.` and `..`) are
/// skipped.
///
+/// The order in which `read_dir` returns entries can change between calls. If reproducible
+/// ordering is required, the entries should be explicitly sorted.
+///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `opendir` function on Unix
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 574eb83d..d569fed 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -492,23 +492,15 @@ impl WriterPanicked {
pub fn into_inner(self) -> Vec<u8> {
self.buf
}
-
- const DESCRIPTION: &'static str =
- "BufWriter inner writer panicked, what data remains unwritten is not known";
}
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
-impl error::Error for WriterPanicked {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- Self::DESCRIPTION
- }
-}
+impl error::Error for WriterPanicked {}
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
impl fmt::Display for WriterPanicked {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", Self::DESCRIPTION)
+ "BufWriter inner writer panicked, what data remains unwritten is not known".fmt(f)
}
}
diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs
index 475d877..e36f2d92 100644
--- a/library/std/src/io/buffered/mod.rs
+++ b/library/std/src/io/buffered/mod.rs
@@ -179,12 +179,7 @@ fn from(iie: IntoInnerError<W>) -> Error {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- error::Error::description(self.error())
- }
-}
+impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W> fmt::Display for IntoInnerError<W> {
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index dcfa189..57a980d 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -1049,15 +1049,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
#[stable(feature = "rust1", since = "1.0.0")]
impl error::Error for Error {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- match self.repr.data() {
- ErrorData::Os(..) | ErrorData::Simple(..) => self.kind().as_str(),
- ErrorData::SimpleMessage(msg) => msg.message,
- ErrorData::Custom(c) => c.error.description(),
- }
- }
-
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn error::Error> {
match self.repr.data() {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index ab417b6..3771699 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -15,7 +15,7 @@
//!
//! If you already know the name of what you are looking for, the fastest way to
//! find it is to use the <a href="#" onclick="window.searchState.focus();">search
-//! bar</a> at the top of the page.
+//! button</a> at the top of the page.
//!
//! Otherwise, you may want to jump to one of these useful sections:
//!
@@ -263,7 +263,6 @@
all(target_vendor = "fortanix", target_env = "sgx"),
feature(slice_index_methods, coerce_unsized, sgx_platform)
)]
-#![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))]
#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))]
#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
//
@@ -371,7 +370,6 @@
#![feature(slice_range)]
#![feature(std_internals)]
#![feature(str_internals)]
-#![feature(strict_provenance_atomic_ptr)]
#![feature(sync_unsafe_cell)]
#![feature(temporary_niche_types)]
#![feature(ub_checks)]
@@ -391,6 +389,7 @@
#![feature(try_with_capacity)]
#![feature(unique_rc_arc)]
#![feature(vec_into_raw_parts)]
+#![feature(wtf8_internals)]
// tidy-alphabetical-end
//
// Library features (unwind):
diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs
index 496443d..345d5b7 100644
--- a/library/std/src/os/windows/ffi.rs
+++ b/library/std/src/os/windows/ffi.rs
@@ -53,12 +53,13 @@
#![stable(feature = "rust1", since = "1.0.0")]
+use alloc::wtf8::Wtf8Buf;
+
use crate::ffi::{OsStr, OsString};
+use crate::fmt;
+use crate::iter::FusedIterator;
use crate::sealed::Sealed;
use crate::sys::os_str::Buf;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::wtf8::EncodeWide;
-use crate::sys_common::wtf8::Wtf8Buf;
use crate::sys_common::{AsInner, FromInner};
/// Windows-specific extensions to [`OsString`].
@@ -130,6 +131,35 @@ pub trait OsStrExt: Sealed {
impl OsStrExt for OsStr {
#[inline]
fn encode_wide(&self) -> EncodeWide<'_> {
- self.as_inner().inner.encode_wide()
+ EncodeWide { inner: self.as_inner().inner.encode_wide() }
}
}
+
+/// Iterator returned by [`OsStrExt::encode_wide`].
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct EncodeWide<'a> {
+ inner: alloc::wtf8::EncodeWide<'a>,
+}
+#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")]
+impl fmt::Debug for EncodeWide<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.inner, f)
+ }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EncodeWide<'_> {
+ type Item = u16;
+
+ #[inline]
+ fn next(&mut self) -> Option<u16> {
+ self.inner.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+}
+#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
+impl FusedIterator for EncodeWide<'_> {}
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index 1c228914..28e9729 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -54,7 +54,7 @@ impl BorrowedSocket<'_> {
///
/// # Safety
///
- /// The resource pointed to by `raw` must remain open for the duration of
+ /// The resource pointed to by `socket` must remain open for the duration of
/// the returned `BorrowedSocket`, and it must not have the value
/// `INVALID_SOCKET`.
#[inline]
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 3899fbf..470d300 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -3677,19 +3677,13 @@ fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
#[stable(since = "1.7.0", feature = "strip_prefix")]
impl fmt::Display for StripPrefixError {
- #[allow(deprecated, deprecated_in_future)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.description().fmt(f)
+ "prefix not found".fmt(f)
}
}
#[stable(since = "1.7.0", feature = "strip_prefix")]
-impl Error for StripPrefixError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "prefix not found"
- }
-}
+impl Error for StripPrefixError {}
#[unstable(feature = "normalize_lexically", issue = "134694")]
impl fmt::Display for NormalizeError {
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index a40e29a..3231125 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -244,7 +244,11 @@ fn drop(&mut self) {
#[inline]
#[stable(feature = "lazy_cell", since = "1.80.0")]
pub fn force(this: &LazyLock<T, F>) -> &T {
- this.once.call_once(|| {
+ this.once.call_once_force(|state| {
+ if state.is_poisoned() {
+ panic_poisoned();
+ }
+
// SAFETY: `call_once` only runs this closure once, ever.
let data = unsafe { &mut *this.data.get() };
let f = unsafe { ManuallyDrop::take(&mut data.f) };
@@ -257,8 +261,7 @@ pub fn force(this: &LazyLock<T, F>) -> &T {
// * the closure was called and initialized `value`.
// * the closure was called and panicked, so this point is never reached.
// * the closure was not called, but a previous call initialized `value`.
- // * the closure was not called because the Once is poisoned, so this point
- // is never reached.
+ // * the closure was not called because the Once is poisoned, which we handled above.
// So `value` has definitely been initialized and will not be modified again.
unsafe { &*(*this.data.get()).value }
}
diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs
index 0cbc611..e3bcb14 100644
--- a/library/std/src/sync/mpmc/utils.rs
+++ b/library/std/src/sync/mpmc/utils.rs
@@ -23,14 +23,13 @@
any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64",),
repr(align(128))
)]
-// arm, mips, mips64, and riscv64 have 32-byte cache line size.
+// arm, mips and mips64 have 32-byte cache line size.
//
// Sources:
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9
-// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7
#[cfg_attr(
any(
target_arch = "arm",
@@ -38,7 +37,6 @@
target_arch = "mips32r6",
target_arch = "mips64",
target_arch = "mips64r6",
- target_arch = "riscv64",
),
repr(align(32))
)]
@@ -47,11 +45,12 @@
// Sources:
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7
#[cfg_attr(target_arch = "s390x", repr(align(256)))]
-// x86 and wasm have 64-byte cache line size.
+// x86, wasm and riscv have 64-byte cache line size.
//
// Sources:
// - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7
+// - https://github.com/golang/go/blob/5e31f78c8a4ed1b872ddc194f0cd1ae931b37d7e/src/internal/cpu/cpu_riscv64.go#L7
//
// All others are assumed to have 64-byte cache line size.
#[cfg_attr(
@@ -64,7 +63,6 @@
target_arch = "mips32r6",
target_arch = "mips64",
target_arch = "mips64r6",
- target_arch = "riscv64",
target_arch = "s390x",
)),
repr(align(64))
diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs
index 03d7fdd..f91c26a 100644
--- a/library/std/src/sync/mpsc.rs
+++ b/library/std/src/sync/mpsc.rs
@@ -1108,12 +1108,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> error::Error for SendError<T> {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "sending on a closed channel"
- }
-}
+impl<T> error::Error for SendError<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Debug for TrySendError<T> {
@@ -1136,15 +1131,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> error::Error for TrySendError<T> {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- match *self {
- TrySendError::Full(..) => "sending on a full channel",
- TrySendError::Disconnected(..) => "sending on a closed channel",
- }
- }
-}
+impl<T> error::Error for TrySendError<T> {}
#[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
impl<T> From<SendError<T>> for TrySendError<T> {
@@ -1168,12 +1155,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl error::Error for RecvError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "receiving on a closed channel"
- }
-}
+impl error::Error for RecvError {}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for TryRecvError {
@@ -1186,15 +1168,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl error::Error for TryRecvError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- match *self {
- TryRecvError::Empty => "receiving on an empty channel",
- TryRecvError::Disconnected => "receiving on a closed channel",
- }
- }
-}
+impl error::Error for TryRecvError {}
#[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
impl From<RecvError> for TryRecvError {
@@ -1221,15 +1195,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")]
-impl error::Error for RecvTimeoutError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- match *self {
- RecvTimeoutError::Timeout => "timed out waiting on channel",
- RecvTimeoutError::Disconnected => "channel is empty and sending half is closed",
- }
- }
-}
+impl error::Error for RecvTimeoutError {}
#[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
impl From<RecvError> for RecvTimeoutError {
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index dc4774d..17abdb9 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -263,12 +263,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Error for PoisonError<T> {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "poisoned lock: another task failed inside"
- }
-}
+impl<T> Error for PoisonError<T> {}
impl<T> PoisonError<T> {
/// Creates a `PoisonError`.
@@ -376,17 +371,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Error for TryLockError<T> {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- match *self {
- #[cfg(panic = "unwind")]
- TryLockError::Poisoned(ref p) => p.description(),
- #[cfg(not(panic = "unwind"))]
- TryLockError::Poisoned(ref p) => match p._never {},
- TryLockError::WouldBlock => "try_lock failed because the operation would block",
- }
- }
-
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn Error> {
match *self {
diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs
index c8fab99..48e2fdd 100644
--- a/library/std/src/sys/alloc/wasm.rs
+++ b/library/std/src/sys/alloc/wasm.rs
@@ -16,12 +16,15 @@
//! The crate itself provides a global allocator which on wasm has no
//! synchronization as there are no threads!
-// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
-#![allow(static_mut_refs)]
+use core::cell::SyncUnsafeCell;
use crate::alloc::{GlobalAlloc, Layout, System};
-static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new();
+struct SyncDlmalloc(dlmalloc::Dlmalloc);
+unsafe impl Sync for SyncDlmalloc {}
+
+static DLMALLOC: SyncUnsafeCell<SyncDlmalloc> =
+ SyncUnsafeCell::new(SyncDlmalloc(dlmalloc::Dlmalloc::new()));
#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
@@ -30,7 +33,7 @@ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
// SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
// Calling malloc() is safe because preconditions on this function match the trait method preconditions.
let _lock = lock::lock();
- unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
+ unsafe { (*DLMALLOC.get()).0.malloc(layout.size(), layout.align()) }
}
#[inline]
@@ -38,7 +41,7 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
// SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
// Calling calloc() is safe because preconditions on this function match the trait method preconditions.
let _lock = lock::lock();
- unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
+ unsafe { (*DLMALLOC.get()).0.calloc(layout.size(), layout.align()) }
}
#[inline]
@@ -46,7 +49,7 @@ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
// SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
// Calling free() is safe because preconditions on this function match the trait method preconditions.
let _lock = lock::lock();
- unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
+ unsafe { (*DLMALLOC.get()).0.free(ptr, layout.size(), layout.align()) }
}
#[inline]
@@ -54,7 +57,7 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
// SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
// Calling realloc() is safe because preconditions on this function match the trait method preconditions.
let _lock = lock::lock();
- unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
+ unsafe { (*DLMALLOC.get()).0.realloc(ptr, layout.size(), layout.align(), new_size) }
}
}
diff --git a/library/std/src/sys/backtrace.rs b/library/std/src/sys/backtrace.rs
index 272d0fa..5768220 100644
--- a/library/std/src/sys/backtrace.rs
+++ b/library/std/src/sys/backtrace.rs
@@ -113,7 +113,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
res = bt_fmt.frame().symbol(frame, symbol);
}
});
- #[cfg(target_os = "nto")]
+ #[cfg(all(target_os = "nto", any(target_env = "nto70", target_env = "nto71")))]
if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
if !hit && print {
use crate::backtrace_rs::SymbolName;
diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs
index cdca73c..a12f692 100644
--- a/library/std/src/sys/fd/unix.rs
+++ b/library/std/src/sys/fd/unix.rs
@@ -37,10 +37,10 @@
//
// On Apple targets however, apparently the 64-bit libc is either buggy or
// intentionally showing odd behavior by rejecting any read with a size
-// larger than or equal to INT_MAX. To handle both of these the read
-// size is capped on both platforms.
+// larger than INT_MAX. To handle both of these the read size is capped on
+// both platforms.
const READ_LIMIT: usize = if cfg!(target_vendor = "apple") {
- libc::c_int::MAX as usize - 1
+ libc::c_int::MAX as usize
} else {
libc::ssize_t::MAX as usize
};
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs
index dbd782f..0276bf6 100644
--- a/library/std/src/sys/fs/mod.rs
+++ b/library/std/src/sys/fs/mod.rs
@@ -117,9 +117,18 @@ pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
#[cfg(unix)]
pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> {
use crate::fs::OpenOptions;
- use crate::os::unix::fs::OpenOptionsExt;
- OpenOptions::new().custom_flags(libc::O_NOFOLLOW).open(path)?.set_permissions(perm)
+ let mut options = OpenOptions::new();
+
+ // ESP-IDF and Horizon do not support O_NOFOLLOW, so we skip setting it.
+ // Their filesystems do not have symbolic links, so no special handling is required.
+ #[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
+ {
+ use crate::os::unix::fs::OpenOptionsExt;
+ options.custom_flags(libc::O_NOFOLLOW);
+ }
+
+ options.open(path)?.set_permissions(perm)
}
#[cfg(not(unix))]
diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs
index 242df10..2389fd1 100644
--- a/library/std/src/sys/net/connection/sgx.rs
+++ b/library/std/src/sys/net/connection/sgx.rs
@@ -452,12 +452,7 @@ pub struct NonIpSockAddr {
host: String,
}
-impl error::Error for NonIpSockAddr {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "Failed to convert address to SocketAddr"
- }
-}
+impl error::Error for NonIpSockAddr {}
impl fmt::Display for NonIpSockAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index bbc704e..96da891 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -1,12 +1,12 @@
//! The underlying OsString/OsStr implementation on Windows is a
//! wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
+use alloc::wtf8::{Wtf8, Wtf8Buf};
use core::clone::CloneToUninit;
use crate::borrow::Cow;
use crate::collections::TryReserveError;
use crate::rc::Rc;
use crate::sync::Arc;
-use crate::sys_common::wtf8::{Wtf8, Wtf8Buf, check_utf8_boundary};
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::{fmt, mem};
@@ -220,7 +220,9 @@ pub unsafe fn truncate_unchecked(&mut self, len: usize) {
/// trailing surrogate half.
#[inline]
pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
- self.inner.extend_from_slice(other);
+ unsafe {
+ self.inner.extend_from_slice_unchecked(other);
+ }
}
}
@@ -238,7 +240,7 @@ pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
#[track_caller]
#[inline]
pub fn check_public_boundary(&self, index: usize) {
- check_utf8_boundary(&self.inner, index);
+ self.inner.check_utf8_boundary(index);
}
#[inline]
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index a998c31..0fe713a 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -1,5 +1,4 @@
use super::hermit_abi;
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
@@ -52,12 +51,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "not supported on hermit yet"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 6e43a79..4a297b6 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -59,8 +59,7 @@ pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
#[inline]
pub fn is_interrupted(code: i32) -> bool {
- use fortanix_sgx_abi::Error;
- code == Error::Interrupted as _
+ code == fortanix_sgx_abi::Error::Interrupted as _
}
pub fn decode_error_kind(code: i32) -> ErrorKind {
diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs
index 70f8386..28d7996 100644
--- a/library/std/src/sys/pal/sgx/os.rs
+++ b/library/std/src/sys/pal/sgx/os.rs
@@ -1,11 +1,10 @@
use fortanix_sgx_abi::{Error, RESULT_SUCCESS};
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
use crate::sys::{decode_error_kind, sgx_ineffective, unsupported};
-use crate::{fmt, io, str};
+use crate::{fmt, io};
pub fn errno() -> i32 {
RESULT_SUCCESS
@@ -59,12 +58,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "not supported in SGX yet"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs
index 8f5976b..cb6e2cb 100644
--- a/library/std/src/sys/pal/solid/os.rs
+++ b/library/std/src/sys/pal/solid/os.rs
@@ -1,5 +1,4 @@
use super::{error, itron, unsupported};
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::path::{self, PathBuf};
use crate::{fmt, io};
@@ -58,12 +57,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "not supported on this platform yet"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs
index 03f3c72..512b3e2 100644
--- a/library/std/src/sys/pal/teeos/os.rs
+++ b/library/std/src/sys/pal/teeos/os.rs
@@ -3,7 +3,6 @@
use core::marker::PhantomData;
use super::unsupported;
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::path::PathBuf;
use crate::{fmt, io, path};
@@ -62,12 +61,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "not supported on this platform yet"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs
index bfd4dc8..aae6cb9 100644
--- a/library/std/src/sys/pal/uefi/os.rs
+++ b/library/std/src/sys/pal/uefi/os.rs
@@ -2,7 +2,6 @@
use r_efi::efi::protocols::{device_path, loaded_image_device_path};
use super::{RawOsError, helpers, unsupported_err};
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::os::uefi;
@@ -122,7 +121,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
let protocol = helpers::image_handle_protocol::<device_path::Protocol>(
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index aef7ab5..400128a 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -382,6 +382,7 @@ pub fn abort_internal() -> ! {
unsafe extern "C" {}
}
target_os = "netbsd" => {
+ #[link(name = "execinfo")]
#[link(name = "pthread")]
#[link(name = "rt")]
unsafe extern "C" {}
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index 1110b77..aec089f 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -7,7 +7,6 @@
use libc::{c_char, c_int, c_void};
-use crate::error::Error as StdError;
use crate::ffi::{CStr, OsStr, OsString};
use crate::os::unix::prelude::*;
use crate::path::{self, PathBuf};
@@ -17,10 +16,7 @@
const TMPBUF_SZ: usize = 128;
-const PATH_SEPARATOR: u8 = cfg_select! {
- target_os = "redox" => b';',
- _ => b':',
-};
+const PATH_SEPARATOR: u8 = if cfg!(target_os = "redox") { b';' } else { b':' };
unsafe extern "C" {
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
@@ -190,33 +186,14 @@ pub fn chdir(p: &path::Path) -> io::Result<()> {
if result == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }
}
-pub struct SplitPaths<'a> {
- iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>, fn(&'a [u8]) -> PathBuf>,
-}
+pub type SplitPaths<'a> = impl Iterator<Item = PathBuf>;
+#[define_opaque(SplitPaths)]
pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> {
- fn bytes_to_path(b: &[u8]) -> PathBuf {
- PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
- }
- fn is_separator(b: &u8) -> bool {
- *b == PATH_SEPARATOR
- }
- let unparsed = unparsed.as_bytes();
- SplitPaths {
- iter: unparsed
- .split(is_separator as fn(&u8) -> bool)
- .map(bytes_to_path as fn(&[u8]) -> PathBuf),
- }
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
- type Item = PathBuf;
- fn next(&mut self) -> Option<PathBuf> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
+ unparsed
+ .as_bytes()
+ .split(|&b| b == PATH_SEPARATOR)
+ .map(|part| PathBuf::from(OsStr::from_bytes(part)))
}
#[derive(Debug)]
@@ -248,12 +225,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "failed to join paths"
- }
-}
+impl crate::error::Error for JoinPathsError {}
#[cfg(target_os = "aix")]
pub fn current_exe() -> io::Result<PathBuf> {
@@ -475,7 +447,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
unsafe {
let result = libc::find_path(
crate::ptr::null_mut(),
- libc::path_base_directory::B_FIND_PATH_IMAGE_PATH,
+ libc::B_FIND_PATH_IMAGE_PATH,
crate::ptr::null_mut(),
name.as_mut_ptr(),
name.len(),
diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs
index 6b0cd14..4798acf 100644
--- a/library/std/src/sys/pal/unix/pipe.rs
+++ b/library/std/src/sys/pal/unix/pipe.rs
@@ -20,6 +20,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
// and musl 0.9.3, and some other targets also have it.
cfg_select! {
any(
+ target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "hurd",
diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/pal/unsupported/os.rs
index a8ef97e..13d2a204 100644
--- a/library/std/src/sys/pal/unsupported/os.rs
+++ b/library/std/src/sys/pal/unsupported/os.rs
@@ -1,5 +1,4 @@
use super::unsupported;
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
@@ -51,12 +50,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "not supported on this platform yet"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs
index 672cf70..151ba25 100644
--- a/library/std/src/sys/pal/wasi/os.rs
+++ b/library/std/src/sys/pal/wasi/os.rs
@@ -1,6 +1,5 @@
#![forbid(unsafe_op_in_unsafe_fn)]
-use crate::error::Error as StdError;
use crate::ffi::{CStr, OsStr, OsString};
use crate::marker::PhantomData;
use crate::os::wasi::prelude::*;
@@ -105,12 +104,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "not supported on wasm yet"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index f331282..1b3c80c 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -8,7 +8,6 @@
use super::api;
#[cfg(not(target_vendor = "uwp"))]
use super::api::WinError;
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::os::windows::ffi::EncodeWide;
use crate::os::windows::prelude::*;
@@ -162,12 +161,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "failed to join paths"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
super::fill_utf16_buf(
diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs
index d612a27..d9b8418 100644
--- a/library/std/src/sys/pal/xous/os.rs
+++ b/library/std/src/sys/pal/xous/os.rs
@@ -1,5 +1,4 @@
use super::unsupported;
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::os::xous::ffi::Error as XousError;
@@ -110,12 +109,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "not supported on this platform yet"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs
index a8ef97e..13d2a204 100644
--- a/library/std/src/sys/pal/zkvm/os.rs
+++ b/library/std/src/sys/pal/zkvm/os.rs
@@ -1,5 +1,4 @@
use super::unsupported;
-use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
@@ -51,12 +50,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl StdError for JoinPathsError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "not supported on this platform yet"
- }
-}
+impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 24b6cff..ec45c72 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -21,7 +21,6 @@
mod tests;
pub mod wstr;
-pub mod wtf8;
// common error constructors
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
deleted file mode 100644
index 50bde88..0000000
--- a/library/std/src/sys_common/wtf8.rs
+++ /dev/null
@@ -1,1083 +0,0 @@
-//! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/).
-//!
-//! This library uses Rust’s type system to maintain
-//! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed),
-//! like the `String` and `&str` types do for UTF-8.
-//!
-//! Since [WTF-8 must not be used
-//! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience),
-//! this library deliberately does not provide access to the underlying bytes
-//! of WTF-8 strings,
-//! nor can it decode WTF-8 from arbitrary bytes.
-//! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points.
-
-// this module is imported from @SimonSapin's repo and has tons of dead code on
-// unix (it's mostly used on windows), so don't worry about dead code here.
-#![allow(dead_code)]
-
-#[cfg(test)]
-mod tests;
-
-use core::char::{MAX_LEN_UTF8, MAX_LEN_UTF16, encode_utf8_raw, encode_utf16_raw};
-use core::clone::CloneToUninit;
-use core::str::next_code_point;
-
-use crate::borrow::Cow;
-use crate::collections::TryReserveError;
-use crate::hash::{Hash, Hasher};
-use crate::iter::FusedIterator;
-use crate::rc::Rc;
-use crate::sync::Arc;
-use crate::sys_common::AsInner;
-use crate::{fmt, mem, ops, slice, str};
-
-const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}";
-
-/// A Unicode code point: from U+0000 to U+10FFFF.
-///
-/// Compares with the `char` type,
-/// which represents a Unicode scalar value:
-/// a code point that is not a surrogate (U+D800 to U+DFFF).
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
-pub struct CodePoint {
- value: u32,
-}
-
-/// Format the code point as `U+` followed by four to six hexadecimal digits.
-/// Example: `U+1F4A9`
-impl fmt::Debug for CodePoint {
- #[inline]
- fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(formatter, "U+{:04X}", self.value)
- }
-}
-
-impl CodePoint {
- /// Unsafely creates a new `CodePoint` without checking the value.
- ///
- /// Only use when `value` is known to be less than or equal to 0x10FFFF.
- #[inline]
- pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint {
- CodePoint { value }
- }
-
- /// Creates a new `CodePoint` if the value is a valid code point.
- ///
- /// Returns `None` if `value` is above 0x10FFFF.
- #[inline]
- pub fn from_u32(value: u32) -> Option<CodePoint> {
- match value {
- 0..=0x10FFFF => Some(CodePoint { value }),
- _ => None,
- }
- }
-
- /// Creates a new `CodePoint` from a `char`.
- ///
- /// Since all Unicode scalar values are code points, this always succeeds.
- #[inline]
- pub fn from_char(value: char) -> CodePoint {
- CodePoint { value: value as u32 }
- }
-
- /// Returns the numeric value of the code point.
- #[inline]
- pub fn to_u32(&self) -> u32 {
- self.value
- }
-
- /// Returns the numeric value of the code point if it is a leading surrogate.
- #[inline]
- pub fn to_lead_surrogate(&self) -> Option<u16> {
- match self.value {
- lead @ 0xD800..=0xDBFF => Some(lead as u16),
- _ => None,
- }
- }
-
- /// Returns the numeric value of the code point if it is a trailing surrogate.
- #[inline]
- pub fn to_trail_surrogate(&self) -> Option<u16> {
- match self.value {
- trail @ 0xDC00..=0xDFFF => Some(trail as u16),
- _ => None,
- }
- }
-
- /// Optionally returns a Unicode scalar value for the code point.
- ///
- /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF).
- #[inline]
- pub fn to_char(&self) -> Option<char> {
- match self.value {
- 0xD800..=0xDFFF => None,
- _ => Some(unsafe { char::from_u32_unchecked(self.value) }),
- }
- }
-
- /// Returns a Unicode scalar value for the code point.
- ///
- /// Returns `'\u{FFFD}'` (the replacement character “�”)
- /// if the code point is a surrogate (from U+D800 to U+DFFF).
- #[inline]
- pub fn to_char_lossy(&self) -> char {
- self.to_char().unwrap_or('\u{FFFD}')
- }
-}
-
-/// An owned, growable string of well-formed WTF-8 data.
-///
-/// Similar to `String`, but can additionally contain surrogate code points
-/// if they’re not in a surrogate pair.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
-pub struct Wtf8Buf {
- bytes: Vec<u8>,
-
- /// Do we know that `bytes` holds a valid UTF-8 encoding? We can easily
- /// know this if we're constructed from a `String` or `&str`.
- ///
- /// It is possible for `bytes` to have valid UTF-8 without this being
- /// set, such as when we're concatenating `&Wtf8`'s and surrogates become
- /// paired, as we don't bother to rescan the entire string.
- is_known_utf8: bool,
-}
-
-impl ops::Deref for Wtf8Buf {
- type Target = Wtf8;
-
- fn deref(&self) -> &Wtf8 {
- self.as_slice()
- }
-}
-
-impl ops::DerefMut for Wtf8Buf {
- fn deref_mut(&mut self) -> &mut Wtf8 {
- self.as_mut_slice()
- }
-}
-
-/// Formats the string in double quotes, with characters escaped according to
-/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
-/// where each `x` is a hexadecimal digit.
-///
-/// For example, the code units [U+0061, U+D800, U+000A] are formatted as
-/// `"a\u{D800}\n"`.
-impl fmt::Debug for Wtf8Buf {
- #[inline]
- fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Debug::fmt(&**self, formatter)
- }
-}
-
-/// Formats the string with unpaired surrogates substituted with the replacement
-/// character, U+FFFD.
-impl fmt::Display for Wtf8Buf {
- fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- if let Some(s) = self.as_known_utf8() {
- fmt::Display::fmt(s, formatter)
- } else {
- fmt::Display::fmt(&**self, formatter)
- }
- }
-}
-
-impl Wtf8Buf {
- /// Creates a new, empty WTF-8 string.
- #[inline]
- pub fn new() -> Wtf8Buf {
- Wtf8Buf { bytes: Vec::new(), is_known_utf8: true }
- }
-
- /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes.
- #[inline]
- pub fn with_capacity(capacity: usize) -> Wtf8Buf {
- Wtf8Buf { bytes: Vec::with_capacity(capacity), is_known_utf8: true }
- }
-
- /// Creates a WTF-8 string from a WTF-8 byte vec.
- ///
- /// Since the byte vec is not checked for valid WTF-8, this function is
- /// marked unsafe.
- #[inline]
- pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf {
- Wtf8Buf { bytes: value, is_known_utf8: false }
- }
-
- /// Creates a WTF-8 string from a UTF-8 `String`.
- ///
- /// This takes ownership of the `String` and does not copy.
- ///
- /// Since WTF-8 is a superset of UTF-8, this always succeeds.
- #[inline]
- pub const fn from_string(string: String) -> Wtf8Buf {
- Wtf8Buf { bytes: string.into_bytes(), is_known_utf8: true }
- }
-
- /// Creates a WTF-8 string from a UTF-8 `&str` slice.
- ///
- /// This copies the content of the slice.
- ///
- /// Since WTF-8 is a superset of UTF-8, this always succeeds.
- #[inline]
- pub fn from_str(s: &str) -> Wtf8Buf {
- Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true }
- }
-
- pub fn clear(&mut self) {
- self.bytes.clear();
- self.is_known_utf8 = true;
- }
-
- /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units.
- ///
- /// This is lossless: calling `.encode_wide()` on the resulting string
- /// will always return the original code units.
- pub fn from_wide(v: &[u16]) -> Wtf8Buf {
- let mut string = Wtf8Buf::with_capacity(v.len());
- for item in char::decode_utf16(v.iter().cloned()) {
- match item {
- Ok(ch) => string.push_char(ch),
- Err(surrogate) => {
- let surrogate = surrogate.unpaired_surrogate();
- // Surrogates are known to be in the code point range.
- let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) };
- // The string will now contain an unpaired surrogate.
- string.is_known_utf8 = false;
- // Skip the WTF-8 concatenation check,
- // surrogate pairs are already decoded by decode_utf16
- string.push_code_point_unchecked(code_point);
- }
- }
- }
- string
- }
-
- /// Appends the given `char` to the end of this string.
- /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check.
- /// Copied from String::push.
- fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
- let mut bytes = [0; MAX_LEN_UTF8];
- let bytes = encode_utf8_raw(code_point.value, &mut bytes);
- self.bytes.extend_from_slice(bytes)
- }
-
- #[inline]
- pub fn as_slice(&self) -> &Wtf8 {
- unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
- }
-
- #[inline]
- pub fn as_mut_slice(&mut self) -> &mut Wtf8 {
- // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would
- // cause them to change from well-formed UTF-8 to ill-formed UTF-8,
- // which would break the assumptions of the `is_known_utf8` field.
- unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) }
- }
-
- /// Converts the string to UTF-8 without validation, if it was created from
- /// valid UTF-8.
- #[inline]
- fn as_known_utf8(&self) -> Option<&str> {
- if self.is_known_utf8 {
- // SAFETY: The buffer is known to be valid UTF-8.
- Some(unsafe { str::from_utf8_unchecked(self.as_bytes()) })
- } else {
- None
- }
- }
-
- /// Reserves capacity for at least `additional` more bytes to be inserted
- /// in the given `Wtf8Buf`.
- /// The collection may reserve more space to avoid frequent reallocations.
- ///
- /// # Panics
- ///
- /// Panics if the new capacity exceeds `isize::MAX` bytes.
- #[inline]
- pub fn reserve(&mut self, additional: usize) {
- self.bytes.reserve(additional)
- }
-
- /// Tries to reserve capacity for at least `additional` more bytes to be
- /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to
- /// avoid frequent reallocations. After calling `try_reserve`, capacity will
- /// be greater than or equal to `self.len() + additional`. Does nothing if
- /// capacity is already sufficient. This method preserves the contents even
- /// if an error occurs.
- ///
- /// # Errors
- ///
- /// If the capacity overflows, or the allocator reports a failure, then an error
- /// is returned.
- #[inline]
- pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
- self.bytes.try_reserve(additional)
- }
-
- #[inline]
- pub fn reserve_exact(&mut self, additional: usize) {
- self.bytes.reserve_exact(additional)
- }
-
- /// Tries to reserve the minimum capacity for exactly `additional` more
- /// bytes to be inserted in the given `Wtf8Buf`. After calling
- /// `try_reserve_exact`, capacity will be greater than or equal to
- /// `self.len() + additional` if it returns `Ok(())`.
- /// Does nothing if the capacity is already sufficient.
- ///
- /// Note that the allocator may give the `Wtf8Buf` more space than it
- /// requests. Therefore, capacity can not be relied upon to be precisely
- /// minimal. Prefer [`try_reserve`] if future insertions are expected.
- ///
- /// [`try_reserve`]: Wtf8Buf::try_reserve
- ///
- /// # Errors
- ///
- /// If the capacity overflows, or the allocator reports a failure, then an error
- /// is returned.
- #[inline]
- pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
- self.bytes.try_reserve_exact(additional)
- }
-
- #[inline]
- pub fn shrink_to_fit(&mut self) {
- self.bytes.shrink_to_fit()
- }
-
- #[inline]
- pub fn shrink_to(&mut self, min_capacity: usize) {
- self.bytes.shrink_to(min_capacity)
- }
-
- #[inline]
- pub fn leak<'a>(self) -> &'a mut Wtf8 {
- unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) }
- }
-
- /// Returns the number of bytes that this string buffer can hold without reallocating.
- #[inline]
- pub fn capacity(&self) -> usize {
- self.bytes.capacity()
- }
-
- /// Append a UTF-8 slice at the end of the string.
- #[inline]
- pub fn push_str(&mut self, other: &str) {
- self.bytes.extend_from_slice(other.as_bytes())
- }
-
- /// Append a WTF-8 slice at the end of the string.
- ///
- /// This replaces newly paired surrogates at the boundary
- /// with a supplementary code point,
- /// like concatenating ill-formed UTF-16 strings effectively would.
- #[inline]
- pub fn push_wtf8(&mut self, other: &Wtf8) {
- match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) {
- // Replace newly paired surrogates by a supplementary code point.
- (Some(lead), Some(trail)) => {
- let len_without_lead_surrogate = self.len() - 3;
- self.bytes.truncate(len_without_lead_surrogate);
- let other_without_trail_surrogate = &other.bytes[3..];
- // 4 bytes for the supplementary code point
- self.bytes.reserve(4 + other_without_trail_surrogate.len());
- self.push_char(decode_surrogate_pair(lead, trail));
- self.bytes.extend_from_slice(other_without_trail_surrogate);
- }
- _ => {
- // If we'll be pushing a string containing a surrogate, we may
- // no longer have UTF-8.
- if self.is_known_utf8 && other.next_surrogate(0).is_some() {
- self.is_known_utf8 = false;
- }
-
- self.bytes.extend_from_slice(&other.bytes);
- }
- }
- }
-
- /// Append a Unicode scalar value at the end of the string.
- #[inline]
- pub fn push_char(&mut self, c: char) {
- self.push_code_point_unchecked(CodePoint::from_char(c))
- }
-
- /// Append a code point at the end of the string.
- ///
- /// This replaces newly paired surrogates at the boundary
- /// with a supplementary code point,
- /// like concatenating ill-formed UTF-16 strings effectively would.
- #[inline]
- pub fn push(&mut self, code_point: CodePoint) {
- if let Some(trail) = code_point.to_trail_surrogate() {
- if let Some(lead) = (&*self).final_lead_surrogate() {
- let len_without_lead_surrogate = self.len() - 3;
- self.bytes.truncate(len_without_lead_surrogate);
- self.push_char(decode_surrogate_pair(lead, trail));
- return;
- }
-
- // We're pushing a trailing surrogate.
- self.is_known_utf8 = false;
- } else if code_point.to_lead_surrogate().is_some() {
- // We're pushing a leading surrogate.
- self.is_known_utf8 = false;
- }
-
- // No newly paired surrogates at the boundary.
- self.push_code_point_unchecked(code_point)
- }
-
- /// Shortens a string to the specified length.
- ///
- /// # Panics
- ///
- /// Panics if `new_len` > current length,
- /// or if `new_len` is not a code point boundary.
- #[inline]
- pub fn truncate(&mut self, new_len: usize) {
- assert!(is_code_point_boundary(self, new_len));
- self.bytes.truncate(new_len)
- }
-
- /// Consumes the WTF-8 string and tries to convert it to a vec of bytes.
- #[inline]
- pub fn into_bytes(self) -> Vec<u8> {
- self.bytes
- }
-
- /// Consumes the WTF-8 string and tries to convert it to UTF-8.
- ///
- /// This does not copy the data.
- ///
- /// If the contents are not well-formed UTF-8
- /// (that is, if the string contains surrogates),
- /// the original WTF-8 string is returned instead.
- pub fn into_string(self) -> Result<String, Wtf8Buf> {
- if self.is_known_utf8 || self.next_surrogate(0).is_none() {
- Ok(unsafe { String::from_utf8_unchecked(self.bytes) })
- } else {
- Err(self)
- }
- }
-
- /// Consumes the WTF-8 string and converts it lossily to UTF-8.
- ///
- /// This does not copy the data (but may overwrite parts of it in place).
- ///
- /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”)
- pub fn into_string_lossy(mut self) -> String {
- if !self.is_known_utf8 {
- let mut pos = 0;
- while let Some((surrogate_pos, _)) = self.next_surrogate(pos) {
- pos = surrogate_pos + 3;
- // Surrogates and the replacement character are all 3 bytes, so
- // they can substituted in-place.
- self.bytes[surrogate_pos..pos]
- .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
- }
- }
- unsafe { String::from_utf8_unchecked(self.bytes) }
- }
-
- /// Converts this `Wtf8Buf` into a boxed `Wtf8`.
- #[inline]
- pub fn into_box(self) -> Box<Wtf8> {
- // SAFETY: relies on `Wtf8` being `repr(transparent)`.
- unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
- }
-
- /// Converts a `Box<Wtf8>` into a `Wtf8Buf`.
- pub fn from_box(boxed: Box<Wtf8>) -> Wtf8Buf {
- let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) };
- Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false }
- }
-
- /// Provides plumbing to core `Vec::extend_from_slice`.
- /// More well behaving alternative to allowing outer types
- /// full mutable access to the core `Vec`.
- #[inline]
- pub(crate) fn extend_from_slice(&mut self, other: &[u8]) {
- self.bytes.extend_from_slice(other);
- self.is_known_utf8 = false;
- }
-}
-
-/// Creates a new WTF-8 string from an iterator of code points.
-///
-/// This replaces surrogate code point pairs with supplementary code points,
-/// like concatenating ill-formed UTF-16 strings effectively would.
-impl FromIterator<CodePoint> for Wtf8Buf {
- fn from_iter<T: IntoIterator<Item = CodePoint>>(iter: T) -> Wtf8Buf {
- let mut string = Wtf8Buf::new();
- string.extend(iter);
- string
- }
-}
-
-/// Append code points from an iterator to the string.
-///
-/// This replaces surrogate code point pairs with supplementary code points,
-/// like concatenating ill-formed UTF-16 strings effectively would.
-impl Extend<CodePoint> for Wtf8Buf {
- fn extend<T: IntoIterator<Item = CodePoint>>(&mut self, iter: T) {
- let iterator = iter.into_iter();
- let (low, _high) = iterator.size_hint();
- // Lower bound of one byte per code point (ASCII only)
- self.bytes.reserve(low);
- iterator.for_each(move |code_point| self.push(code_point));
- }
-
- #[inline]
- fn extend_one(&mut self, code_point: CodePoint) {
- self.push(code_point);
- }
-
- #[inline]
- fn extend_reserve(&mut self, additional: usize) {
- // Lower bound of one byte per code point (ASCII only)
- self.bytes.reserve(additional);
- }
-}
-
-/// A borrowed slice of well-formed WTF-8 data.
-///
-/// Similar to `&str`, but can additionally contain surrogate code points
-/// if they’re not in a surrogate pair.
-#[derive(Eq, Ord, PartialEq, PartialOrd)]
-#[repr(transparent)]
-pub struct Wtf8 {
- bytes: [u8],
-}
-
-impl AsInner<[u8]> for Wtf8 {
- #[inline]
- fn as_inner(&self) -> &[u8] {
- &self.bytes
- }
-}
-
-/// Formats the string in double quotes, with characters escaped according to
-/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
-/// where each `x` is a hexadecimal digit.
-impl fmt::Debug for Wtf8 {
- fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result {
- use crate::fmt::Write;
- for c in s.chars().flat_map(|c| c.escape_debug()) {
- f.write_char(c)?
- }
- Ok(())
- }
-
- formatter.write_str("\"")?;
- let mut pos = 0;
- while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
- write_str_escaped(formatter, unsafe {
- str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos])
- })?;
- write!(formatter, "\\u{{{:x}}}", surrogate)?;
- pos = surrogate_pos + 3;
- }
- write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?;
- formatter.write_str("\"")
- }
-}
-
-/// Formats the string with unpaired surrogates substituted with the replacement
-/// character, U+FFFD.
-impl fmt::Display for Wtf8 {
- fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- let wtf8_bytes = &self.bytes;
- let mut pos = 0;
- loop {
- match self.next_surrogate(pos) {
- Some((surrogate_pos, _)) => {
- formatter.write_str(unsafe {
- str::from_utf8_unchecked(&wtf8_bytes[pos..surrogate_pos])
- })?;
- formatter.write_str(UTF8_REPLACEMENT_CHARACTER)?;
- pos = surrogate_pos + 3;
- }
- None => {
- let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) };
- if pos == 0 { return s.fmt(formatter) } else { return formatter.write_str(s) }
- }
- }
- }
- }
-}
-
-impl Wtf8 {
- /// Creates a WTF-8 slice from a UTF-8 `&str` slice.
- ///
- /// Since WTF-8 is a superset of UTF-8, this always succeeds.
- #[inline]
- pub fn from_str(value: &str) -> &Wtf8 {
- unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
- }
-
- /// Creates a WTF-8 slice from a WTF-8 byte slice.
- ///
- /// Since the byte slice is not checked for valid WTF-8, this functions is
- /// marked unsafe.
- #[inline]
- pub unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
- // SAFETY: start with &[u8], end with fancy &[u8]
- unsafe { &*(value as *const [u8] as *const Wtf8) }
- }
-
- /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice.
- ///
- /// Since the byte slice is not checked for valid WTF-8, this functions is
- /// marked unsafe.
- #[inline]
- unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 {
- // SAFETY: start with &mut [u8], end with fancy &mut [u8]
- unsafe { &mut *(value as *mut [u8] as *mut Wtf8) }
- }
-
- /// Returns the length, in WTF-8 bytes.
- #[inline]
- pub fn len(&self) -> usize {
- self.bytes.len()
- }
-
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.bytes.is_empty()
- }
-
- /// Returns the code point at `position` if it is in the ASCII range,
- /// or `b'\xFF'` otherwise.
- ///
- /// # Panics
- ///
- /// Panics if `position` is beyond the end of the string.
- #[inline]
- pub fn ascii_byte_at(&self, position: usize) -> u8 {
- match self.bytes[position] {
- ascii_byte @ 0x00..=0x7F => ascii_byte,
- _ => 0xFF,
- }
- }
-
- /// Returns an iterator for the string’s code points.
- #[inline]
- pub fn code_points(&self) -> Wtf8CodePoints<'_> {
- Wtf8CodePoints { bytes: self.bytes.iter() }
- }
-
- /// Access raw bytes of WTF-8 data
- #[inline]
- pub fn as_bytes(&self) -> &[u8] {
- &self.bytes
- }
-
- /// Tries to convert the string to UTF-8 and return a `&str` slice.
- ///
- /// Returns `None` if the string contains surrogates.
- ///
- /// This does not copy the data.
- #[inline]
- pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
- str::from_utf8(&self.bytes)
- }
-
- /// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`.
- pub fn to_owned(&self) -> Wtf8Buf {
- Wtf8Buf { bytes: self.bytes.to_vec(), is_known_utf8: false }
- }
-
- /// Lossily converts the string to UTF-8.
- /// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8.
- ///
- /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”).
- ///
- /// This only copies the data if necessary (if it contains any surrogate).
- pub fn to_string_lossy(&self) -> Cow<'_, str> {
- let Some((surrogate_pos, _)) = self.next_surrogate(0) else {
- return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) });
- };
- let wtf8_bytes = &self.bytes;
- let mut utf8_bytes = Vec::with_capacity(self.len());
- utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]);
- utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
- let mut pos = surrogate_pos + 3;
- loop {
- match self.next_surrogate(pos) {
- Some((surrogate_pos, _)) => {
- utf8_bytes.extend_from_slice(&wtf8_bytes[pos..surrogate_pos]);
- utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
- pos = surrogate_pos + 3;
- }
- None => {
- utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]);
- return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) });
- }
- }
- }
- }
-
- /// Converts the WTF-8 string to potentially ill-formed UTF-16
- /// and return an iterator of 16-bit code units.
- ///
- /// This is lossless:
- /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units
- /// would always return the original WTF-8 string.
- #[inline]
- pub fn encode_wide(&self) -> EncodeWide<'_> {
- EncodeWide { code_points: self.code_points(), extra: 0 }
- }
-
- #[inline]
- fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> {
- let mut iter = self.bytes[pos..].iter();
- loop {
- let b = *iter.next()?;
- if b < 0x80 {
- pos += 1;
- } else if b < 0xE0 {
- iter.next();
- pos += 2;
- } else if b == 0xED {
- match (iter.next(), iter.next()) {
- (Some(&b2), Some(&b3)) if b2 >= 0xA0 => {
- return Some((pos, decode_surrogate(b2, b3)));
- }
- _ => pos += 3,
- }
- } else if b < 0xF0 {
- iter.next();
- iter.next();
- pos += 3;
- } else {
- iter.next();
- iter.next();
- iter.next();
- pos += 4;
- }
- }
- }
-
- #[inline]
- fn final_lead_surrogate(&self) -> Option<u16> {
- match self.bytes {
- [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
- _ => None,
- }
- }
-
- #[inline]
- fn initial_trail_surrogate(&self) -> Option<u16> {
- match self.bytes {
- [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)),
- _ => None,
- }
- }
-
- pub fn clone_into(&self, buf: &mut Wtf8Buf) {
- buf.is_known_utf8 = false;
- self.bytes.clone_into(&mut buf.bytes);
- }
-
- /// Boxes this `Wtf8`.
- #[inline]
- pub fn into_box(&self) -> Box<Wtf8> {
- let boxed: Box<[u8]> = self.bytes.into();
- unsafe { mem::transmute(boxed) }
- }
-
- /// Creates a boxed, empty `Wtf8`.
- pub fn empty_box() -> Box<Wtf8> {
- let boxed: Box<[u8]> = Default::default();
- unsafe { mem::transmute(boxed) }
- }
-
- #[inline]
- pub fn into_arc(&self) -> Arc<Wtf8> {
- let arc: Arc<[u8]> = Arc::from(&self.bytes);
- unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) }
- }
-
- #[inline]
- pub fn into_rc(&self) -> Rc<Wtf8> {
- let rc: Rc<[u8]> = Rc::from(&self.bytes);
- unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) }
- }
-
- #[inline]
- pub fn make_ascii_lowercase(&mut self) {
- self.bytes.make_ascii_lowercase()
- }
-
- #[inline]
- pub fn make_ascii_uppercase(&mut self) {
- self.bytes.make_ascii_uppercase()
- }
-
- #[inline]
- pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
- Wtf8Buf { bytes: self.bytes.to_ascii_lowercase(), is_known_utf8: false }
- }
-
- #[inline]
- pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
- Wtf8Buf { bytes: self.bytes.to_ascii_uppercase(), is_known_utf8: false }
- }
-
- #[inline]
- pub fn is_ascii(&self) -> bool {
- self.bytes.is_ascii()
- }
-
- #[inline]
- pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
- self.bytes.eq_ignore_ascii_case(&other.bytes)
- }
-}
-
-/// Returns a slice of the given string for the byte range \[`begin`..`end`).
-///
-/// # Panics
-///
-/// Panics when `begin` and `end` do not point to code point boundaries,
-/// or point beyond the end of the string.
-impl ops::Index<ops::Range<usize>> for Wtf8 {
- type Output = Wtf8;
-
- #[inline]
- fn index(&self, range: ops::Range<usize>) -> &Wtf8 {
- // is_code_point_boundary checks that the index is in [0, .len()]
- if range.start <= range.end
- && is_code_point_boundary(self, range.start)
- && is_code_point_boundary(self, range.end)
- {
- unsafe { slice_unchecked(self, range.start, range.end) }
- } else {
- slice_error_fail(self, range.start, range.end)
- }
- }
-}
-
-/// Returns a slice of the given string from byte `begin` to its end.
-///
-/// # Panics
-///
-/// Panics when `begin` is not at a code point boundary,
-/// or is beyond the end of the string.
-impl ops::Index<ops::RangeFrom<usize>> for Wtf8 {
- type Output = Wtf8;
-
- #[inline]
- fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 {
- // is_code_point_boundary checks that the index is in [0, .len()]
- if is_code_point_boundary(self, range.start) {
- unsafe { slice_unchecked(self, range.start, self.len()) }
- } else {
- slice_error_fail(self, range.start, self.len())
- }
- }
-}
-
-/// Returns a slice of the given string from its beginning to byte `end`.
-///
-/// # Panics
-///
-/// Panics when `end` is not at a code point boundary,
-/// or is beyond the end of the string.
-impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
- type Output = Wtf8;
-
- #[inline]
- fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 {
- // is_code_point_boundary checks that the index is in [0, .len()]
- if is_code_point_boundary(self, range.end) {
- unsafe { slice_unchecked(self, 0, range.end) }
- } else {
- slice_error_fail(self, 0, range.end)
- }
- }
-}
-
-impl ops::Index<ops::RangeFull> for Wtf8 {
- type Output = Wtf8;
-
- #[inline]
- fn index(&self, _range: ops::RangeFull) -> &Wtf8 {
- self
- }
-}
-
-#[inline]
-fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
- // The first byte is assumed to be 0xED
- 0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F
-}
-
-#[inline]
-fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
- let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32);
- unsafe { char::from_u32_unchecked(code_point) }
-}
-
-/// Copied from str::is_char_boundary
-#[inline]
-pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
- if index == 0 {
- return true;
- }
- match slice.bytes.get(index) {
- None => index == slice.len(),
- Some(&b) => (b as i8) >= -0x40,
- }
-}
-
-/// Verify that `index` is at the edge of either a valid UTF-8 codepoint
-/// (i.e. a codepoint that's not a surrogate) or of the whole string.
-///
-/// These are the cases currently permitted by `OsStr::slice_encoded_bytes`.
-/// Splitting between surrogates is valid as far as WTF-8 is concerned, but
-/// we do not permit it in the public API because WTF-8 is considered an
-/// implementation detail.
-#[track_caller]
-#[inline]
-pub fn check_utf8_boundary(slice: &Wtf8, index: usize) {
- if index == 0 {
- return;
- }
- match slice.bytes.get(index) {
- Some(0xED) => (), // Might be a surrogate
- Some(&b) if (b as i8) >= -0x40 => return,
- Some(_) => panic!("byte index {index} is not a codepoint boundary"),
- None if index == slice.len() => return,
- None => panic!("byte index {index} is out of bounds"),
- }
- if slice.bytes[index + 1] >= 0xA0 {
- // There's a surrogate after index. Now check before index.
- if index >= 3 && slice.bytes[index - 3] == 0xED && slice.bytes[index - 2] >= 0xA0 {
- panic!("byte index {index} lies between surrogate codepoints");
- }
- }
-}
-
-/// Copied from core::str::raw::slice_unchecked
-#[inline]
-pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
- // SAFETY: memory layout of a &[u8] and &Wtf8 are the same
- unsafe {
- let len = end - begin;
- let start = s.as_bytes().as_ptr().add(begin);
- Wtf8::from_bytes_unchecked(slice::from_raw_parts(start, len))
- }
-}
-
-/// Copied from core::str::raw::slice_error_fail
-#[inline(never)]
-pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! {
- assert!(begin <= end);
- panic!("index {begin} and/or {end} in `{s:?}` do not lie on character boundary");
-}
-
-/// Iterator for the code points of a WTF-8 string.
-///
-/// Created with the method `.code_points()`.
-#[derive(Clone)]
-pub struct Wtf8CodePoints<'a> {
- bytes: slice::Iter<'a, u8>,
-}
-
-impl Iterator for Wtf8CodePoints<'_> {
- type Item = CodePoint;
-
- #[inline]
- fn next(&mut self) -> Option<CodePoint> {
- // SAFETY: `self.bytes` has been created from a WTF-8 string
- unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint { value: c }) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.bytes.len();
- (len.saturating_add(3) / 4, Some(len))
- }
-}
-
-/// Generates a wide character sequence for potentially ill-formed UTF-16.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct EncodeWide<'a> {
- code_points: Wtf8CodePoints<'a>,
- extra: u16,
-}
-
-// Copied from libunicode/u_str.rs
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for EncodeWide<'_> {
- type Item = u16;
-
- #[inline]
- fn next(&mut self) -> Option<u16> {
- if self.extra != 0 {
- let tmp = self.extra;
- self.extra = 0;
- return Some(tmp);
- }
-
- let mut buf = [0; MAX_LEN_UTF16];
- self.code_points.next().map(|code_point| {
- let n = encode_utf16_raw(code_point.value, &mut buf).len();
- if n == 2 {
- self.extra = buf[1];
- }
- buf[0]
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let (low, high) = self.code_points.size_hint();
- let ext = (self.extra != 0) as usize;
- // every code point gets either one u16 or two u16,
- // so this iterator is between 1 or 2 times as
- // long as the underlying iterator.
- (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext)))
- }
-}
-
-#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
-impl FusedIterator for EncodeWide<'_> {}
-
-impl Hash for CodePoint {
- #[inline]
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.value.hash(state)
- }
-}
-
-impl Hash for Wtf8Buf {
- #[inline]
- fn hash<H: Hasher>(&self, state: &mut H) {
- state.write(&self.bytes);
- 0xfeu8.hash(state)
- }
-}
-
-impl Hash for Wtf8 {
- #[inline]
- fn hash<H: Hasher>(&self, state: &mut H) {
- state.write(&self.bytes);
- 0xfeu8.hash(state)
- }
-}
-
-#[unstable(feature = "clone_to_uninit", issue = "126799")]
-unsafe impl CloneToUninit for Wtf8 {
- #[inline]
- #[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut u8) {
- // SAFETY: we're just a transparent wrapper around [u8]
- unsafe { self.bytes.clone_to_uninit(dst) }
- }
-}
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 07bb41f..84fbb4c 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -717,12 +717,7 @@ pub const fn duration(&self) -> Duration {
}
#[stable(feature = "time2", since = "1.8.0")]
-impl Error for SystemTimeError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "other time was not earlier than self"
- }
-}
+impl Error for SystemTimeError {}
#[stable(feature = "time2", since = "1.8.0")]
impl fmt::Display for SystemTimeError {
diff --git a/library/std/tests/sync/lazy_lock.rs b/library/std/tests/sync/lazy_lock.rs
index 6c14b79..68aeea8 100644
--- a/library/std/tests/sync/lazy_lock.rs
+++ b/library/std/tests/sync/lazy_lock.rs
@@ -34,16 +34,6 @@ fn default() -> Self {
}
#[test]
-#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
-fn lazy_poisoning() {
- let x: LazyCell<String> = LazyCell::new(|| panic!("kaboom"));
- for _ in 0..2 {
- let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len()));
- assert!(res.is_err());
- }
-}
-
-#[test]
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
fn sync_lazy_new() {
static CALLED: AtomicUsize = AtomicUsize::new(0);
@@ -123,16 +113,6 @@ fn xs() -> &'static Vec<i32> {
assert_eq!(xs(), &vec![1, 2, 3]);
}
-#[test]
-#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
-fn sync_lazy_poisoning() {
- let x: LazyLock<String> = LazyLock::new(|| panic!("kaboom"));
- for _ in 0..2 {
- let res = panic::catch_unwind(|| x.len());
- assert!(res.is_err());
- }
-}
-
// Check that we can infer `T` from closure's type.
#[test]
fn lazy_type_inference() {
@@ -146,17 +126,6 @@ fn assert_traits<T: Send + Sync>() {}
}
#[test]
-#[should_panic = "has previously been poisoned"]
-fn lazy_force_mut_panic() {
- let mut lazy = LazyLock::<String>::new(|| panic!());
- panic::catch_unwind(panic::AssertUnwindSafe(|| {
- let _ = LazyLock::force_mut(&mut lazy);
- }))
- .unwrap_err();
- let _ = &*lazy;
-}
-
-#[test]
fn lazy_force_mut() {
let s = "abc".to_owned();
let mut lazy = LazyLock::new(move || s);
@@ -165,3 +134,56 @@ fn lazy_force_mut() {
p.clear();
LazyLock::force_mut(&mut lazy);
}
+
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+fn lazy_poisoning() {
+ let x: LazyCell<String> = LazyCell::new(|| panic!("kaboom"));
+ for _ in 0..2 {
+ let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len()));
+ assert!(res.is_err());
+ }
+}
+
+/// Verifies that when a `LazyLock` is poisoned, it panics with the correct error message ("LazyLock
+/// instance has previously been poisoned") instead of the underlying `Once` error message.
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+#[should_panic(expected = "LazyLock instance has previously been poisoned")]
+fn lazy_lock_deref_panic() {
+ let lazy: LazyLock<String> = LazyLock::new(|| panic!("initialization failed"));
+
+ // First access will panic during initialization.
+ let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+ let _ = &*lazy;
+ }));
+
+ // Second access should panic with the poisoned message.
+ let _ = &*lazy;
+}
+
+#[test]
+#[should_panic(expected = "LazyLock instance has previously been poisoned")]
+fn lazy_lock_deref_mut_panic() {
+ let mut lazy: LazyLock<String> = LazyLock::new(|| panic!("initialization failed"));
+
+ // First access will panic during initialization.
+ let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+ let _ = LazyLock::force_mut(&mut lazy);
+ }));
+
+ // Second access should panic with the poisoned message.
+ let _ = &*lazy;
+}
+
+/// Verifies that when the initialization closure panics with a custom message, that message is
+/// preserved and not overridden by `LazyLock`.
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+#[should_panic(expected = "custom panic message from closure")]
+fn lazy_lock_preserves_closure_panic_message() {
+ let lazy: LazyLock<String> = LazyLock::new(|| panic!("custom panic message from closure"));
+
+ // This should panic with the original message from the closure.
+ let _ = &*lazy;
+}
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 40e0836..2ece53e 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -312,6 +312,12 @@
kernel, cputype, processor = uname.decode(default_encoding).split(maxsplit=2)
+ # ON NetBSD, use `uname -p` to set the CPU type
+ if kernel == "NetBSD":
+ cputype = (
+ subprocess.check_output(["uname", "-p"]).strip().decode(default_encoding)
+ )
+
# The goal here is to come up with the same triple as LLVM would,
# at least for the subset of platforms we're willing to target.
kerneltype_mapper = {
@@ -433,10 +439,16 @@
kernel = "linux-androideabi"
else:
kernel += "eabihf"
- elif cputype in {"armv7l", "armv8l"}:
+ elif cputype in {"armv6hf", "earmv6hf"}:
+ cputype = "armv6"
+ if kernel == "unknown-netbsd":
+ kernel += "-eabihf"
+ elif cputype in {"armv7l", "earmv7hf", "armv8l"}:
cputype = "armv7"
if kernel == "linux-android":
kernel = "linux-androideabi"
+ elif kernel == "unknown-netbsd":
+ kernel += "-eabihf"
else:
kernel += "eabihf"
elif cputype == "mips":
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 6ca32ac..0b75e85 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -26,7 +26,9 @@
use crate::core::builder::{
Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
};
-use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
+use crate::core::config::{
+ CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
+};
use crate::utils::build_stamp;
use crate::utils::build_stamp::BuildStamp;
use crate::utils::exec::command;
@@ -96,10 +98,20 @@ fn copy_extra_objects(
}
deps
}
+
+ /// Returns true if the standard library should be uplifted from stage 1.
+ ///
+ /// Uplifting is enabled if we're building a stage2+ libstd and full bootstrap is
+ /// disabled.
+ pub fn should_be_uplifted_from_stage_1(builder: &Builder<'_>, stage: u32) -> bool {
+ stage > 1 && !builder.config.full_bootstrap
+ }
}
impl Step for Std {
- type Output = ();
+ /// Build stamp of std, if it was indeed built or uplifted.
+ type Output = Option<BuildStamp>;
+
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -122,7 +134,9 @@ fn make_run(run: RunConfig<'_>) {
trace!(force_recompile);
run.builder.ensure(Std {
- build_compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
+ // Note: we don't use compiler_for_std here, so that `x build library --stage 2`
+ // builds a stage2 rustc.
+ build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target),
target: run.target,
crates,
force_recompile,
@@ -136,15 +150,20 @@ fn make_run(run: RunConfig<'_>) {
/// This will build the standard library for a particular stage of the build
/// using the `compiler` targeting the `target` architecture. The artifacts
/// created will also be linked into the sysroot directory.
- fn run(self, builder: &Builder<'_>) {
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
let target = self.target;
- // We already have std ready to be used for stage 0.
- if self.build_compiler.stage == 0 {
+ // In most cases, we already have the std ready to be used for stage 0.
+ // However, if we are doing a local rebuild (so the build compiler can compile the standard
+ // library even on stage 0), and we're cross-compiling (so the stage0 standard library for
+ // *target* is not available), we still allow the stdlib to be built here.
+ if self.build_compiler.stage == 0
+ && !(builder.local_rebuild && target != builder.host_target)
+ {
let compiler = self.build_compiler;
builder.ensure(StdLink::from_std(self, compiler));
- return;
+ return None;
}
let build_compiler = if builder.download_rustc() && self.force_recompile {
@@ -169,7 +188,7 @@ fn run(self, builder: &Builder<'_>) {
&sysroot,
builder.config.ci_rust_std_contents(),
);
- return;
+ return None;
}
if builder.config.keep_stage.contains(&build_compiler.stage)
@@ -185,7 +204,7 @@ fn run(self, builder: &Builder<'_>) {
self.copy_extra_objects(builder, &build_compiler, target);
builder.ensure(StdLink::from_std(self, build_compiler));
- return;
+ return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
}
let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
@@ -193,24 +212,9 @@ fn run(self, builder: &Builder<'_>) {
// Stage of the stdlib that we're building
let stage = build_compiler.stage;
- // If we're building a stage2+ libstd, full bootstrap is
- // disabled and we have a stage1 libstd already compiled for the given target,
- // then simply uplift a previously built stage1 library.
- if build_compiler.stage > 1
- && !builder.config.full_bootstrap
- // This estimates if a stage1 libstd exists for the given target. If we're not
- // cross-compiling, it should definitely exist by the time we're building a stage2
- // libstd.
- // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
- // rustc needs to link to a cross-compiled libstd, so again we should have a stage1
- // libstd for the given target prepared.
- // Even if we guess wrong in the cross-compiled case, the worst that should happen is
- // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
- // don't pay the libstd build cost twice.
- && (target == builder.host_target || builder.config.hosts.contains(&target))
- {
+ if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) {
let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
- builder.std(build_compiler_for_std_to_uplift, target);
+ let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
let msg = if build_compiler_for_std_to_uplift.host == target {
format!(
@@ -231,7 +235,7 @@ fn run(self, builder: &Builder<'_>) {
self.copy_extra_objects(builder, &build_compiler, target);
builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
- return;
+ return stage_1_stamp;
}
target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
@@ -284,11 +288,13 @@ fn run(self, builder: &Builder<'_>) {
build_compiler,
target,
);
+
+ let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
run_cargo(
builder,
cargo,
vec![],
- &build_stamp::libstd_stamp(builder, build_compiler, target),
+ &stamp,
target_deps,
self.is_for_mir_opt_tests, // is_check
false,
@@ -298,6 +304,7 @@ fn run(self, builder: &Builder<'_>) {
self,
builder.compiler(build_compiler.stage, builder.config.host_target),
));
+ Some(stamp)
}
fn metadata(&self) -> Option<StepMetadata> {
@@ -560,29 +567,36 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
// If `compiler-rt` is available ensure that the `c` feature of the
// `compiler-builtins` crate is enabled and it's configured to learn where
// `compiler-rt` is located.
- let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
- // NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce `submodules = false`, so this is a no-op.
- // But, the user could still decide to manually use an in-tree submodule.
- //
- // NOTE: if we're using system llvm, we'll end up building a version of `compiler-rt` that doesn't match the LLVM we're linking to.
- // That's probably ok? At least, the difference wasn't enforced before. There's a comment in
- // the compiler_builtins build script that makes me nervous, though:
- // https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
- builder.require_submodule(
- "src/llvm-project",
- Some(
- "The `build.optimized-compiler-builtins` config option \
- requires `compiler-rt` sources from LLVM.",
- ),
- );
- let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
- assert!(compiler_builtins_root.exists());
- // The path to `compiler-rt` is also used by `profiler_builtins` (above),
- // so if you're changing something here please also change that as appropriate.
- cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
- " compiler-builtins-c"
- } else {
- ""
+ let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
+ CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
+ cargo.env("LLVM_COMPILER_RT_LIB", path);
+ " compiler-builtins-c"
+ }
+ CompilerBuiltins::BuildLLVMFuncs => {
+ // NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce
+ // `submodules = false`, so this is a no-op. But, the user could still decide to
+ // manually use an in-tree submodule.
+ //
+ // NOTE: if we're using system llvm, we'll end up building a version of `compiler-rt`
+ // that doesn't match the LLVM we're linking to. That's probably ok? At least, the
+ // difference wasn't enforced before. There's a comment in the compiler_builtins build
+ // script that makes me nervous, though:
+ // https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
+ builder.require_submodule(
+ "src/llvm-project",
+ Some(
+ "The `build.optimized-compiler-builtins` config option \
+ requires `compiler-rt` sources from LLVM.",
+ ),
+ );
+ let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
+ assert!(compiler_builtins_root.exists());
+ // The path to `compiler-rt` is also used by `profiler_builtins` (above),
+ // so if you're changing something here please also change that as appropriate.
+ cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
+ " compiler-builtins-c"
+ }
+ CompilerBuiltins::BuildRustOnly => "",
};
// `libtest` uses this to know whether or not to support
@@ -1309,9 +1323,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
cargo.env("CFG_OMIT_GIT_HASH", "1");
}
- if let Some(backend) = builder.config.default_codegen_backend(target) {
- cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
- }
+ cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
let target_config = builder.config.target_config.get(&target);
@@ -2008,6 +2020,7 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
let host_llvm_bin_dir = command(&host_llvm_config)
.arg("--bindir")
+ .cached()
.run_capture_stdout(builder)
.stdout()
.trim()
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index daac75c..f113dd7 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -21,7 +21,9 @@
use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name};
use crate::core::build_steps::doc::DocumentationFormat;
-use crate::core::build_steps::tool::{self, RustcPrivateCompilers, Tool};
+use crate::core::build_steps::tool::{
+ self, RustcPrivateCompilers, Tool, ToolTargetBuildMode, get_tool_target_compiler,
+};
use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
use crate::core::build_steps::{compile, llvm};
use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
@@ -75,7 +77,10 @@ fn make_run(run: RunConfig<'_>) {
/// Builds the `rust-docs` installer component.
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let host = self.host;
- builder.default_doc(&[]);
+ // FIXME: explicitly enumerate the steps that should be executed here, and gather their
+ // documentation, rather than running all default steps and then read their output
+ // from a shared directory.
+ builder.run_default_doc_steps();
let dest = "share/doc/rust/html";
@@ -91,6 +96,8 @@ fn metadata(&self) -> Option<StepMetadata> {
}
}
+/// Builds the `rust-docs-json` installer component.
+/// It contains the documentation of the standard library in JSON format.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct JsonDocs {
build_compiler: Compiler,
@@ -108,12 +115,11 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(JsonDocs {
- build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
+ build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
target: run.target,
});
}
- /// Builds the `rust-docs-json` installer component.
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let target = self.target;
let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
@@ -130,15 +136,26 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
tarball.add_bulk_dir(directory, dest);
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler))
+ }
}
+/// Builds the `rustc-docs` installer component.
+/// Apart from the documentation of the `rustc_*` crates, it also includes the documentation of
+/// various in-tree helper tools (bootstrap, build_helper, tidy),
+/// and also rustc_private tools like rustdoc, clippy, miri or rustfmt.
+///
+/// It is currently hosted at <https://doc.rust-lang.org/nightly/nightly-rustc>.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct RustcDocs {
- pub host: TargetSelection,
+ target: TargetSelection,
}
impl Step for RustcDocs {
- type Output = Option<GeneratedTarball>;
+ type Output = GeneratedTarball;
+
const DEFAULT: bool = true;
const IS_HOST: bool = true;
@@ -148,18 +165,17 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(RustcDocs { host: run.target });
+ run.builder.ensure(RustcDocs { target: run.target });
}
- /// Builds the `rustc-docs` installer component.
- fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
- let host = self.host;
- builder.default_doc(&[]);
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let target = self.target;
+ builder.run_default_doc_steps();
- let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
+ let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
tarball.set_product_name("Rustc Documentation");
- tarball.add_bulk_dir(builder.compiler_doc_out(host), "share/doc/rust/html/rustc");
- Some(tarball.generate())
+ tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc");
+ tarball.generate()
}
}
@@ -354,9 +370,13 @@ fn get_cc_search_dirs(
(bin_path, lib_path)
}
+/// Builds the `rust-mingw` installer component.
+///
+/// This contains all the bits and pieces to run the MinGW Windows targets
+/// without any extra installed software (e.g., we bundle gcc, libraries, etc.).
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Mingw {
- pub host: TargetSelection,
+ target: TargetSelection,
}
impl Step for Mingw {
@@ -368,39 +388,46 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(Mingw { host: run.target });
+ run.builder.ensure(Mingw { target: run.target });
}
- /// Builds the `rust-mingw` installer component.
- ///
- /// This contains all the bits and pieces to run the MinGW Windows targets
- /// without any extra installed software (e.g., we bundle gcc, libraries, etc).
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
- let host = self.host;
- if !host.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
+ let target = self.target;
+ if !target.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
return None;
}
- let mut tarball = Tarball::new(builder, "rust-mingw", &host.triple);
+ let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
tarball.set_product_name("Rust MinGW");
- make_win_dist(tarball.image_dir(), host, builder);
+ make_win_dist(tarball.image_dir(), target, builder);
Some(tarball.generate())
}
fn metadata(&self) -> Option<StepMetadata> {
- Some(StepMetadata::dist("mingw", self.host))
+ Some(StepMetadata::dist("mingw", self.target))
}
}
+/// Creates the `rustc` installer component.
+///
+/// This includes:
+/// - The compiler and LLVM.
+/// - Debugger scripts.
+/// - Various helper tools, e.g. LLD or Rust Analyzer proc-macro server (if enabled).
+/// - The licenses of all code used by the compiler.
+///
+/// It does not include any standard library.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Rustc {
- pub compiler: Compiler,
+ /// This is the compiler that we will *ship* in this dist step.
+ pub target_compiler: Compiler,
}
impl Step for Rustc {
type Output = GeneratedTarball;
+
const DEFAULT: bool = true;
const IS_HOST: bool = true;
@@ -409,19 +436,19 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
- run.builder
- .ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.target) });
+ run.builder.ensure(Rustc {
+ target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
+ });
}
- /// Creates the `rustc` installer component.
fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
- let compiler = self.compiler;
- let host = self.compiler.host;
+ let target_compiler = self.target_compiler;
+ let target = self.target_compiler.host;
- let tarball = Tarball::new(builder, "rustc", &host.triple);
+ let tarball = Tarball::new(builder, "rustc", &target.triple);
// Prepare the rustc "image", what will actually end up getting installed
- prepare_image(builder, compiler, tarball.image_dir());
+ prepare_image(builder, target_compiler, tarball.image_dir());
// On MinGW we've got a few runtime DLL dependencies that we need to
// include.
@@ -430,16 +457,16 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
// anything requiring us to distribute a license, but it's likely the
// install will *also* include the rust-mingw package, which also needs
// licenses, so to be safe we just include it here in all MinGW packages.
- if host.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
- runtime_dll_dist(tarball.image_dir(), host, builder);
+ if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
+ runtime_dll_dist(tarball.image_dir(), target, builder);
tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
}
return tarball.generate();
- fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
- let host = compiler.host;
- let src = builder.sysroot(compiler);
+ fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
+ let target = target_compiler.host;
+ let src = builder.sysroot(target_compiler);
// Copy rustc binary
t!(fs::create_dir_all(image.join("bin")));
@@ -452,17 +479,11 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
.as_ref()
.is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
{
- let rustdoc = builder.rustdoc_for_compiler(compiler);
+ let rustdoc = builder.rustdoc_for_compiler(target_compiler);
builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
}
- let ra_proc_macro_srv_compiler =
- builder.compiler_for(compiler.stage, builder.config.host_target, compiler.host);
- let compilers = RustcPrivateCompilers::from_build_compiler(
- builder,
- ra_proc_macro_srv_compiler,
- compiler.host,
- );
+ let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
@@ -472,11 +493,11 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
}
- let libdir_relative = builder.libdir_relative(compiler);
+ let libdir_relative = builder.libdir_relative(target_compiler);
// Copy runtime DLLs needed by the compiler
if libdir_relative.to_str() != Some("bin") {
- let libdir = builder.rustc_libdir(compiler);
+ let libdir = builder.rustc_libdir(target_compiler);
for entry in builder.read_dir(&libdir) {
// A safeguard that we will not ship libgccjit.so from the libdir, in case the
// GCC codegen backend is enabled by default.
@@ -503,15 +524,15 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
// components like the llvm tools and LLD. LLD is included below and
// tools/LLDB come later, so let's just throw it in the rustc
// component for now.
- maybe_install_llvm_runtime(builder, host, image);
+ maybe_install_llvm_runtime(builder, target, image);
- let dst_dir = image.join("lib/rustlib").join(host).join("bin");
+ let dst_dir = image.join("lib/rustlib").join(target).join("bin");
t!(fs::create_dir_all(&dst_dir));
// Copy over lld if it's there
if builder.config.lld_enabled {
- let src_dir = builder.sysroot_target_bindir(compiler, host);
- let rust_lld = exe("rust-lld", compiler.host);
+ let src_dir = builder.sysroot_target_bindir(target_compiler, target);
+ let rust_lld = exe("rust-lld", target_compiler.host);
builder.copy_link(
&src_dir.join(&rust_lld),
&dst_dir.join(&rust_lld),
@@ -521,7 +542,7 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
t!(fs::create_dir(&self_contained_lld_dst_dir));
for name in crate::LLD_FILE_NAMES {
- let exe_name = exe(name, compiler.host);
+ let exe_name = exe(name, target_compiler.host);
builder.copy_link(
&self_contained_lld_src_dir.join(&exe_name),
&self_contained_lld_dst_dir.join(&exe_name),
@@ -530,10 +551,12 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
}
}
- if builder.config.llvm_enabled(compiler.host) && builder.config.llvm_tools_enabled {
- let src_dir = builder.sysroot_target_bindir(compiler, host);
- let llvm_objcopy = exe("llvm-objcopy", compiler.host);
- let rust_objcopy = exe("rust-objcopy", compiler.host);
+ if builder.config.llvm_enabled(target_compiler.host)
+ && builder.config.llvm_tools_enabled
+ {
+ let src_dir = builder.sysroot_target_bindir(target_compiler, target);
+ let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
+ let rust_objcopy = exe("rust-objcopy", target_compiler.host);
builder.copy_link(
&src_dir.join(&llvm_objcopy),
&dst_dir.join(&rust_objcopy),
@@ -542,8 +565,8 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
}
if builder.tool_enabled("wasm-component-ld") {
- let src_dir = builder.sysroot_target_bindir(compiler, host);
- let ld = exe("wasm-component-ld", compiler.host);
+ let src_dir = builder.sysroot_target_bindir(target_compiler, target);
+ let ld = exe("wasm-component-ld", target_compiler.host);
builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
}
@@ -564,7 +587,7 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
}
// Debugger scripts
- builder.ensure(DebuggerScripts { sysroot: image.to_owned(), host });
+ builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
// HTML copyright files
let file_list = builder.ensure(super::run::GenerateCopyright);
@@ -590,14 +613,16 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
}
fn metadata(&self) -> Option<StepMetadata> {
- Some(StepMetadata::dist("rustc", self.compiler.host))
+ Some(StepMetadata::dist("rustc", self.target_compiler.host))
}
}
+/// Copies debugger scripts for `target` into the given compiler `sysroot`.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct DebuggerScripts {
+ /// Sysroot of a compiler into which will the debugger scripts be copied to.
pub sysroot: PathBuf,
- pub host: TargetSelection,
+ pub target: TargetSelection,
}
impl Step for DebuggerScripts {
@@ -607,16 +632,15 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.never()
}
- /// Copies debugger scripts for `target` into the `sysroot` specified.
fn run(self, builder: &Builder<'_>) {
- let host = self.host;
+ let target = self.target;
let sysroot = self.sysroot;
let dst = sysroot.join("lib/rustlib/etc");
t!(fs::create_dir_all(&dst));
let cp_debugger_script = |file: &str| {
builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
};
- if host.contains("windows-msvc") {
+ if target.contains("windows-msvc") {
// windbg debugger scripts
builder.install(
&builder.src.join("src/etc/rust-windbg.cmd"),
@@ -730,12 +754,25 @@ fn copy_target_libs(
}
}
+/// Builds the standard library (`rust-std`) dist component for a given `target`.
+/// This includes the standard library dynamic library file (e.g. .so/.dll), along with stdlib
+/// .rlibs.
+///
+/// Note that due to uplifting, we actually ship the stage 1 library
+/// (built using the stage1 compiler) even with a stage 2 dist, unless `full-bootstrap` is enabled.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Std {
- pub compiler: Compiler,
+ /// Compiler that will build the standard library.
+ pub build_compiler: Compiler,
pub target: TargetSelection,
}
+impl Std {
+ pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
+ Std { build_compiler: builder.compiler_for_std(builder.top_stage), target }
+ }
+}
+
impl Step for Std {
type Output = Option<GeneratedTarball>;
const DEFAULT: bool = true;
@@ -745,31 +782,25 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(Std {
- compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
- ),
- target: run.target,
- });
+ run.builder.ensure(Std::new(run.builder, run.target));
}
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
- let compiler = self.compiler;
+ let build_compiler = self.build_compiler;
let target = self.target;
- if skip_host_target_lib(builder, compiler) {
+ if skip_host_target_lib(builder, build_compiler) {
return None;
}
- builder.std(compiler, target);
+ // It's possible that std was uplifted and thus built with a different build compiler
+ // So we need to read the stamp that was actually generated when std was built
+ let stamp =
+ builder.std(build_compiler, target).expect("Standard library has to be built for dist");
let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
tarball.include_target_in_component_name(true);
- let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
- let stamp = build_stamp::libstd_stamp(builder, compiler_to_use, target);
verify_uefi_rlib_format(builder, target, &stamp);
copy_target_libs(builder, target, tarball.image_dir(), &stamp);
@@ -777,7 +808,7 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
}
fn metadata(&self) -> Option<StepMetadata> {
- Some(StepMetadata::dist("std", self.target).built_by(self.compiler))
+ Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
}
}
@@ -787,8 +818,9 @@ fn metadata(&self) -> Option<StepMetadata> {
/// (Don't confuse this with [`RustDev`], without the `c`!)
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct RustcDev {
- pub compiler: Compiler,
- pub target: TargetSelection,
+ /// The compiler that will build rustc which will be shipped in this component.
+ build_compiler: Compiler,
+ target: TargetSelection,
}
impl Step for RustcDev {
@@ -802,28 +834,27 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(RustcDev {
- compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
- ),
+ // We currently always ship a stage 2 rustc-dev component, so we build it with the
+ // stage 1 compiler. This might change in the future.
+ // The precise stage used here is important, so we hard-code it.
+ build_compiler: run.builder.compiler(1, run.builder.config.host_target),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
- let compiler = self.compiler;
+ let build_compiler = self.build_compiler;
let target = self.target;
- if skip_host_target_lib(builder, compiler) {
+ if skip_host_target_lib(builder, build_compiler) {
return None;
}
- builder.ensure(compile::Rustc::new(compiler, target));
+ // Build the compiler that we will ship
+ builder.ensure(compile::Rustc::new(build_compiler, target));
let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
- let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
- let stamp = build_stamp::librustc_stamp(builder, compiler_to_use, target);
+ let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
copy_target_libs(builder, target, tarball.image_dir(), &stamp);
let src_files = &["Cargo.lock"];
@@ -847,16 +878,25 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
+ }
}
+/// The `rust-analysis` component used to create a tarball of save-analysis metadata.
+///
+/// This component has been deprecated and its contents now only include a warning about
+/// its non-availability.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Analysis {
- pub compiler: Compiler,
- pub target: TargetSelection,
+ build_compiler: Compiler,
+ target: TargetSelection,
}
impl Step for Analysis {
type Output = Option<GeneratedTarball>;
+
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -865,24 +905,17 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
+ // The step just produces a deprecation notice, so we just hardcode stage 1
run.builder.ensure(Analysis {
- // Find the actual compiler (handling the full bootstrap option) which
- // produced the save-analysis data because that data isn't copied
- // through the sysroot uplifting.
- compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
- ),
+ build_compiler: run.builder.compiler(1, run.builder.config.host_target),
target: run.target,
});
}
- /// Creates a tarball of (degenerate) save-analysis metadata, if available.
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
- let compiler = self.compiler;
+ let compiler = self.build_compiler;
let target = self.target;
- if !builder.config.is_host_target(compiler.host) {
+ if skip_host_target_lib(builder, compiler) {
return None;
}
@@ -905,6 +938,10 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
+ }
}
/// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
@@ -1251,10 +1288,9 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Cargo {
- build_compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
+ build_compiler: get_tool_target_compiler(
+ run.builder,
+ ToolTargetBuildMode::Build(run.target),
),
target: run.target,
});
@@ -1285,11 +1321,16 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
+ }
}
+/// Distribute the rust-analyzer component, which is used as a LSP by various IDEs.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct RustAnalyzer {
- pub build_compiler: Compiler,
+ pub compilers: RustcPrivateCompilers,
pub target: TargetSelection,
}
@@ -1305,21 +1346,14 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(RustAnalyzer {
- build_compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
- ),
+ compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let target = self.target;
- let compilers =
- RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
-
- let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(compilers));
+ let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
tarball.set_overlay(OverlayKind::RustAnalyzer);
@@ -1328,11 +1362,18 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(
+ StepMetadata::dist("rust-analyzer", self.target)
+ .built_by(self.compilers.build_compiler()),
+ )
+ }
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Clippy {
- pub build_compiler: Compiler,
+ pub compilers: RustcPrivateCompilers,
pub target: TargetSelection,
}
@@ -1348,25 +1389,19 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Clippy {
- build_compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
- ),
+ compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let target = self.target;
- let compilers =
- RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
// Prepare the image directory
// We expect clippy to build, because we've exited this step above if tool
// state for clippy isn't testing.
- let clippy = builder.ensure(tool::Clippy::from_compilers(compilers));
- let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(compilers));
+ let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
+ let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
let mut tarball = Tarball::new(builder, "clippy", &target.triple);
tarball.set_overlay(OverlayKind::Clippy);
@@ -1376,11 +1411,15 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
tarball.add_legal_and_readme_to("share/doc/clippy");
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
+ }
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Miri {
- pub build_compiler: Compiler,
+ pub compilers: RustcPrivateCompilers,
pub target: TargetSelection,
}
@@ -1396,11 +1435,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Miri {
- build_compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
- ),
+ compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
target: run.target,
});
}
@@ -1413,10 +1448,8 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
return None;
}
- let compilers =
- RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
- let miri = builder.ensure(tool::Miri::from_compilers(compilers));
- let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(compilers));
+ let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
+ let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
tarball.set_overlay(OverlayKind::Miri);
@@ -1426,11 +1459,15 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
tarball.add_legal_and_readme_to("share/doc/miri");
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
+ }
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct CraneliftCodegenBackend {
- pub build_compiler: Compiler,
+ pub compilers: RustcPrivateCompilers,
pub target: TargetSelection,
}
@@ -1454,11 +1491,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(CraneliftCodegenBackend {
- build_compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
- ),
+ compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
target: run.target,
});
}
@@ -1472,8 +1505,6 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
}
let target = self.target;
- let compilers =
- RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
if !target_supports_cranelift_backend(target) {
builder.info("target not supported by rustc_codegen_cranelift. skipping");
return None;
@@ -1484,6 +1515,7 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
tarball.is_preview(true);
tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
+ let compilers = self.compilers;
let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
if builder.config.dry_run() {
@@ -1513,15 +1545,15 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
fn metadata(&self) -> Option<StepMetadata> {
Some(
- StepMetadata::dist("rustc_codegen_cranelift", self.build_compiler.host)
- .built_by(self.build_compiler),
+ StepMetadata::dist("rustc_codegen_cranelift", self.target)
+ .built_by(self.compilers.build_compiler()),
)
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Rustfmt {
- pub build_compiler: Compiler,
+ pub compilers: RustcPrivateCompilers,
pub target: TargetSelection,
}
@@ -1537,21 +1569,14 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Rustfmt {
- build_compiler: run.builder.compiler_for(
- run.builder.top_stage,
- run.builder.config.host_target,
- run.target,
- ),
+ compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
- let compilers =
- RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
-
- let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(compilers));
- let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(compilers));
+ let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
+ let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
tarball.set_overlay(OverlayKind::Rustfmt);
@@ -1561,12 +1586,16 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
tarball.add_legal_and_readme_to("share/doc/rustfmt");
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
+ }
}
+/// Extended archive that contains the compiler, standard library and a bunch of tools.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Extended {
- stage: u32,
- host: TargetSelection,
+ build_compiler: Compiler,
target: TargetSelection,
}
@@ -1582,8 +1611,9 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Extended {
- stage: run.builder.top_stage,
- host: run.builder.config.host_target,
+ build_compiler: run
+ .builder
+ .compiler(run.builder.top_stage - 1, run.builder.host_target),
target: run.target,
});
}
@@ -1591,10 +1621,7 @@ fn make_run(run: RunConfig<'_>) {
/// Creates a combined installer for the specified target in the provided stage.
fn run(self, builder: &Builder<'_>) {
let target = self.target;
- let stage = self.stage;
- let compiler = builder.compiler_for(self.stage, self.host, self.target);
-
- builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
+ builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
let mut tarballs = Vec::new();
let mut built_tools = HashSet::new();
@@ -1607,34 +1634,38 @@ macro_rules! add_component {
};
}
- let target_compiler = builder.compiler(stage, target);
+ let rustc_private_compilers =
+ RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
+ let build_compiler = rustc_private_compilers.build_compiler();
+ let target_compiler = rustc_private_compilers.target_compiler();
+
// When rust-std package split from rustc, we needed to ensure that during
// upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
// the std files during uninstall. To do this ensure that rustc comes
// before rust-std in the list below.
- tarballs.push(builder.ensure(Rustc { compiler: target_compiler }));
- tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
+ tarballs.push(builder.ensure(Rustc { target_compiler }));
+ tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
if target.is_windows_gnu() {
- tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
+ tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
}
add_component!("rust-docs" => Docs { host: target });
// Std stage N is documented with compiler stage N
add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
- add_component!("cargo" => Cargo { build_compiler: compiler, target });
- add_component!("rustfmt" => Rustfmt { build_compiler: compiler, target });
- add_component!("rust-analyzer" => RustAnalyzer { build_compiler: compiler, target });
+ add_component!("cargo" => Cargo { build_compiler, target });
+ add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
+ add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
add_component!("llvm-components" => LlvmTools { target });
- add_component!("clippy" => Clippy { build_compiler: compiler, target });
- add_component!("miri" => Miri { build_compiler: compiler, target });
- add_component!("analysis" => Analysis { compiler, target });
+ add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
+ add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
+ add_component!("analysis" => Analysis { build_compiler, target });
add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
- build_compiler: compiler,
+ compilers: rustc_private_compilers,
target
});
add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
- build_compiler: compiler,
+ build_compiler,
target
});
@@ -2100,6 +2131,10 @@ fn filter(contents: &str, marker: &str) -> String {
}
}
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
+ }
}
fn add_env(
@@ -2236,6 +2271,7 @@ fn maybe_install_llvm(
{
trace!("LLVM already built, installing LLVM files");
let mut cmd = command(host_llvm_config);
+ cmd.cached();
cmd.arg("--libfiles");
builder.verbose(|| println!("running {cmd:?}"));
let files = cmd.run_capture_stdout(builder).stdout();
@@ -2562,15 +2598,17 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
/// Tarball intended for internal consumption to ease rustc/std development.
///
+/// It only packages the binaries that were already compiled when bootstrap itself was built.
+///
/// Should not be considered stable by end users.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Bootstrap {
- pub target: TargetSelection,
+ target: TargetSelection,
}
impl Step for Bootstrap {
type Output = Option<GeneratedTarball>;
- const DEFAULT: bool = false;
+
const IS_HOST: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -2597,6 +2635,10 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
Some(tarball.generate())
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("bootstrap", self.target))
+ }
}
/// Tarball containing a prebuilt version of the build-manifest tool, intended to be used by the
@@ -2605,12 +2647,12 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
/// Should not be considered stable by end users.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct BuildManifest {
- pub target: TargetSelection,
+ target: TargetSelection,
}
impl Step for BuildManifest {
type Output = GeneratedTarball;
- const DEFAULT: bool = false;
+
const IS_HOST: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -2628,16 +2670,20 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
tarball.add_file(&build_manifest, "bin", FileType::Executable);
tarball.generate()
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("build-manifest", self.target))
+ }
}
/// Tarball containing artifacts necessary to reproduce the build of rustc.
///
-/// Currently this is the PGO profile data.
+/// Currently this is the PGO (and possibly BOLT) profile data.
///
/// Should not be considered stable by end users.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ReproducibleArtifacts {
- pub target: TargetSelection,
+ target: TargetSelection,
}
impl Step for ReproducibleArtifacts {
@@ -2670,6 +2716,10 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
}
if added_anything { Some(tarball.generate()) } else { None }
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("reproducible-artifacts", self.target))
+ }
}
/// Tarball containing a prebuilt version of the libgccjit library,
@@ -2677,7 +2727,7 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
/// backend needing a prebuilt libLLVM).
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Gcc {
- pub target: TargetSelection,
+ target: TargetSelection,
}
impl Step for Gcc {
@@ -2697,4 +2747,8 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
tarball.generate()
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::dist("gcc", self.target))
+ }
}
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 7fe19c0..9ef1fee 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -616,7 +616,7 @@ fn make_run(run: RunConfig<'_>) {
return;
}
run.builder.ensure(Std {
- build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
+ build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
target: run.target,
format: if run.builder.config.cmd.json() {
DocumentationFormat::Json
@@ -784,7 +784,7 @@ fn doc_std(
let description =
format!("library{} in {} format", crate_description(requested_crates), format.as_str());
- let _guard = builder.msg(Kind::Doc, description, None, build_compiler, target);
+ let _guard = builder.msg(Kind::Doc, description, Mode::Std, build_compiler, target);
cargo.into_cmd().run(builder);
builder.cp_link_r(&out_dir, out);
@@ -994,7 +994,7 @@ fn make_run(run: RunConfig<'_>) {
(compilers.build_compiler(), Mode::ToolRustc)
} else {
// bootstrap/host tools have to be documented with the stage 0 compiler
- (prepare_doc_compiler(run.builder, target, 1), Mode::ToolBootstrap)
+ (prepare_doc_compiler(run.builder, run.builder.host_target, 1), Mode::ToolBootstrap)
};
run.builder.ensure($tool { build_compiler, mode, target });
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 4457258..ce68dbf 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -7,6 +7,7 @@
use std::{env, fs};
use crate::core::build_steps::dist;
+use crate::core::build_steps::tool::RustcPrivateCompilers;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::core::config::{Config, TargetSelection};
use crate::utils::exec::command;
@@ -64,17 +65,14 @@ fn is_dir_writable_for_user(dir: &Path) -> bool {
fn install_sh(
builder: &Builder<'_>,
package: &str,
- stage: u32,
- host: Option<TargetSelection>,
+ build_compiler: impl Into<Option<Compiler>>,
+ target: Option<TargetSelection>,
tarball: &GeneratedTarball,
) {
- let _guard = builder.msg(
- Kind::Install,
- package,
- None,
- (host.unwrap_or(builder.host_target), stage),
- host,
- );
+ let _guard = match build_compiler.into() {
+ Some(build_compiler) => builder.msg(Kind::Install, package, None, build_compiler, target),
+ None => builder.msg_unstaged(Kind::Install, package, target.unwrap_or(builder.host_target)),
+ };
let prefix = default_path(&builder.config.prefix, "/usr/local");
let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
@@ -166,10 +164,10 @@ macro_rules! install {
IS_HOST: $IS_HOST:expr,
$run_item:block $(, $c:ident)*;)+) => {
$(
- #[derive(Debug, Clone, Hash, PartialEq, Eq)]
+ #[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct $name {
- pub compiler: Compiler,
- pub target: TargetSelection,
+ build_compiler: Compiler,
+ target: TargetSelection,
}
impl $name {
@@ -193,7 +191,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure($name {
- compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
+ build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.builder.config.host_target),
target: run.target,
});
}
@@ -208,96 +206,95 @@ fn run($sel, $builder: &Builder<'_>) {
install!((self, builder, _config),
Docs, path = "src/doc", _config.docs, IS_HOST: false, {
let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
- install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
+ install_sh(builder, "docs", self.build_compiler, Some(self.target), &tarball);
};
Std, path = "library/std", true, IS_HOST: false, {
// `expect` should be safe, only None when host != build, but this
// only runs when host == build
- let tarball = builder.ensure(dist::Std {
- compiler: self.compiler,
- target: self.target
- }).expect("missing std");
- install_sh(builder, "std", self.compiler.stage, Some(self.target), &tarball);
+ let std = dist::Std::new(builder, self.target);
+ let build_compiler = std.build_compiler;
+ let tarball = builder.ensure(std).expect("missing std");
+ install_sh(builder, "std", build_compiler, Some(self.target), &tarball);
};
Cargo, alias = "cargo", Self::should_build(_config), IS_HOST: true, {
let tarball = builder
- .ensure(dist::Cargo { build_compiler: self.compiler, target: self.target })
+ .ensure(dist::Cargo { build_compiler: self.build_compiler, target: self.target })
.expect("missing cargo");
- install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
+ install_sh(builder, "cargo", self.build_compiler, Some(self.target), &tarball);
};
RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), IS_HOST: true, {
if let Some(tarball) =
- builder.ensure(dist::RustAnalyzer { build_compiler: self.compiler, target: self.target })
+ builder.ensure(dist::RustAnalyzer { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target), target: self.target })
{
- install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
+ install_sh(builder, "rust-analyzer", self.build_compiler, Some(self.target), &tarball);
} else {
builder.info(
- &format!("skipping Install rust-analyzer stage{} ({})", self.compiler.stage, self.target),
+ &format!("skipping Install rust-analyzer stage{} ({})", self.build_compiler.stage + 1, self.target),
);
}
};
Clippy, alias = "clippy", Self::should_build(_config), IS_HOST: true, {
let tarball = builder
- .ensure(dist::Clippy { build_compiler: self.compiler, target: self.target })
+ .ensure(dist::Clippy { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target), target: self.target })
.expect("missing clippy");
- install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
+ install_sh(builder, "clippy", self.build_compiler, Some(self.target), &tarball);
};
Miri, alias = "miri", Self::should_build(_config), IS_HOST: true, {
- if let Some(tarball) = builder.ensure(dist::Miri { build_compiler: self.compiler, target: self.target }) {
- install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
+ if let Some(tarball) = builder.ensure(dist::Miri { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target) , target: self.target }) {
+ install_sh(builder, "miri", self.build_compiler, Some(self.target), &tarball);
} else {
// Miri is only available on nightly
builder.info(
- &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
+ &format!("skipping Install miri stage{} ({})", self.build_compiler.stage + 1, self.target),
);
}
};
LlvmTools, alias = "llvm-tools", _config.llvm_tools_enabled && _config.llvm_enabled(_config.host_target), IS_HOST: true, {
if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) {
- install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
+ install_sh(builder, "llvm-tools", None, Some(self.target), &tarball);
} else {
builder.info(
- &format!("skipping llvm-tools stage{} ({}): external LLVM", self.compiler.stage, self.target),
+ &format!("skipping llvm-tools ({}): external LLVM", self.target),
);
}
};
Rustfmt, alias = "rustfmt", Self::should_build(_config), IS_HOST: true, {
if let Some(tarball) = builder.ensure(dist::Rustfmt {
- build_compiler: self.compiler,
+ compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target),
target: self.target
}) {
- install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball);
+ install_sh(builder, "rustfmt", self.build_compiler, Some(self.target), &tarball);
} else {
builder.info(
- &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target),
+ &format!("skipping Install Rustfmt stage{} ({})", self.build_compiler.stage + 1, self.target),
);
}
};
Rustc, path = "compiler/rustc", true, IS_HOST: true, {
let tarball = builder.ensure(dist::Rustc {
- compiler: builder.compiler(builder.top_stage, self.target),
+ target_compiler: builder.compiler(self.build_compiler.stage + 1, self.target),
});
- install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
+ install_sh(builder, "rustc", self.build_compiler, Some(self.target), &tarball);
};
RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), IS_HOST: true, {
if let Some(tarball) = builder.ensure(dist::CraneliftCodegenBackend {
- build_compiler: self.compiler,
+ compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target),
target: self.target
}) {
- install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball);
+ install_sh(builder, "rustc-codegen-cranelift", self.build_compiler, Some(self.target), &tarball);
} else {
builder.info(
&format!("skipping Install CodegenBackend(\"cranelift\") stage{} ({})",
- self.compiler.stage, self.target),
+ self.build_compiler.stage + 1, self.target),
);
}
};
LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), IS_HOST: true, {
- if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.compiler, target: self.target }) {
- install_sh(builder, "llvm-bitcode-linker", self.compiler.stage, Some(self.target), &tarball);
+ if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.build_compiler, target: self.target }) {
+ install_sh(builder, "llvm-bitcode-linker", self.build_compiler, Some(self.target), &tarball);
} else {
builder.info(
- &format!("skipping llvm-bitcode-linker stage{} ({})", self.compiler.stage, self.target),
+ &format!("skipping llvm-bitcode-linker stage{} ({})", self.build_compiler.stage + 1, self.target),
);
}
};
@@ -305,7 +302,7 @@ fn run($sel, $builder: &Builder<'_>) {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Src {
- pub stage: u32,
+ stage: u32,
}
impl Step for Src {
@@ -325,6 +322,6 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) {
let tarball = builder.ensure(dist::Src);
- install_sh(builder, "src", self.stage, None, &tarball);
+ install_sh(builder, "src", None, None, &tarball);
}
}
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 70259f0..d47c149 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -486,8 +486,11 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult {
let LlvmResult { host_llvm_config, .. } =
builder.ensure(Llvm { target: builder.config.host_target });
if !builder.config.dry_run() {
- let llvm_bindir =
- command(&host_llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
+ let llvm_bindir = command(&host_llvm_config)
+ .arg("--bindir")
+ .cached()
+ .run_capture_stdout(builder)
+ .stdout();
let host_bin = Path::new(llvm_bindir.trim());
cfg.define(
"LLVM_TABLEGEN",
@@ -593,7 +596,13 @@ fn metadata(&self) -> Option<StepMetadata> {
}
pub fn get_llvm_version(builder: &Builder<'_>, llvm_config: &Path) -> String {
- command(llvm_config).arg("--version").run_capture_stdout(builder).stdout().trim().to_owned()
+ command(llvm_config)
+ .arg("--version")
+ .cached()
+ .run_capture_stdout(builder)
+ .stdout()
+ .trim()
+ .to_owned()
}
pub fn get_llvm_version_major(builder: &Builder<'_>, llvm_config: &Path) -> u8 {
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index c6288f6..d9de6b7e 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -5,13 +5,14 @@
use std::path::PathBuf;
+use build_helper::exit;
use clap_complete::{Generator, shells};
use crate::core::build_steps::dist::distdir;
use crate::core::build_steps::test;
use crate::core::build_steps::tool::{self, RustcPrivateCompilers, SourceType, Tool};
use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
-use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
+use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
use crate::core::config::TargetSelection;
use crate::core::config::flags::get_completion;
use crate::utils::exec::command;
@@ -100,8 +101,17 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
}
}
+/// Invoke the Miri tool on a specified file.
+///
+/// Note that Miri always executed on the host, as it is an interpreter.
+/// That means that `x run miri --target FOO` will build miri for the host,
+/// prepare a miri sysroot for the target `FOO` and then execute miri with
+/// the target `FOO`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Miri {
+ /// The build compiler that will build miri and the target compiler to which miri links.
+ compilers: RustcPrivateCompilers,
+ /// The target which will miri interpret.
target: TargetSelection,
}
@@ -113,14 +123,9 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(Miri { target: run.target });
- }
+ let builder = run.builder;
- fn run(self, builder: &Builder<'_>) {
- let host = builder.build.host_target;
- let target = self.target;
-
- // `x run` uses stage 0 by default but miri does not work well with stage 0.
+ // `x run` uses stage 0 by default, but miri does not work well with stage 0.
// Change the stage to 1 if it's not set explicitly.
let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
builder.top_stage
@@ -129,14 +134,22 @@ fn run(self, builder: &Builder<'_>) {
};
if stage == 0 {
- eprintln!("miri cannot be run at stage 0");
- std::process::exit(1);
+ eprintln!("ERROR: miri cannot be run at stage 0");
+ exit!(1);
}
- // This compiler runs on the host, we'll just use it for the target.
- let compilers = RustcPrivateCompilers::new(builder, stage, target);
- let miri_build = builder.ensure(tool::Miri::from_compilers(compilers));
- let host_compiler = miri_build.build_compiler;
+ // Miri always runs on the host, because it can interpret code for any target
+ let compilers = RustcPrivateCompilers::new(builder, stage, builder.host_target);
+
+ run.builder.ensure(Miri { compilers, target: run.target });
+ }
+
+ fn run(self, builder: &Builder<'_>) {
+ let host = builder.build.host_target;
+ let compilers = self.compilers;
+ let target = self.target;
+
+ builder.ensure(tool::Miri::from_compilers(compilers));
// Get a target sysroot for Miri.
let miri_sysroot =
@@ -147,7 +160,7 @@ fn run(self, builder: &Builder<'_>) {
// add_rustc_lib_path does not add the path that contains librustc_driver-<...>.so.
let mut miri = tool::prepare_tool_cargo(
builder,
- host_compiler,
+ compilers.build_compiler(),
Mode::ToolRustc,
host,
Kind::Run,
@@ -167,6 +180,10 @@ fn run(self, builder: &Builder<'_>) {
miri.into_cmd().run(builder);
}
+
+ fn metadata(&self) -> Option<StepMetadata> {
+ Some(StepMetadata::run("miri", self.target).built_by(self.compilers.build_compiler()))
+ }
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 269e7da..26b4aaa 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -153,7 +153,7 @@ fn run(self, builder: &Builder<'_>) {
}
// Build all the default documentation.
- builder.default_doc(&[]);
+ builder.run_default_doc_steps();
// Build the linkchecker before calling `msg`, since GHA doesn't support nested groups.
let linkchecker = builder.tool_cmd(Tool::Linkchecker);
@@ -208,7 +208,7 @@ fn run(self, builder: &Builder<'_>) {
panic!("Cannot run html-check tests");
}
// Ensure that a few different kinds of documentation are available.
- builder.default_doc(&[]);
+ builder.run_default_doc_steps();
builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
builder,
builder.top_stage,
@@ -1719,7 +1719,7 @@ fn run(self, builder: &Builder<'_>) {
if suite == "debuginfo" {
builder.ensure(dist::DebuggerScripts {
sysroot: builder.sysroot(compiler).to_path_buf(),
- host: target,
+ target,
});
}
if suite == "run-make" {
@@ -1850,7 +1850,7 @@ fn run(self, builder: &Builder<'_>) {
// Tells compiletest which codegen backend to use.
// It is used to e.g. ignore tests that don't support that codegen backend.
cmd.arg("--default-codegen-backend")
- .arg(builder.config.default_codegen_backend(compiler.host).unwrap().name());
+ .arg(builder.config.default_codegen_backend(compiler.host).name());
}
if builder.build.config.llvm_enzyme {
@@ -2025,8 +2025,6 @@ fn run(self, builder: &Builder<'_>) {
cmd.arg("--verbose");
}
- cmd.arg("--json");
-
if builder.config.rustc_debug_assertions {
cmd.arg("--with-rustc-debug-assertions");
}
@@ -2043,6 +2041,7 @@ fn run(self, builder: &Builder<'_>) {
if !builder.config.dry_run() {
let llvm_version = get_llvm_version(builder, &host_llvm_config);
let llvm_components = command(&host_llvm_config)
+ .cached()
.arg("--components")
.run_capture_stdout(builder)
.stdout();
@@ -2062,8 +2061,11 @@ fn run(self, builder: &Builder<'_>) {
// separate compilations. We can add LLVM's library path to the
// rustc args as a workaround.
if !builder.config.dry_run() && suite.ends_with("fulldeps") {
- let llvm_libdir =
- command(&host_llvm_config).arg("--libdir").run_capture_stdout(builder).stdout();
+ let llvm_libdir = command(&host_llvm_config)
+ .cached()
+ .arg("--libdir")
+ .run_capture_stdout(builder)
+ .stdout();
let link_llvm = if target.is_msvc() {
format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
} else {
@@ -3117,45 +3119,55 @@ fn make_run(run: RunConfig<'_>) {
///
/// FIXME(#136822): dist components are under-tested.
fn run(self, builder: &Builder<'_>) {
- builder.info("Distcheck");
- let dir = builder.tempdir().join("distcheck");
- let _ = fs::remove_dir_all(&dir);
- t!(fs::create_dir_all(&dir));
+ // Use a temporary directory completely outside the current checkout, to avoid reusing any
+ // local source code, built artifacts or configuration by accident
+ let root_dir = std::env::temp_dir().join("distcheck");
- // Guarantee that these are built before we begin running.
- builder.ensure(dist::PlainSourceTarball);
- builder.ensure(dist::Src);
+ // Check that we can build some basic things from the plain source tarball
+ builder.info("Distcheck plain source tarball");
+ let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
+ let plain_src_dir = root_dir.join("distcheck-plain-src");
+ builder.clear_dir(&plain_src_dir);
+
+ let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
+ .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
+ .unwrap_or_default();
command("tar")
.arg("-xf")
- .arg(builder.ensure(dist::PlainSourceTarball).tarball())
+ .arg(plain_src_tarball.tarball())
.arg("--strip-components=1")
- .current_dir(&dir)
+ .current_dir(&plain_src_dir)
.run(builder);
command("./configure")
- .args(&builder.config.configure_args)
+ .arg("--set")
+ .arg("rust.omit-git-hash=false")
+ .args(&configure_args)
.arg("--enable-vendor")
- .current_dir(&dir)
+ .current_dir(&plain_src_dir)
.run(builder);
command(helpers::make(&builder.config.host_target.triple))
.arg("check")
- .current_dir(&dir)
+ // Do not run the build as if we were in CI, otherwise git would be assumed to be
+ // present, but we build from a tarball here
+ .env("GITHUB_ACTIONS", "0")
+ .current_dir(&plain_src_dir)
.run(builder);
// Now make sure that rust-src has all of libstd's dependencies
builder.info("Distcheck rust-src");
- let dir = builder.tempdir().join("distcheck-src");
- let _ = fs::remove_dir_all(&dir);
- t!(fs::create_dir_all(&dir));
+ let src_tarball = builder.ensure(dist::Src);
+ let src_dir = root_dir.join("distcheck-src");
+ builder.clear_dir(&src_dir);
command("tar")
.arg("-xf")
- .arg(builder.ensure(dist::Src).tarball())
+ .arg(src_tarball.tarball())
.arg("--strip-components=1")
- .current_dir(&dir)
+ .current_dir(&src_dir)
.run(builder);
- let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
+ let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
command(&builder.initial_cargo)
// Will read the libstd Cargo.toml
// which uses the unstable `public-dependency` feature.
@@ -3163,7 +3175,7 @@ fn run(self, builder: &Builder<'_>) {
.arg("generate-lockfile")
.arg("--manifest-path")
.arg(&toml)
- .current_dir(&dir)
+ .current_dir(&src_dir)
.run(builder);
}
}
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index 7b860ce..0e9d4e7 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -19,6 +19,7 @@
pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'static str>)> {
[
("src/tools/cargo/Cargo.toml", vec!["src/tools/cargo"]),
+ ("src/tools/clippy/clippy_test_deps/Cargo.toml", vec![]),
("src/tools/rust-analyzer/Cargo.toml", vec![]),
("compiler/rustc_codegen_cranelift/Cargo.toml", vec![]),
("compiler/rustc_codegen_gcc/Cargo.toml", vec![]),
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 7219240..cdf6fe5 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -132,10 +132,7 @@ pub fn compiler(&self) -> Compiler {
}
pub fn into_cmd(self) -> BootstrapCommand {
- let mut cmd: BootstrapCommand = self.into();
- // Disable caching for commands originating from Cargo-related operations.
- cmd.do_not_cache();
- cmd
+ self.into()
}
/// Same as [`Cargo::new`] except this one doesn't configure the linker with
@@ -1085,7 +1082,7 @@ fn cargo(
&& let Some(llvm_config) = self.llvm_config(target)
{
let llvm_libdir =
- command(llvm_config).arg("--libdir").run_capture_stdout(self).stdout();
+ command(llvm_config).cached().arg("--libdir").run_capture_stdout(self).stdout();
if target.is_msvc() {
rustflags.arg(&format!("-Clink-arg=-LIBPATH:{llvm_libdir}"));
} else {
@@ -1326,12 +1323,7 @@ fn cargo(
if let Some(limit) = limit
&& (build_compiler_stage == 0
- || self
- .config
- .default_codegen_backend(target)
- .cloned()
- .unwrap_or_default()
- .is_llvm())
+ || self.config.default_codegen_backend(target).is_llvm())
{
rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
}
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 40460bf..b224a7e 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -22,6 +22,7 @@
};
use crate::core::config::flags::Subcommand;
use crate::core::config::{DryRun, TargetSelection};
+use crate::utils::build_stamp::BuildStamp;
use crate::utils::cache::Cache;
use crate::utils::exec::{BootstrapCommand, ExecutionContext, command};
use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t};
@@ -144,8 +145,7 @@ fn metadata(&self) -> Option<StepMetadata> {
}
/// Metadata that describes an executed step, mostly for testing and tracing.
-#[allow(unused)]
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StepMetadata {
name: String,
kind: Kind,
@@ -181,6 +181,10 @@ pub fn test(name: &str, target: TargetSelection) -> Self {
Self::new(name, target, Kind::Test)
}
+ pub fn run(name: &str, target: TargetSelection) -> Self {
+ Self::new(name, target, Kind::Run)
+ }
+
fn new(name: &str, target: TargetSelection, kind: Kind) -> Self {
Self { name: name.to_string(), kind, target, built_by: None, stage: None, metadata: None }
}
@@ -1308,8 +1312,9 @@ pub fn execute_cli(&self) {
self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths);
}
- pub fn default_doc(&self, paths: &[PathBuf]) {
- self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
+ /// Run all default documentation steps to build documentation.
+ pub fn run_default_doc_steps(&self) {
+ self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
}
pub fn doc_rust_lang_org_channel(&self) -> String {
@@ -1355,6 +1360,30 @@ pub fn compiler(&self, stage: u32, host: TargetSelection) -> Compiler {
self.ensure(compile::Assemble { target_compiler: Compiler::new(stage, host) })
}
+ /// This function can be used to provide a build compiler for building
+ /// the standard library, in order to avoid unnecessary rustc builds in case where std uplifting
+ /// would happen anyway.
+ ///
+ /// This is an important optimization mainly for CI.
+ ///
+ /// Normally, to build stage N libstd, we need stage N rustc.
+ /// However, if we know that we will uplift libstd from stage 1 anyway, building the stage N
+ /// rustc can be wasteful.
+ /// In particular, if we do a cross-compiling dist stage 2 build from target1 to target2,
+ /// we need:
+ /// - stage 2 libstd for target2 (uplifted from stage 1, where it was built by target1 rustc)
+ /// - stage 2 rustc for target2
+ ///
+ /// However, without this optimization, we would also build stage 2 rustc for **target1**,
+ /// which is completely wasteful.
+ pub fn compiler_for_std(&self, stage: u32) -> Compiler {
+ if compile::Std::should_be_uplifted_from_stage_1(self, stage) {
+ self.compiler(1, self.host_target)
+ } else {
+ self.compiler(stage, self.host_target)
+ }
+ }
+
/// Similar to `compiler`, except handles the full-bootstrap option to
/// silently use the stage1 compiler instead of a stage2 compiler if one is
/// requested.
@@ -1411,6 +1440,8 @@ pub fn compiler_for(
/// The standard library will be linked to the sysroot of the passed compiler.
///
/// Prefer using this method rather than manually invoking `Std::new`.
+ ///
+ /// Returns an optional build stamp, if libstd was indeed built.
#[cfg_attr(
feature = "tracing",
instrument(
@@ -1424,29 +1455,38 @@ pub fn compiler_for(
),
),
)]
- pub fn std(&self, compiler: Compiler, target: TargetSelection) {
+ pub fn std(&self, compiler: Compiler, target: TargetSelection) -> Option<BuildStamp> {
// FIXME: make the `Std` step return some type-level "proof" that std was indeed built,
// and then require passing that to all Cargo invocations that we do.
- // The "stage 0" std is always precompiled and comes with the stage0 compiler, so we have
- // special logic for it, to avoid creating needless and confusing Std steps that don't
+ // The "stage 0" std is almost always precompiled and comes with the stage0 compiler, so we
+ // have special logic for it, to avoid creating needless and confusing Std steps that don't
// actually build anything.
+ // We only allow building the stage0 stdlib if we do a local rebuild, so the stage0 compiler
+ // actually comes from in-tree sources, and we're cross-compiling, so the stage0 for the
+ // given `target` is not available.
if compiler.stage == 0 {
if target != compiler.host {
- panic!(
- r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
+ if self.local_rebuild {
+ self.ensure(Std::new(compiler, target))
+ } else {
+ panic!(
+ r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
You have to build a stage1 compiler for `{}` first, and then use it to build a standard library for `{target}`.
+Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler built from in-tree sources.
",
- compiler.host
- )
+ compiler.host
+ )
+ }
+ } else {
+ // We still need to link the prebuilt standard library into the ephemeral stage0 sysroot
+ self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
+ None
}
-
- // We still need to link the prebuilt standard library into the ephemeral stage0 sysroot
- self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
} else {
// This step both compiles the std and links it into the compiler's sysroot.
// Yes, it's quite magical and side-effecty.. would be nice to refactor later.
- self.ensure(Std::new(compiler, target));
+ self.ensure(Std::new(compiler, target))
}
}
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 2afba25..b079117 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -854,6 +854,18 @@ fn build_library_stage_0() {
}
#[test]
+ fn build_library_stage_0_local_rebuild() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("build")
+ .path("library")
+ .stage(0)
+ .targets(&[TEST_TRIPLE_1])
+ .args(&["--set", "build.local-rebuild=true"])
+ .render_steps(), @"[build] rustc 0 <host> -> std 0 <target1>");
+ }
+
+ #[test]
fn build_library_stage_1() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
@@ -1054,6 +1066,7 @@ fn build_all() {
[build] rustc 1 <host> -> rustc 2 <target1>
[build] rustc 2 <host> -> std 2 <host>
[build] rustc 2 <host> -> std 2 <target1>
+ [build] rustc 1 <host> -> std 1 <target2>
[build] rustc 2 <host> -> std 2 <target2>
");
}
@@ -1110,9 +1123,8 @@ fn dist_baseline() {
[doc] book/2018-edition (book) <host>
[build] rustdoc 1 <host>
[doc] rustc 1 <host> -> standalone 2 <host>
+ [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> rustc 2 <host>
- [build] rustdoc 2 <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> error-index 2 <host>
[doc] rustc 1 <host> -> error-index 2 <host>
[doc] nomicon (book) <host>
@@ -1129,12 +1141,16 @@ fn dist_baseline() {
[doc] rustc 1 <host> -> releases 2 <host>
[build] rustc 0 <host> -> RustInstaller 1 <host>
[dist] docs <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[]
+ [doc] rustc 1 <host> -> std 1 <host> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <host>
[dist] mingw <host>
+ [build] rustdoc 2 <host>
[build] rustc 0 <host> -> GenerateCopyright 1 <host>
[dist] rustc <host>
[dist] rustc 1 <host> -> std 1 <host>
+ [dist] rustc 1 <host> -> rustc-dev 2 <host>
[dist] src <>
+ [dist] reproducible-artifacts <host>
"
);
}
@@ -1168,12 +1184,11 @@ fn dist_extended() {
[doc] book/2018-edition (book) <host>
[build] rustdoc 1 <host>
[doc] rustc 1 <host> -> standalone 2 <host>
+ [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> rustc 2 <host>
[build] rustc 1 <host> -> LldWrapper 2 <host>
[build] rustc 1 <host> -> WasmComponentLd 2 <host>
[build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
- [build] rustdoc 2 <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> error-index 2 <host>
[doc] rustc 1 <host> -> error-index 2 <host>
[doc] nomicon (book) <host>
@@ -1190,21 +1205,34 @@ fn dist_extended() {
[doc] rustc 1 <host> -> releases 2 <host>
[build] rustc 0 <host> -> RustInstaller 1 <host>
[dist] docs <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[]
+ [doc] rustc 1 <host> -> std 1 <host> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <host>
[dist] mingw <host>
+ [build] rustdoc 2 <host>
[build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <host>
[build] rustc 0 <host> -> GenerateCopyright 1 <host>
[dist] rustc <host>
[dist] rustc 1 <host> -> std 1 <host>
+ [dist] rustc 1 <host> -> rustc-dev 2 <host>
+ [dist] rustc 1 <host> -> analysis 2 <host>
[dist] src <>
[build] rustc 1 <host> -> cargo 2 <host>
+ [dist] rustc 1 <host> -> cargo 2 <host>
[build] rustc 1 <host> -> rust-analyzer 2 <host>
+ [dist] rustc 1 <host> -> rust-analyzer 2 <host>
[build] rustc 1 <host> -> rustfmt 2 <host>
[build] rustc 1 <host> -> cargo-fmt 2 <host>
+ [dist] rustc 1 <host> -> rustfmt 2 <host>
[build] rustc 1 <host> -> clippy-driver 2 <host>
[build] rustc 1 <host> -> cargo-clippy 2 <host>
+ [dist] rustc 1 <host> -> clippy 2 <host>
[build] rustc 1 <host> -> miri 2 <host>
[build] rustc 1 <host> -> cargo-miri 2 <host>
+ [dist] rustc 1 <host> -> miri 2 <host>
+ [doc] rustc 2 <host> -> std 2 <host> crates=[]
+ [dist] rustc 2 <host> -> json-docs 3 <host>
+ [dist] rustc 1 <host> -> extended 2 <host>
+ [dist] reproducible-artifacts <host>
");
}
@@ -1236,10 +1264,9 @@ fn dist_with_targets() {
[doc] book/2018-edition (book) <target1>
[doc] rustc 1 <host> -> standalone 2 <host>
[doc] rustc 1 <host> -> standalone 2 <target1>
+ [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+ [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> rustc 2 <host>
- [build] rustdoc 2 <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
- [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> error-index 2 <host>
[doc] rustc 1 <host> -> error-index 2 <host>
[doc] nomicon (book) <host>
@@ -1267,16 +1294,20 @@ fn dist_with_targets() {
[build] rustc 0 <host> -> RustInstaller 1 <host>
[dist] docs <host>
[dist] docs <target1>
- [doc] rustc 2 <host> -> std 2 <host> crates=[]
- [doc] rustc 2 <host> -> std 2 <target1> crates=[]
+ [doc] rustc 1 <host> -> std 1 <host> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <host>
+ [doc] rustc 1 <host> -> std 1 <target1> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <target1>
[dist] mingw <host>
[dist] mingw <target1>
+ [build] rustdoc 2 <host>
[build] rustc 0 <host> -> GenerateCopyright 1 <host>
[dist] rustc <host>
[dist] rustc 1 <host> -> std 1 <host>
- [build] rustc 2 <host> -> std 2 <target1>
- [dist] rustc 2 <host> -> std 2 <target1>
+ [dist] rustc 1 <host> -> std 1 <target1>
+ [dist] rustc 1 <host> -> rustc-dev 2 <host>
[dist] src <>
+ [dist] reproducible-artifacts <host>
"
);
}
@@ -1302,9 +1333,8 @@ fn dist_with_hosts() {
[doc] book/2018-edition (book) <host>
[build] rustdoc 1 <host>
[doc] rustc 1 <host> -> standalone 2 <host>
+ [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> rustc 2 <host>
- [build] rustdoc 2 <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> error-index 2 <host>
[doc] rustc 1 <host> -> error-index 2 <host>
[build] llvm <target1>
@@ -1327,14 +1357,20 @@ fn dist_with_hosts() {
[doc] rustc 1 <host> -> releases 2 <host>
[build] rustc 0 <host> -> RustInstaller 1 <host>
[dist] docs <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[]
+ [doc] rustc 1 <host> -> std 1 <host> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <host>
[dist] mingw <host>
+ [build] rustdoc 2 <host>
[build] rustc 0 <host> -> GenerateCopyright 1 <host>
[dist] rustc <host>
[build] rustdoc 2 <target1>
[dist] rustc <target1>
[dist] rustc 1 <host> -> std 1 <host>
+ [dist] rustc 1 <host> -> rustc-dev 2 <host>
+ [dist] rustc 1 <host> -> rustc-dev 2 <target1>
[dist] src <>
+ [dist] reproducible-artifacts <host>
+ [dist] reproducible-artifacts <target1>
"
);
}
@@ -1367,10 +1403,9 @@ fn dist_with_targets_and_hosts() {
[doc] book/2018-edition (book) <target1>
[doc] rustc 1 <host> -> standalone 2 <host>
[doc] rustc 1 <host> -> standalone 2 <target1>
+ [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+ [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> rustc 2 <host>
- [build] rustdoc 2 <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
- [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> error-index 2 <host>
[doc] rustc 1 <host> -> error-index 2 <host>
[build] llvm <target1>
@@ -1403,17 +1438,24 @@ fn dist_with_targets_and_hosts() {
[build] rustc 0 <host> -> RustInstaller 1 <host>
[dist] docs <host>
[dist] docs <target1>
- [doc] rustc 2 <host> -> std 2 <host> crates=[]
- [doc] rustc 2 <host> -> std 2 <target1> crates=[]
+ [doc] rustc 1 <host> -> std 1 <host> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <host>
+ [doc] rustc 1 <host> -> std 1 <target1> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <target1>
[dist] mingw <host>
[dist] mingw <target1>
+ [build] rustdoc 2 <host>
[build] rustc 0 <host> -> GenerateCopyright 1 <host>
[dist] rustc <host>
[build] rustdoc 2 <target1>
[dist] rustc <target1>
[dist] rustc 1 <host> -> std 1 <host>
[dist] rustc 1 <host> -> std 1 <target1>
+ [dist] rustc 1 <host> -> rustc-dev 2 <host>
+ [dist] rustc 1 <host> -> rustc-dev 2 <target1>
[dist] src <>
+ [dist] reproducible-artifacts <host>
+ [dist] reproducible-artifacts <target1>
"
);
}
@@ -1440,9 +1482,7 @@ fn dist_with_empty_host() {
[build] rustdoc 1 <host>
[build] rustc 1 <host> -> std 1 <host>
[doc] rustc 1 <host> -> standalone 2 <target1>
- [build] rustc 1 <host> -> rustc 2 <host>
- [build] rustdoc 2 <host>
- [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+ [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[doc] nomicon (book) <target1>
[doc] rustc 1 <host> -> reference (book) 2 <target1>
[doc] rustdoc (book) <target1>
@@ -1455,17 +1495,15 @@ fn dist_with_empty_host() {
[doc] rustc 1 <host> -> releases 2 <target1>
[build] rustc 0 <host> -> RustInstaller 1 <host>
[dist] docs <target1>
- [doc] rustc 2 <host> -> std 2 <target1> crates=[]
+ [doc] rustc 1 <host> -> std 1 <target1> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <target1>
[dist] mingw <target1>
- [build] rustc 2 <host> -> std 2 <target1>
- [dist] rustc 2 <host> -> std 2 <target1>
+ [dist] rustc 1 <host> -> std 1 <target1>
");
}
- /// This also serves as an important regression test for <https://github.com/rust-lang/rust/issues/138123>
- /// and <https://github.com/rust-lang/rust/issues/138004>.
#[test]
- fn dist_all_cross() {
+ fn dist_all_cross_extended() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx
@@ -1488,10 +1526,7 @@ fn dist_all_cross() {
[build] rustdoc 1 <host>
[build] rustc 1 <host> -> std 1 <host>
[doc] rustc 1 <host> -> standalone 2 <target1>
- [build] rustc 1 <host> -> rustc 2 <host>
- [build] rustc 1 <host> -> WasmComponentLd 2 <host>
- [build] rustdoc 2 <host>
- [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+ [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] llvm <target1>
[build] rustc 1 <host> -> rustc 2 <target1>
[build] rustc 1 <host> -> WasmComponentLd 2 <target1>
@@ -1511,29 +1546,108 @@ fn dist_all_cross() {
[doc] rustc 1 <host> -> releases 2 <target1>
[build] rustc 0 <host> -> RustInstaller 1 <host>
[dist] docs <target1>
- [doc] rustc 2 <host> -> std 2 <target1> crates=[]
+ [doc] rustc 1 <host> -> std 1 <target1> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <target1>
[dist] mingw <target1>
[build] rustdoc 2 <target1>
[build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <target1>
[build] rustc 0 <host> -> GenerateCopyright 1 <host>
[dist] rustc <target1>
[dist] rustc 1 <host> -> std 1 <target1>
+ [dist] rustc 1 <host> -> rustc-dev 2 <target1>
+ [dist] rustc 1 <host> -> analysis 2 <target1>
[dist] src <>
[build] rustc 1 <host> -> cargo 2 <target1>
+ [dist] rustc 1 <host> -> cargo 2 <target1>
[build] rustc 1 <host> -> rust-analyzer 2 <target1>
+ [dist] rustc 1 <host> -> rust-analyzer 2 <target1>
[build] rustc 1 <host> -> rustfmt 2 <target1>
[build] rustc 1 <host> -> cargo-fmt 2 <target1>
+ [dist] rustc 1 <host> -> rustfmt 2 <target1>
[build] rustc 1 <host> -> clippy-driver 2 <target1>
[build] rustc 1 <host> -> cargo-clippy 2 <target1>
+ [dist] rustc 1 <host> -> clippy 2 <target1>
[build] rustc 1 <host> -> miri 2 <target1>
[build] rustc 1 <host> -> cargo-miri 2 <target1>
+ [dist] rustc 1 <host> -> miri 2 <target1>
[build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
[doc] rustc 2 <target1> -> std 2 <target1> crates=[]
+ [dist] rustc 2 <target1> -> json-docs 3 <target1>
+ [dist] rustc 1 <host> -> extended 2 <target1>
+ [dist] reproducible-artifacts <target1>
");
}
- // Enable dist cranelift tarball by default with `x dist` if cranelift is enabled in
- // `rust.codegen-backends`.
+ /// Simulates e.g. the powerpc64 builder, which is fully cross-compiled from x64, but it does
+ /// not build docs. Crucially, it shouldn't build host stage 2 rustc.
+ ///
+ /// This is a regression test for <https://github.com/rust-lang/rust/issues/138123>
+ /// and <https://github.com/rust-lang/rust/issues/138004>.
+ #[test]
+ fn dist_all_cross_extended_no_docs() {
+ let ctx = TestCtx::new();
+ let steps = ctx
+ .config("dist")
+ .hosts(&[TEST_TRIPLE_1])
+ .targets(&[TEST_TRIPLE_1])
+ .args(&[
+ "--set",
+ "rust.channel=nightly",
+ "--set",
+ "build.extended=true",
+ "--set",
+ "build.docs=false",
+ ])
+ .get_steps();
+
+ // Make sure that we don't build stage2 host rustc
+ steps.assert_no_match(|m| {
+ m.name == "rustc"
+ && m.built_by.map(|b| b.stage) == Some(1)
+ && *m.target.triple == host_target()
+ });
+
+ insta::assert_snapshot!(
+ steps.render(), @r"
+ [dist] mingw <target1>
+ [build] llvm <host>
+ [build] llvm <target1>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 0 <host> -> WasmComponentLd 1 <host>
+ [build] rustc 1 <host> -> std 1 <target1>
+ [build] rustc 1 <host> -> std 1 <host>
+ [build] rustc 1 <host> -> rustc 2 <target1>
+ [build] rustc 1 <host> -> WasmComponentLd 2 <target1>
+ [build] rustdoc 2 <target1>
+ [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <target1>
+ [build] rustc 0 <host> -> GenerateCopyright 1 <host>
+ [build] rustc 0 <host> -> RustInstaller 1 <host>
+ [dist] rustc <target1>
+ [dist] rustc 1 <host> -> std 1 <target1>
+ [dist] rustc 1 <host> -> rustc-dev 2 <target1>
+ [dist] rustc 1 <host> -> analysis 2 <target1>
+ [dist] src <>
+ [build] rustc 1 <host> -> cargo 2 <target1>
+ [dist] rustc 1 <host> -> cargo 2 <target1>
+ [build] rustc 1 <host> -> rust-analyzer 2 <target1>
+ [dist] rustc 1 <host> -> rust-analyzer 2 <target1>
+ [build] rustc 1 <host> -> rustfmt 2 <target1>
+ [build] rustc 1 <host> -> cargo-fmt 2 <target1>
+ [dist] rustc 1 <host> -> rustfmt 2 <target1>
+ [build] rustc 1 <host> -> clippy-driver 2 <target1>
+ [build] rustc 1 <host> -> cargo-clippy 2 <target1>
+ [dist] rustc 1 <host> -> clippy 2 <target1>
+ [build] rustc 1 <host> -> miri 2 <target1>
+ [build] rustc 1 <host> -> cargo-miri 2 <target1>
+ [dist] rustc 1 <host> -> miri 2 <target1>
+ [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
+ [dist] rustc 1 <host> -> extended 2 <target1>
+ [dist] reproducible-artifacts <target1>
+ ");
+ }
+
+ /// Enable dist cranelift tarball by default with `x dist` if cranelift is enabled in
+ /// `rust.codegen-backends`.
#[test]
fn dist_cranelift_by_default() {
let ctx = TestCtx::new();
@@ -1555,10 +1669,9 @@ fn dist_cranelift_by_default() {
[doc] book/2018-edition (book) <host>
[build] rustdoc 1 <host>
[doc] rustc 1 <host> -> standalone 2 <host>
+ [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> rustc 2 <host>
[build] rustc 1 <host> -> rustc_codegen_cranelift 2 <host>
- [build] rustdoc 2 <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
[build] rustc 1 <host> -> error-index 2 <host>
[doc] rustc 1 <host> -> error-index 2 <host>
[doc] nomicon (book) <host>
@@ -1575,13 +1688,86 @@ fn dist_cranelift_by_default() {
[doc] rustc 1 <host> -> releases 2 <host>
[build] rustc 0 <host> -> RustInstaller 1 <host>
[dist] docs <host>
- [doc] rustc 2 <host> -> std 2 <host> crates=[]
+ [doc] rustc 1 <host> -> std 1 <host> crates=[]
+ [dist] rustc 1 <host> -> json-docs 2 <host>
[dist] mingw <host>
+ [build] rustdoc 2 <host>
[build] rustc 0 <host> -> GenerateCopyright 1 <host>
[dist] rustc <host>
[dist] rustc 1 <host> -> rustc_codegen_cranelift 2 <host>
[dist] rustc 1 <host> -> std 1 <host>
+ [dist] rustc 1 <host> -> rustc-dev 2 <host>
[dist] src <>
+ [dist] reproducible-artifacts <host>
+ ");
+ }
+
+ #[test]
+ fn dist_bootstrap() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx
+ .config("dist")
+ .path("bootstrap")
+ .render_steps(), @r"
+ [build] rustc 0 <host> -> RustInstaller 1 <host>
+ [dist] bootstrap <host>
+ ");
+ }
+
+ #[test]
+ fn dist_library_stage_0_local_rebuild() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("dist")
+ .path("rust-std")
+ .stage(0)
+ .targets(&[TEST_TRIPLE_1])
+ .args(&["--set", "build.local-rebuild=true"])
+ .render_steps(), @r"
+ [build] rustc 0 <host> -> std 0 <target1>
+ [build] rustc 0 <host> -> RustInstaller 1 <host>
+ [dist] rustc 0 <host> -> std 0 <target1>
+ ");
+ }
+
+ #[test]
+ fn dist_rustc_docs() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx
+ .config("dist")
+ .path("rustc-docs")
+ .render_steps(), @r"
+ [build] rustc 0 <host> -> UnstableBookGen 1 <host>
+ [build] rustc 0 <host> -> Rustbook 1 <host>
+ [doc] unstable-book (book) <host>
+ [build] llvm <host>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 1 <host> -> std 1 <host>
+ [doc] book (book) <host>
+ [doc] book/first-edition (book) <host>
+ [doc] book/second-edition (book) <host>
+ [doc] book/2018-edition (book) <host>
+ [build] rustdoc 1 <host>
+ [doc] rustc 1 <host> -> standalone 2 <host>
+ [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+ [build] rustc 1 <host> -> rustc 2 <host>
+ [build] rustc 1 <host> -> error-index 2 <host>
+ [doc] rustc 1 <host> -> error-index 2 <host>
+ [doc] nomicon (book) <host>
+ [doc] rustc 1 <host> -> reference (book) 2 <host>
+ [doc] rustdoc (book) <host>
+ [doc] rust-by-example (book) <host>
+ [build] rustc 0 <host> -> LintDocs 1 <host>
+ [doc] rustc (book) <host>
+ [doc] cargo (book) <host>
+ [doc] clippy (book) <host>
+ [doc] embedded-book (book) <host>
+ [doc] edition-guide (book) <host>
+ [doc] style-guide (book) <host>
+ [doc] rustc 1 <host> -> releases 2 <host>
+ [build] rustc 0 <host> -> RustInstaller 1 <host>
");
}
@@ -2126,6 +2312,214 @@ fn doc_reference() {
[doc] rustc 1 <host> -> reference (book) 2 <host>
");
}
+
+ #[test]
+ fn clippy_ci() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("clippy")
+ .path("ci")
+ .stage(2)
+ .render_steps(), @r"
+ [build] llvm <host>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 1 <host> -> std 1 <host>
+ [build] rustc 0 <host> -> clippy-driver 1 <host>
+ [build] rustc 0 <host> -> cargo-clippy 1 <host>
+ [clippy] rustc 1 <host> -> bootstrap 2 <host>
+ [clippy] rustc 1 <host> -> std 1 <host>
+ [clippy] rustc 1 <host> -> rustc 2 <host>
+ [check] rustc 1 <host> -> rustc 2 <host>
+ [clippy] rustc 1 <host> -> rustc_codegen_gcc 2 <host>
+ ");
+ }
+
+ #[test]
+ fn clippy_compiler_stage1() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("clippy")
+ .path("compiler")
+ .render_steps(), @r"
+ [build] llvm <host>
+ [clippy] rustc 0 <host> -> rustc 1 <host>
+ ");
+ }
+
+ #[test]
+ fn clippy_compiler_stage2() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("clippy")
+ .path("compiler")
+ .stage(2)
+ .render_steps(), @r"
+ [build] llvm <host>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 1 <host> -> std 1 <host>
+ [build] rustc 0 <host> -> clippy-driver 1 <host>
+ [build] rustc 0 <host> -> cargo-clippy 1 <host>
+ [clippy] rustc 1 <host> -> rustc 2 <host>
+ ");
+ }
+
+ #[test]
+ fn clippy_std_stage1() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("clippy")
+ .path("std")
+ .render_steps(), @r"
+ [build] llvm <host>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 0 <host> -> clippy-driver 1 <host>
+ [build] rustc 0 <host> -> cargo-clippy 1 <host>
+ [clippy] rustc 1 <host> -> std 1 <host>
+ ");
+ }
+
+ #[test]
+ fn clippy_std_stage2() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("clippy")
+ .path("std")
+ .stage(2)
+ .render_steps(), @r"
+ [build] llvm <host>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 1 <host> -> std 1 <host>
+ [build] rustc 1 <host> -> rustc 2 <host>
+ [build] rustc 1 <host> -> clippy-driver 2 <host>
+ [build] rustc 1 <host> -> cargo-clippy 2 <host>
+ [clippy] rustc 2 <host> -> std 2 <host>
+ ");
+ }
+
+ #[test]
+ fn clippy_miri_stage1() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("clippy")
+ .path("miri")
+ .stage(1)
+ .render_steps(), @r"
+ [build] llvm <host>
+ [check] rustc 0 <host> -> rustc 1 <host>
+ [clippy] rustc 0 <host> -> miri 1 <host>
+ ");
+ }
+
+ #[test]
+ fn clippy_miri_stage2() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("clippy")
+ .path("miri")
+ .stage(2)
+ .render_steps(), @r"
+ [build] llvm <host>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 1 <host> -> std 1 <host>
+ [check] rustc 1 <host> -> rustc 2 <host>
+ [build] rustc 0 <host> -> clippy-driver 1 <host>
+ [build] rustc 0 <host> -> cargo-clippy 1 <host>
+ [clippy] rustc 1 <host> -> miri 2 <host>
+ ");
+ }
+
+ #[test]
+ fn clippy_bootstrap() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("clippy")
+ .path("bootstrap")
+ .render_steps(), @"[clippy] rustc 0 <host> -> bootstrap 1 <host>");
+ }
+
+ #[test]
+ fn install_extended() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("install")
+ .args(&[
+ // Using backslashes fails with `--set`
+ "--set", &format!("install.prefix={}", ctx.dir().display()).replace("\\", "/"),
+ "--set", &format!("install.sysconfdir={}", ctx.dir().display()).replace("\\", "/"),
+ "--set", "build.extended=true"
+ ])
+ .render_steps(), @r"
+ [build] llvm <host>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 0 <host> -> WasmComponentLd 1 <host>
+ [build] rustc 0 <host> -> UnstableBookGen 1 <host>
+ [build] rustc 0 <host> -> Rustbook 1 <host>
+ [doc] unstable-book (book) <host>
+ [build] rustc 1 <host> -> std 1 <host>
+ [doc] book (book) <host>
+ [doc] book/first-edition (book) <host>
+ [doc] book/second-edition (book) <host>
+ [doc] book/2018-edition (book) <host>
+ [build] rustdoc 1 <host>
+ [doc] rustc 1 <host> -> standalone 2 <host>
+ [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+ [build] rustc 1 <host> -> rustc 2 <host>
+ [build] rustc 1 <host> -> WasmComponentLd 2 <host>
+ [build] rustc 1 <host> -> error-index 2 <host>
+ [doc] rustc 1 <host> -> error-index 2 <host>
+ [doc] nomicon (book) <host>
+ [doc] rustc 1 <host> -> reference (book) 2 <host>
+ [doc] rustdoc (book) <host>
+ [doc] rust-by-example (book) <host>
+ [build] rustc 0 <host> -> LintDocs 1 <host>
+ [doc] rustc (book) <host>
+ [doc] cargo (book) <host>
+ [doc] clippy (book) <host>
+ [doc] embedded-book (book) <host>
+ [doc] edition-guide (book) <host>
+ [doc] style-guide (book) <host>
+ [doc] rustc 1 <host> -> releases 2 <host>
+ [build] rustc 0 <host> -> RustInstaller 1 <host>
+ [dist] docs <host>
+ [dist] rustc 1 <host> -> std 1 <host>
+ [build] rustdoc 2 <host>
+ [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <host>
+ [build] rustc 0 <host> -> GenerateCopyright 1 <host>
+ [dist] rustc <host>
+ [build] rustc 1 <host> -> cargo 2 <host>
+ [dist] rustc 1 <host> -> cargo 2 <host>
+ [build] rustc 1 <host> -> rust-analyzer 2 <host>
+ [dist] rustc 1 <host> -> rust-analyzer 2 <host>
+ [build] rustc 1 <host> -> rustfmt 2 <host>
+ [build] rustc 1 <host> -> cargo-fmt 2 <host>
+ [dist] rustc 1 <host> -> rustfmt 2 <host>
+ [build] rustc 1 <host> -> clippy-driver 2 <host>
+ [build] rustc 1 <host> -> cargo-clippy 2 <host>
+ [dist] rustc 1 <host> -> clippy 2 <host>
+ [build] rustc 1 <host> -> miri 2 <host>
+ [build] rustc 1 <host> -> cargo-miri 2 <host>
+ [dist] rustc 1 <host> -> miri 2 <host>
+ [dist] src <>
+ ");
+ }
+
+ // Check that `x run miri --target FOO` actually builds miri for the host.
+ #[test]
+ fn run_miri() {
+ let ctx = TestCtx::new();
+ insta::assert_snapshot!(
+ ctx.config("run")
+ .path("miri")
+ .stage(1)
+ .targets(&[TEST_TRIPLE_1])
+ .render_steps(), @r"
+ [build] llvm <host>
+ [build] rustc 0 <host> -> rustc 1 <host>
+ [build] rustc 0 <host> -> miri 1 <host>
+ [build] rustc 0 <host> -> cargo-miri 1 <host>
+ [run] rustc 0 <host> -> miri 1 <target1>
+ ");
+ }
}
struct ExecutedSteps {
@@ -2180,6 +2574,21 @@ fn assert_not_contains<M: Into<StepMetadata>>(&self, metadata: M) {
}
}
+ /// Make sure that no metadata matches the given `func`.
+ #[track_caller]
+ fn assert_no_match<F>(&self, func: F)
+ where
+ F: Fn(StepMetadata) -> bool,
+ {
+ for metadata in self.steps.iter().filter_map(|s| s.metadata.clone()) {
+ if func(metadata.clone()) {
+ panic!(
+ "Metadata {metadata:?} was found, even though it should have not been present"
+ );
+ }
+ }
+ }
+
fn contains(&self, metadata: &StepMetadata) -> bool {
self.steps
.iter()
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index f579bdd..a8eb563 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -46,8 +46,8 @@
};
use crate::core::config::toml::target::Target;
use crate::core::config::{
- DebuginfoLevel, DryRun, GccCiMode, LlvmLibunwind, Merge, ReplaceOpt, RustcLto, SplitDebuginfo,
- StringOrBool, threads_from_config,
+ CompilerBuiltins, DebuginfoLevel, DryRun, GccCiMode, LlvmLibunwind, Merge, ReplaceOpt,
+ RustcLto, SplitDebuginfo, StringOrBool, threads_from_config,
};
use crate::core::download::{
DownloadContext, download_beta_toolchain, is_download_ci_available, maybe_download_rustfmt,
@@ -121,8 +121,7 @@ pub struct Config {
pub patch_binaries_for_nix: Option<bool>,
pub stage0_metadata: build_helper::stage0_parser::Stage0,
pub android_ndk: Option<PathBuf>,
- /// Whether to use the `c` feature of the `compiler_builtins` crate.
- pub optimized_compiler_builtins: bool,
+ pub optimized_compiler_builtins: CompilerBuiltins,
pub stdout_is_tty: bool,
pub stderr_is_tty: bool,
@@ -327,59 +326,6 @@ pub struct Config {
}
impl Config {
- #[cfg_attr(
- feature = "tracing",
- instrument(target = "CONFIG_HANDLING", level = "trace", name = "Config::default_opts")
- )]
- pub fn default_opts() -> Config {
- #[cfg(feature = "tracing")]
- span!(target: "CONFIG_HANDLING", tracing::Level::TRACE, "constructing default config");
-
- Config {
- bypass_bootstrap_lock: false,
- llvm_optimize: true,
- ninja_in_file: true,
- llvm_static_stdcpp: false,
- llvm_libzstd: false,
- backtrace: true,
- rust_optimize: RustOptimize::Bool(true),
- rust_optimize_tests: true,
- rust_randomize_layout: false,
- submodules: None,
- docs: true,
- docs_minification: true,
- rust_rpath: true,
- rust_strip: false,
- channel: "dev".to_string(),
- codegen_tests: true,
- rust_dist_src: true,
- rust_codegen_backends: vec![CodegenBackendKind::Llvm],
- deny_warnings: true,
- bindir: "bin".into(),
- dist_include_mingw_linker: true,
- dist_compression_profile: "fast".into(),
-
- stdout_is_tty: std::io::stdout().is_terminal(),
- stderr_is_tty: std::io::stderr().is_terminal(),
-
- // set by build.rs
- host_target: get_host_target(),
-
- src: {
- let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
- // Undo `src/bootstrap`
- manifest_dir.parent().unwrap().parent().unwrap().to_owned()
- },
- out: PathBuf::from("build"),
-
- // This is needed by codegen_ssa on macOS to ship `llvm-objcopy` aliased to
- // `rust-objcopy` to workaround bad `strip`s on macOS.
- llvm_tools_enabled: true,
-
- ..Default::default()
- }
- }
-
pub fn set_dry_run(&mut self, dry_run: DryRun) {
self.exec_ctx.set_dry_run(dry_run);
}
@@ -1014,8 +960,8 @@ pub(crate) fn parse_inner(
Subcommand::Dist => flags_stage.or(build_dist_stage).unwrap_or(2),
Subcommand::Install => flags_stage.or(build_install_stage).unwrap_or(2),
Subcommand::Perf { .. } => flags_stage.unwrap_or(1),
- // These are all bootstrap tools, which don't depend on the compiler.
- // The stage we pass shouldn't matter, but use 0 just in case.
+ // Most of the run commands execute bootstrap tools, which don't depend on the compiler.
+ // Other commands listed here should always use bootstrap tools.
Subcommand::Clean { .. }
| Subcommand::Run { .. }
| Subcommand::Setup { .. }
@@ -1023,23 +969,38 @@ pub(crate) fn parse_inner(
| Subcommand::Vendor { .. } => flags_stage.unwrap_or(0),
};
- // Now check that the selected stage makes sense, and if not, print a warning and end
+ let local_rebuild = build_local_rebuild.unwrap_or(false);
+
+ let check_stage0 = |kind: &str| {
+ if local_rebuild {
+ eprintln!("WARNING: running {kind} in stage 0. This might not work as expected.");
+ } else {
+ eprintln!(
+ "ERROR: cannot {kind} anything on stage 0. Use at least stage 1 or set build.local-rebuild=true and use a stage0 compiler built from in-tree sources."
+ );
+ exit!(1);
+ }
+ };
+
+ // Now check that the selected stage makes sense, and if not, print an error and end
match (stage, &flags_cmd) {
(0, Subcommand::Build { .. }) => {
- eprintln!("ERROR: cannot build anything on stage 0. Use at least stage 1.");
- exit!(1);
+ check_stage0("build");
}
(0, Subcommand::Check { .. }) => {
- eprintln!("ERROR: cannot check anything on stage 0. Use at least stage 1.");
- exit!(1);
+ check_stage0("check");
}
(0, Subcommand::Doc { .. }) => {
- eprintln!("ERROR: cannot document anything on stage 0. Use at least stage 1.");
- exit!(1);
+ check_stage0("doc");
}
(0, Subcommand::Clippy { .. }) => {
- eprintln!("ERROR: cannot run clippy on stage 0. Use at least stage 1.");
- exit!(1);
+ check_stage0("clippy");
+ }
+ (0, Subcommand::Dist) => {
+ check_stage0("dist");
+ }
+ (0, Subcommand::Install) => {
+ check_stage0("install");
}
_ => {}
}
@@ -1154,7 +1115,11 @@ pub(crate) fn parse_inner(
let rustfmt_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/rustfmt"));
let optimized_compiler_builtins =
- build_optimized_compiler_builtins.unwrap_or(channel != "dev");
+ build_optimized_compiler_builtins.unwrap_or(if channel == "dev" {
+ CompilerBuiltins::BuildRustOnly
+ } else {
+ CompilerBuiltins::BuildLLVMFuncs
+ });
let vendor = build_vendor.unwrap_or(
rust_info.is_from_tarball()
&& src.join("vendor").exists()
@@ -1276,7 +1241,7 @@ pub(crate) fn parse_inner(
llvm_use_libcxx: llvm_use_libcxx.unwrap_or(false),
llvm_use_linker,
llvm_version_suffix,
- local_rebuild: build_local_rebuild.unwrap_or(false),
+ local_rebuild,
locked_deps: build_locked_deps.unwrap_or(false),
low_priority: build_low_priority.unwrap_or(false),
mandir: install_mandir.map(PathBuf::from),
@@ -1705,8 +1670,9 @@ pub fn enabled_codegen_backends(&self, target: TargetSelection) -> &[CodegenBack
/// Returns the codegen backend that should be configured as the *default* codegen backend
/// for a rustc compiled by bootstrap.
- pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<&CodegenBackendKind> {
- self.enabled_codegen_backends(target).first()
+ pub fn default_codegen_backend(&self, target: TargetSelection) -> &CodegenBackendKind {
+ // We're guaranteed to have always at least one codegen backend listed.
+ self.enabled_codegen_backends(target).first().unwrap()
}
pub fn jemalloc(&self, target: TargetSelection) -> bool {
@@ -1717,11 +1683,11 @@ pub fn rpath_enabled(&self, target: TargetSelection) -> bool {
self.target_config.get(&target).and_then(|t| t.rpath).unwrap_or(self.rust_rpath)
}
- pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
+ pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> &CompilerBuiltins {
self.target_config
.get(&target)
- .and_then(|t| t.optimized_compiler_builtins)
- .unwrap_or(self.optimized_compiler_builtins)
+ .and_then(|t| t.optimized_compiler_builtins.as_ref())
+ .unwrap_or(&self.optimized_compiler_builtins)
}
pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs
index dbd05fd..5999348 100644
--- a/src/bootstrap/src/core/config/mod.rs
+++ b/src/bootstrap/src/core/config/mod.rs
@@ -218,6 +218,33 @@ fn merge(
}
}
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub enum CompilerBuiltins {
+ #[default]
+ // Only build native rust intrinsic compiler functions.
+ BuildRustOnly,
+ // Some intrinsic functions have a C implementation provided by LLVM's
+ // compiler-rt builtins library. Build them from the LLVM source included
+ // with Rust.
+ BuildLLVMFuncs,
+ // Similar to BuildLLVMFuncs, but specify a path to an existing library
+ // containing LLVM's compiler-rt builtins instead of compiling them.
+ LinkLLVMBuiltinsLib(String),
+}
+
+impl<'de> Deserialize<'de> for CompilerBuiltins {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ Ok(match Deserialize::deserialize(deserializer)? {
+ StringOrBool::Bool(false) => Self::BuildRustOnly,
+ StringOrBool::Bool(true) => Self::BuildLLVMFuncs,
+ StringOrBool::String(path) => Self::LinkLLVMBuiltinsLib(path),
+ })
+ }
+}
+
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub enum DebuginfoLevel {
#[default]
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 50eba12..e93525f 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -17,7 +17,7 @@
use crate::core::build_steps::llvm;
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
use crate::core::config::toml::TomlConfig;
-use crate::core::config::{LldMode, Target, TargetSelection};
+use crate::core::config::{CompilerBuiltins, LldMode, StringOrBool, Target, TargetSelection};
use crate::utils::tests::git::git_test;
pub(crate) fn parse(config: &str) -> Config {
@@ -183,7 +183,11 @@ fn override_toml() {
);
assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
assert!(!config.deny_warnings, "setting boolean value");
- assert!(config.optimized_compiler_builtins, "setting boolean value");
+ assert_eq!(
+ config.optimized_compiler_builtins,
+ CompilerBuiltins::BuildLLVMFuncs,
+ "setting boolean value"
+ );
assert_eq!(
config.tools,
Some(["cargo".to_string()].into_iter().collect()),
@@ -212,7 +216,7 @@ fn override_toml() {
let darwin = TargetSelection::from_user("aarch64-apple-darwin");
let darwin_values = Target {
runner: Some("apple".into()),
- optimized_compiler_builtins: Some(false),
+ optimized_compiler_builtins: Some(CompilerBuiltins::BuildRustOnly),
..Default::default()
};
assert_eq!(
diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs
index 728367b..25c19f1 100644
--- a/src/bootstrap/src/core/config/toml/build.rs
+++ b/src/bootstrap/src/core/config/toml/build.rs
@@ -11,7 +11,7 @@
use serde::{Deserialize, Deserializer};
use crate::core::config::toml::ReplaceOpt;
-use crate::core::config::{Merge, StringOrBool};
+use crate::core::config::{CompilerBuiltins, Merge, StringOrBool};
use crate::{HashSet, PathBuf, define_config, exit};
define_config! {
@@ -65,7 +65,7 @@ struct Build {
// NOTE: only parsed by bootstrap.py, `--feature build-metrics` enables metrics unconditionally
metrics: Option<bool> = "metrics",
android_ndk: Option<PathBuf> = "android-ndk",
- optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
+ optimized_compiler_builtins: Option<CompilerBuiltins> = "optimized-compiler-builtins",
jobs: Option<u32> = "jobs",
compiletest_diff_tool: Option<String> = "compiletest-diff-tool",
compiletest_allow_stage0: Option<bool> = "compiletest-allow-stage0",
diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs
index 3dab8d1..c54df45 100644
--- a/src/bootstrap/src/core/config/toml/rust.rs
+++ b/src/bootstrap/src/core/config/toml/rust.rs
@@ -269,9 +269,9 @@ macro_rules! warn {
err!(current_profiler, profiler, "build");
let current_optimized_compiler_builtins =
- current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+ current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins.clone());
let optimized_compiler_builtins =
- ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+ ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins.clone());
err!(current_optimized_compiler_builtins, optimized_compiler_builtins, "build");
// We always build the in-tree compiler on cross targets, so we only care
@@ -415,6 +415,10 @@ pub(crate) fn parse_codegen_backends(
};
found_backends.push(backend);
}
+ if found_backends.is_empty() {
+ eprintln!("ERROR: `{section}.codegen-backends` should not be set to `[]`");
+ exit!(1);
+ }
found_backends
}
diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs
index 2c06fd0..020602e 100644
--- a/src/bootstrap/src/core/config/toml/target.rs
+++ b/src/bootstrap/src/core/config/toml/target.rs
@@ -11,7 +11,9 @@
use serde::{Deserialize, Deserializer};
-use crate::core::config::{LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool};
+use crate::core::config::{
+ CompilerBuiltins, LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool,
+};
use crate::{CodegenBackendKind, HashSet, PathBuf, define_config, exit};
define_config! {
@@ -39,7 +41,7 @@ struct TomlTarget {
no_std: Option<bool> = "no-std",
codegen_backends: Option<Vec<String>> = "codegen-backends",
runner: Option<String> = "runner",
- optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
+ optimized_compiler_builtins: Option<CompilerBuiltins> = "optimized-compiler-builtins",
jemalloc: Option<bool> = "jemalloc",
}
}
@@ -71,7 +73,7 @@ pub struct Target {
pub runner: Option<String>,
pub no_std: bool,
pub codegen_backends: Option<Vec<CodegenBackendKind>>,
- pub optimized_compiler_builtins: Option<bool>,
+ pub optimized_compiler_builtins: Option<CompilerBuiltins>,
pub jemalloc: Option<bool>,
}
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index de7cada..099ec48 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -18,7 +18,7 @@
use crate::builder::Kind;
#[cfg(not(test))]
use crate::core::build_steps::tool;
-use crate::core::config::Target;
+use crate::core::config::{CompilerBuiltins, Target};
use crate::utils::exec::command;
use crate::{Build, Subcommand};
@@ -34,6 +34,7 @@ pub struct Finder {
// Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
const STAGE0_MISSING_TARGETS: &[&str] = &[
"armv7a-vex-v5",
+ "riscv64a23-unknown-linux-gnu",
// just a dummy comment so the list doesn't get onelined
"aarch64_be-unknown-hermit",
"aarch64_be-unknown-none-softfloat",
@@ -330,7 +331,8 @@ pub fn check(build: &mut Build) {
// compiler-rt c fallbacks for wasm cannot be built with gcc
if target.contains("wasm")
- && (build.config.optimized_compiler_builtins(*target)
+ && (*build.config.optimized_compiler_builtins(*target)
+ != CompilerBuiltins::BuildRustOnly
|| build.config.rust_std_features.contains("compiler-builtins-c"))
{
let cc_tool = build.cc_tool(*target);
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index ec7edbf..b8ee83b 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -1950,6 +1950,20 @@ fn remove_dir(&self, dir: &Path) {
t!(fs::remove_dir_all(dir))
}
+ /// Make sure that `dir` will be an empty existing directory after this function ends.
+ /// If it existed before, it will be first deleted.
+ fn clear_dir(&self, dir: &Path) {
+ if self.config.dry_run() {
+ return;
+ }
+
+ #[cfg(feature = "tracing")]
+ let _span = trace_io!("dir-clear", ?dir);
+
+ let _ = std::fs::remove_dir_all(dir);
+ self.create_dir(dir);
+ }
+
fn read_dir(&self, dir: &Path) -> impl Iterator<Item = fs::DirEntry> {
let iter = match fs::read_dir(dir) {
Ok(v) => v,
diff --git a/src/bootstrap/src/utils/build_stamp.rs b/src/bootstrap/src/utils/build_stamp.rs
index 6c79385..4c35388 100644
--- a/src/bootstrap/src/utils/build_stamp.rs
+++ b/src/bootstrap/src/utils/build_stamp.rs
@@ -136,13 +136,13 @@ pub fn codegen_backend_stamp(
}
/// Cargo's output path for the standard library in a given stage, compiled
-/// by a particular compiler for the specified target.
+/// by a particular `build_compiler` for the specified `target`.
pub fn libstd_stamp(
builder: &Builder<'_>,
- compiler: Compiler,
+ build_compiler: Compiler,
target: TargetSelection,
) -> BuildStamp {
- BuildStamp::new(&builder.cargo_out(compiler, Mode::Std, target)).with_prefix("libstd")
+ BuildStamp::new(&builder.cargo_out(build_compiler, Mode::Std, target)).with_prefix("libstd")
}
/// Cargo's output path for librustc in a given stage, compiled by a particular
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 4fb5891..606d88d 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -516,4 +516,19 @@ pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
severity: ChangeSeverity::Info,
summary: "Build/check now supports forwarding `--timings` flag to cargo.",
},
+ ChangeInfo {
+ change_id: 145472,
+ severity: ChangeSeverity::Warning,
+ summary: "It is no longer possible to `x dist` or `x install` with stage 0. All dist and install commands have to be on stage 1+.",
+ },
+ ChangeInfo {
+ change_id: 143689,
+ severity: ChangeSeverity::Info,
+ summary: "The `optimized-compiler-builtins` option now accepts a path to an existing compiler-rt builtins library.",
+ },
+ ChangeInfo {
+ change_id: 145876,
+ severity: ChangeSeverity::Info,
+ summary: "It is now possible to `check/build/dist` the standard stage 0 library if you use a stage0 rustc built from in-tree sources. This is useful for quickly cross-compiling the standard library. You have to enable build.local-rebuild for this to work.",
+ },
];
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index 9a536f7..e09f308 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -264,8 +264,11 @@ pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
self
}
- pub fn do_not_cache(&mut self) -> &mut Self {
- self.should_cache = false;
+ /// Cache the command. If it will be executed multiple times with the exact same arguments
+ /// and environment variables in the same bootstrap invocation, the previous result will be
+ /// loaded from memory.
+ pub fn cached(&mut self) -> &mut Self {
+ self.should_cache = true;
self
}
@@ -425,7 +428,7 @@ impl From<Command> for BootstrapCommand {
fn from(command: Command) -> Self {
let program = command.get_program().to_owned();
Self {
- should_cache: true,
+ should_cache: false,
command,
failure_behavior: BehaviorOnFailure::Exit,
run_in_dry_run: false,
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 4514827..e802c02 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -510,6 +510,8 @@ pub fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String {
#[track_caller]
pub fn git(source_dir: Option<&Path>) -> BootstrapCommand {
let mut git = command("git");
+ // git commands are almost always read-only, so cache them by default
+ git.cached();
if let Some(source_dir) = source_dir {
git.current_dir(source_dir);
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index 40006ac..90fd57d 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -250,8 +250,14 @@ fn render_suite_outcome(&self, outcome: Outcome<'_>, suite: &SuiteOutcome) {
if failure.stdout.is_some() || failure.message.is_some() {
println!("---- {} stdout ----", failure.name);
if let Some(stdout) = &failure.stdout {
- println!("{stdout}");
+ // Captured test output normally ends with a newline,
+ // so only use `println!` if it doesn't.
+ print!("{stdout}");
+ if !stdout.ends_with('\n') {
+ println!("\n\\ (no newline at end of output)");
+ }
}
+ println!("---- {} stdout end ----", failure.name);
if let Some(message) = &failure.message {
println!("NOTE: {message}");
}
diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs
index 983680b..3332187 100644
--- a/src/bootstrap/src/utils/tests/mod.rs
+++ b/src/bootstrap/src/utils/tests/mod.rs
@@ -31,6 +31,10 @@ pub fn new() -> Self {
Self { directory }
}
+ pub fn dir(&self) -> &Path {
+ self.directory.path()
+ }
+
/// Starts a new invocation of bootstrap that executes `kind` as its top level command
/// (i.e. `x <kind>`). Returns a builder that configures the created config through CLI flags.
pub fn config(&self, kind: &str) -> ConfigBuilder {
diff --git a/src/build_helper/src/npm.rs b/src/build_helper/src/npm.rs
index 86cf618..5a7df09 100644
--- a/src/build_helper/src/npm.rs
+++ b/src/build_helper/src/npm.rs
@@ -27,7 +27,7 @@ pub fn install(src_root_path: &Path, out_dir: &Path, npm: &Path) -> Result<PathB
}
// disable a bunch of things we don't want.
// this makes tidy output less noisy, and also significantly improves runtime
- // of repeated tidy invokations.
+ // of repeated tidy invocations.
cmd.args(&["--audit=false", "--save=false", "--fund=false"]);
cmd.current_dir(out_dir);
let exit_status = cmd.spawn()?.wait()?;
diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs
index 62974be..8ba8f1a 100644
--- a/src/ci/citool/src/analysis.rs
+++ b/src/ci/citool/src/analysis.rs
@@ -75,7 +75,7 @@ fn eq(&self, other: &Self) -> bool {
}
}
- fn get_steps(step: &BuildStep) -> Vec<StepByName> {
+ fn get_steps(step: &BuildStep) -> Vec<StepByName<'_>> {
step.linearize_steps().into_iter().map(|v| StepByName(v)).collect()
}
diff --git a/src/ci/citool/src/test_dashboard.rs b/src/ci/citool/src/test_dashboard.rs
index 8fbd0d3..c9de388 100644
--- a/src/ci/citool/src/test_dashboard.rs
+++ b/src/ci/citool/src/test_dashboard.rs
@@ -33,7 +33,7 @@ fn write_page<T: Template>(dir: &Path, name: &str, template: &T) -> anyhow::Resu
Ok(())
}
-fn gather_test_suites(job_metrics: &HashMap<JobName, JobMetrics>) -> TestSuites {
+fn gather_test_suites(job_metrics: &HashMap<JobName, JobMetrics>) -> TestSuites<'_> {
struct CoarseTestSuite<'a> {
tests: BTreeMap<String, Test<'a>>,
}
diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs
index 0367d34..3176cb6 100644
--- a/src/ci/citool/src/utils.rs
+++ b/src/ci/citool/src/utils.rs
@@ -31,6 +31,6 @@ pub fn output_details<F>(summary: &str, func: F)
}
/// Normalizes Windows-style path delimiters to Unix-style paths.
-pub fn normalize_path_delimiters(name: &str) -> Cow<str> {
+pub fn normalize_path_delimiters(name: &str) -> Cow<'_, str> {
if name.contains("\\") { name.replace('\\', "/").into() } else { name.into() }
}
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile b/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
index cdbc1cd..0bb51af 100644
--- a/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
@@ -26,23 +26,10 @@
ENV HOST=aarch64-pc-windows-gnullvm
-# We are bootstrapping this target and cannot use previously built artifacts.
-# Without this option Clang is given `"-I/checkout/obj/build/aarch64-pc-windows-gnullvm/ci-llvm/include"`
-# despite no such directory existing:
-# $ ls obj/dist-windows-gnullvm/build/aarch64-pc-windows-gnullvm/ -1
-# llvm
-# stage2
-ENV NO_DOWNLOAD_CI_LLVM 1
-
ENV RUST_CONFIGURE_ARGS \
- --enable-extended \
+ --enable-full-tools \
--enable-profiler \
--enable-sanitizers \
- --disable-docs \
- --set llvm.download-ci-llvm=false \
- --set rust.llvm-tools=false
-# LLVM cross tools are not installed into expected location so copying fails.
-# Probably will solve itself once this target can host itself on Windows.
-# --enable-full-tools \
+ --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOST --target $HOST
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
index 1ee3951..da0c065 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
@@ -28,23 +28,10 @@
ENV HOST=x86_64-pc-windows-gnullvm
ENV TARGETS=i686-pc-windows-gnullvm,x86_64-pc-windows-gnullvm
-# We are bootstrapping this target and cannot use previously built artifacts.
-# Without this option Clang is given `"-I/checkout/obj/build/aarch64-pc-windows-gnullvm/ci-llvm/include"`
-# despite no such directory existing:
-# $ ls obj/dist-windows-gnullvm/build/aarch64-pc-windows-gnullvm/ -1
-# llvm
-# stage2
-ENV NO_DOWNLOAD_CI_LLVM 1
-
ENV RUST_CONFIGURE_ARGS \
- --enable-extended \
+ --enable-full-tools \
--enable-profiler \
--enable-sanitizers \
- --disable-docs \
- --set llvm.download-ci-llvm=false \
- --set rust.llvm-tools=false
-# LLVM cross tools are not installed into expected location so copying fails.
-# Probably will solve itself once these targets can host themselves on Windows.
-# --enable-full-tools \
+ --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOST --target $TARGETS
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index b97568b..5052d86 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -38,11 +38,15 @@
--build=x86_64-unknown-linux-gnu \
--enable-debug \
--enable-lld \
+ --set rust.debuginfo-level-tests=1 \
--set llvm.use-linker=lld \
--set target.x86_64-unknown-linux-gnu.linker=clang \
--set target.x86_64-unknown-linux-gnu.cc=clang \
--set target.x86_64-unknown-linux-gnu.cxx=clang++
+# This job checks:
+# - That ui tests can be built with `-Cdebuginfo=1`
+
# This job appears to be checking two separate things:
# - That we can build the compiler with `--enable-debug`
# (without necessarily testing the result).
@@ -51,4 +55,5 @@
ENV SCRIPT \
python3 ../x.py --stage 2 build && \
+ python3 ../x.py --stage 2 test tests/ui && \
python3 ../x.py --stage 2 test tests/run-make
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
index 98fd31a..5bafd89 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
@@ -33,9 +33,7 @@
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
-# We are disabling CI LLVM since distcheck is an offline build.
-ENV NO_DOWNLOAD_CI_LLVM 1
+# Make distcheck builds faster
+ENV DISTCHECK_CONFIGURE_ARGS "--enable-sccache"
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.omit-git-hash=false
-ENV SCRIPT python3 ../x.py --stage 2 test distcheck
-ENV DIST_SRC 1
+ENV SCRIPT python3 ../x.py test distcheck
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 409d2cb..35b9456 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -104,10 +104,10 @@
# These jobs automatically inherit envs.pr, to avoid repeating it in each job
# definition.
#
-# PR CI jobs will be automatically registered as Auto CI jobs or overriden. When
+# PR CI jobs will be automatically registered as Auto CI jobs or overridden. When
# automatically registered, the PR CI job configuration will be copied as an
-# Auto CI job but with `continue_on_error` overriden to `false` (to fail-fast).
-# When overriden, `citool` will check for equivalence between the PR and CI job
+# Auto CI job but with `continue_on_error` overridden to `false` (to fail-fast).
+# When overridden, `citool` will check for equivalence between the PR and CI job
# of the same name modulo `continue_on_error` and `env`.
pr:
- name: pr-check-1
@@ -166,7 +166,7 @@
#
# Auto jobs may not specify `continue_on_error: true`, and thus will fail-fast.
#
-# Unless explicitly overriden, PR CI jobs will be automatically registered as
+# Unless explicitly overridden, PR CI jobs will be automatically registered as
# Auto CI jobs.
auto:
#############################
diff --git a/src/ci/scripts/free-disk-space-linux.sh b/src/ci/scripts/free-disk-space-linux.sh
index 32649fe..ac3c9cf 100755
--- a/src/ci/scripts/free-disk-space-linux.sh
+++ b/src/ci/scripts/free-disk-space-linux.sh
@@ -221,10 +221,13 @@
)
fi
- sudo apt-get -qq remove -y --fix-missing "${packages[@]}"
+ WAIT_DPKG_LOCK="-o DPkg::Lock::Timeout=60"
+ sudo apt-get ${WAIT_DPKG_LOCK} -qq remove -y --fix-missing "${packages[@]}"
- sudo apt-get autoremove -y || echo "::warning::The command [sudo apt-get autoremove -y] failed"
- sudo apt-get clean || echo "::warning::The command [sudo apt-get clean] failed failed"
+ sudo apt-get ${WAIT_DPKG_LOCK} autoremove -y \
+ || echo "::warning::The command [sudo apt-get autoremove -y] failed"
+ sudo apt-get ${WAIT_DPKG_LOCK} clean \
+ || echo "::warning::The command [sudo apt-get clean] failed"
}
# Remove Docker images.
diff --git a/src/doc/nomicon b/src/doc/nomicon
index 3ff3843..57ed447 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit 3ff384320598bbe8d8cfe5cb8f18f78a3a3e6b15
+Subproject commit 57ed4473660565d9357fcae176b358d7e8724ebf
diff --git a/src/doc/reference b/src/doc/reference
index 59b8af8..89f67b3 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 59b8af811886313577615c2cf0e045f01faed88b
+Subproject commit 89f67b3c1b904cbcd9ed55e443d6fc67c8ca2769
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index adc1f3b..ad27f82 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit adc1f3b9012ad3255eea2054ca30596a953d053d
+Subproject commit ad27f82c18464525c761a4a8db2e01785da59e1f
diff --git a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
index 04d6469..5ff3118 100644
--- a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
+++ b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
@@ -3,8 +3,8 @@
on:
workflow_dispatch:
schedule:
- # Run at 04:00 UTC every Monday and Thursday
- - cron: '0 4 * * 1,4'
+ # Run at 04:00 UTC every Monday
+ - cron: '0 4 * * 1'
jobs:
pull:
diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version
index 6ec700b..f412399 100644
--- a/src/doc/rustc-dev-guide/rust-version
+++ b/src/doc/rustc-dev-guide/rust-version
@@ -1 +1 @@
-6bcdcc73bd11568fd85f5a38b58e1eda054ad1cd
+a1dbb443527bd126452875eb5d5860c1d001d761
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index 025a078..a161273 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -103,6 +103,7 @@
- [The `rustdoc-json` test suite](./rustdoc-internals/rustdoc-json-test-suite.md)
- [GPU offload internals](./offload/internals.md)
- [Installation](./offload/installation.md)
+ - [Usage](./offload/usage.md)
- [Autodiff internals](./autodiff/internals.md)
- [Installation](./autodiff/installation.md)
- [How to debug](./autodiff/debugging.md)
diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md
index 057e4a4..f395772 100644
--- a/src/doc/rustc-dev-guide/src/about-this-guide.md
+++ b/src/doc/rustc-dev-guide/src/about-this-guide.md
@@ -74,7 +74,6 @@
of the team procedures, active working groups, and the team calendar.
- [std-dev-guide] -- a similar guide for developing the standard library.
- [The t-compiler zulip][z]
-- `#contribute` and `#wg-rustup` on [Discord](https://discord.gg/rust-lang).
- The [Rust Internals forum][rif], a place to ask questions and
discuss Rust's internals
- The [Rust reference][rr], even though it doesn't specifically talk about
diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
index da425d8..bfd75eb 100644
--- a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
+++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
@@ -23,7 +23,7 @@
### Overview
-- Stage 0: the pre-compiled compiler
+- Stage 0: the pre-compiled compiler and standard library
- Stage 1: from current code, by an earlier compiler
- Stage 2: the truly current compiler
- Stage 3: the same-result test
@@ -192,7 +192,7 @@
artifacts'). If you're working on the standard library, this is normally the
test command you want.
- `./x build --stage 0` means to build with the stage0 `rustc`.
-- `./x doc --stage 0` means to document using the stage0 `rustdoc`.
+- `./x doc --stage 1` means to document using the stage0 `rustdoc`.
#### Examples of what *not* to do
@@ -211,7 +211,7 @@
In short, _stage 0 uses the `stage0` compiler to create `stage0` artifacts which
will later be uplifted to be the stage1 compiler_.
-In each stage, two major steps are performed:
+In each stage besides 0, two major steps are performed:
1. `std` is compiled by the stage N compiler.
2. That `std` is linked to programs built by the stage N compiler, including the
diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
index 1b6b87e..1693432 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
@@ -20,7 +20,7 @@
the compiler. Rust prides itself on helpful error messages and long-form
explanations are no exception. However, before error explanations are
overhauled[^new-explanations] it is a bit open as to how exactly they should be
-written, as always: ask your reviewer or ask around on the Rust Discord or Zulip.
+written, as always: ask your reviewer or ask around on the Rust Zulip.
[^new-explanations]: See the draft RFC [here][new-explanations-rfc].
diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md
index 04d2e37..87e26d3 100644
--- a/src/doc/rustc-dev-guide/src/getting-started.md
+++ b/src/doc/rustc-dev-guide/src/getting-started.md
@@ -11,7 +11,6 @@
chapter on how to build and run the compiler](./building/how-to-build-and-run.md).
[internals]: https://internals.rust-lang.org
-[rust-discord]: http://discord.gg/rust-lang
[rust-zulip]: https://rust-lang.zulipchat.com
[coc]: https://www.rust-lang.org/policies/code-of-conduct
[walkthrough]: ./walkthrough.md
@@ -20,8 +19,7 @@
## Asking Questions
If you have questions, please make a post on the [Rust Zulip server][rust-zulip] or
-[internals.rust-lang.org][internals]. If you are contributing to Rustup, be aware they are not on
-Zulip - you can ask questions in `#wg-rustup` [on Discord][rust-discord].
+[internals.rust-lang.org][internals].
See the [list of teams and working groups][governance] and [the Community page][community] on the
official website for more resources.
@@ -30,19 +28,23 @@
As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
-The compiler team (or `t-compiler`) usually hangs out in Zulip [in this
-"stream"][z]; it will be easiest to get questions answered there.
+The compiler team (or `t-compiler`) usually hangs out in Zulip in
+[the #t-compiler channel][z-t-compiler];
+questions about how the compiler works can go in [#t-compiler/help][z-help].
-[z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler
+[z-t-compiler]: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler
+[z-help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp
**Please ask questions!** A lot of people report feeling that they are "wasting
-expert time", but nobody on `t-compiler` feels this way. Contributors are
+expert's time", but nobody on `t-compiler` feels this way. Contributors are
important to us.
Also, if you feel comfortable, prefer public topics, as this means others can
see the questions and answers, and perhaps even integrate them back into this
guide :)
+**Tip**: If you're not a native English speaker and feel unsure about writing, try using a translator to help. But avoid using LLM tools that generate long, complex words. In daily teamwork, **simple and clear words** are best for easy understanding. Even small typos or grammar mistakes can make you seem more human, and people connect better with humans.
+
### Experts
Not all `t-compiler` members are experts on all parts of `rustc`; it's a
@@ -162,15 +164,12 @@
- [Triaging issues][triage]: categorizing, replicating, and minimizing issues is very helpful to the Rust maintainers.
- [Working groups][wg]: there are a bunch of working groups on a wide variety
of rust-related things.
-- Answer questions in the _Get Help!_ channels on the [Rust Discord
- server][rust-discord], on [users.rust-lang.org][users], or on
- [StackOverflow][so].
+- Answer questions on [users.rust-lang.org][users], or on [Stack Overflow][so].
- Participate in the [RFC process](https://github.com/rust-lang/rfcs).
- Find a [requested community library][community-library], build it, and publish
it to [Crates.io](http://crates.io). Easier said than done, but very, very
valuable!
-[rust-discord]: https://discord.gg/rust-lang
[users]: https://users.rust-lang.org/
[so]: http://stackoverflow.com/questions/tagged/rust
[community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library
diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md
index 447c6fd..8f0511a 100644
--- a/src/doc/rustc-dev-guide/src/git.md
+++ b/src/doc/rustc-dev-guide/src/git.md
@@ -338,13 +338,13 @@
### Keeping things up to date
-The above section on [Rebasing](#rebasing) is a specific
+The [above section](#rebasing) is a specific
guide on rebasing work and dealing with merge conflicts.
Here is some general advice about how to keep your local repo
up-to-date with upstream changes:
Using `git pull upstream master` while on your local master branch regularly
-will keep it up-to-date. You will also want to rebase your feature branches
+will keep it up-to-date. You will also want to keep your feature branches
up-to-date as well. After pulling, you can checkout the feature branches
and rebase them:
diff --git a/src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.png b/src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.png
index c445f35..7c6c845 100644
--- a/src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.png
+++ b/src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.png b/src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.png
index 718411a..7baa37e 100644
--- a/src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.png
+++ b/src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/github-cli.png b/src/doc/rustc-dev-guide/src/img/github-cli.png
index c3b0e77..88ba95f 100644
--- a/src/doc/rustc-dev-guide/src/img/github-cli.png
+++ b/src/doc/rustc-dev-guide/src/img/github-cli.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/github-whitespace-changes.png b/src/doc/rustc-dev-guide/src/img/github-whitespace-changes.png
index 9a19a10..e235a30 100644
--- a/src/doc/rustc-dev-guide/src/img/github-whitespace-changes.png
+++ b/src/doc/rustc-dev-guide/src/img/github-whitespace-changes.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.png b/src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.png
index 35f0459..ce4dec1 100644
--- a/src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.png
+++ b/src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/other-peoples-commits.png b/src/doc/rustc-dev-guide/src/img/other-peoples-commits.png
index e4fc2c7..0c949d88 100644
--- a/src/doc/rustc-dev-guide/src/img/other-peoples-commits.png
+++ b/src/doc/rustc-dev-guide/src/img/other-peoples-commits.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/rustbot-submodules.png b/src/doc/rustc-dev-guide/src/img/rustbot-submodules.png
index c2e6937..c099fdf 100644
--- a/src/doc/rustc-dev-guide/src/img/rustbot-submodules.png
+++ b/src/doc/rustc-dev-guide/src/img/rustbot-submodules.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/submodule-conflicts.png b/src/doc/rustc-dev-guide/src/img/submodule-conflicts.png
index e90a6bb..5d4caf0 100644
--- a/src/doc/rustc-dev-guide/src/img/submodule-conflicts.png
+++ b/src/doc/rustc-dev-guide/src/img/submodule-conflicts.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/wpa-initial-memory.png b/src/doc/rustc-dev-guide/src/img/wpa-initial-memory.png
index b602066..177d92c 100644
--- a/src/doc/rustc-dev-guide/src/img/wpa-initial-memory.png
+++ b/src/doc/rustc-dev-guide/src/img/wpa-initial-memory.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/wpa-stack.png b/src/doc/rustc-dev-guide/src/img/wpa-stack.png
index 29eb5a5..a4a7135 100644
--- a/src/doc/rustc-dev-guide/src/img/wpa-stack.png
+++ b/src/doc/rustc-dev-guide/src/img/wpa-stack.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/macro-expansion.md b/src/doc/rustc-dev-guide/src/macro-expansion.md
index 54d6d2b..96f12b7 100644
--- a/src/doc/rustc-dev-guide/src/macro-expansion.md
+++ b/src/doc/rustc-dev-guide/src/macro-expansion.md
@@ -517,8 +517,9 @@
are about to ask the MBE parser to parse. We will consume the raw stream of
tokens and output a binding of metavariables to corresponding token trees.
The parsing session can be used to report parser errors.
-- a `matcher` variable is a sequence of [`MatcherLoc`]s that we want to match
- the token stream against. They're converted from token trees before matching.
+- a `matcher` variable is a sequence of [`MatcherLoc`]s that we want to match the token stream
+ against. They're converted from the original token trees in the macro's definition before
+ matching.
[`MatcherLoc`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/mbe/macro_parser/enum.MatcherLoc.html
@@ -544,41 +545,26 @@
The macro parser does pretty much exactly the same as a normal regex parser
with one exception: in order to parse different types of metavariables, such as
`ident`, `block`, `expr`, etc., the macro parser must call back to the normal
-Rust parser. Both the definition and invocation of macros are parsed using
-the parser in a process which is non-intuitively self-referential.
+Rust parser.
-The code to parse macro _definitions_ is in
-[`compiler/rustc_expand/src/mbe/macro_rules.rs`][code_mr]. It defines the
-pattern for matching a macro definition as `$( $lhs:tt => $rhs:tt );+`. In
-other words, a `macro_rules` definition should have in its body at least one
-occurrence of a token tree followed by `=>` followed by another token tree.
-When the compiler comes to a `macro_rules` definition, it uses this pattern to
-match the two token trees per the rules of the definition of the macro, _thereby
-utilizing the macro parser itself_. In our example definition, the
-metavariable `$lhs` would match the patterns of both arms: `(print
-$mvar:ident)` and `(print twice $mvar:ident)`. And `$rhs` would match the
-bodies of both arms: `{ println!("{}", $mvar); }` and `{ println!("{}", $mvar);
-println!("{}", $mvar); }`. The parser keeps this knowledge around for when it
-needs to expand a macro invocation.
+The code to parse macro definitions is in [`compiler/rustc_expand/src/mbe/macro_rules.rs`][code_mr].
+For more information about the macro parser's implementation, see the comments in
+[`compiler/rustc_expand/src/mbe/macro_parser.rs`][code_mp].
-When the compiler comes to a macro invocation, it parses that invocation using
-a NFA-based macro parser described above. However, the matcher variable
-used is the first token tree (`$lhs`) extracted from the arms of the macro
-_definition_. Using our example, we would try to match the token stream `print
-foo` from the invocation against the matchers `print $mvar:ident` and `print
-twice $mvar:ident` that we previously extracted from the definition. The
-algorithm is exactly the same, but when the macro parser comes to a place in the
-current matcher where it needs to match a _non-terminal_ (e.g. `$mvar:ident`),
-it calls back to the normal Rust parser to get the contents of that
-non-terminal. In this case, the Rust parser would look for an `ident` token,
-which it finds (`foo`) and returns to the macro parser. Then, the macro parser
-proceeds in parsing as normal. Also, note that exactly one of the matchers from
-the various arms should match the invocation; if there is more than one match,
-the parse is ambiguous, while if there are no matches at all, there is a syntax
+Using our example, we would try to match the token stream `print foo` from the invocation against
+the matchers `print $mvar:ident` and `print twice $mvar:ident` that we previously extracted from the
+rules in the macro definition. When the macro parser comes to a place in the current matcher where
+it needs to match a _non-terminal_ (e.g. `$mvar:ident`), it calls back to the normal Rust parser to
+get the contents of that non-terminal. In this case, the Rust parser would look for an `ident`
+token, which it finds (`foo`) and returns to the macro parser. Then, the macro parser continues
+parsing.
+
+Note that exactly one of the matchers from the various rules should match the invocation; if there is
+more than one match, the parse is ambiguous, while if there are no matches at all, there is a syntax
error.
-For more information about the macro parser's implementation, see the comments
-in [`compiler/rustc_expand/src/mbe/macro_parser.rs`][code_mp].
+Assuming exactly one rule matches, macro expansion will then *transcribe* the right-hand side of the
+rule, substituting the values of any matches it captured when matching against the left-hand side.
## Procedural Macros
diff --git a/src/doc/rustc-dev-guide/src/offload/installation.md b/src/doc/rustc-dev-guide/src/offload/installation.md
index b376e96..d1ebf33 100644
--- a/src/doc/rustc-dev-guide/src/offload/installation.md
+++ b/src/doc/rustc-dev-guide/src/offload/installation.md
@@ -1,6 +1,6 @@
# Installation
-In the future, `std::offload` should become available in nightly builds for users. For now, everyone still needs to build rustc from source.
+`std::offload` is partly available in nightly builds for users. For now, everyone however still needs to build rustc from source to use all features of it.
## Build instructions
@@ -42,30 +42,3 @@
```
./x test --stage 1 tests/codegen-llvm/gpu_offload
```
-
-## Usage
-It is important to use a clang compiler build on the same llvm as rustc. Just calling clang without the full path will likely use your system clang, which probably will be incompatible.
-```
-/absolute/path/to/rust/build/x86_64-unknown-linux-gnu/stage1/bin/rustc --edition=2024 --crate-type cdylib src/main.rs --emit=llvm-ir -O -C lto=fat -Cpanic=abort -Zoffload=Enable
-/absolute/path/to/rust/build/x86_64-unknown-linux-gnu/llvm/bin/clang++ -fopenmp --offload-arch=native -g -O3 main.ll -o main -save-temps
-LIBOMPTARGET_INFO=-1 ./main
-```
-The first step will generate a `main.ll` file, which has enough instructions to cause the offload runtime to move data to and from a gpu.
-The second step will use clang as the compilation driver to compile our IR file down to a working binary. Only a very small Rust subset will work out of the box here, unless
-you use features like build-std, which are not covered by this guide. Look at the codegen test to get a feeling for how to write a working example.
-In the last step you can run your binary, if all went well you will see a data transfer being reported:
-```
-omptarget device 0 info: Entering OpenMP data region with being_mapper at unknown:0:0 with 1 arguments:
-omptarget device 0 info: tofrom(unknown)[1024]
-omptarget device 0 info: Creating new map entry with HstPtrBase=0x00007fffffff9540, HstPtrBegin=0x00007fffffff9540, TgtAllocBegin=0x0000155547200000, TgtPtrBegin=0x0000155547200000, Size=1024, DynRefCount=1, HoldRefCount=0, Name=unknown
-omptarget device 0 info: Copying data from host to device, HstPtr=0x00007fffffff9540, TgtPtr=0x0000155547200000, Size=1024, Name=unknown
-omptarget device 0 info: OpenMP Host-Device pointer mappings after block at unknown:0:0:
-omptarget device 0 info: Host Ptr Target Ptr Size (B) DynRefCount HoldRefCount Declaration
-omptarget device 0 info: 0x00007fffffff9540 0x0000155547200000 1024 1 0 unknown at unknown:0:0
-// some other output
-omptarget device 0 info: Exiting OpenMP data region with end_mapper at unknown:0:0 with 1 arguments:
-omptarget device 0 info: tofrom(unknown)[1024]
-omptarget device 0 info: Mapping exists with HstPtrBegin=0x00007fffffff9540, TgtPtrBegin=0x0000155547200000, Size=1024, DynRefCount=0 (decremented, delayed deletion), HoldRefCount=0
-omptarget device 0 info: Copying data from device to host, TgtPtr=0x0000155547200000, HstPtr=0x00007fffffff9540, Size=1024, Name=unknown
-omptarget device 0 info: Removing map entry with HstPtrBegin=0x00007fffffff9540, TgtPtrBegin=0x0000155547200000, Size=1024, Name=unknown
-```
diff --git a/src/doc/rustc-dev-guide/src/offload/usage.md b/src/doc/rustc-dev-guide/src/offload/usage.md
new file mode 100644
index 0000000..9f51998
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/offload/usage.md
@@ -0,0 +1,112 @@
+# Usage
+
+This feature is work-in-progress, and not ready for usage. The instructions here are for contributors, or people interested in following the latest progress.
+We currently work on launching the following Rust kernel on the GPU. To follow along, copy it to a `src/lib.rs` file.
+
+```rust
+#![feature(abi_gpu_kernel)]
+#![no_std]
+
+#[cfg(target_os = "linux")]
+extern crate libc;
+#[cfg(target_os = "linux")]
+use libc::c_char;
+
+use core::mem;
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[cfg(target_os = "linux")]
+#[unsafe(no_mangle)]
+#[inline(never)]
+fn main() {
+ let array_c: *mut [f64; 256] =
+ unsafe { libc::calloc(256, (mem::size_of::<f64>()) as libc::size_t) as *mut [f64; 256] };
+ let output = c"The first element is zero %f\n";
+ let output2 = c"The first element is NOT zero %f\n";
+ let output3 = c"The second element is %f\n";
+ unsafe {
+ let val: *const c_char = if (*array_c)[0] < 0.1 {
+ output.as_ptr()
+ } else {
+ output2.as_ptr()
+ };
+ libc::printf(val, (*array_c)[0]);
+ }
+
+ unsafe {
+ kernel_1(array_c);
+ }
+ core::hint::black_box(&array_c);
+ unsafe {
+ let val: *const c_char = if (*array_c)[0] < 0.1 {
+ output.as_ptr()
+ } else {
+ output2.as_ptr()
+ };
+ libc::printf(val, (*array_c)[0]);
+ libc::printf(output3.as_ptr(), (*array_c)[1]);
+ }
+}
+
+#[cfg(target_os = "linux")]
+unsafe extern "C" {
+ pub fn kernel_1(array_b: *mut [f64; 256]);
+}
+```
+
+## Compile instructions
+It is important to use a clang compiler build on the same llvm as rustc. Just calling clang without the full path will likely use your system clang, which probably will be incompatible. So either substitute clang/lld invocations below with absolute path, or set your `PATH` accordingly.
+
+First we generate the host (cpu) code. The first build is just to compile libc, take note of the hashed path. Then we call rustc directly to build our host code, while providing the libc artifact to rustc.
+```
+cargo +offload build -r -v
+rustc +offload --edition 2024 src/lib.rs -g --crate-type cdylib -C opt-level=3 -C panic=abort -C lto=fat -L dependency=/absolute_path_to/target/release/deps --extern libc=/absolute_path_to/target/release/deps/liblibc-<HASH>.rlib --emit=llvm-bc,llvm-ir -Zoffload=Enable -Zunstable-options
+```
+
+Now we generate the device code. Replace the target-cpu with the right code for your gpu.
+```
+RUSTFLAGS="-Ctarget-cpu=gfx90a --emit=llvm-bc,llvm-ir" cargo +offload build -Zunstable-options -r -v --target amdgcn-amd-amdhsa -Zbuild-std=core
+```
+
+Now find the <libname>.ll under target/amdgcn-amd-amdhsa folder and copy it to a device.ll file (or adjust the file names below).
+If you work on an NVIDIA or Intel gpu, please adjust the names acordingly and open an issue to share your results (either if you succeed or fail).
+First we compile our .ll files (good for manual inspections) to .bc files and clean up leftover artifacts. The cleanup is important, otherwise caching might interfere on following runs.
+```
+opt lib.ll -o lib.bc
+opt device.ll -o device.bc
+rm *.o
+rm bare.amdgcn.gfx90a.img*
+```
+
+```
+clang-offload-packager" "-o" "host.out" "--image=file=device.bc,triple=amdgcn-amd-amdhsa,arch=gfx90a,kind=openmp"
+
+clang-21" "-cc1" "-triple" "x86_64-unknown-linux-gnu" "-S" "-save-temps=cwd" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "lib.rs" "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-funwind-tables=2" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-resource-dir" "/<ABSOLUTE_PATH_TO>/rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21" "-ferror-limit" "19" "-fopenmp" "-fopenmp-offload-mandatory" "-fgnuc-version=4.2.1" "-fskip-odr-check-in-gmf" "-fembed-offload-object=host.out" "-fopenmp-targets=amdgcn-amd-amdhsa" "-faddrsig" "-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o" "host.s" "-x" "ir" "lib.bc"
+
+clang-21" "-cc1as" "-triple" "x86_64-unknown-linux-gnu" "-filetype" "obj" "-main-file-name" "lib.rs" "-target-cpu" "x86-64" "-mrelocation-model" "pic" "-o" "host.o" "host.s"
+
+clang-linker-wrapper" "--should-extract=gfx90a" "--device-compiler=amdgcn-amd-amdhsa=-g" "--device-compiler=amdgcn-amd-amdhsa=-save-temps=cwd" "--device-linker=amdgcn-amd-amdhsa=-lompdevice" "--host-triple=x86_64-unknown-linux-gnu" "--save-temps" "--linker-path=/ABSOlUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/lld/bin/ld.lld" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-pie" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "bare" "/lib/../lib64/Scrt1.o" "/lib/../lib64/crti.o" "/ABSOLUTE_PATH_TO/crtbeginS.o" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/bin/../lib/x86_64-unknown-linux-gnu" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21/lib/x86_64-unknown-linux-gnu" "-L/lib/../lib64" "-L/usr/lib64" "-L/lib" "-L/usr/lib" "host.o" "-lstdc++" "-lm" "-lomp" "-lomptarget" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib" "-lgcc_s" "-lgcc" "-lpthread" "-lc" "-lgcc_s" "-lgcc" "/ABSOLUTE_PATH_TO/crtendS.o" "/lib/../lib64/crtn.o"
+```
+
+Especially for the last command I recommend to not fix the paths, but rather just re-generate them by copying a bare-mode openmp example and compiling it with your clang. By adding `-###` to your clang invocation, you can see the invidual steps.
+```
+myclang++ -fuse-ld=lld -O3 -fopenmp -fopenmp-offload-mandatory --offload-arch=gfx90a omp_bare.cpp -o main -###
+```
+
+In the final step, you can now run your binary
+
+```
+./main
+The first element is zero 0.000000
+The first element is NOT zero 21.000000
+The second element is 0.000000
+```
+
+To receive more information about the memory transfer, you can enable info printing with
+```
+LIBOMPTARGET_INFO=-1 ./main
+```
diff --git a/src/doc/rustc-dev-guide/src/queries/example-0.png b/src/doc/rustc-dev-guide/src/queries/example-0.png
index 14b46c4..dd67d5f 100644
--- a/src/doc/rustc-dev-guide/src/queries/example-0.png
+++ b/src/doc/rustc-dev-guide/src/queries/example-0.png
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md
index 750e4fa..a8cc959 100644
--- a/src/doc/rustc-dev-guide/src/tests/ci.md
+++ b/src/doc/rustc-dev-guide/src/tests/ci.md
@@ -84,16 +84,15 @@
> Thus, it is a good idea to run `./x doc xxx` locally for any doc comment
> changes to help catch these early.
-PR jobs are defined in the `pr` section of [`jobs.yml`]. They run under the
-`rust-lang/rust` repository, and their results can be observed directly on the
-PR, in the "CI checks" section at the bottom of the PR page.
+PR jobs are defined in the `pr` section of [`jobs.yml`]. Their results can be observed
+directly on the PR, in the "CI checks" section at the bottom of the PR page.
### Auto builds
Before a commit can be merged into the `master` branch, it needs to pass our
complete test suite. We call this an `auto` build. This build runs tens of CI
jobs that exercise various tests across operating systems and targets. The full
-test suite is quite slow; it can take two hours or more until all the `auto` CI
+test suite is quite slow; it can take several hours until all the `auto` CI
jobs finish.
Most platforms only run the build steps, some run a restricted set of tests,
@@ -136,14 +135,21 @@
[`jobs.yml`] will be executed. We call this mode a "fast try build". Such a try build
will not execute any tests, and it will allow compilation warnings. It is useful when you want to
get an optimized toolchain as fast as possible, for a crater run or performance benchmarks,
-even if it might not be working fully correctly.
+even if it might not be working fully correctly. If you want to do a full build for the default try job,
+specify its job name in a job pattern (explained below).
-If you want to run a custom CI job in a try build and make sure that it passes all tests and does
-not produce any compilation warnings, you can select CI jobs to be executed by adding lines
-containing `try-job: <job pattern>` to the PR description. All such specified jobs will be executed
-in the try build once the `@bors try` command is used on the PR.
+If you want to run custom CI job(s) in a try build and make sure that they pass all tests and do
+not produce any compilation warnings, you can select CI jobs to be executed by specifying a *job pattern*,
+which can be used in one of two ways:
+- You can add a set of `try-job: <job pattern>` directives to the PR description (described below) and then
+ simply run `@bors try`. CI will read these directives and run the jobs that you have specified. This is
+ useful if you want to rerun the same set of try jobs multiple times, after incrementally modifying a PR.
+- You can specify the job pattern using the `jobs` parameter of the try command: `@bors try jobs=<job pattern>`.
+ This is useful for one-off try builds with specific jobs. Note that the `jobs` parameter has a higher priority
+ than the PR description directives.
+ - There can also be multiple patterns specified, e.g. `@bors try jobs=job1,job2,job3`.
-Each pattern can either be an exact name of a job or a glob pattern that matches multiple jobs,
+Each job pattern can either be an exact name of a job or a glob pattern that matches multiple jobs,
for example `*msvc*` or `*-alt`. You can start at most 20 jobs in a single try build. When using
glob patterns, you might want to wrap them in backticks (`` ` ``) to avoid GitHub rendering
the pattern as Markdown.
@@ -182,26 +188,19 @@
> However, it can be less flexible because you cannot adjust the set of tests
> that are exercised this way.
-Try jobs are defined in the `try` section of [`jobs.yml`]. They are executed on
-the `try` branch under the `rust-lang/rust` repository and
+Try builds are executed on the `try` branch under the `rust-lang/rust` repository and
their results can be seen [here](https://github.com/rust-lang/rust/actions),
although usually you will be notified of the result by a comment made by bors on
the corresponding PR.
-Note that if you start the default try job using `@bors try`, it will skip building several `dist` components and running post-optimization tests, to make the build duration shorter. If you want to execute the full build as it would happen before a merge, add an explicit `try-job` pattern with the name of the default try job (currently `dist-x86_64-linux`).
+Multiple try builds can execute concurrently across different PRs, but there can be at most
+a single try build running on a single PR at any given time.
-Multiple try builds can execute concurrently across different PRs.
-
-<div class="warning">
-
-Bors identifies try jobs by commit hash. This means that if you have two PRs
-containing the same (latest) commits, running `@bors try` will result in the
-*same* try job and it really confuses `bors`. Please refrain from doing so.
-
-</div>
+Note that try builds are handled using the new [bors][new-bors] implementation.
[rustc-perf]: https://github.com/rust-lang/rustc-perf
[crater]: https://github.com/rust-lang/crater
+[new-bors]: https://github.com/rust-lang/bors
### Modifying CI jobs
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index f4ba9a0..fbbeb7e 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -111,6 +111,7 @@
| `forbid-output` | A pattern which must not appear in stderr/`cfail` output | `ui`, `incremental` | Regex pattern |
| `run-flags` | Flags passed to the test executable | `ui` | Arbitrary flags |
| `known-bug` | No error annotation needed due to known bug | `ui`, `crashes`, `incremental` | Issue number `#123456` |
+| `compare-output-by-lines` | Compare the output by lines, rather than as a single string | All | N/A |
[^check_stdout]: presently <!-- date-check: Oct 2024 --> this has a weird quirk
where the test binary's stdout and stderr gets concatenated and then
diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md
index b19d94d..75cf782 100644
--- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md
+++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md
@@ -18,12 +18,8 @@
is merged.
If you are worried that a pull request might break the Fuchsia builder and want
-to test it out before submitting it to the bors queue, simply add this line to
-your PR description:
-
-> try-job: x86_64-fuchsia
-
-Then when you `@bors try` it will pick the job that builds Fuchsia.
+to test it out before submitting it to the bors queue, simply ask bors to run
+the try job that builds the Fuchsia integration: `@bors try jobs=x86_64-fuchsia`.
## Building Fuchsia locally
diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md
index d549ec6..a6a7374 100644
--- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md
+++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md
@@ -40,12 +40,8 @@
this workflow notifies us if a given compiler change would break it.
If you are worried that a pull request might break the Rust for Linux builder
-and want to test it out before submitting it to the bors queue, simply add this
-line to your PR description:
-
-> try-job: x86_64-rust-for-linux
-
-Then when you `@bors try` it will pick the job that builds the Rust for Linux
-integration.
+and want to test it out before submitting it to the bors queue, simply ask
+bors to run the try job that builds the Rust for Linux integration:
+`@bors try jobs=x86_64-rust-for-linux`.
[rfl-ping]: ../../notification-groups/rust-for-linux.md
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index 25dd581..d3a2c40 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -95,6 +95,7 @@
[Normalization](#normalization)).
- `dont-check-compiler-stderr` — Ignores stderr from the compiler.
- `dont-check-compiler-stdout` — Ignores stdout from the compiler.
+- `compare-output-by-lines` — Some tests have non-deterministic orders of output, so we need to compare by lines.
UI tests run with `-Zdeduplicate-diagnostics=no` flag which disables rustc's
built-in diagnostic deduplication mechanism. This means you may see some
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index b53494ed9..e0d637a 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -49,6 +49,7 @@
- [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
- [aarch64-unknown-linux-musl](platform-support/aarch64-unknown-linux-musl.md)
- [aarch64_be-unknown-none-softfloat](platform-support/aarch64_be-unknown-none-softfloat.md)
+ - [aarch64_be-unknown-linux-musl](platform-support/aarch64_be-unknown-linux-musl.md)
- [amdgcn-amd-amdhsa](platform-support/amdgcn-amd-amdhsa.md)
- [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)
- [arm-none-eabi](platform-support/arm-none-eabi.md)
@@ -106,6 +107,7 @@
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
- [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
- [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md)
+ - [riscv64a23-unknown-linux-gnu](platform-support/riscv64a23-unknown-linux-gnu.md)
- [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
- [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
diff --git a/src/doc/rustc/src/command-line-arguments/print-options.md b/src/doc/rustc/src/command-line-arguments/print-options.md
index 1f33e91..fed19d6 100644
--- a/src/doc/rustc/src/command-line-arguments/print-options.md
+++ b/src/doc/rustc/src/command-line-arguments/print-options.md
@@ -32,7 +32,7 @@
## `sysroot`
-Abosulte path to the sysroot.
+Absolute path to the sysroot.
Example (with rustup and the stable toolchain):
diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png
index 0da45e5..3aad635 100644
--- a/src/doc/rustc/src/images/image1.png
+++ b/src/doc/rustc/src/images/image1.png
Binary files differ
diff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png
index a9cf23f..085b1c4 100644
--- a/src/doc/rustc/src/images/image2.png
+++ b/src/doc/rustc/src/images/image2.png
Binary files differ
diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png
index 844a2fe..ee332f5 100644
--- a/src/doc/rustc/src/images/image3.png
+++ b/src/doc/rustc/src/images/image3.png
Binary files differ
diff --git a/src/doc/rustc/src/images/llvm-cov-show-01.png b/src/doc/rustc/src/images/llvm-cov-show-01.png
index 35f0459..ce4dec1 100644
--- a/src/doc/rustc/src/images/llvm-cov-show-01.png
+++ b/src/doc/rustc/src/images/llvm-cov-show-01.png
Binary files differ
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 3bf8799..edfc2db 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -103,7 +103,6 @@
[`powerpc64le-unknown-linux-gnu`](platform-support/powerpc64le-unknown-linux-gnu.md) | PPC64LE Linux (kernel 3.10+, glibc 2.17)
[`powerpc64le-unknown-linux-musl`](platform-support/powerpc64le-unknown-linux-musl.md) | PPC64LE Linux (kernel 4.19+, musl 1.2.3)
[`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20+, glibc 2.29)
-[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20+, musl 1.2.3)
[`s390x-unknown-linux-gnu`](platform-support/s390x-unknown-linux-gnu.md) | S390x Linux (kernel 3.2+, glibc 2.17)
[`x86_64-apple-darwin`](platform-support/apple-darwin.md) | 64-bit macOS (10.12+, Sierra+)
[`x86_64-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | 64-bit x86 MinGW (Windows 10+), LLVM ABI
@@ -183,6 +182,7 @@
[`riscv32imac-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA)
[`riscv32imafc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
[`riscv32imc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA)
+[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20+, musl 1.2.3)
`riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
`riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
`sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4+, glibc 2.23)
@@ -273,6 +273,7 @@
[`aarch64_be-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit (big-endian)
`aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
`aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
+[`aarch64_be-unknown-linux-musl`](platform-support/aarch64_be-unknown-linux-musl.md) | ✓ | ✓ | ARM64 Linux (big-endian) with musl-libc 1.2.5
[`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian)
[`aarch64_be-unknown-none-softfloat`](platform-support/aarch64_be-unknown-none-softfloat.md) | * | | Bare big-endian ARM64, softfloat
[`amdgcn-amd-amdhsa`](platform-support/amdgcn-amd-amdhsa.md) | * | | `-Ctarget-cpu=gfx...` to specify [the AMD GPU] to compile for
@@ -327,8 +328,8 @@
[`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
[`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [^x86_32-floats-return-ABI]
[`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | LoongArch64 OpenHarmony
-[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32D ABI)
-[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32S ABI)
+[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch32 Bare-metal (ILP32D ABI)
+[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch32 Bare-metal (ILP32S ABI)
[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux
[`m68k-unknown-none-elf`](platform-support/m68k-unknown-none-elf.md) | | | Motorola 680x0
`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
@@ -391,6 +392,7 @@
[`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
[`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX
+[`riscv64a23-unknown-linux-gnu`](platform-support/riscv64a23-unknown-linux-gnu.md) | ✓ | ✓ | RISC-V Linux (kernel 6.8.0+, glibc 2.39)
[`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | ✓ | | S390x Linux (kernel 3.2, musl 1.2.3)
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+
diff --git a/src/doc/rustc/src/platform-support/aarch64_be-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/aarch64_be-unknown-linux-musl.md
new file mode 100644
index 0000000..3e816dc
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/aarch64_be-unknown-linux-musl.md
@@ -0,0 +1,49 @@
+# aarch64_be-unknown-linux-musl
+
+**Tier: 3**
+
+ARM64 Linux (big-endian) with musl-libc.
+
+## Target maintainers
+
+[@neuschaefer](https://github.com/neuschaefer)
+[@Gelbpunkt](https://github.com/Gelbpunkt)
+
+## Requirements
+
+The target requires a `aarch64_be-*-linux-musl` toolchain, which likely has to
+be built from source because this is a rare combination. [Buildroot] provides
+a way of doing so:
+
+- select _Target options_ → _Target Architecture_ → _AArch64 (big endian)_
+- select _Toolchain_ → _C library_ → _musl_
+- select _Toolchain_ → _Enable C++ support_
+
+Host tools are supported.
+
+[Buildroot]: https://buildroot.org/
+
+
+## Building the target
+
+The target can be enabled in bootstrap.toml:
+
+```toml
+[build]
+target = ["aarch64_be-unknown-linux-musl"]
+
+[target.aarch64_be-unknown-linux-musl]
+cc = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-cc"
+cxx = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-c++"
+linker = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-cc"
+ar = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-ar"
+ranlib = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-ranlib"
+musl-root = "/path/to/buildroot/staging"
+runner = "qemu-aarch64_be -L /path/to/buildroot/target"
+crt-static = "/path/to/buildroot/target"
+```
+
+
+## Testing
+
+Binaries can be run under `qemu-aarch64_be` or under a big-endian Linux kernel.
diff --git a/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md
new file mode 100644
index 0000000..2cbaaa8
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md
@@ -0,0 +1,41 @@
+# `riscv64a23-unknown-linux-gnu`
+
+**Tier: 3**
+
+RISC-V target using the ratified [RVA23 Profile](https://github.com/riscv/riscv-profiles/blob/main/src/rva23-profile.adoc).
+This target will enable all mandary features of rva23u64 by default.
+
+## Target maintainers
+
+[@ZhongyaoChen](https://github.com/ZhongyaoChen)
+[@CaiWeiran](https://github.com/CaiWeiran)
+
+## Requirements
+
+This target can be sucessfully build on the following platform: ubuntu 24.04 (Linux Kernel version 6.8.0, glibc 2.39).
+
+Other platforms may work, but are not tested. Please contanct if you encounter any issues.
+
+## Building the target
+
+Tier-3 target is not distributed through `rustup`.
+
+You need to build your own Rust, the target can be build with:
+
+```bash
+./x build --target riscv64a23-unknown-linux-gnu
+```
+
+## Building Rust programs
+
+Add the toolchain:
+
+```bash
+rustup toolchain link rva23-toolchain {path-to-rust}/build/host/stage2
+```
+
+Then cross compile crates with:
+
+```bash
+RUSTFLAGS="-C linker=riscv64-linux-gnu-gcc" cargo +rva23-toolchain build --target=riscv64a23-unknown-linux-gnu
+```
diff --git a/src/doc/rustdoc/src/images/collapsed-long-item.png b/src/doc/rustdoc/src/images/collapsed-long-item.png
index c382870..6de759f 100644
--- a/src/doc/rustdoc/src/images/collapsed-long-item.png
+++ b/src/doc/rustdoc/src/images/collapsed-long-item.png
Binary files differ
diff --git a/src/doc/rustdoc/src/images/collapsed-trait-impls.png b/src/doc/rustdoc/src/images/collapsed-trait-impls.png
index f685656..96cc7db 100644
--- a/src/doc/rustdoc/src/images/collapsed-trait-impls.png
+++ b/src/doc/rustdoc/src/images/collapsed-trait-impls.png
Binary files differ
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 7bd2970..25c929a 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -196,7 +196,7 @@
### Document keywords
-This is for Rust compiler internal use only.
+This is for internal use in the std library.
Rust keywords are documented in the standard library (look for `match` for example).
@@ -211,6 +211,23 @@
mod empty_mod {}
```
+### Document builtin attributes
+
+This is for internal use in the std library.
+
+Rust builtin attributes are documented in the standard library (look for `repr` for example).
+
+To do so, the `#[doc(attribute = "...")]` attribute is used. Example:
+
+```rust
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+
+/// Some documentation about the attribute.
+#[doc(attribute = "repr")]
+mod empty_mod {}
+```
+
### Use the Rust logo as the crate logo
This is for official Rust project use only.
@@ -796,3 +813,7 @@
"you today?",
]
```
+
+## `--generate-macro-expansion`: Generate macros expansion toggles in source code
+
+This flag enables the generation of toggles to expand macros in the HTML source code pages.
diff --git a/src/etc/installer/gfx/rust-logo.png b/src/etc/installer/gfx/rust-logo.png
index 99ee750..49d8d0d 100644
--- a/src/etc/installer/gfx/rust-logo.png
+++ b/src/etc/installer/gfx/rust-logo.png
Binary files differ
diff --git a/src/gcc b/src/gcc
index 04ce66d..4e995bd 160000
--- a/src/gcc
+++ b/src/gcc
@@ -1 +1 @@
-Subproject commit 04ce66d8c918de9273bd7101638ad8724edf5e21
+Subproject commit 4e995bd73c4490edfe5080ec6014d63aa9abed5f
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 5d36ffc..2985971a0 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -12,20 +12,20 @@
arrayvec = { version = "0.7", default-features = false }
askama = { version = "0.14", default-features = false, features = ["alloc", "config", "derive"] }
base64 = "0.21.7"
-indexmap = "2"
-itertools = "0.12"
+indexmap.workspace = true
+itertools.workspace = true
minifier = { version = "0.3.5", default-features = false }
pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] }
regex = "1"
rustdoc-json-types = { path = "../rustdoc-json-types" }
serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
+serde_json.workspace = true
smallvec = "1.8.1"
stringdex = { version = "0.0.1-alpha4" }
-tempfile = "3"
+tempfile.workspace = true
threadpool = "1.8.1"
-tracing = "0.1"
tracing-tree = "0.3.0"
+tracing.workspace = true
unicode-segmentation = "1.9"
# tidy-alphabetical-end
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 0d98c64..8461e15 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -572,30 +572,30 @@ pub(crate) fn build_impl(
super::build_deref_target_impls(cx, &trait_items, ret);
}
- // Return if the trait itself or any types of the generic parameters are doc(hidden).
- let mut stack: Vec<&Type> = vec![&for_];
+ if !document_hidden {
+ // Return if the trait itself or any types of the generic parameters are doc(hidden).
+ let mut stack: Vec<&Type> = vec![&for_];
- if let Some(did) = trait_.as_ref().map(|t| t.def_id())
- && !document_hidden
- && tcx.is_doc_hidden(did)
- {
- return;
- }
-
- if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
- stack.extend(generics);
- }
-
- while let Some(ty) = stack.pop() {
- if let Some(did) = ty.def_id(&cx.cache)
- && !document_hidden
+ if let Some(did) = trait_.as_ref().map(|t| t.def_id())
&& tcx.is_doc_hidden(did)
{
return;
}
- if let Some(generics) = ty.generics() {
+
+ if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
stack.extend(generics);
}
+
+ while let Some(ty) = stack.pop() {
+ if let Some(did) = ty.def_id(&cx.cache)
+ && tcx.is_doc_hidden(did)
+ {
+ return;
+ }
+ if let Some(generics) = ty.generics() {
+ stack.extend(generics);
+ }
+ }
}
if let Some(did) = trait_.as_ref().map(|t| t.def_id()) {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 92bd4a4..fcff156 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -226,15 +226,28 @@ fn mapped_root_modules<T>(
}
pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> {
- fn as_keyword(did: DefId, tcx: TyCtxt<'_>) -> Option<(DefId, Symbol)> {
+ self.retrieve_keywords_or_documented_attributes(tcx, sym::keyword)
+ }
+ pub(crate) fn documented_attributes(
+ &self,
+ tcx: TyCtxt<'_>,
+ ) -> impl Iterator<Item = (DefId, Symbol)> {
+ self.retrieve_keywords_or_documented_attributes(tcx, sym::attribute)
+ }
+
+ fn retrieve_keywords_or_documented_attributes(
+ &self,
+ tcx: TyCtxt<'_>,
+ name: Symbol,
+ ) -> impl Iterator<Item = (DefId, Symbol)> {
+ let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> {
tcx.get_attrs(did, sym::doc)
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
- .filter(|meta| meta.has_name(sym::keyword))
+ .filter(|meta| meta.has_name(name))
.find_map(|meta| meta.value_str())
.map(|value| (did, value))
- }
-
- self.mapped_root_modules(tcx, as_keyword)
+ };
+ self.mapped_root_modules(tcx, as_target)
}
pub(crate) fn primitives(
@@ -592,6 +605,20 @@ pub(crate) fn is_extern_crate(&self) -> bool {
pub(crate) fn is_keyword(&self) -> bool {
self.type_() == ItemType::Keyword
}
+ pub(crate) fn is_attribute(&self) -> bool {
+ self.type_() == ItemType::Attribute
+ }
+ /// Returns `true` if the item kind is one of the following:
+ ///
+ /// * `ItemType::Primitive`
+ /// * `ItemType::Keyword`
+ /// * `ItemType::Attribute`
+ ///
+ /// They are considered fake because they only exist thanks to their
+ /// `#[doc(primitive|keyword|attribute)]` attribute.
+ pub(crate) fn is_fake_item(&self) -> bool {
+ matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute)
+ }
pub(crate) fn is_stripped(&self) -> bool {
match self.kind {
StrippedItem(..) => true,
@@ -735,7 +762,9 @@ pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
// Primitives and Keywords are written in the source code as private modules.
// The modules need to be private so that nobody actually uses them, but the
// keywords and primitives that they are documenting are public.
- ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public),
+ ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => {
+ return Some(Visibility::Public);
+ }
// Variant fields inherit their enum's visibility.
StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
return None;
@@ -942,7 +971,12 @@ pub(crate) enum ItemKind {
AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
/// An item that has been stripped by a rustdoc pass
StrippedItem(Box<ItemKind>),
+ /// This item represents a module with a `#[doc(keyword = "...")]` attribute which is used
+ /// to generate documentation for Rust keywords.
KeywordItem,
+ /// This item represents a module with a `#[doc(attribute = "...")]` attribute which is used
+ /// to generate documentation for Rust builtin attributes.
+ AttributeItem,
}
impl ItemKind {
@@ -983,7 +1017,8 @@ pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
| RequiredAssocTypeItem(..)
| AssocTypeItem(..)
| StrippedItem(_)
- | KeywordItem => [].iter(),
+ | KeywordItem
+ | AttributeItem => [].iter(),
}
}
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 813fdee..6fc1e43 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -60,6 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
let primitives = local_crate.primitives(cx.tcx);
let keywords = local_crate.keywords(cx.tcx);
+ let documented_attributes = local_crate.documented_attributes(cx.tcx);
{
let ItemKind::ModuleItem(m) = &mut module.inner.kind else { unreachable!() };
m.items.extend(primitives.map(|(def_id, prim)| {
@@ -73,6 +74,9 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
m.items.extend(keywords.map(|(def_id, kw)| {
Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem, cx)
}));
+ m.items.extend(documented_attributes.into_iter().map(|(def_id, kw)| {
+ Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::AttributeItem, cx)
+ }));
}
Crate { module, external_traits: Box::new(mem::take(&mut cx.external_traits)) }
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index c52c723..450ac04 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -305,6 +305,8 @@ pub(crate) struct RenderOptions {
pub(crate) parts_out_dir: Option<PathToParts>,
/// disable minification of CSS/JS
pub(crate) disable_minification: bool,
+ /// If `true`, HTML source pages will generate the possibility to expand macros.
+ pub(crate) generate_macro_expansion: bool,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -786,6 +788,7 @@ fn println_condition(condition: Condition) {
let show_type_layout = matches.opt_present("show-type-layout");
let nocapture = matches.opt_present("nocapture");
let generate_link_to_definition = matches.opt_present("generate-link-to-definition");
+ let generate_macro_expansion = matches.opt_present("generate-macro-expansion");
let extern_html_root_takes_precedence =
matches.opt_present("extern-html-root-takes-precedence");
let html_no_source = matches.opt_present("html-no-source");
@@ -801,6 +804,13 @@ fn println_condition(condition: Condition) {
.with_note("`--generate-link-to-definition` option will be ignored")
.emit();
}
+ if generate_macro_expansion && (show_coverage || output_format != OutputFormat::Html) {
+ dcx.struct_warn(
+ "`--generate-macro-expansion` option can only be used with HTML output format",
+ )
+ .with_note("`--generate-macro-expansion` option will be ignored")
+ .emit();
+ }
let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
let with_examples = matches.opt_strs("with-examples");
@@ -881,6 +891,7 @@ fn println_condition(condition: Condition) {
unstable_features,
emit,
generate_link_to_definition,
+ generate_macro_expansion,
call_locations,
no_emit_shared: false,
html_no_source,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index e89733b..b8aaafc 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -31,6 +31,7 @@
use crate::clean::{self, ItemId};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
+use crate::html::macro_expansion::{ExpandedCode, source_macro_expansion};
use crate::passes;
use crate::passes::Condition::*;
use crate::passes::collect_intra_doc_links::LinkCollector;
@@ -334,11 +335,19 @@ pub(crate) fn run_global_ctxt(
show_coverage: bool,
render_options: RenderOptions,
output_format: OutputFormat,
-) -> (clean::Crate, RenderOptions, Cache) {
+) -> (clean::Crate, RenderOptions, Cache, FxHashMap<rustc_span::BytePos, Vec<ExpandedCode>>) {
// Certain queries assume that some checks were run elsewhere
// (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
// so type-check everything other than function bodies in this crate before running lints.
+ let expanded_macros = {
+ // We need for these variables to be removed to ensure that the `Crate` won't be "stolen"
+ // anymore.
+ let (_resolver, krate) = &*tcx.resolver_for_lowering().borrow();
+
+ source_macro_expansion(&krate, &render_options, output_format, tcx.sess.source_map())
+ };
+
// NOTE: this does not call `tcx.analysis()` so that we won't
// typeck function bodies or run the default rustc lints.
// (see `override_queries` in the `config`)
@@ -448,7 +457,7 @@ pub(crate) fn run_global_ctxt(
tcx.dcx().abort_if_errors();
- (krate, ctxt.render_options, ctxt.cache)
+ (krate, ctxt.render_options, ctxt.cache, expanded_macros)
}
/// Due to <https://github.com/rust-lang/rust/pull/73566>,
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index c03d16a..ee5f260 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -96,7 +96,8 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
| ImplAssocConstItem(..)
| RequiredAssocTypeItem(..)
| AssocTypeItem(..)
- | KeywordItem => kind,
+ | KeywordItem
+ | AttributeItem => kind,
}
}
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index cb6837d..29b4c4c 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -372,7 +372,8 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
| clean::RequiredAssocTypeItem(..)
| clean::AssocTypeItem(..)
| clean::StrippedItem(..)
- | clean::KeywordItem => {
+ | clean::KeywordItem
+ | clean::AttributeItem => {
// FIXME: Do these need handling?
// The person writing this comment doesn't know.
// So would rather leave them to an expert,
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 142a9d7..e94ef51 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -57,6 +57,7 @@ pub(crate) enum ItemType {
TraitAlias = 25,
// This number is reserved for use in JavaScript
// Generic = 26,
+ Attribute = 27,
}
impl Serialize for ItemType {
@@ -148,6 +149,7 @@ fn from(item: &'a clean::Item) -> ItemType {
clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType,
clean::ForeignTypeItem => ItemType::ForeignType,
clean::KeywordItem => ItemType::Keyword,
+ clean::AttributeItem => ItemType::Attribute,
clean::TraitAliasItem(..) => ItemType::TraitAlias,
clean::ProcMacroItem(mac) => match mac.kind {
MacroKind::Bang => ItemType::Macro,
@@ -236,6 +238,7 @@ pub(crate) fn as_str(&self) -> &'static str {
ItemType::ProcAttribute => "attr",
ItemType::ProcDerive => "derive",
ItemType::TraitAlias => "traitalias",
+ ItemType::Attribute => "attribute",
}
}
pub(crate) fn is_method(&self) -> bool {
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index aa4be4d..305c8c3 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -31,15 +31,6 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
/// reset the information between each call to `item` by using `restore_module_data`.
type ModuleData;
- /// Sets up any state required for the renderer. When this is called the cache has already been
- /// populated.
- fn init(
- krate: clean::Crate,
- options: RenderOptions,
- cache: Cache,
- tcx: TyCtxt<'tcx>,
- ) -> Result<(Self, clean::Crate), Error>;
-
/// This method is called right before call [`Self::item`]. This method returns a type
/// containing information that needs to be reset after the [`Self::item`] method has been
/// called with the [`Self::restore_module_data`] method.
@@ -105,18 +96,23 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
}
/// Main method for rendering a crate.
-pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
+pub(crate) fn run_format<
+ 'tcx,
+ T: FormatRenderer<'tcx>,
+ F: FnOnce(clean::Crate, RenderOptions, Cache, TyCtxt<'tcx>) -> Result<(T, clean::Crate), Error>,
+>(
krate: clean::Crate,
options: RenderOptions,
cache: Cache,
tcx: TyCtxt<'tcx>,
+ init: F,
) -> Result<(), Error> {
let prof = &tcx.sess.prof;
let emit_crate = options.should_emit_crate();
let (mut format_renderer, krate) = prof
.verbose_generic_activity_with_arg("create_renderer", T::descr())
- .run(|| T::init(krate, options, cache, tcx))?;
+ .run(|| init(krate, options, cache, tcx))?;
if !emit_crate {
return Ok(());
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 272180f..feafb41 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -5,6 +5,7 @@
//!
//! Use the `render_with_highlighting` to highlight some rust code.
+use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt::{self, Display, Write};
@@ -17,6 +18,7 @@
use super::format::{self, write_str};
use crate::clean::PrimitiveType;
use crate::html::escape::EscapeBodyText;
+use crate::html::macro_expansion::ExpandedCode;
use crate::html::render::{Context, LinkFromSrc};
/// This type is needed in case we want to render links on items to allow to go to their definition.
@@ -163,11 +165,22 @@ struct TokenHandler<'a, 'tcx, F: Write> {
current_class: Option<Class>,
/// We need to keep the `Class` for each element because it could contain a `Span` which is
/// used to generate links.
- pending_elems: Vec<(&'a str, Option<Class>)>,
+ pending_elems: Vec<(Cow<'a, str>, Option<Class>)>,
href_context: Option<HrefContext<'a, 'tcx>>,
write_line_number: fn(&mut F, u32, &'static str),
}
+impl<F: Write> std::fmt::Debug for TokenHandler<'_, '_, F> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("TokenHandler")
+ .field("closing_tags", &self.closing_tags)
+ .field("pending_exit_span", &self.pending_exit_span)
+ .field("current_class", &self.current_class)
+ .field("pending_elems", &self.pending_elems)
+ .finish()
+ }
+}
+
impl<F: Write> TokenHandler<'_, '_, F> {
fn handle_exit_span(&mut self) {
// We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
@@ -220,6 +233,10 @@ fn write_pending_elems(&mut self, current_class: Option<Class>) -> bool {
} else {
None
};
+ // To prevent opening a macro expansion span being closed right away because
+ // the currently open item is replaced by a new class.
+ let last_pending =
+ self.pending_elems.pop_if(|(_, class)| *class == Some(Class::Expansion));
for (text, class) in self.pending_elems.iter() {
string(
self.out,
@@ -233,6 +250,16 @@ fn write_pending_elems(&mut self, current_class: Option<Class>) -> bool {
if let Some(close_tag) = close_tag {
exit_span(self.out, close_tag);
}
+ if let Some((text, class)) = last_pending {
+ string(
+ self.out,
+ EscapeBodyText(&text),
+ class,
+ &self.href_context,
+ close_tag.is_none(),
+ self.write_line_number,
+ );
+ }
}
self.pending_elems.clear();
true
@@ -271,6 +298,100 @@ fn empty_line_number(out: &mut impl Write, _: u32, extra: &'static str) {
out.write_str(extra).unwrap();
}
+fn get_next_expansion(
+ expanded_codes: &[ExpandedCode],
+ line: u32,
+ span: Span,
+) -> Option<&ExpandedCode> {
+ expanded_codes.iter().find(|code| code.start_line == line && code.span.lo() > span.lo())
+}
+
+fn get_expansion<'a, W: Write>(
+ token_handler: &mut TokenHandler<'_, '_, W>,
+ expanded_codes: &'a [ExpandedCode],
+ line: u32,
+ span: Span,
+) -> Option<&'a ExpandedCode> {
+ if let Some(expanded_code) = get_next_expansion(expanded_codes, line, span) {
+ let (closing, reopening) = if let Some(current_class) = token_handler.current_class
+ && let class = current_class.as_html()
+ && !class.is_empty()
+ {
+ ("</span>", format!("<span class=\"{class}\">"))
+ } else {
+ ("", String::new())
+ };
+ let id = format!("expand-{line}");
+ token_handler.pending_elems.push((
+ Cow::Owned(format!(
+ "{closing}\
+<span class=expansion>\
+ <input id={id} \
+ tabindex=0 \
+ type=checkbox \
+ aria-label=\"Collapse/expand macro\" \
+ title=\"\"Collapse/expand macro\">{reopening}",
+ )),
+ Some(Class::Expansion),
+ ));
+ Some(expanded_code)
+ } else {
+ None
+ }
+}
+
+fn start_expansion(out: &mut Vec<(Cow<'_, str>, Option<Class>)>, expanded_code: &ExpandedCode) {
+ out.push((
+ Cow::Owned(format!(
+ "<span class=expanded>{}</span><span class=original>",
+ expanded_code.code,
+ )),
+ Some(Class::Expansion),
+ ));
+}
+
+fn end_expansion<'a, W: Write>(
+ token_handler: &mut TokenHandler<'_, '_, W>,
+ expanded_codes: &'a [ExpandedCode],
+ expansion_start_tags: &[(&'static str, Class)],
+ line: u32,
+ span: Span,
+) -> Option<&'a ExpandedCode> {
+ if let Some(expanded_code) = get_next_expansion(expanded_codes, line, span) {
+ // We close the current "original" content.
+ token_handler.pending_elems.push((Cow::Borrowed("</span>"), Some(Class::Expansion)));
+ return Some(expanded_code);
+ }
+ if expansion_start_tags.is_empty() && token_handler.closing_tags.is_empty() {
+ // No need tag opened so we can just close expansion.
+ token_handler.pending_elems.push((Cow::Borrowed("</span></span>"), Some(Class::Expansion)));
+ return None;
+ }
+
+ // If tags were opened inside the expansion, we need to close them and re-open them outside
+ // of the expansion span.
+ let mut out = String::new();
+ let mut end = String::new();
+
+ let mut closing_tags = token_handler.closing_tags.iter().peekable();
+ let mut start_closing_tags = expansion_start_tags.iter().peekable();
+
+ while let (Some(tag), Some(start_tag)) = (closing_tags.peek(), start_closing_tags.peek())
+ && tag == start_tag
+ {
+ closing_tags.next();
+ start_closing_tags.next();
+ }
+ for (tag, class) in start_closing_tags.chain(closing_tags) {
+ out.push_str(tag);
+ end.push_str(&format!("<span class=\"{}\">", class.as_html()));
+ }
+ token_handler
+ .pending_elems
+ .push((Cow::Owned(format!("</span></span>{out}{end}")), Some(Class::Expansion)));
+ None
+}
+
#[derive(Clone, Copy)]
pub(super) struct LineInfo {
pub(super) start_line: u32,
@@ -317,7 +438,7 @@ pub(super) fn write_code(
closing_tags: Vec::new(),
pending_exit_span: None,
current_class: None,
- pending_elems: Vec::new(),
+ pending_elems: Vec::with_capacity(20),
href_context,
write_line_number: match line_info {
Some(line_info) => {
@@ -338,12 +459,23 @@ pub(super) fn write_code(
(0, u32::MAX)
};
+ let (expanded_codes, file_span) = match token_handler.href_context.as_ref().and_then(|c| {
+ let expanded_codes = c.context.shared.expanded_codes.get(&c.file_span.lo())?;
+ Some((expanded_codes, c.file_span))
+ }) {
+ Some((expanded_codes, file_span)) => (expanded_codes.as_slice(), file_span),
+ None => (&[] as &[ExpandedCode], DUMMY_SP),
+ };
+ let mut current_expansion = get_expansion(&mut token_handler, expanded_codes, line, file_span);
+ token_handler.write_pending_elems(None);
+ let mut expansion_start_tags = Vec::new();
+
Classifier::new(
&src,
token_handler.href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP),
decoration_info,
)
- .highlight(&mut |highlight| {
+ .highlight(&mut |span, highlight| {
match highlight {
Highlight::Token { text, class } => {
// If we received a `ExitSpan` event and then have a non-compatible `Class`, we
@@ -369,10 +501,42 @@ pub(super) fn write_code(
if text == "\n" {
line += 1;
if line < max_lines {
- token_handler.pending_elems.push((text, Some(Class::Backline(line))));
+ token_handler
+ .pending_elems
+ .push((Cow::Borrowed(text), Some(Class::Backline(line))));
+ }
+ if current_expansion.is_none() {
+ current_expansion =
+ get_expansion(&mut token_handler, expanded_codes, line, span);
+ expansion_start_tags = token_handler.closing_tags.clone();
+ }
+ if let Some(ref current_expansion) = current_expansion
+ && current_expansion.span.lo() == span.hi()
+ {
+ start_expansion(&mut token_handler.pending_elems, current_expansion);
}
} else {
- token_handler.pending_elems.push((text, class));
+ token_handler.pending_elems.push((Cow::Borrowed(text), class));
+
+ let mut need_end = false;
+ if let Some(ref current_expansion) = current_expansion {
+ if current_expansion.span.lo() == span.hi() {
+ start_expansion(&mut token_handler.pending_elems, current_expansion);
+ } else if current_expansion.end_line == line
+ && span.hi() >= current_expansion.span.hi()
+ {
+ need_end = true;
+ }
+ }
+ if need_end {
+ current_expansion = end_expansion(
+ &mut token_handler,
+ expanded_codes,
+ &expansion_start_tags,
+ line,
+ span,
+ );
+ }
}
}
Highlight::EnterSpan { class } => {
@@ -440,6 +604,8 @@ enum Class {
QuestionMark,
Decoration(&'static str),
Backline(u32),
+ /// Macro expansion.
+ Expansion,
}
impl Class {
@@ -489,6 +655,7 @@ fn as_html(self) -> &'static str {
Class::QuestionMark => "question-mark",
Class::Decoration(kind) => kind,
Class::Backline(_) => "",
+ Class::Expansion => "",
}
}
@@ -513,7 +680,8 @@ fn get_span(self) -> Option<Span> {
| Self::Lifetime
| Self::QuestionMark
| Self::Decoration(_)
- | Self::Backline(_) => None,
+ | Self::Backline(_)
+ | Self::Expansion => None,
}
}
}
@@ -628,6 +796,13 @@ fn new(info: &DecorationInfo) -> Self {
}
}
+/// Convenient wrapper to create a [`Span`] from a position in the file.
+fn new_span(lo: u32, text: &str, file_span: Span) -> Span {
+ let hi = lo + text.len() as u32;
+ let file_lo = file_span.lo();
+ file_span.with_lo(file_lo + BytePos(lo)).with_hi(file_lo + BytePos(hi))
+}
+
/// Processes program tokens, classifying strings of text by highlighting
/// category (`Class`).
struct Classifier<'src> {
@@ -660,13 +835,6 @@ fn new(src: &'src str, file_span: Span, decoration_info: Option<&DecorationInfo>
}
}
- /// Convenient wrapper to create a [`Span`] from a position in the file.
- fn new_span(&self, lo: u32, text: &str) -> Span {
- let hi = lo + text.len() as u32;
- let file_lo = self.file_span.lo();
- self.file_span.with_lo(file_lo + BytePos(lo)).with_hi(file_lo + BytePos(hi))
- }
-
/// Concatenate colons and idents as one when possible.
fn get_full_ident_path(&mut self) -> Vec<(TokenKind, usize, usize)> {
let start = self.byte_pos as usize;
@@ -735,18 +903,18 @@ fn next(&mut self) -> Option<(TokenKind, &'src str, u32)> {
/// The general structure for this method is to iterate over each token,
/// possibly giving it an HTML span with a class specifying what flavor of
/// token is used.
- fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'src>)) {
+ fn highlight(mut self, sink: &mut dyn FnMut(Span, Highlight<'src>)) {
loop {
if let Some(decs) = self.decorations.as_mut() {
let byte_pos = self.byte_pos;
let n_starts = decs.starts.iter().filter(|(i, _)| byte_pos >= *i).count();
for (_, kind) in decs.starts.drain(0..n_starts) {
- sink(Highlight::EnterSpan { class: Class::Decoration(kind) });
+ sink(DUMMY_SP, Highlight::EnterSpan { class: Class::Decoration(kind) });
}
let n_ends = decs.ends.iter().filter(|i| byte_pos >= **i).count();
for _ in decs.ends.drain(0..n_ends) {
- sink(Highlight::ExitSpan);
+ sink(DUMMY_SP, Highlight::ExitSpan);
}
}
@@ -784,14 +952,22 @@ fn advance(
&mut self,
token: TokenKind,
text: &'src str,
- sink: &mut dyn FnMut(Highlight<'src>),
+ sink: &mut dyn FnMut(Span, Highlight<'src>),
before: u32,
) {
let lookahead = self.peek();
- let no_highlight = |sink: &mut dyn FnMut(_)| sink(Highlight::Token { text, class: None });
- let whitespace = |sink: &mut dyn FnMut(_)| {
+ let file_span = self.file_span;
+ let no_highlight = |sink: &mut dyn FnMut(_, _)| {
+ sink(new_span(before, text, file_span), Highlight::Token { text, class: None })
+ };
+ let whitespace = |sink: &mut dyn FnMut(_, _)| {
+ let mut start = 0u32;
for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {
- sink(Highlight::Token { text: part, class: None });
+ sink(
+ new_span(before + start, part, file_span),
+ Highlight::Token { text: part, class: None },
+ );
+ start += part.len() as u32;
}
};
let class = match token {
@@ -807,8 +983,8 @@ fn advance(
// leading identifier.
TokenKind::Bang if self.in_macro => {
self.in_macro = false;
- sink(Highlight::Token { text, class: None });
- sink(Highlight::ExitSpan);
+ sink(new_span(before, text, file_span), Highlight::Token { text, class: None });
+ sink(DUMMY_SP, Highlight::ExitSpan);
return;
}
@@ -819,12 +995,18 @@ fn advance(
Some((TokenKind::Whitespace, _)) => return whitespace(sink),
Some((TokenKind::Ident, "mut")) => {
self.next();
- sink(Highlight::Token { text: "*mut", class: Some(Class::RefKeyWord) });
+ sink(
+ DUMMY_SP,
+ Highlight::Token { text: "*mut", class: Some(Class::RefKeyWord) },
+ );
return;
}
Some((TokenKind::Ident, "const")) => {
self.next();
- sink(Highlight::Token { text: "*const", class: Some(Class::RefKeyWord) });
+ sink(
+ DUMMY_SP,
+ Highlight::Token { text: "*const", class: Some(Class::RefKeyWord) },
+ );
return;
}
_ => Class::RefKeyWord,
@@ -832,18 +1014,21 @@ fn advance(
TokenKind::And => match self.tokens.peek() {
Some((TokenKind::And, _)) => {
self.next();
- sink(Highlight::Token { text: "&&", class: None });
+ sink(DUMMY_SP, Highlight::Token { text: "&&", class: None });
return;
}
Some((TokenKind::Eq, _)) => {
self.next();
- sink(Highlight::Token { text: "&=", class: None });
+ sink(DUMMY_SP, Highlight::Token { text: "&=", class: None });
return;
}
Some((TokenKind::Whitespace, _)) => return whitespace(sink),
Some((TokenKind::Ident, "mut")) => {
self.next();
- sink(Highlight::Token { text: "&mut", class: Some(Class::RefKeyWord) });
+ sink(
+ DUMMY_SP,
+ Highlight::Token { text: "&mut", class: Some(Class::RefKeyWord) },
+ );
return;
}
_ => Class::RefKeyWord,
@@ -853,19 +1038,19 @@ fn advance(
TokenKind::Eq => match lookahead {
Some(TokenKind::Eq) => {
self.next();
- sink(Highlight::Token { text: "==", class: None });
+ sink(DUMMY_SP, Highlight::Token { text: "==", class: None });
return;
}
Some(TokenKind::Gt) => {
self.next();
- sink(Highlight::Token { text: "=>", class: None });
+ sink(DUMMY_SP, Highlight::Token { text: "=>", class: None });
return;
}
_ => return no_highlight(sink),
},
TokenKind::Minus if lookahead == Some(TokenKind::Gt) => {
self.next();
- sink(Highlight::Token { text: "->", class: None });
+ sink(DUMMY_SP, Highlight::Token { text: "->", class: None });
return;
}
@@ -916,16 +1101,22 @@ fn advance(
self.next();
if let Some(TokenKind::OpenBracket) = self.peek() {
self.in_attribute = true;
- sink(Highlight::EnterSpan { class: Class::Attribute });
+ sink(
+ new_span(before, text, file_span),
+ Highlight::EnterSpan { class: Class::Attribute },
+ );
}
- sink(Highlight::Token { text: "#", class: None });
- sink(Highlight::Token { text: "!", class: None });
+ sink(DUMMY_SP, Highlight::Token { text: "#", class: None });
+ sink(DUMMY_SP, Highlight::Token { text: "!", class: None });
return;
}
// Case 2: #[outer_attribute]
Some(TokenKind::OpenBracket) => {
self.in_attribute = true;
- sink(Highlight::EnterSpan { class: Class::Attribute });
+ sink(
+ new_span(before, text, file_span),
+ Highlight::EnterSpan { class: Class::Attribute },
+ );
}
_ => (),
}
@@ -934,8 +1125,11 @@ fn advance(
TokenKind::CloseBracket => {
if self.in_attribute {
self.in_attribute = false;
- sink(Highlight::Token { text: "]", class: None });
- sink(Highlight::ExitSpan);
+ sink(
+ new_span(before, text, file_span),
+ Highlight::Token { text: "]", class: None },
+ );
+ sink(DUMMY_SP, Highlight::ExitSpan);
return;
}
return no_highlight(sink);
@@ -956,15 +1150,16 @@ fn advance(
TokenKind::GuardedStrPrefix => return no_highlight(sink),
TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => {
self.in_macro = true;
- sink(Highlight::EnterSpan { class: Class::Macro(self.new_span(before, text)) });
- sink(Highlight::Token { text, class: None });
+ let span = new_span(before, text, file_span);
+ sink(DUMMY_SP, Highlight::EnterSpan { class: Class::Macro(span) });
+ sink(span, Highlight::Token { text, class: None });
return;
}
TokenKind::Ident => match get_real_ident_class(text, false) {
None => match text {
- "Option" | "Result" => Class::PreludeTy(self.new_span(before, text)),
+ "Option" | "Result" => Class::PreludeTy(new_span(before, text, file_span)),
"Some" | "None" | "Ok" | "Err" => {
- Class::PreludeVal(self.new_span(before, text))
+ Class::PreludeVal(new_span(before, text, file_span))
}
// "union" is a weak keyword and is only considered as a keyword when declaring
// a union type.
@@ -973,13 +1168,13 @@ fn advance(
self.in_macro_nonterminal = false;
Class::MacroNonTerminal
}
- "self" | "Self" => Class::Self_(self.new_span(before, text)),
- _ => Class::Ident(self.new_span(before, text)),
+ "self" | "Self" => Class::Self_(new_span(before, text, file_span)),
+ _ => Class::Ident(new_span(before, text, file_span)),
},
Some(c) => c,
},
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
- Class::Ident(self.new_span(before, text))
+ Class::Ident(new_span(before, text, file_span))
}
TokenKind::Lifetime { .. }
| TokenKind::RawLifetime
@@ -988,8 +1183,13 @@ fn advance(
};
// Anything that didn't return above is the simple case where we the
// class just spans a single token, so we can use the `string` method.
+ let mut start = 0u32;
for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {
- sink(Highlight::Token { text: part, class: Some(class) });
+ sink(
+ new_span(before + start, part, file_span),
+ Highlight::Token { text: part, class: Some(class) },
+ );
+ start += part.len() as u32;
}
}
@@ -1042,9 +1242,9 @@ fn exit_span(out: &mut impl Write, closing_tag: &str) {
/// Note that if `context` is not `None` and that the given `klass` contains a `Span`, the function
/// will then try to find this `span` in the `span_correspondence_map`. If found, it'll then
/// generate a link for this element (which corresponds to where its definition is located).
-fn string<T: Display, W: Write>(
+fn string<W: Write>(
out: &mut W,
- text: T,
+ text: EscapeBodyText<'_>,
klass: Option<Class>,
href_context: &Option<HrefContext<'_, '_>>,
open_tag: bool,
@@ -1052,6 +1252,9 @@ fn string<T: Display, W: Write>(
) {
if let Some(Class::Backline(line)) = klass {
write_line_number_callback(out, line, "\n");
+ } else if let Some(Class::Expansion) = klass {
+ // This has already been escaped so we get the text to write it directly.
+ out.write_str(text.0).unwrap();
} else if let Some(closing_tag) =
string_without_closing_tag(out, text, klass, href_context, open_tag)
{
diff --git a/src/librustdoc/html/macro_expansion.rs b/src/librustdoc/html/macro_expansion.rs
new file mode 100644
index 0000000..9098e92
--- /dev/null
+++ b/src/librustdoc/html/macro_expansion.rs
@@ -0,0 +1,156 @@
+use rustc_ast::visit::{Visitor, walk_crate, walk_expr, walk_item, walk_pat, walk_stmt};
+use rustc_ast::{Crate, Expr, Item, Pat, Stmt};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::source_map::SourceMap;
+use rustc_span::{BytePos, Span};
+
+use crate::config::{OutputFormat, RenderOptions};
+
+/// It returns the expanded macros correspondence map.
+pub(crate) fn source_macro_expansion(
+ krate: &Crate,
+ render_options: &RenderOptions,
+ output_format: OutputFormat,
+ source_map: &SourceMap,
+) -> FxHashMap<BytePos, Vec<ExpandedCode>> {
+ if output_format == OutputFormat::Html
+ && !render_options.html_no_source
+ && render_options.generate_macro_expansion
+ {
+ let mut expanded_visitor = ExpandedCodeVisitor { expanded_codes: Vec::new(), source_map };
+ walk_crate(&mut expanded_visitor, krate);
+ expanded_visitor.compute_expanded()
+ } else {
+ Default::default()
+ }
+}
+
+/// Contains information about macro expansion in the source code pages.
+#[derive(Debug)]
+pub(crate) struct ExpandedCode {
+ /// The line where the macro expansion starts.
+ pub(crate) start_line: u32,
+ /// The line where the macro expansion ends.
+ pub(crate) end_line: u32,
+ /// The source code of the expanded macro.
+ pub(crate) code: String,
+ /// The span of macro callsite.
+ pub(crate) span: Span,
+}
+
+/// Contains temporary information of macro expanded code.
+///
+/// As we go through the HIR visitor, if any span overlaps with another, they will
+/// both be merged.
+struct ExpandedCodeInfo {
+ /// Callsite of the macro.
+ span: Span,
+ /// Expanded macro source code (HTML escaped).
+ code: String,
+ /// Span of macro-generated code.
+ expanded_span: Span,
+}
+
+/// HIR visitor which retrieves expanded macro.
+///
+/// Once done, the `expanded_codes` will be transformed into a vec of [`ExpandedCode`]
+/// which contains the information needed when running the source code highlighter.
+pub(crate) struct ExpandedCodeVisitor<'ast> {
+ expanded_codes: Vec<ExpandedCodeInfo>,
+ source_map: &'ast SourceMap,
+}
+
+impl<'ast> ExpandedCodeVisitor<'ast> {
+ fn handle_new_span<F: Fn() -> String>(&mut self, new_span: Span, f: F) {
+ if new_span.is_dummy() || !new_span.from_expansion() {
+ return;
+ }
+ let callsite_span = new_span.source_callsite();
+ if let Some(index) =
+ self.expanded_codes.iter().position(|info| info.span.overlaps(callsite_span))
+ {
+ let info = &mut self.expanded_codes[index];
+ if new_span.contains(info.expanded_span) {
+ // New macro expansion recursively contains the old one, so replace it.
+ info.span = callsite_span;
+ info.expanded_span = new_span;
+ info.code = f();
+ } else {
+ // We push the new item after the existing one.
+ let expanded_code = &mut self.expanded_codes[index];
+ expanded_code.code.push('\n');
+ expanded_code.code.push_str(&f());
+ let lo = BytePos(expanded_code.expanded_span.lo().0.min(new_span.lo().0));
+ let hi = BytePos(expanded_code.expanded_span.hi().0.min(new_span.hi().0));
+ expanded_code.expanded_span = expanded_code.expanded_span.with_lo(lo).with_hi(hi);
+ }
+ } else {
+ // We add a new item.
+ self.expanded_codes.push(ExpandedCodeInfo {
+ span: callsite_span,
+ code: f(),
+ expanded_span: new_span,
+ });
+ }
+ }
+
+ fn compute_expanded(mut self) -> FxHashMap<BytePos, Vec<ExpandedCode>> {
+ self.expanded_codes.sort_unstable_by(|item1, item2| item1.span.cmp(&item2.span));
+ let mut expanded: FxHashMap<BytePos, Vec<ExpandedCode>> = FxHashMap::default();
+ for ExpandedCodeInfo { span, code, .. } in self.expanded_codes {
+ if let Ok(lines) = self.source_map.span_to_lines(span)
+ && !lines.lines.is_empty()
+ {
+ let mut out = String::new();
+ super::highlight::write_code(&mut out, &code, None, None, None);
+ let first = lines.lines.first().unwrap();
+ let end = lines.lines.last().unwrap();
+ expanded.entry(lines.file.start_pos).or_default().push(ExpandedCode {
+ start_line: first.line_index as u32 + 1,
+ end_line: end.line_index as u32 + 1,
+ code: out,
+ span,
+ });
+ }
+ }
+ expanded
+ }
+}
+
+// We need to use the AST pretty printing because:
+//
+// 1. HIR pretty printing doesn't display accurately the code (like `impl Trait`).
+// 2. `SourceMap::snippet_opt` might fail if the source is not available.
+impl<'ast> Visitor<'ast> for ExpandedCodeVisitor<'ast> {
+ fn visit_expr(&mut self, expr: &'ast Expr) {
+ if expr.span.from_expansion() {
+ self.handle_new_span(expr.span, || rustc_ast_pretty::pprust::expr_to_string(expr));
+ } else {
+ walk_expr(self, expr);
+ }
+ }
+
+ fn visit_item(&mut self, item: &'ast Item) {
+ if item.span.from_expansion() {
+ self.handle_new_span(item.span, || rustc_ast_pretty::pprust::item_to_string(item));
+ } else {
+ walk_item(self, item);
+ }
+ }
+
+ fn visit_stmt(&mut self, stmt: &'ast Stmt) {
+ if stmt.span.from_expansion() {
+ self.handle_new_span(stmt.span, || rustc_ast_pretty::pprust::stmt_to_string(stmt));
+ } else {
+ walk_stmt(self, stmt);
+ }
+ }
+
+ fn visit_pat(&mut self, pat: &'ast Pat) {
+ if pat.span.from_expansion() {
+ self.handle_new_span(pat.span, || rustc_ast_pretty::pprust::pat_to_string(pat));
+ } else {
+ walk_pat(self, pat);
+ }
+ }
+}
diff --git a/src/librustdoc/html/mod.rs b/src/librustdoc/html/mod.rs
index 481ed16..d42f478 100644
--- a/src/librustdoc/html/mod.rs
+++ b/src/librustdoc/html/mod.rs
@@ -3,6 +3,7 @@
pub(crate) mod highlight;
pub(crate) mod layout;
mod length_limit;
+pub(crate) mod macro_expansion;
// used by the error-index generator, so it needs to be public
pub mod markdown;
pub(crate) mod render;
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index e4fca09..5f92ab2 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -12,7 +12,7 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::edition::Edition;
-use rustc_span::{FileName, Symbol, sym};
+use rustc_span::{BytePos, FileName, Symbol, sym};
use tracing::info;
use super::print_item::{full_path, print_item, print_item_path};
@@ -28,6 +28,7 @@
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
+use crate::html::macro_expansion::ExpandedCode;
use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary};
use crate::html::render::write_shared::write_shared;
use crate::html::url_parts_builder::UrlPartsBuilder;
@@ -139,6 +140,7 @@ pub(crate) struct SharedContext<'tcx> {
/// Correspondence map used to link types used in the source code pages to allow to click on
/// links to jump to the type's definition.
pub(crate) span_correspondence_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
+ pub(crate) expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
/// The [`Cache`] used during rendering.
pub(crate) cache: Cache,
pub(crate) call_locations: AllCallLocations,
@@ -216,7 +218,7 @@ fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
} else {
it.name.as_ref().unwrap().as_str()
};
- if !it.is_primitive() && !it.is_keyword() {
+ if !it.is_fake_item() {
if !is_module {
title.push_str(" in ");
}
@@ -458,20 +460,13 @@ pub(crate) fn href_from_span_relative(
}
}
-/// Generates the documentation for `crate` into the directory `dst`
-impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
- fn descr() -> &'static str {
- "html"
- }
-
- const RUN_ON_MODULE: bool = true;
- type ModuleData = ContextInfo;
-
- fn init(
+impl<'tcx> Context<'tcx> {
+ pub(crate) fn init(
krate: clean::Crate,
options: RenderOptions,
cache: Cache,
tcx: TyCtxt<'tcx>,
+ expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
) -> Result<(Self, clean::Crate), Error> {
// need to save a copy of the options for rendering the index page
let md_opts = options.clone();
@@ -579,6 +574,7 @@ fn init(
cache,
call_locations,
should_merge: options.should_merge,
+ expanded_codes,
};
let dst = output;
@@ -604,6 +600,16 @@ fn init(
Ok((cx, krate))
}
+}
+
+/// Generates the documentation for `crate` into the directory `dst`
+impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
+ fn descr() -> &'static str {
+ "html"
+ }
+
+ const RUN_ON_MODULE: bool = true;
+ type ModuleData = ContextInfo;
fn save_module_data(&mut self) -> Self::ModuleData {
self.deref_id_map.borrow_mut().clear();
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 8d7f057..6db90c9 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1029,6 +1029,7 @@ fn assoc_const(
) -> impl fmt::Display {
let tcx = cx.tcx();
fmt::from_fn(move |w| {
+ render_attributes_in_code(w, it, &" ".repeat(indent), cx);
write!(
w,
"{indent}{vis}const <a{href} class=\"constant\">{name}</a>{generics}: {ty}",
@@ -1136,10 +1137,10 @@ fn assoc_method(
let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
header_len += 4;
let indent_str = " ";
- write!(w, "{}", render_attributes_in_pre(meth, indent_str, cx))?;
+ render_attributes_in_code(w, meth, indent_str, cx);
(4, indent_str, Ending::NoNewline)
} else {
- render_attributes_in_code(w, meth, cx);
+ render_attributes_in_code(w, meth, "", cx);
(0, "", Ending::Newline)
};
write!(
@@ -1309,28 +1310,28 @@ fn render_assoc_item(
})
}
-// When an attribute is rendered inside a `<pre>` tag, it is formatted using
-// a whitespace prefix and newline.
-fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
- fmt::from_fn(move |f| {
- for a in it.attributes(cx.tcx(), cx.cache()) {
- writeln!(f, "{prefix}{a}")?;
- }
- Ok(())
- })
-}
-
struct CodeAttribute(String);
-fn render_code_attribute(code_attr: CodeAttribute, w: &mut impl fmt::Write) {
- write!(w, "<div class=\"code-attribute\">{}</div>", code_attr.0).unwrap();
+fn render_code_attribute(prefix: &str, code_attr: CodeAttribute, w: &mut impl fmt::Write) {
+ write!(
+ w,
+ "<div class=\"code-attribute\">{prefix}{attr}</div>",
+ prefix = prefix,
+ attr = code_attr.0
+ )
+ .unwrap();
}
// When an attribute is rendered inside a <code> tag, it is formatted using
// a div to produce a newline after it.
-fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) {
+fn render_attributes_in_code(
+ w: &mut impl fmt::Write,
+ it: &clean::Item,
+ prefix: &str,
+ cx: &Context<'_>,
+) {
for attr in it.attributes(cx.tcx(), cx.cache()) {
- render_code_attribute(CodeAttribute(attr), w);
+ render_code_attribute(prefix, CodeAttribute(attr), w);
}
}
@@ -1342,7 +1343,7 @@ fn render_repr_attributes_in_code(
item_type: ItemType,
) {
if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) {
- render_code_attribute(CodeAttribute(repr), w);
+ render_code_attribute("", CodeAttribute(repr), w);
}
}
@@ -2534,6 +2535,7 @@ pub(crate) enum ItemSection {
AssociatedConstants,
ForeignTypes,
Keywords,
+ Attributes,
AttributeMacros,
DeriveMacros,
TraitAliases,
@@ -2566,6 +2568,7 @@ impl ItemSection {
AssociatedConstants,
ForeignTypes,
Keywords,
+ Attributes,
AttributeMacros,
DeriveMacros,
TraitAliases,
@@ -2595,6 +2598,7 @@ fn id(self) -> &'static str {
Self::AssociatedConstants => "associated-consts",
Self::ForeignTypes => "foreign-types",
Self::Keywords => "keywords",
+ Self::Attributes => "attributes",
Self::AttributeMacros => "attributes",
Self::DeriveMacros => "derives",
Self::TraitAliases => "trait-aliases",
@@ -2624,6 +2628,7 @@ fn name(self) -> &'static str {
Self::AssociatedConstants => "Associated Constants",
Self::ForeignTypes => "Foreign Types",
Self::Keywords => "Keywords",
+ Self::Attributes => "Attributes",
Self::AttributeMacros => "Attribute Macros",
Self::DeriveMacros => "Derive Macros",
Self::TraitAliases => "Trait Aliases",
@@ -2654,6 +2659,7 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection {
ItemType::AssocConst => ItemSection::AssociatedConstants,
ItemType::ForeignType => ItemSection::ForeignTypes,
ItemType::Keyword => ItemSection::Keywords,
+ ItemType::Attribute => ItemSection::Attributes,
ItemType::ProcAttribute => ItemSection::AttributeMacros,
ItemType::ProcDerive => ItemSection::DeriveMacros,
ItemType::TraitAlias => ItemSection::TraitAliases,
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 407238d..afa438f 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -20,8 +20,8 @@
AssocItemLink, AssocItemRender, Context, ImplRenderingParameters, RenderMode,
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
- render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
- render_impl, render_repr_attributes_in_code, render_rightside, render_stability_since_raw,
+ render_assoc_item, render_assoc_items, render_attributes_in_code, render_impl,
+ render_repr_attributes_in_code, render_rightside, render_stability_since_raw,
render_stability_since_raw_with_extra, write_section_heading,
};
use crate::clean;
@@ -107,13 +107,6 @@ fn document_type_layout(&self) -> impl fmt::Display {
}
item_template_methods!($($rest)*);
};
- (render_attributes_in_pre $($rest:tt)*) => {
- fn render_attributes_in_pre(&self) -> impl fmt::Display {
- let (item, cx) = self.item_and_cx();
- render_attributes_in_pre(item, "", cx)
- }
- item_template_methods!($($rest)*);
- };
(render_assoc_items $($rest:tt)*) => {
fn render_assoc_items(&self) -> impl fmt::Display {
let (item, cx) = self.item_and_cx();
@@ -180,6 +173,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
clean::ConstantItem(..) => "Constant ",
clean::ForeignTypeItem => "Foreign Type ",
clean::KeywordItem => "Keyword ",
+ clean::AttributeItem => "Attribute ",
clean::TraitAliasItem(..) => "Trait Alias ",
_ => {
// We don't generate pages for any other type.
@@ -200,7 +194,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
let src_href =
if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
- let path_components = if item.is_primitive() || item.is_keyword() {
+ let path_components = if item.is_fake_item() {
vec![]
} else {
let cur = &cx.current;
@@ -259,7 +253,9 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp
clean::ForeignTypeItem => {
write!(buf, "{}", item_foreign_type(cx, item))
}
- clean::KeywordItem => write!(buf, "{}", item_keyword(cx, item)),
+ clean::KeywordItem | clean::AttributeItem => {
+ write!(buf, "{}", item_keyword_or_attribute(cx, item))
+ }
clean::TraitAliasItem(ta) => {
write!(buf, "{}", item_trait_alias(cx, item, ta))
}
@@ -457,7 +453,12 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
write!(
w,
"<dt{id}>\
- <code>{vis}{imp}</code>{stab_tags}\
+ <code>"
+ )?;
+ render_attributes_in_code(w, myitem, "", cx);
+ write!(
+ w,
+ "{vis}{imp}</code>{stab_tags}\
</dt>",
vis = visibility_print_with_space(myitem, cx),
imp = import.print(cx)
@@ -625,11 +626,11 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp
let notable_traits = notable_traits_button(&f.decl.output, cx).maybe_display();
wrap_item(w, |w| {
+ render_attributes_in_code(w, it, "", cx);
write!(
w,
- "{attrs}{vis}{constness}{asyncness}{safety}{abi}fn \
+ "{vis}{constness}{asyncness}{safety}{abi}fn \
{name}{generics}{decl}{notable_traits}{where_clause}",
- attrs = render_attributes_in_pre(it, "", cx),
vis = visibility,
constness = constness,
asyncness = asyncness,
@@ -666,10 +667,10 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
// Output the trait definition
wrap_item(w, |mut w| {
+ render_attributes_in_code(&mut w, it, "", cx);
write!(
w,
- "{attrs}{vis}{safety}{is_auto}trait {name}{generics}{bounds}",
- attrs = render_attributes_in_pre(it, "", cx),
+ "{vis}{safety}{is_auto}trait {name}{generics}{bounds}",
vis = visibility_print_with_space(it, cx),
safety = t.safety(tcx).print_with_space(),
is_auto = if t.is_auto(tcx) { "auto " } else { "" },
@@ -1240,10 +1241,10 @@ fn item_trait_alias(
) -> impl fmt::Display {
fmt::from_fn(|w| {
wrap_item(w, |w| {
+ render_attributes_in_code(w, it, "", cx);
write!(
w,
- "{attrs}trait {name}{generics} = {bounds}{where_clause};",
- attrs = render_attributes_in_pre(it, "", cx),
+ "trait {name}{generics} = {bounds}{where_clause};",
name = it.name.unwrap(),
generics = t.generics.print(cx),
bounds = print_bounds(&t.bounds, true, cx),
@@ -1268,10 +1269,10 @@ fn item_trait_alias(
fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> impl fmt::Display {
fmt::from_fn(|w| {
wrap_item(w, |w| {
+ render_attributes_in_code(w, it, "", cx);
write!(
w,
- "{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
- attrs = render_attributes_in_pre(it, "", cx),
+ "{vis}type {name}{generics}{where_clause} = {type_};",
vis = visibility_print_with_space(it, cx),
name = it.name.unwrap(),
generics = t.generics.print(cx),
@@ -1452,7 +1453,21 @@ struct ItemUnion<'a, 'cx> {
impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
fn render_union(&self) -> impl Display {
- render_union(self.it, Some(self.generics), self.fields, self.cx)
+ render_union(
+ self.it,
+ Some(self.generics),
+ self.fields,
+ self.def_id,
+ self.is_type_alias,
+ self.cx,
+ )
+ }
+
+ fn print_field_attrs(&self, field: &'a clean::Item) -> impl Display {
+ fmt::from_fn(move |w| {
+ render_attributes_in_code(w, field, "", self.cx);
+ Ok(())
+ })
}
fn document_field(&self, field: &'a clean::Item) -> impl Display {
@@ -1479,27 +1494,6 @@ fn fields_iter(&self) -> impl Iterator<Item = (&'a clean::Item, &'a clean::Type)
_ => None,
})
}
-
- fn render_attributes_in_pre(&self) -> impl fmt::Display {
- fmt::from_fn(move |f| {
- if self.is_type_alias {
- // For now the only attributes we render for type aliases are `repr` attributes.
- if let Some(repr) = clean::repr_attributes(
- self.cx.tcx(),
- self.cx.cache(),
- self.def_id,
- ItemType::Union,
- ) {
- writeln!(f, "{repr}")?;
- };
- } else {
- for a in self.it.attributes(self.cx.tcx(), self.cx.cache()) {
- writeln!(f, "{a}")?;
- }
- }
- Ok(())
- })
- }
}
fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display {
@@ -1563,7 +1557,7 @@ fn render_into<W: fmt::Write>(
// For now the only attributes we render for type aliases are `repr` attributes.
render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Enum);
} else {
- render_attributes_in_code(w, it, cx);
+ render_attributes_in_code(w, it, "", cx);
}
write!(
w,
@@ -1702,7 +1696,7 @@ fn render_enum_fields(
if v.is_stripped() {
continue;
}
- write!(w, "{}", render_attributes_in_pre(v, TAB, cx))?;
+ render_attributes_in_code(w, v, TAB, cx);
w.write_str(TAB)?;
match v.kind {
clean::VariantItem(ref var) => match var.kind {
@@ -1786,6 +1780,7 @@ fn item_variants(
)
.maybe_display()
)?;
+ render_attributes_in_code(w, variant, "", cx);
if let clean::VariantItem(ref var) = variant.kind
&& let clean::VariantKind::CLike = var.kind
{
@@ -1859,7 +1854,12 @@ fn item_variants(
"<div class=\"sub-variant-field\">\
<span id=\"{id}\" class=\"section-header\">\
<a href=\"#{id}\" class=\"anchor field\">§</a>\
- <code>{f}: {t}</code>\
+ <code>"
+ )?;
+ render_attributes_in_code(w, field, "", cx);
+ write!(
+ w,
+ "{f}: {t}</code>\
</span>\
{doc}\
</div>",
@@ -1882,6 +1882,7 @@ fn item_macro(cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) -> impl fmt:
fmt::from_fn(|w| {
wrap_item(w, |w| {
// FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
+ render_attributes_in_code(w, it, "", cx);
if !t.macro_rules {
write!(w, "{}", visibility_print_with_space(it, cx))?;
}
@@ -1950,7 +1951,7 @@ fn item_constant(
fmt::from_fn(|w| {
wrap_item(w, |w| {
let tcx = cx.tcx();
- render_attributes_in_code(w, it, cx);
+ render_attributes_in_code(w, it, "", cx);
write!(
w,
@@ -2018,7 +2019,7 @@ fn render_into<W: fmt::Write>(
// For now the only attributes we render for type aliases are `repr` attributes.
render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Struct);
} else {
- render_attributes_in_code(w, it, cx);
+ render_attributes_in_code(w, it, "", cx);
}
write!(
w,
@@ -2094,10 +2095,15 @@ fn item_fields(
w,
"<span id=\"{id}\" class=\"{item_type} section-header\">\
<a href=\"#{id}\" class=\"anchor field\">§</a>\
- <code>{field_name}: {ty}</code>\
+ <code>",
+ item_type = ItemType::StructField,
+ )?;
+ render_attributes_in_code(w, field, "", cx);
+ write!(
+ w,
+ "{field_name}: {ty}</code>\
</span>\
{doc}",
- item_type = ItemType::StructField,
ty = ty.print(cx),
doc = document(cx, field, Some(it), HeadingOffset::H3),
)?;
@@ -2115,7 +2121,7 @@ fn item_static(
) -> impl fmt::Display {
fmt::from_fn(move |w| {
wrap_item(w, |w| {
- render_attributes_in_code(w, it, cx);
+ render_attributes_in_code(w, it, "", cx);
write!(
w,
"{vis}{safe}static {mutability}{name}: {typ}",
@@ -2135,7 +2141,7 @@ fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
fmt::from_fn(|w| {
wrap_item(w, |w| {
w.write_str("extern {\n")?;
- render_attributes_in_code(w, it, cx);
+ render_attributes_in_code(w, it, "", cx);
write!(w, " {}type {};\n}}", visibility_print_with_space(it, cx), it.name.unwrap(),)
})?;
@@ -2148,7 +2154,7 @@ fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
})
}
-fn item_keyword(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
+fn item_keyword_or_attribute(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
document(cx, it, None, HeadingOffset::H2)
}
@@ -2358,9 +2364,17 @@ fn render_union(
it: &clean::Item,
g: Option<&clean::Generics>,
fields: &[clean::Item],
+ def_id: DefId,
+ is_type_alias: bool,
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |mut f| {
+ if is_type_alias {
+ // For now the only attributes we render for type aliases are `repr` attributes.
+ render_repr_attributes_in_code(f, cx, def_id, ItemType::Union);
+ } else {
+ render_attributes_in_code(f, it, "", cx);
+ }
write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?;
let where_displayed = if let Some(generics) = g {
@@ -2390,6 +2404,7 @@ fn render_union(
for field in fields {
if let clean::StructFieldItem(ref ty) = field.kind {
+ render_attributes_in_code(&mut f, field, " ", cx);
writeln!(
f,
" {}{}: {},",
@@ -2481,11 +2496,15 @@ fn render_struct_fields(
if toggle {
toggle_open(&mut *w, format_args!("{count_fields} fields"));
}
+ if has_visible_fields {
+ writeln!(w)?;
+ }
for field in fields {
if let clean::StructFieldItem(ref ty) = field.kind {
- write!(
+ render_attributes_in_code(w, field, &format!("{tab} "), cx);
+ writeln!(
w,
- "\n{tab} {vis}{name}: {ty},",
+ "{tab} {vis}{name}: {ty},",
vis = visibility_print_with_space(field, cx),
name = field.name.unwrap(),
ty = ty.print(cx)
@@ -2495,12 +2514,12 @@ fn render_struct_fields(
if has_visible_fields {
if has_stripped_entries {
- write!(
+ writeln!(
w,
- "\n{tab} <span class=\"comment\">/* private fields */</span>"
+ "{tab} <span class=\"comment\">/* private fields */</span>"
)?;
}
- write!(w, "\n{tab}")?;
+ write!(w, "{tab}")?;
} else if has_stripped_entries {
write!(w, " <span class=\"comment\">/* private fields */</span> ")?;
}
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 846d3ad..8bc2e0b 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -35,7 +35,7 @@ pub(crate) enum LinkFromSrc {
/// 1. Generate a `span` correspondence map which links an item `span` to its definition `span`.
/// 2. Collect the source code files.
///
-/// It returns the `krate`, the source code files and the `span` correspondence map.
+/// It returns the source code files and the `span` correspondence map.
///
/// Note about the `span` correspondence map: the keys are actually `(lo, hi)` of `span`s. We don't
/// need the `span` context later on, only their position, so instead of keeping a whole `Span`, we
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index a3c6bf9..5c02e2e 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -75,6 +75,7 @@
--function-link-color: #ad7c37;
--macro-link-color: #068000;
--keyword-link-color: #3873ad;
+ --attribute-link-color: #3873ad;
--mod-link-color: #3873ad;
--link-color: #3873ad;
--sidebar-link-color: #356da4;
@@ -180,6 +181,7 @@
--function-link-color: #2bab63;
--macro-link-color: #09bd00;
--keyword-link-color: #d2991d;
+ --attribute-link-color: #d2991d;
--mod-link-color: #d2991d;
--link-color: #d2991d;
--sidebar-link-color: #fdbf35;
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index dc27d79..09d289d 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -400,6 +400,10 @@
color: var(--keyword-link-color);
}
+span.attribute, a.attribute {
+ color: var(--attribute-link-color);
+}
+
a {
color: var(--link-color);
text-decoration: none;
@@ -956,6 +960,40 @@
.example-wrap.digits-8 { --example-wrap-digits-count: 8ch; }
.example-wrap.digits-9 { --example-wrap-digits-count: 9ch; }
+.example-wrap .expansion {
+ position: relative;
+ display: inline;
+}
+.example-wrap .expansion > input {
+ display: block;
+ position: absolute;
+ appearance: none;
+ content: '↕';
+ left: -20px;
+ top: 0;
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ cursor: pointer;
+ color: var(--main-color);
+ padding: 0 2px;
+ line-height: 20px;
+}
+.example-wrap .expansion > input::after {
+ content: "↕";
+}
+.example-wrap .expansion .expanded {
+ display: none;
+ color: var(--main-color);
+}
+.example-wrap .expansion > input:checked ~ .expanded,
+.example-wrap .expansion > input:checked ~ * .expanded {
+ display: inherit;
+}
+.example-wrap .expansion > input:checked ~ .original,
+.example-wrap .expansion > input:checked ~ * .original {
+ display: none;
+}
+
.example-wrap [data-nosnippet] {
width: calc(var(--example-wrap-digits-count) + var(--line-number-padding) * 2);
}
@@ -964,6 +1002,17 @@
var(--example-wrap-digits-count) + var(--line-number-padding) * 2
+ var(--line-number-right-margin));
}
+.src .example-wrap .expansion [data-nosnippet] {
+ /* FIXME: Once <https://bugzilla.mozilla.org/show_bug.cgi?id=1949948> is solved, uncomment
+ next line and remove the two other rules. */
+ /*left: calc((
+ var(--example-wrap-digits-count) + var(--line-number-padding) * 2
+ + var(--line-number-right-margin)) * -1);*/
+ position: initial;
+ margin-left: calc((
+ var(--example-wrap-digits-count) + var(--line-number-padding) * 2
+ + var(--line-number-right-margin)) * -1);
+}
.example-wrap [data-nosnippet] {
color: var(--src-line-numbers-span-color);
@@ -978,9 +1027,6 @@
position: absolute;
left: 0;
}
-.example-wrap .line-highlighted[data-nosnippet] {
- background-color: var(--src-line-number-highlighted-background-color);
-}
.example-wrap pre > code {
position: relative;
display: block;
@@ -995,6 +1041,9 @@
.example-wrap [data-nosnippet]:target {
border-right: none;
}
+.example-wrap .line-highlighted[data-nosnippet] {
+ background-color: var(--src-line-number-highlighted-background-color);
+}
.example-wrap.hide-lines [data-nosnippet] {
display: none;
}
@@ -3145,6 +3194,7 @@
--function-link-color: #ad7c37;
--macro-link-color: #068000;
--keyword-link-color: #3873ad;
+ --attribute-link-color: #3873ad;
--mod-link-color: #3873ad;
--link-color: #3873ad;
--sidebar-link-color: #356da4;
@@ -3249,6 +3299,7 @@
--function-link-color: #2bab63;
--macro-link-color: #09bd00;
--keyword-link-color: #d2991d;
+ --attribute-link-color: #d2991d;
--mod-link-color: #d2991d;
--link-color: #d2991d;
--sidebar-link-color: #fdbf35;
@@ -3362,6 +3413,7 @@
--function-link-color: #fdd687;
--macro-link-color: #a37acc;
--keyword-link-color: #39afd7;
+ --attribute-link-color: #39afd7;
--mod-link-color: #39afd7;
--link-color: #39afd7;
--sidebar-link-color: #53b1db;
diff --git a/src/librustdoc/html/static/images/favicon-32x32.png b/src/librustdoc/html/static/images/favicon-32x32.png
index 69b8613..0670c4d 100644
--- a/src/librustdoc/html/static/images/favicon-32x32.png
+++ b/src/librustdoc/html/static/images/favicon-32x32.png
Binary files differ
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 4fcba5f..75febd6 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -790,6 +790,7 @@
//block("associatedconstant", "associated-consts", "Associated Constants");
block("foreigntype", "foreign-types", "Foreign Types");
block("keyword", "keywords", "Keywords");
+ block("attribute", "attributes", "Attributes");
block("attr", "attributes", "Attribute Macros");
block("derive", "derives", "Derive Macros");
block("traitalias", "trait-aliases", "Trait Aliases");
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 3fb4db3..b003bcc 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -119,6 +119,7 @@
"derive",
"traitalias", // 25
"generic",
+ "attribute",
];
// used for special search precedence
@@ -2058,7 +2059,7 @@
displayPath = item.modulePath + "::";
href = this.rootPath + item.modulePath.replace(/::/g, "/") +
"/index.html#reexport." + name;
- } else if (type === "primitive" || type === "keyword") {
+ } else if (type === "primitive" || type === "keyword" || type === "attribute") {
displayPath = "";
exactPath = "";
href = this.rootPath + path.replace(/::/g, "/") +
@@ -4560,6 +4561,8 @@
"attribute macro",
"derive macro",
"trait alias",
+ "",
+ "attribute",
];
// @ts-expect-error
let currentResults;
diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html
index b5d3367..171e079 100644
--- a/src/librustdoc/html/templates/item_union.html
+++ b/src/librustdoc/html/templates/item_union.html
@@ -1,5 +1,4 @@
<pre class="rust item-decl"><code>
- {{ self.render_attributes_in_pre()|safe }}
{{ self.render_union()|safe }}
</code></pre>
{% if !self.is_type_alias %}
@@ -13,7 +12,7 @@
{% let name = field.name.expect("union field name") %}
<span id="structfield.{{ name }}" class="{{ ItemType::StructField +}} section-header"> {# #}
<a href="#structfield.{{ name }}" class="anchor field">§</a> {# #}
- <code>{{ name }}: {{+ self.print_ty(ty)|safe }}</code> {# #}
+ <code>{{+ self.print_field_attrs(field)|safe }}{{ name }}: {{+ self.print_ty(ty)|safe }}</code> {# #}
</span>
{% if let Some(stability_class) = self.stability_field(field) %}
<span class="stab {{ stability_class }}"></span>
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 5fab8ad..f052071 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -52,7 +52,7 @@ pub(super) fn convert_item(&self, item: &clean::Item) -> Option<Item> {
let clean::ItemInner { name, item_id, .. } = *item.inner;
let id = self.id_from_item(item);
let inner = match item.kind {
- clean::KeywordItem => return None,
+ clean::KeywordItem | clean::AttributeItem => return None,
clean::StrippedItem(ref inner) => {
match &**inner {
// We document stripped modules as with `Module::is_stripped` set to
@@ -85,7 +85,7 @@ pub(super) fn convert_item(&self, item: &clean::Item) -> Option<Item> {
fn ids(&self, items: &[clean::Item]) -> Vec<Id> {
items
.iter()
- .filter(|i| !i.is_stripped() && !i.is_keyword())
+ .filter(|i| !i.is_stripped() && !i.is_keyword() && !i.is_attribute())
.map(|i| self.id_from_item(i))
.collect()
}
@@ -93,7 +93,10 @@ fn ids(&self, items: &[clean::Item]) -> Vec<Id> {
fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> {
items
.iter()
- .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(i)))
+ .map(|i| {
+ (!i.is_stripped() && !i.is_keyword() && !i.is_attribute())
+ .then(|| self.id_from_item(i))
+ })
.collect()
}
}
@@ -332,8 +335,8 @@ fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum
bounds: b.into_json(renderer),
type_: Some(t.item_type.as_ref().unwrap_or(&t.type_).into_json(renderer)),
},
- // `convert_item` early returns `None` for stripped items and keywords.
- KeywordItem => unreachable!(),
+ // `convert_item` early returns `None` for stripped items, keywords and attributes.
+ KeywordItem | AttributeItem => unreachable!(),
StrippedItem(inner) => {
match inner.as_ref() {
ModuleItem(m) => ItemEnum::Module(Module {
@@ -887,6 +890,7 @@ fn from_clean(kind: &ItemType, _renderer: &JsonRenderer<'_>) -> Self {
AssocType => ItemKind::AssocType,
ForeignType => ItemKind::ExternType,
Keyword => ItemKind::Keyword,
+ Attribute => ItemKind::Attribute,
TraitAlias => ItemKind::TraitAlias,
ProcAttribute => ItemKind::ProcAttribute,
ProcDerive => ItemKind::ProcDerive,
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 760e48b..b724d7e 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -175,15 +175,8 @@ fn target(sess: &rustc_session::Session) -> types::Target {
}
}
-impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
- fn descr() -> &'static str {
- "json"
- }
-
- const RUN_ON_MODULE: bool = false;
- type ModuleData = ();
-
- fn init(
+impl<'tcx> JsonRenderer<'tcx> {
+ pub(crate) fn init(
krate: clean::Crate,
options: RenderOptions,
cache: Cache,
@@ -205,6 +198,15 @@ fn init(
krate,
))
}
+}
+
+impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
+ fn descr() -> &'static str {
+ "json"
+ }
+
+ const RUN_ON_MODULE: bool = false;
+ type ModuleData = ();
fn save_module_data(&mut self) -> Self::ModuleData {
unreachable!("RUN_ON_MODULE = false, should never call save_module_data")
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 28dbd8b..f62eba4 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -1,4 +1,5 @@
// tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![doc(
html_root_url = "https://doc.rust-lang.org/nightly/",
html_playground_url = "https://play.rust-lang.org/"
@@ -11,8 +12,8 @@
#![feature(file_buffered)]
#![feature(format_args_nl)]
#![feature(if_let_guard)]
+#![feature(iter_advance_by)]
#![feature(iter_intersperse)]
-#![feature(round_char_boundary)]
#![feature(rustc_private)]
#![feature(test)]
#![warn(rustc::internal)]
@@ -80,6 +81,8 @@
use tracing::info;
use crate::clean::utils::DOC_RUST_LANG_ORG_VERSION;
+use crate::error::Error;
+use crate::formats::cache::Cache;
/// A macro to create a FxHashMap.
///
@@ -663,6 +666,14 @@ fn opts() -> Vec<RustcOptGroup> {
"disable the minification of CSS/JS files (perma-unstable, do not use with cached files)",
"",
),
+ opt(
+ Unstable,
+ Flag,
+ "",
+ "generate-macro-expansion",
+ "Add possibility to expand macros in the HTML source code pages",
+ "",
+ ),
// deprecated / removed options
opt(
Stable,
@@ -726,20 +737,32 @@ pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) {
}
}
-fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
+fn run_renderer<
+ 'tcx,
+ T: formats::FormatRenderer<'tcx>,
+ F: FnOnce(
+ clean::Crate,
+ config::RenderOptions,
+ Cache,
+ TyCtxt<'tcx>,
+ ) -> Result<(T, clean::Crate), Error>,
+>(
krate: clean::Crate,
renderopts: config::RenderOptions,
cache: formats::cache::Cache,
tcx: TyCtxt<'tcx>,
+ init: F,
) {
- match formats::run_format::<T>(krate, renderopts, cache, tcx) {
+ match formats::run_format::<T, F>(krate, renderopts, cache, tcx, init) {
Ok(_) => tcx.dcx().abort_if_errors(),
Err(e) => {
let mut msg =
tcx.dcx().struct_fatal(format!("couldn't generate documentation: {}", e.error));
let file = e.file.display().to_string();
if !file.is_empty() {
- msg.note(format!("failed to create or modify \"{file}\""));
+ msg.note(format!("failed to create or modify {e}"));
+ } else {
+ msg.note(format!("failed to create or modify file: {e}"));
}
msg.emit();
}
@@ -862,6 +885,7 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
let scrape_examples_options = options.scrape_examples_options.clone();
let bin_crate = options.bin_crate;
+ let output_format = options.output_format;
let config = core::create_config(input, options, &render_options);
let registered_lints = config.register_lints.is_some();
@@ -886,9 +910,10 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
sess.dcx().fatal("Compilation failed, aborting rustdoc");
}
- let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || {
- core::run_global_ctxt(tcx, show_coverage, render_options, output_format)
- });
+ let (krate, render_opts, mut cache, expanded_macros) = sess
+ .time("run_global_ctxt", || {
+ core::run_global_ctxt(tcx, show_coverage, render_options, output_format)
+ });
info!("finished with rustc");
if let Some(options) = scrape_examples_options {
@@ -919,10 +944,24 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
info!("going to format");
match output_format {
config::OutputFormat::Html => sess.time("render_html", || {
- run_renderer::<html::render::Context<'_>>(krate, render_opts, cache, tcx)
+ run_renderer(
+ krate,
+ render_opts,
+ cache,
+ tcx,
+ |krate, render_opts, cache, tcx| {
+ html::render::Context::init(
+ krate,
+ render_opts,
+ cache,
+ tcx,
+ expanded_macros,
+ )
+ },
+ )
}),
config::OutputFormat::Json => sess.time("render_json", || {
- run_renderer::<json::JsonRenderer<'_>>(krate, render_opts, cache, tcx)
+ run_renderer(krate, render_opts, cache, tcx, json::JsonRenderer::init)
}),
// Already handled above with doctest runners.
config::OutputFormat::Doctest => unreachable!(),
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 8028afe..e0ea760 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -67,6 +67,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
| clean::ImportItem(_)
| clean::PrimitiveItem(_)
| clean::KeywordItem
+ | clean::AttributeItem
| clean::ModuleItem(_)
| clean::TraitAliasItem(_)
| clean::ForeignFunctionItem(..)
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index bad51d7..719b7c6 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -19,7 +19,7 @@
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_middle::{bug, span_bug, ty};
use rustc_resolve::rustdoc::{
- MalformedGenerics, has_primitive_or_keyword_docs, prepare_to_doc_link_resolution,
+ MalformedGenerics, has_primitive_or_keyword_or_attribute_docs, prepare_to_doc_link_resolution,
source_span_for_markdown_range, strip_generics_from_path,
};
use rustc_session::config::CrateType;
@@ -1073,7 +1073,7 @@ fn resolve_links(&mut self, item: &Item) {
&& let Some(def_id) = item.item_id.as_def_id()
&& let Some(def_id) = def_id.as_local()
&& !self.cx.tcx.effective_visibilities(()).is_exported(def_id)
- && !has_primitive_or_keyword_docs(&item.attrs.other_attrs)
+ && !has_primitive_or_keyword_or_attribute_docs(&item.attrs.other_attrs)
{
// Skip link resolution for non-exported items.
return;
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 19cf15d..da09117 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -1,9 +1,11 @@
//! Detects invalid HTML (like an unclosed `<span>`) in doc comments.
+use std::borrow::Cow;
use std::iter::Peekable;
use std::ops::Range;
use std::str::CharIndices;
+use itertools::Itertools as _;
use pulldown_cmark::{BrokenLink, Event, LinkType, Parser, Tag, TagEnd};
use rustc_hir::HirId;
use rustc_resolve::rustdoc::source_span_for_markdown_range;
@@ -101,7 +103,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
});
};
- let mut tags = Vec::new();
+ let mut tagp = TagParser::new();
let mut is_in_comment = None;
let mut in_code_block = false;
@@ -126,70 +128,65 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
};
let p = Parser::new_with_broken_link_callback(dox, main_body_opts(), Some(&mut replacer))
- .into_offset_iter();
+ .into_offset_iter()
+ .coalesce(|a, b| {
+ // for some reason, pulldown-cmark splits html blocks into separate events for each line.
+ // we undo this, in order to handle multi-line tags.
+ match (a, b) {
+ ((Event::Html(_), ra), (Event::Html(_), rb)) if ra.end == rb.start => {
+ let merged = ra.start..rb.end;
+ Ok((Event::Html(Cow::Borrowed(&dox[merged.clone()]).into()), merged))
+ }
+ x => Err(x),
+ }
+ });
for (event, range) in p {
match event {
Event::Start(Tag::CodeBlock(_)) => in_code_block = true,
Event::Html(text) | Event::InlineHtml(text) if !in_code_block => {
- extract_tags(&mut tags, &text, range, &mut is_in_comment, &report_diag)
+ tagp.extract_tags(&text, range, &mut is_in_comment, &report_diag)
}
Event::End(TagEnd::CodeBlock) => in_code_block = false,
_ => {}
}
}
- for (tag, range) in tags.iter().filter(|(t, _)| {
- let t = t.to_lowercase();
- !ALLOWED_UNCLOSED.contains(&t.as_str())
- }) {
- report_diag(format!("unclosed HTML tag `{tag}`"), range, true);
- }
-
if let Some(range) = is_in_comment {
report_diag("Unclosed HTML comment".to_string(), &range, false);
+ } else if let &Some(quote_pos) = &tagp.quote_pos {
+ let qr = Range { start: quote_pos, end: quote_pos };
+ report_diag(
+ format!("unclosed quoted HTML attribute on tag `{}`", &tagp.tag_name),
+ &qr,
+ false,
+ );
+ } else {
+ if !tagp.tag_name.is_empty() {
+ report_diag(
+ format!("incomplete HTML tag `{}`", &tagp.tag_name),
+ &(tagp.tag_start_pos..dox.len()),
+ false,
+ );
+ }
+ for (tag, range) in tagp.tags.iter().filter(|(t, _)| {
+ let t = t.to_lowercase();
+ !is_implicitly_self_closing(&t)
+ }) {
+ report_diag(format!("unclosed HTML tag `{tag}`"), range, true);
+ }
}
}
+/// These tags are interpreted as self-closing if they lack an explicit closing tag.
const ALLOWED_UNCLOSED: &[&str] = &[
"area", "base", "br", "col", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
"source", "track", "wbr",
];
-fn drop_tag(
- tags: &mut Vec<(String, Range<usize>)>,
- tag_name: String,
- range: Range<usize>,
- f: &impl Fn(String, &Range<usize>, bool),
-) {
- let tag_name_low = tag_name.to_lowercase();
- if let Some(pos) = tags.iter().rposition(|(t, _)| t.to_lowercase() == tag_name_low) {
- // If the tag is nested inside a "<script>" or a "<style>" tag, no warning should
- // be emitted.
- let should_not_warn = tags.iter().take(pos + 1).any(|(at, _)| {
- let at = at.to_lowercase();
- at == "script" || at == "style"
- });
- for (last_tag_name, last_tag_span) in tags.drain(pos + 1..) {
- if should_not_warn {
- continue;
- }
- let last_tag_name_low = last_tag_name.to_lowercase();
- if ALLOWED_UNCLOSED.contains(&last_tag_name_low.as_str()) {
- continue;
- }
- // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
- // So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
- // have `h3`, meaning the tag wasn't closed as it should have.
- f(format!("unclosed HTML tag `{last_tag_name}`"), &last_tag_span, true);
- }
- // Remove the `tag_name` that was originally closed
- tags.pop();
- } else {
- // It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
- // but it helps for the visualization).
- f(format!("unopened HTML tag `{tag_name}`"), &range, false);
- }
+/// Allows constructs like `<img>`, but not `<img`.
+fn is_implicitly_self_closing(tag_name: &str) -> bool {
+ ALLOWED_UNCLOSED.contains(&tag_name)
}
fn extract_path_backwards(text: &str, end_pos: usize) -> Option<usize> {
@@ -252,151 +249,292 @@ fn is_valid_for_html_tag_name(c: char, is_empty: bool) -> bool {
c.is_ascii_alphabetic() || !is_empty && (c == '-' || c.is_ascii_digit())
}
-fn extract_html_tag(
- tags: &mut Vec<(String, Range<usize>)>,
- text: &str,
- range: &Range<usize>,
- start_pos: usize,
- iter: &mut Peekable<CharIndices<'_>>,
- f: &impl Fn(String, &Range<usize>, bool),
-) {
- let mut tag_name = String::new();
- let mut is_closing = false;
- let mut prev_pos = start_pos;
+/// Parse html tags to ensure they are well-formed
+#[derive(Debug, Clone)]
+struct TagParser {
+ tags: Vec<(String, Range<usize>)>,
+ /// Name of the tag that is being parsed, if we are within a tag.
+ ///
+ /// Since the `<` and name of a tag must appear on the same line with no whitespace,
+ /// if this is the empty string, we are not in a tag.
+ tag_name: String,
+ tag_start_pos: usize,
+ is_closing: bool,
+ /// `true` if we are within a tag, but not within its name.
+ in_attrs: bool,
+ /// If we are in a quoted attribute, what quote char does it use?
+ ///
+ /// This needs to be stored in the struct since HTML5 allows newlines in quoted attrs.
+ quote: Option<char>,
+ quote_pos: Option<usize>,
+ after_eq: bool,
+}
- loop {
- let (pos, c) = match iter.peek() {
- Some((pos, c)) => (*pos, *c),
- // In case we reached the of the doc comment, we want to check that it's an
- // unclosed HTML tag. For example "/// <h3".
- None => (prev_pos, '\0'),
- };
- prev_pos = pos;
- // Checking if this is a closing tag (like `</a>` for `<a>`).
- if c == '/' && tag_name.is_empty() {
- is_closing = true;
- } else if is_valid_for_html_tag_name(c, tag_name.is_empty()) {
- tag_name.push(c);
- } else {
- if !tag_name.is_empty() {
- let mut r = Range { start: range.start + start_pos, end: range.start + pos };
- if c == '>' {
- // In case we have a tag without attribute, we can consider the span to
- // refer to it fully.
- r.end += 1;
+impl TagParser {
+ fn new() -> Self {
+ Self {
+ tags: Vec::new(),
+ tag_name: String::with_capacity(8),
+ tag_start_pos: 0,
+ is_closing: false,
+ in_attrs: false,
+ quote: None,
+ quote_pos: None,
+ after_eq: false,
+ }
+ }
+
+ fn drop_tag(&mut self, range: Range<usize>, f: &impl Fn(String, &Range<usize>, bool)) {
+ let tag_name_low = self.tag_name.to_lowercase();
+ if let Some(pos) = self.tags.iter().rposition(|(t, _)| t.to_lowercase() == tag_name_low) {
+ // If the tag is nested inside a "<script>" or a "<style>" tag, no warning should
+ // be emitted.
+ let should_not_warn = self.tags.iter().take(pos + 1).any(|(at, _)| {
+ let at = at.to_lowercase();
+ at == "script" || at == "style"
+ });
+ for (last_tag_name, last_tag_span) in self.tags.drain(pos + 1..) {
+ if should_not_warn {
+ continue;
}
- if is_closing {
- // In case we have "</div >" or even "</div >".
- if c != '>' {
- if !c.is_whitespace() {
- // It seems like it's not a valid HTML tag.
- break;
- }
- let mut found = false;
- for (new_pos, c) in text[pos..].char_indices() {
+ let last_tag_name_low = last_tag_name.to_lowercase();
+ if is_implicitly_self_closing(&last_tag_name_low) {
+ continue;
+ }
+ // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
+ // So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
+ // have `h3`, meaning the tag wasn't closed as it should have.
+ f(format!("unclosed HTML tag `{last_tag_name}`"), &last_tag_span, true);
+ }
+ // Remove the `tag_name` that was originally closed
+ self.tags.pop();
+ } else {
+ // It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
+ // but it helps for the visualization).
+ f(format!("unopened HTML tag `{}`", &self.tag_name), &range, false);
+ }
+ }
+
+ /// Handle a `<` that appeared while parsing a tag.
+ fn handle_lt_in_tag(
+ &mut self,
+ range: Range<usize>,
+ lt_pos: usize,
+ f: &impl Fn(String, &Range<usize>, bool),
+ ) {
+ let global_pos = range.start + lt_pos;
+ // is this check needed?
+ if global_pos == self.tag_start_pos {
+ // `<` is in the tag because it is the start.
+ return;
+ }
+ // tried to start a new tag while in a tag
+ f(
+ format!("incomplete HTML tag `{}`", &self.tag_name),
+ &(self.tag_start_pos..global_pos),
+ false,
+ );
+ self.tag_parsed();
+ }
+
+ fn extract_html_tag(
+ &mut self,
+ text: &str,
+ range: &Range<usize>,
+ start_pos: usize,
+ iter: &mut Peekable<CharIndices<'_>>,
+ f: &impl Fn(String, &Range<usize>, bool),
+ ) {
+ let mut prev_pos = start_pos;
+
+ 'outer_loop: loop {
+ let (pos, c) = match iter.peek() {
+ Some((pos, c)) => (*pos, *c),
+ // In case we reached the of the doc comment, we want to check that it's an
+ // unclosed HTML tag. For example "/// <h3".
+ None if self.tag_name.is_empty() => (prev_pos, '\0'),
+ None => break,
+ };
+ prev_pos = pos;
+ if c == '/' && self.tag_name.is_empty() {
+ // Checking if this is a closing tag (like `</a>` for `<a>`).
+ self.is_closing = true;
+ } else if !self.in_attrs && is_valid_for_html_tag_name(c, self.tag_name.is_empty()) {
+ self.tag_name.push(c);
+ } else {
+ if !self.tag_name.is_empty() {
+ self.in_attrs = true;
+ let mut r = Range { start: range.start + start_pos, end: range.start + pos };
+ if c == '>' {
+ // In case we have a tag without attribute, we can consider the span to
+ // refer to it fully.
+ r.end += 1;
+ }
+ if self.is_closing {
+ // In case we have "</div >" or even "</div >".
+ if c != '>' {
if !c.is_whitespace() {
- if c == '>' {
- r.end = range.start + new_pos + 1;
- found = true;
- }
+ // It seems like it's not a valid HTML tag.
break;
}
- }
- if !found {
- break;
- }
- }
- drop_tag(tags, tag_name, r, f);
- } else {
- let mut is_self_closing = false;
- let mut quote_pos = None;
- if c != '>' {
- let mut quote = None;
- let mut after_eq = false;
- for (i, c) in text[pos..].char_indices() {
- if !c.is_whitespace() {
- if let Some(q) = quote {
- if c == q {
- quote = None;
- quote_pos = None;
- after_eq = false;
+ let mut found = false;
+ for (new_pos, c) in text[pos..].char_indices() {
+ if !c.is_whitespace() {
+ if c == '>' {
+ r.end = range.start + new_pos + 1;
+ found = true;
+ } else if c == '<' {
+ self.handle_lt_in_tag(range.clone(), pos + new_pos, f);
}
- } else if c == '>' {
break;
- } else if c == '/' && !after_eq {
- is_self_closing = true;
- } else {
- if is_self_closing {
- is_self_closing = false;
- }
- if (c == '"' || c == '\'') && after_eq {
- quote = Some(c);
- quote_pos = Some(pos + i);
- } else if c == '=' {
- after_eq = true;
- }
}
- } else if quote.is_none() {
- after_eq = false;
+ }
+ if !found {
+ break 'outer_loop;
}
}
- }
- if let Some(quote_pos) = quote_pos {
- let qr = Range { start: quote_pos, end: quote_pos };
- f(
- format!("unclosed quoted HTML attribute on tag `{tag_name}`"),
- &qr,
- false,
- );
- }
- if is_self_closing {
- // https://html.spec.whatwg.org/#parse-error-non-void-html-element-start-tag-with-trailing-solidus
- let valid = ALLOWED_UNCLOSED.contains(&&tag_name[..])
- || tags.iter().take(pos + 1).any(|(at, _)| {
- let at = at.to_lowercase();
- at == "svg" || at == "math"
- });
- if !valid {
- f(format!("invalid self-closing HTML tag `{tag_name}`"), &r, false);
- }
+ self.drop_tag(r, f);
+ self.tag_parsed();
} else {
- tags.push((tag_name, r));
+ self.extract_opening_tag(text, range, r, pos, c, iter, f)
}
}
+ break;
}
- break;
+ iter.next();
}
- iter.next();
}
-}
-fn extract_tags(
- tags: &mut Vec<(String, Range<usize>)>,
- text: &str,
- range: Range<usize>,
- is_in_comment: &mut Option<Range<usize>>,
- f: &impl Fn(String, &Range<usize>, bool),
-) {
- let mut iter = text.char_indices().peekable();
-
- while let Some((start_pos, c)) = iter.next() {
- if is_in_comment.is_some() {
- if text[start_pos..].starts_with("-->") {
- *is_in_comment = None;
+ fn extract_opening_tag(
+ &mut self,
+ text: &str,
+ range: &Range<usize>,
+ r: Range<usize>,
+ pos: usize,
+ c: char,
+ iter: &mut Peekable<CharIndices<'_>>,
+ f: &impl Fn(String, &Range<usize>, bool),
+ ) {
+ // we can store this as a local, since html5 does require the `/` and `>`
+ // to not be separated by whitespace.
+ let mut is_self_closing = false;
+ if c != '>' {
+ 'parse_til_gt: {
+ for (i, c) in text[pos..].char_indices() {
+ if !c.is_whitespace() {
+ debug_assert_eq!(self.quote_pos.is_some(), self.quote.is_some());
+ if let Some(q) = self.quote {
+ if c == q {
+ self.quote = None;
+ self.quote_pos = None;
+ self.after_eq = false;
+ }
+ } else if c == '>' {
+ break 'parse_til_gt;
+ } else if c == '<' {
+ self.handle_lt_in_tag(range.clone(), pos + i, f);
+ } else if c == '/' && !self.after_eq {
+ is_self_closing = true;
+ } else {
+ if is_self_closing {
+ is_self_closing = false;
+ }
+ if (c == '"' || c == '\'') && self.after_eq {
+ self.quote = Some(c);
+ self.quote_pos = Some(pos + i);
+ } else if c == '=' {
+ self.after_eq = true;
+ }
+ }
+ } else if self.quote.is_none() {
+ self.after_eq = false;
+ }
+ if !is_self_closing && !self.tag_name.is_empty() {
+ iter.next();
+ }
+ }
+ // if we've run out of text but still haven't found a `>`,
+ // return early without calling `tag_parsed` or emitting lints.
+ // this allows us to either find the `>` in a later event
+ // or emit a lint about it being missing.
+ return;
}
- } else if c == '<' {
- if text[start_pos..].starts_with("<!--") {
- // We skip the "!--" part. (Once `advance_by` is stable, might be nice to use it!)
- iter.next();
- iter.next();
- iter.next();
- *is_in_comment = Some(Range {
- start: range.start + start_pos,
- end: range.start + start_pos + 3,
+ }
+ if is_self_closing {
+ // https://html.spec.whatwg.org/#parse-error-non-void-html-element-start-tag-with-trailing-solidus
+ let valid = ALLOWED_UNCLOSED.contains(&&self.tag_name[..])
+ || self.tags.iter().take(pos + 1).any(|(at, _)| {
+ let at = at.to_lowercase();
+ at == "svg" || at == "math"
});
- } else {
- extract_html_tag(tags, text, &range, start_pos, &mut iter, f);
+ if !valid {
+ f(format!("invalid self-closing HTML tag `{}`", self.tag_name), &r, false);
+ }
+ } else if !self.tag_name.is_empty() {
+ self.tags.push((std::mem::take(&mut self.tag_name), r));
+ }
+ self.tag_parsed();
+ }
+ /// Finished parsing a tag, reset related data.
+ fn tag_parsed(&mut self) {
+ self.tag_name.clear();
+ self.is_closing = false;
+ self.in_attrs = false;
+ }
+
+ fn extract_tags(
+ &mut self,
+ text: &str,
+ range: Range<usize>,
+ is_in_comment: &mut Option<Range<usize>>,
+ f: &impl Fn(String, &Range<usize>, bool),
+ ) {
+ let mut iter = text.char_indices().peekable();
+ let mut prev_pos = 0;
+ loop {
+ if self.quote.is_some() {
+ debug_assert!(self.in_attrs && self.quote_pos.is_some());
+ }
+ if self.in_attrs
+ && let Some(&(start_pos, _)) = iter.peek()
+ {
+ self.extract_html_tag(text, &range, start_pos, &mut iter, f);
+ // if no progress is being made, move forward forcefully.
+ if prev_pos == start_pos {
+ iter.next();
+ }
+ prev_pos = start_pos;
+ continue;
+ }
+ let Some((start_pos, c)) = iter.next() else { break };
+ if is_in_comment.is_some() {
+ if text[start_pos..].starts_with("-->") {
+ *is_in_comment = None;
+ }
+ } else if c == '<' {
+ // "<!--" is a valid attribute name under html5, so don't treat it as a comment if we're in a tag.
+ if self.tag_name.is_empty() && text[start_pos..].starts_with("<!--") {
+ // We skip the "!--" part. (Once `advance_by` is stable, might be nice to use it!)
+ iter.next();
+ iter.next();
+ iter.next();
+ *is_in_comment = Some(Range {
+ start: range.start + start_pos,
+ end: range.start + start_pos + 4,
+ });
+ } else {
+ if self.tag_name.is_empty() {
+ self.tag_start_pos = range.start + start_pos;
+ }
+ self.extract_html_tag(text, &range, start_pos, &mut iter, f);
+ }
+ } else if !self.tag_name.is_empty() {
+ // partially inside html tag that spans across events
+ self.extract_html_tag(text, &range, start_pos, &mut iter, f);
}
}
}
}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustdoc/passes/lint/html_tags/tests.rs b/src/librustdoc/passes/lint/html_tags/tests.rs
new file mode 100644
index 0000000..81c1d21
--- /dev/null
+++ b/src/librustdoc/passes/lint/html_tags/tests.rs
@@ -0,0 +1,73 @@
+use std::cell::RefCell;
+
+use super::*;
+
+#[test]
+fn test_extract_tags_nested_unclosed() {
+ let mut tagp = TagParser::new();
+ let diags = RefCell::new(Vec::new());
+ let dox = "<div>\n<br</div>";
+ tagp.extract_tags(dox, 0..dox.len(), &mut None, &|s, r, b| {
+ diags.borrow_mut().push((s, r.clone(), b));
+ });
+ assert_eq!(diags.borrow().len(), 1, "did not get expected diagnostics: {diags:?}");
+ assert_eq!(diags.borrow()[0].1, 6..9)
+}
+
+#[test]
+fn test_extract_tags_taglike_in_attr() {
+ let mut tagp = TagParser::new();
+ let diags = RefCell::new(Vec::new());
+ let dox = "<img src='<div>'>";
+ tagp.extract_tags(dox, 0..dox.len(), &mut None, &|s, r, b| {
+ diags.borrow_mut().push((s, r.clone(), b));
+ });
+ assert_eq!(diags.borrow().len(), 0, "unexpected diagnostics: {diags:?}");
+}
+
+#[test]
+fn test_extract_tags_taglike_in_multiline_attr() {
+ let mut tagp = TagParser::new();
+ let diags = RefCell::new(Vec::new());
+ let dox = "<img src=\"\nasd\n<div>\n\">";
+ tagp.extract_tags(dox, 0..dox.len(), &mut None, &|s, r, b| {
+ diags.borrow_mut().push((s, r.clone(), b));
+ });
+ assert_eq!(diags.borrow().len(), 0, "unexpected diagnostics: {diags:?}");
+}
+
+#[test]
+fn test_extract_tags_taglike_in_multievent_attr() {
+ let mut tagp = TagParser::new();
+ let diags = RefCell::new(Vec::new());
+ let dox = "<img src='<div>'>";
+ let split_point = 10;
+ let mut p = |range: Range<usize>| {
+ tagp.extract_tags(&dox[range.clone()], range, &mut None, &|s, r, b| {
+ diags.borrow_mut().push((s, r.clone(), b));
+ })
+ };
+ p(0..split_point);
+ p(split_point..dox.len());
+ assert_eq!(diags.borrow().len(), 0, "unexpected diagnostics: {diags:?}");
+}
+
+#[test]
+fn test_extract_tags_taglike_in_multiline_multievent_attr() {
+ let mut tagp = TagParser::new();
+ let diags = RefCell::new(Vec::new());
+ let dox = "<img src='\n foo:\n </div>\n <p/>\n <div>\n'>";
+ let mut p = |range: Range<usize>| {
+ tagp.extract_tags(&dox[range.clone()], range, &mut None, &|s, r, b| {
+ diags.borrow_mut().push((s, r.clone(), b));
+ })
+ };
+ let mut offset = 0;
+ for ln in dox.split_inclusive('\n') {
+ let new_offset = offset + ln.len();
+ p(offset..new_offset);
+ offset = new_offset;
+ }
+ assert_eq!(diags.borrow().len(), 0, "unexpected diagnostics: {diags:?}");
+ assert_eq!(tagp.tags.len(), 1);
+}
diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs
index 14ec587..5139ca3 100644
--- a/src/librustdoc/passes/propagate_stability.rs
+++ b/src/librustdoc/passes/propagate_stability.rs
@@ -106,7 +106,8 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
| ItemKind::RequiredAssocTypeItem(..)
| ItemKind::AssocTypeItem(..)
| ItemKind::PrimitiveItem(..)
- | ItemKind::KeywordItem => own_stability,
+ | ItemKind::KeywordItem
+ | ItemKind::AttributeItem => own_stability,
ItemKind::StrippedItem(..) => unreachable!(),
}
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index eedbbca..99d2252 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -133,6 +133,8 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
// Keywords are never stripped
clean::KeywordItem => {}
+ // Attributes are never stripped
+ clean::AttributeItem => {}
}
let fastreturn = match i.kind {
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 9f71d6a..16034c1 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -18,7 +18,6 @@
use rustc_span::{BytePos, FileName, SourceFile};
use tracing::{debug, trace, warn};
-use crate::formats::renderer::FormatRenderer;
use crate::html::render::Context;
use crate::{clean, config, formats};
@@ -276,7 +275,8 @@ pub(crate) fn run(
let inner = move || -> Result<(), String> {
// Generates source files for examples
renderopts.no_emit_shared = true;
- let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?;
+ let (cx, _) = Context::init(krate, renderopts, cache, tcx, Default::default())
+ .map_err(|e| e.to_string())?;
// Collect CrateIds corresponding to provided target crates
// If two different versions of the crate in the dependency tree, then examples will be
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index b8b6195..4d31409 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -49,7 +49,8 @@ fn visit_inner_recur(&mut self, kind: &'a ItemKind) {
| ImplAssocConstItem(..)
| RequiredAssocTypeItem(..)
| AssocTypeItem(..)
- | KeywordItem => {}
+ | KeywordItem
+ | AttributeItem => {}
}
}
diff --git a/src/llvm-project b/src/llvm-project
index 9a1f898..19f0a49 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 9a1f898064f52269bc94675dcbd620b46d45d173
+Subproject commit 19f0a49c5c3f4ba88b5e7ac620b9a0d8574c09cb
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 40f8900..658d379 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -37,8 +37,8 @@
// will instead cause conflicts. See #94591 for more. (This paragraph and the "Latest feature" line
// are deliberately not in a doc comment, because they need not be in public docs.)
//
-// Latest feature: Add Attribute::MacroUse
-pub const FORMAT_VERSION: u32 = 55;
+// Latest feature: Add `ItemKind::Attribute`.
+pub const FORMAT_VERSION: u32 = 56;
/// The root of the emitted JSON blob.
///
@@ -552,6 +552,11 @@ pub enum ItemKind {
/// [`Item`]s of this kind only come from the come library and exist solely
/// to carry documentation for the respective keywords.
Keyword,
+ /// An attribute declaration.
+ ///
+ /// [`Item`]s of this kind only come from the core library and exist solely
+ /// to carry documentation for the respective builtin attributes.
+ Attribute,
}
/// Specific fields of an item.
diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml
index 7e0c4be..05d5f21 100644
--- a/src/tools/build-manifest/Cargo.toml
+++ b/src/tools/build-manifest/Cargo.toml
@@ -4,9 +4,9 @@
edition = "2021"
[dependencies]
-toml = "0.5"
+toml = "0.7"
serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
+serde_json.workspace = true
anyhow = "1.0.32"
flate2 = "1.0.26"
xz2 = "0.1.7"
diff --git a/src/tools/bump-stage0/Cargo.toml b/src/tools/bump-stage0/Cargo.toml
index 6ee7a83..b7f3625 100644
--- a/src/tools/bump-stage0/Cargo.toml
+++ b/src/tools/bump-stage0/Cargo.toml
@@ -11,4 +11,4 @@
curl = "0.4.38"
indexmap = { version = "2.0.0", features = ["serde"] }
serde = { version = "1.0.125", features = ["derive"] }
-toml = "0.5.7"
+toml = "0.7"
diff --git a/src/tools/cargo b/src/tools/cargo
index 71eb84f..a6c58d4 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 71eb84f21aef43c07580c6aed6f806a6299f5042
+Subproject commit a6c58d43051d01d83f55a3e61ef5f5b2b0dd6bd9
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 2add525b..b361893 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -65,13 +65,6 @@
name = "dogfood"
harness = false
-# quine-mc_cluskey makes up a significant part of the runtime in dogfood
-# due to the number of conditions in the clippy_lints crate
-# and enabling optimizations for that specific dependency helps a bit
-# without increasing total build times.
-[profile.dev.package.quine-mc_cluskey]
-opt-level = 3
-
[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = ['cfg(bootstrap)']
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index d468993..c8594cf 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -7,7 +7,7 @@
#![feature(iter_intersperse)]
#![feature(iter_partition_in_place)]
#![feature(never_type)]
-#![feature(round_char_boundary)]
+#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![feature(rustc_private)]
#![feature(stmt_expr_attributes)]
#![feature(unwrap_infallible)]
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index b16924b..d02952e 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -190,5 +190,5 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
/// and a rustc warning would be triggered, see #15301
fn fn_is_externally_exported(cx: &LateContext<'_>, def_id: DefId) -> bool {
let attrs = cx.tcx.codegen_fn_attrs(def_id);
- attrs.contains_extern_indicator(cx.tcx, def_id)
+ attrs.contains_extern_indicator()
}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
index ec5fb27..b898920 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -49,17 +49,7 @@ pub(super) fn check<'tcx>(
true
},
(ty::Int(_) | ty::Uint(_), ty::RawPtr(_, _)) => {
- span_lint_and_then(
- cx,
- USELESS_TRANSMUTE,
- e.span,
- "transmute from an integer to a pointer",
- |diag| {
- if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
- diag.span_suggestion(e.span, "try", arg.as_ty(to_ty.to_string()), Applicability::Unspecified);
- }
- },
- );
+ // Handled by the upstream rustc `integer_to_ptr_transmutes` lint
true
},
_ => false,
diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed
index 04c8f67..375a101 100644
--- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed
+++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed
@@ -1,4 +1,3 @@
-#![feature(round_char_boundary)]
#![warn(clippy::char_indices_as_byte_indices)]
trait StrExt {
diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs
index 773a4fc..eebc399 100644
--- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs
+++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs
@@ -1,4 +1,3 @@
-#![feature(round_char_boundary)]
#![warn(clippy::char_indices_as_byte_indices)]
trait StrExt {
diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr
index e2b4c1d..fae81fd 100644
--- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr
+++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr
@@ -1,12 +1,12 @@
error: indexing into a string with a character position where a byte index is expected
- --> tests/ui/char_indices_as_byte_indices.rs:13:24
+ --> tests/ui/char_indices_as_byte_indices.rs:12:24
|
LL | let _ = prim[..idx];
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
- --> tests/ui/char_indices_as_byte_indices.rs:12:10
+ --> tests/ui/char_indices_as_byte_indices.rs:11:10
|
LL | for (idx, _) in prim.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
@@ -19,14 +19,14 @@
|
error: passing a character position to a method that expects a byte index
- --> tests/ui/char_indices_as_byte_indices.rs:15:23
+ --> tests/ui/char_indices_as_byte_indices.rs:14:23
|
LL | prim.split_at(idx);
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
- --> tests/ui/char_indices_as_byte_indices.rs:12:10
+ --> tests/ui/char_indices_as_byte_indices.rs:11:10
|
LL | for (idx, _) in prim.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
@@ -37,14 +37,14 @@
|
error: passing a character position to a method that expects a byte index
- --> tests/ui/char_indices_as_byte_indices.rs:19:49
+ --> tests/ui/char_indices_as_byte_indices.rs:18:49
|
LL | let _ = prim[..prim.floor_char_boundary(idx)];
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
- --> tests/ui/char_indices_as_byte_indices.rs:12:10
+ --> tests/ui/char_indices_as_byte_indices.rs:11:10
|
LL | for (idx, _) in prim.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
@@ -55,14 +55,14 @@
|
error: indexing into a string with a character position where a byte index is expected
- --> tests/ui/char_indices_as_byte_indices.rs:29:24
+ --> tests/ui/char_indices_as_byte_indices.rs:28:24
|
LL | let _ = prim[..c.0];
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
- --> tests/ui/char_indices_as_byte_indices.rs:28:9
+ --> tests/ui/char_indices_as_byte_indices.rs:27:9
|
LL | for c in prim.chars().enumerate() {
| ^ ^^^^^^^^^^^
@@ -73,14 +73,14 @@
|
error: passing a character position to a method that expects a byte index
- --> tests/ui/char_indices_as_byte_indices.rs:31:23
+ --> tests/ui/char_indices_as_byte_indices.rs:30:23
|
LL | prim.split_at(c.0);
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
- --> tests/ui/char_indices_as_byte_indices.rs:28:9
+ --> tests/ui/char_indices_as_byte_indices.rs:27:9
|
LL | for c in prim.chars().enumerate() {
| ^ ^^^^^^^^^^^
@@ -91,14 +91,14 @@
|
error: indexing into a string with a character position where a byte index is expected
- --> tests/ui/char_indices_as_byte_indices.rs:36:26
+ --> tests/ui/char_indices_as_byte_indices.rs:35:26
|
LL | let _ = string[..idx];
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
- --> tests/ui/char_indices_as_byte_indices.rs:35:10
+ --> tests/ui/char_indices_as_byte_indices.rs:34:10
|
LL | for (idx, _) in string.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
@@ -109,14 +109,14 @@
|
error: passing a character position to a method that expects a byte index
- --> tests/ui/char_indices_as_byte_indices.rs:38:25
+ --> tests/ui/char_indices_as_byte_indices.rs:37:25
|
LL | string.split_at(idx);
| ^^^
|
= note: a character can take up more than one byte, so they are not interchangeable
note: position comes from the enumerate iterator
- --> tests/ui/char_indices_as_byte_indices.rs:35:10
+ --> tests/ui/char_indices_as_byte_indices.rs:34:10
|
LL | for (idx, _) in string.chars().enumerate() {
| ^^^ ^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr
index 8723505..f32e83d 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.stderr
+++ b/src/tools/clippy/tests/ui/ptr_arg.stderr
@@ -268,10 +268,10 @@
| ^^^^^^^^^^^ help: change this to: `&mut str`
error: eliding a lifetime that's named elsewhere is confusing
- --> tests/ui/ptr_arg.rs:314:36
+ --> tests/ui/ptr_arg.rs:314:56
|
LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str {
- | ^^ ^^ ---- the same lifetime is elided here
+ | -- -- ^^^^ the same lifetime is elided here
| | |
| | the lifetime is named here
| the lifetime is named here
diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs
index e968e7a..e709910 100644
--- a/src/tools/clippy/tests/ui/transmute.rs
+++ b/src/tools/clippy/tests/ui/transmute.rs
@@ -4,6 +4,7 @@
dead_code,
clippy::borrow_as_ptr,
unnecessary_transmutes,
+ integer_to_ptr_transmutes,
clippy::needless_lifetimes,
clippy::missing_transmute_annotations
)]
@@ -60,12 +61,10 @@ fn useless() {
//~^ useless_transmute
let _: *const usize = std::mem::transmute(5_isize);
- //~^ useless_transmute
let _ = std::ptr::dangling::<usize>();
let _: *const usize = std::mem::transmute(1 + 1usize);
- //~^ useless_transmute
let _ = (1 + 1_usize) as *const usize;
}
diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr
index 79528ec..9478db0 100644
--- a/src/tools/clippy/tests/ui/transmute.stderr
+++ b/src/tools/clippy/tests/ui/transmute.stderr
@@ -1,5 +1,5 @@
error: transmute from a reference to a pointer
- --> tests/ui/transmute.rs:33:27
+ --> tests/ui/transmute.rs:34:27
|
LL | let _: *const T = core::mem::transmute(t);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T`
@@ -8,61 +8,49 @@
= help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
error: transmute from a reference to a pointer
- --> tests/ui/transmute.rs:36:25
+ --> tests/ui/transmute.rs:37:25
|
LL | let _: *mut T = core::mem::transmute(t);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T`
error: transmute from a reference to a pointer
- --> tests/ui/transmute.rs:39:27
+ --> tests/ui/transmute.rs:40:27
|
LL | let _: *const U = core::mem::transmute(t);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U`
error: transmute from a type (`std::vec::Vec<i32>`) to itself
- --> tests/ui/transmute.rs:47:27
+ --> tests/ui/transmute.rs:48:27
|
LL | let _: Vec<i32> = core::mem::transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`std::vec::Vec<i32>`) to itself
- --> tests/ui/transmute.rs:50:27
+ --> tests/ui/transmute.rs:51:27
|
LL | let _: Vec<i32> = core::mem::transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`std::vec::Vec<i32>`) to itself
- --> tests/ui/transmute.rs:53:27
+ --> tests/ui/transmute.rs:54:27
|
LL | let _: Vec<i32> = std::mem::transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`std::vec::Vec<i32>`) to itself
- --> tests/ui/transmute.rs:56:27
+ --> tests/ui/transmute.rs:57:27
|
LL | let _: Vec<i32> = std::mem::transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`std::vec::Vec<i32>`) to itself
- --> tests/ui/transmute.rs:59:27
+ --> tests/ui/transmute.rs:60:27
|
LL | let _: Vec<i32> = my_transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^
-error: transmute from an integer to a pointer
- --> tests/ui/transmute.rs:62:31
- |
-LL | let _: *const usize = std::mem::transmute(5_isize);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize`
-
-error: transmute from an integer to a pointer
- --> tests/ui/transmute.rs:67:31
- |
-LL | let _: *const usize = std::mem::transmute(1 + 1usize);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize`
-
error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`)
- --> tests/ui/transmute.rs:99:24
+ --> tests/ui/transmute.rs:98:24
|
LL | let _: Usize = core::mem::transmute(int_const_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,25 +59,25 @@
= help: to override `-D warnings` add `#[allow(clippy::crosspointer_transmute)]`
error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
- --> tests/ui/transmute.rs:102:24
+ --> tests/ui/transmute.rs:101:24
|
LL | let _: Usize = core::mem::transmute(int_mut_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
- --> tests/ui/transmute.rs:105:31
+ --> tests/ui/transmute.rs:104:31
|
LL | let _: *const Usize = core::mem::transmute(my_int());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
- --> tests/ui/transmute.rs:108:29
+ --> tests/ui/transmute.rs:107:29
|
LL | let _: *mut Usize = core::mem::transmute(my_int());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a `u8` to a `bool`
- --> tests/ui/transmute.rs:115:28
+ --> tests/ui/transmute.rs:114:28
|
LL | let _: bool = unsafe { std::mem::transmute(0_u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
@@ -98,7 +86,7 @@
= help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]`
error: transmute from a `&[u8]` to a `&str`
- --> tests/ui/transmute.rs:122:28
+ --> tests/ui/transmute.rs:121:28
|
LL | let _: &str = unsafe { std::mem::transmute(B) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -107,16 +95,16 @@
= help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]`
error: transmute from a `&mut [u8]` to a `&mut str`
- --> tests/ui/transmute.rs:125:32
+ --> tests/ui/transmute.rs:124:32
|
LL | let _: &mut str = unsafe { std::mem::transmute(mb) };
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
error: transmute from a `&[u8]` to a `&str`
- --> tests/ui/transmute.rs:128:30
+ --> tests/ui/transmute.rs:127:30
|
LL | const _: &str = unsafe { std::mem::transmute(B) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
-error: aborting due to 18 previous errors
+error: aborting due to 16 previous errors
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index e7ad2a1..02f67f7 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -13,9 +13,6 @@
// We should see an error message for each transmute, and no error messages for
// the casts, since the casts are the recommended fixes.
- // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast
- let _ptr_i32_transmute = unsafe { usize::MAX as *const i32 };
- //~^ useless_transmute
let ptr_i32 = usize::MAX as *const i32;
// e has type *T, U is *U_0, and either U_0: Sized ...
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
index 42a8177..c5e1564 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -13,9 +13,6 @@ fn main() {
// We should see an error message for each transmute, and no error messages for
// the casts, since the casts are the recommended fixes.
- // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast
- let _ptr_i32_transmute = unsafe { transmute::<usize, *const i32>(usize::MAX) };
- //~^ useless_transmute
let ptr_i32 = usize::MAX as *const i32;
// e has type *T, U is *U_0, and either U_0: Sized ...
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
index 7746f08..f39a64d 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
@@ -1,14 +1,5 @@
-error: transmute from an integer to a pointer
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:17:39
- |
-LL | let _ptr_i32_transmute = unsafe { transmute::<usize, *const i32>(usize::MAX) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `usize::MAX as *const i32`
- |
- = note: `-D clippy::useless-transmute` implied by `-D warnings`
- = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
-
error: transmute from a pointer to a pointer
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:22:38
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:19:38
|
LL | let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +13,7 @@
|
error: transmute from a pointer to a pointer
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:29:46
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:26:46
|
LL | let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,7 +25,7 @@
|
error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:36:50
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:33:50
|
LL | let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, usize>(ptr_i32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize`
@@ -43,40 +34,43 @@
= help: to override `-D warnings` add `#[allow(clippy::transmutes_expressible_as_ptr_casts)]`
error: transmute from a reference to a pointer
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:43:41
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:40:41
|
LL | let _array_ptr_transmute = unsafe { transmute::<&[i32; 4], *const [i32; 4]>(array_ref) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]`
+ |
+ = note: `-D clippy::useless-transmute` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
error: transmute from `fn(usize) -> u8` to `*const usize` which could be expressed as a pointer cast instead
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:52:41
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:49:41
|
LL | let _usize_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, *const usize>(foo) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize`
error: transmute from `fn(usize) -> u8` to `usize` which could be expressed as a pointer cast instead
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:57:49
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:54:49
|
LL | let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize`
error: transmute from `*const u32` to `usize` which could be expressed as a pointer cast instead
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:61:36
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:58:36
|
LL | let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&1u32 as *const u32 as usize`
error: transmute from a reference to a pointer
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:73:14
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:70:14
|
LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
error: transmute from `fn()` to `*const u8` which could be expressed as a pointer cast instead
- --> tests/ui/transmutes_expressible_as_ptr_casts.rs:92:28
+ --> tests/ui/transmutes_expressible_as_ptr_casts.rs:89:28
|
LL | let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(f as *const u8)`
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/collect-license-metadata/Cargo.toml b/src/tools/collect-license-metadata/Cargo.toml
index edf9e5c..7f2e57c 100644
--- a/src/tools/collect-license-metadata/Cargo.toml
+++ b/src/tools/collect-license-metadata/Cargo.toml
@@ -8,5 +8,5 @@
[dependencies]
anyhow = "1.0.65"
serde = { version = "1.0.147", features = ["derive"] }
-serde_json = "1.0.85"
+serde_json.workspace = true
spdx-rs = "0.5.1"
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index cdada5a..fb71275 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -20,22 +20,22 @@
getopts = "0.2"
glob = "0.3.0"
home = "0.5.5"
-indexmap = "2.0.0"
+indexmap.workspace = true
miropt-test-tools = { path = "../miropt-test-tools" }
rayon = "1.10.0"
regex = "1.0"
rustfix = "0.8.1"
semver = { version = "1.0.23", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
-tracing = "0.1"
+serde_json.workspace = true
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["ansi", "env-filter", "fmt", "parking_lot", "smallvec"] }
+tracing.workspace = true
unified-diff = "0.2.1"
walkdir = "2"
# tidy-alphabetical-end
[target.'cfg(unix)'.dependencies]
-libc = "0.2"
+libc.workspace = true
[target.'cfg(windows)'.dependencies]
miow = "0.6"
diff --git a/src/tools/compiletest/src/bin/main.rs b/src/tools/compiletest/src/bin/main.rs
index 1f777e7..8fac6cc 100644
--- a/src/tools/compiletest/src/bin/main.rs
+++ b/src/tools/compiletest/src/bin/main.rs
@@ -2,7 +2,7 @@
use std::io::IsTerminal;
use std::sync::Arc;
-use compiletest::{early_config_check, log_config, parse_config, run_tests};
+use compiletest::{early_config_check, parse_config, run_tests};
fn main() {
tracing_subscriber::fmt::init();
@@ -19,6 +19,5 @@ fn main() {
early_config_check(&config);
- log_config(&config);
run_tests(config);
}
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 7fc80c1..b72c0b7 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -8,7 +8,7 @@
use semver::Version;
use serde::de::{Deserialize, Deserializer, Error as _};
-use crate::executor::{ColorConfig, OutputFormat};
+use crate::executor::ColorConfig;
use crate::fatal;
use crate::util::{Utf8PathBufExt, add_dylib_path, string_enum};
@@ -565,13 +565,6 @@ pub struct Config {
/// FIXME: this is *way* too coarse; the user can't select *which* info to verbosely dump.
pub verbose: bool,
- /// (Useless) Adjust libtest output format.
- ///
- /// FIXME: the hand-rolled executor does not support non-JSON output, because `compiletest` need
- /// to package test outcome as `libtest`-esque JSON that `bootstrap` can intercept *anyway*.
- /// However, now that we don't use the `libtest` executor, this is useless.
- pub format: OutputFormat,
-
/// Whether to use colors in test output.
///
/// Note: the exact control mechanism is delegated to [`colored`].
@@ -768,7 +761,6 @@ pub fn incomplete_for_rustdoc_gui_test() -> Config {
adb_device_status: Default::default(),
lldb_python_dir: Default::default(),
verbose: Default::default(),
- format: Default::default(),
color: Default::default(),
remote_test_client: Default::default(),
compare_mode: Default::default(),
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 00007aa..f2ad049 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -205,6 +205,8 @@ pub struct TestProps {
pub dont_require_annotations: HashSet<ErrorKind>,
/// Whether pretty printers should be disabled in gdb.
pub disable_gdb_pretty_printers: bool,
+ /// Compare the output by lines, rather than as a single string.
+ pub compare_output_by_lines: bool,
}
mod directives {
@@ -254,6 +256,7 @@ mod directives {
// This isn't a real directive, just one that is probably mistyped often
pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
pub const DISABLE_GDB_PRETTY_PRINTERS: &'static str = "disable-gdb-pretty-printers";
+ pub const COMPARE_OUTPUT_BY_LINES: &'static str = "compare-output-by-lines";
}
impl TestProps {
@@ -310,6 +313,7 @@ pub fn new() -> Self {
add_core_stubs: false,
dont_require_annotations: Default::default(),
disable_gdb_pretty_printers: false,
+ compare_output_by_lines: false,
}
}
@@ -664,6 +668,11 @@ fn split_flags(flags: &str) -> Vec<String> {
DISABLE_GDB_PRETTY_PRINTERS,
&mut self.disable_gdb_pretty_printers,
);
+ config.set_name_directive(
+ ln,
+ COMPARE_OUTPUT_BY_LINES,
+ &mut self.compare_output_by_lines,
+ );
},
);
diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs
index 59690ff..0ef84fb 100644
--- a/src/tools/compiletest/src/directives/directive_names.rs
+++ b/src/tools/compiletest/src/directives/directive_names.rs
@@ -17,6 +17,7 @@
"check-run-results",
"check-stdout",
"check-test-line-numbers-match",
+ "compare-output-by-lines",
"compile-flags",
"disable-gdb-pretty-printers",
"doc-flags",
diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs
index df64f12..fdd7155 100644
--- a/src/tools/compiletest/src/executor.rs
+++ b/src/tools/compiletest/src/executor.rs
@@ -1,5 +1,9 @@
//! This module contains a reimplementation of the subset of libtest
//! functionality needed by compiletest.
+//!
+//! FIXME(Zalathar): Much of this code was originally designed to mimic libtest
+//! as closely as possible, for ease of migration. Now that libtest is no longer
+//! used, we can potentially redesign things to be a better fit for compiletest.
use std::borrow::Cow;
use std::collections::HashMap;
@@ -207,7 +211,7 @@ fn is_failed(&self) -> bool {
///
/// Adapted from `filter_tests` in libtest.
///
-/// FIXME(#139660): After the libtest dependency is removed, redesign the whole filtering system to
+/// FIXME(#139660): Now that libtest has been removed, redesign the whole filtering system to
/// do a better job of understanding and filtering _paths_, instead of being tied to libtest's
/// substring/exact matching behaviour.
fn filter_tests(opts: &Config, tests: Vec<CollectedTest>) -> Vec<CollectedTest> {
@@ -249,7 +253,7 @@ fn get_concurrency() -> usize {
}
}
-/// Information needed to create a `test::TestDescAndFn`.
+/// Information that was historically needed to create a libtest `TestDescAndFn`.
pub(crate) struct CollectedTest {
pub(crate) desc: CollectedTestDesc,
pub(crate) config: Arc<Config>,
@@ -257,7 +261,7 @@ pub(crate) struct CollectedTest {
pub(crate) revision: Option<String>,
}
-/// Information needed to create a `test::TestDesc`.
+/// Information that was historically needed to create a libtest `TestDesc`.
pub(crate) struct CollectedTestDesc {
pub(crate) name: String,
pub(crate) ignore: bool,
@@ -274,18 +278,6 @@ pub enum ColorConfig {
NeverColor,
}
-/// Format of the test results output.
-#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
-pub enum OutputFormat {
- /// Verbose output
- Pretty,
- /// Quiet output
- #[default]
- Terse,
- /// JSON output
- Json,
-}
-
/// Whether test is expected to panic or not.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub(crate) enum ShouldPanic {
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 469dd68..8737fec 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -9,7 +9,6 @@
mod tests;
pub mod common;
-pub mod compute_diff;
mod debuggers;
pub mod diagnostics;
pub mod directives;
@@ -43,8 +42,7 @@
expected_output_path, output_base_dir, output_relative_path,
};
use crate::directives::DirectivesCache;
-use crate::executor::{CollectedTest, ColorConfig, OutputFormat};
-use crate::util::logv;
+use crate::executor::{CollectedTest, ColorConfig};
/// Creates the `Config` instance for this invocation of compiletest.
///
@@ -137,9 +135,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
"overwrite stderr/stdout files instead of complaining about a mismatch",
)
.optflag("", "fail-fast", "stop as soon as possible after any test fails")
- .optflag("", "quiet", "print one character per test instead of one line")
.optopt("", "color", "coloring: auto, always, never", "WHEN")
- .optflag("", "json", "emit json output instead of plaintext output")
.optopt("", "target", "the target to build for", "TARGET")
.optopt("", "host", "the host to build for", "HOST")
.optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
@@ -203,7 +199,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
"COMMAND",
)
.reqopt("", "minicore-path", "path to minicore aux library", "PATH")
- .optflag("N", "no-new-executor", "disables the new test executor, and uses libtest instead")
.optopt(
"",
"debugger",
@@ -436,12 +431,6 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
&& !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
lldb_python_dir: matches.opt_str("lldb-python-dir"),
verbose: matches.opt_present("verbose"),
- format: match (matches.opt_present("quiet"), matches.opt_present("json")) {
- (true, true) => panic!("--quiet and --json are incompatible"),
- (true, false) => OutputFormat::Terse,
- (false, true) => OutputFormat::Json,
- (false, false) => OutputFormat::Pretty,
- },
only_modified: matches.opt_present("only-modified"),
color,
remote_test_client: matches.opt_str("remote-test-client").map(Utf8PathBuf::from),
@@ -486,52 +475,6 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
}
}
-pub fn log_config(config: &Config) {
- let c = config;
- logv(c, "configuration:".to_string());
- logv(c, format!("compile_lib_path: {}", config.compile_lib_path));
- logv(c, format!("run_lib_path: {}", config.run_lib_path));
- logv(c, format!("rustc_path: {}", config.rustc_path));
- logv(c, format!("cargo_path: {:?}", config.cargo_path));
- logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
-
- logv(c, format!("src_root: {}", config.src_root));
- logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root));
-
- logv(c, format!("build_root: {}", config.build_root));
- logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root));
-
- logv(c, format!("sysroot_base: {}", config.sysroot_base));
-
- logv(c, format!("stage: {}", config.stage));
- logv(c, format!("stage_id: {}", config.stage_id));
- logv(c, format!("mode: {}", config.mode));
- logv(c, format!("run_ignored: {}", config.run_ignored));
- logv(c, format!("filters: {:?}", config.filters));
- logv(c, format!("skip: {:?}", config.skip));
- logv(c, format!("filter_exact: {}", config.filter_exact));
- logv(
- c,
- format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
- );
- logv(c, format!("runner: {}", opt_str(&config.runner)));
- logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
- logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
- logv(c, format!("target: {}", config.target));
- logv(c, format!("host: {}", config.host));
- logv(c, format!("android-cross-path: {}", config.android_cross_path));
- logv(c, format!("adb_path: {}", config.adb_path));
- logv(c, format!("adb_test_dir: {}", config.adb_test_dir));
- logv(c, format!("adb_device_status: {}", config.adb_device_status));
- logv(c, format!("ar: {}", config.ar));
- logv(c, format!("target-linker: {:?}", config.target_linker));
- logv(c, format!("host-linker: {:?}", config.host_linker));
- logv(c, format!("verbose: {}", config.verbose));
- logv(c, format!("format: {:?}", config.format));
- logv(c, format!("minicore_path: {}", config.minicore_path));
- logv(c, "\n".to_string());
-}
-
pub fn opt_str(maybestr: &Option<String>) -> &str {
match *maybestr {
None => "(none)",
@@ -548,6 +491,8 @@ pub fn opt_str2(maybestr: Option<String>) -> String {
/// Called by `main` after the config has been parsed.
pub fn run_tests(config: Arc<Config>) {
+ debug!(?config, "run_tests");
+
// If we want to collect rustfix coverage information,
// we first make sure that the coverage file does not exist.
// It will be created later on.
@@ -601,7 +546,7 @@ pub fn run_tests(config: Arc<Config>) {
configs.push(config.clone());
};
- // Discover all of the tests in the test suite directory, and build a libtest
+ // Discover all of the tests in the test suite directory, and build a `CollectedTest`
// structure for each test (or each revision of a multi-revision test).
let mut tests = Vec::new();
for c in configs {
@@ -613,50 +558,35 @@ pub fn run_tests(config: Arc<Config>) {
// Delegate to the executor to filter and run the big list of test structures
// created during test discovery. When the executor decides to run a test,
// it will return control to the rest of compiletest by calling `runtest::run`.
- // FIXME(Zalathar): Once we're confident that we won't need to revert the
- // removal of the libtest-based executor, remove this Result and other
- // remnants of the old executor.
- let res: io::Result<bool> = Ok(executor::run_tests(&config, tests));
+ let ok = executor::run_tests(&config, tests);
- // Check the outcome reported by libtest.
- match res {
- Ok(true) => {}
- Ok(false) => {
- // We want to report that the tests failed, but we also want to give
- // some indication of just what tests we were running. Especially on
- // CI, where there can be cross-compiled tests for a lot of
- // architectures, without this critical information it can be quite
- // easy to miss which tests failed, and as such fail to reproduce
- // the failure locally.
+ // Check the outcome reported by the executor.
+ if !ok {
+ // We want to report that the tests failed, but we also want to give
+ // some indication of just what tests we were running. Especially on
+ // CI, where there can be cross-compiled tests for a lot of
+ // architectures, without this critical information it can be quite
+ // easy to miss which tests failed, and as such fail to reproduce
+ // the failure locally.
- let mut msg = String::from("Some tests failed in compiletest");
- write!(msg, " suite={}", config.suite).unwrap();
+ let mut msg = String::from("Some tests failed in compiletest");
+ write!(msg, " suite={}", config.suite).unwrap();
- if let Some(compare_mode) = config.compare_mode.as_ref() {
- write!(msg, " compare_mode={}", compare_mode).unwrap();
- }
-
- if let Some(pass_mode) = config.force_pass_mode.as_ref() {
- write!(msg, " pass_mode={}", pass_mode).unwrap();
- }
-
- write!(msg, " mode={}", config.mode).unwrap();
- write!(msg, " host={}", config.host).unwrap();
- write!(msg, " target={}", config.target).unwrap();
-
- println!("{msg}");
-
- std::process::exit(1);
+ if let Some(compare_mode) = config.compare_mode.as_ref() {
+ write!(msg, " compare_mode={}", compare_mode).unwrap();
}
- Err(e) => {
- // We don't know if tests passed or not, but if there was an error
- // during testing we don't want to just succeed (we may not have
- // tested something), so fail.
- //
- // This should realistically "never" happen, so don't try to make
- // this a pretty error message.
- panic!("I/O failure during tests: {:?}", e);
+
+ if let Some(pass_mode) = config.force_pass_mode.as_ref() {
+ write!(msg, " pass_mode={}", pass_mode).unwrap();
}
+
+ write!(msg, " mode={}", config.mode).unwrap();
+ write!(msg, " host={}", config.host).unwrap();
+ write!(msg, " target={}", config.target).unwrap();
+
+ println!("{msg}");
+
+ std::process::exit(1);
}
}
@@ -691,7 +621,11 @@ fn merge(&mut self, mut other: Self) {
///
/// This always inspects _all_ test files in the suite (e.g. all 17k+ ui tests),
/// regardless of whether any filters/tests were specified on the command-line,
-/// because filtering is handled later by libtest.
+/// because filtering is handled later by code that was copied from libtest.
+///
+/// FIXME(Zalathar): Now that we no longer rely on libtest, try to overhaul
+/// test discovery to take into account the filters/tests specified on the
+/// command-line, instead of having to enumerate everything.
pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest> {
debug!("making tests from {}", config.src_test_suite_root);
let common_inputs_stamp = common_inputs_stamp(&config);
@@ -805,7 +739,7 @@ fn modified_tests(config: &Config, dir: &Utf8Path) -> Result<Vec<Utf8PathBuf>, S
}
/// Recursively scans a directory to find test files and create test structures
-/// that will be handed over to libtest.
+/// that will be handed over to the executor.
fn collect_tests_from_dir(
cx: &TestCollectorCx,
dir: &Utf8Path,
@@ -871,7 +805,7 @@ fn collect_tests_from_dir(
if is_test(file_name)
&& (!cx.config.only_modified || cx.modified_tests.contains(&file_path))
{
- // We found a test file, so create the corresponding libtest structures.
+ // We found a test file, so create the corresponding test structures.
debug!(%file_path, "found test file");
// Record the stem of the test file, to check for overlaps later.
@@ -915,7 +849,7 @@ pub fn is_test(file_name: &str) -> bool {
}
/// For a single test file, creates one or more test structures (one per revision) that can be
-/// handed over to libtest to run, possibly in parallel.
+/// handed over to the executor to run, possibly in parallel.
fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &TestPaths) {
// For run-make tests, each "test file" is actually a _directory_ containing an `rmake.rs`. But
// for the purposes of directive parsing, we want to look at that recipe file, not the directory
@@ -929,7 +863,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
// Scan the test file to discover its revisions, if any.
let early_props = EarlyProps::from_file(&cx.config, &test_path);
- // Normally we create one libtest structure per revision, with two exceptions:
+ // Normally we create one structure per revision, with two exceptions:
// - If a test doesn't use revisions, create a dummy revision (None) so that
// the test can still run.
// - Incremental tests inherently can't run their revisions in parallel, so
@@ -944,12 +878,12 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
// For each revision (or the sole dummy revision), create and append a
// `CollectedTest` that can be handed over to the test executor.
collector.tests.extend(revisions.into_iter().map(|revision| {
- // Create a test name and description to hand over to libtest.
+ // Create a test name and description to hand over to the executor.
let src_file = fs::File::open(&test_path).expect("open test file to parse ignores");
let test_name = make_test_name(&cx.config, testpaths, revision);
- // Create a libtest description for the test/revision.
+ // Create a description struct for the test/revision.
// This is where `ignore-*`/`only-*`/`needs-*` directives are handled,
- // because they need to set the libtest ignored flag.
+ // because they historically needed to set the libtest ignored flag.
let mut desc = make_test_description(
&cx.config,
&cx.cache,
@@ -961,10 +895,12 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
);
// If a test's inputs haven't changed since the last time it ran,
- // mark it as ignored so that libtest will skip it.
+ // mark it as ignored so that the executor will skip it.
if !cx.config.force_rerun && is_up_to_date(cx, testpaths, &early_props, revision) {
desc.ignore = true;
// Keep this in sync with the "up-to-date" message detected by bootstrap.
+ // FIXME(Zalathar): Now that we are no longer tied to libtest, we could
+ // find a less fragile way to communicate this status to bootstrap.
desc.ignore_message = Some("up-to-date".into());
}
@@ -1104,7 +1040,7 @@ fn add_dir(&mut self, path: &Utf8Path) {
}
}
-/// Creates a name for this test/revision that can be handed over to libtest.
+/// Creates a name for this test/revision that can be handed over to the executor.
fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> String {
// Print the name of the file, relative to the sources root.
let path = testpaths.file.strip_prefix(&config.src_root).unwrap();
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 2402ed9..867624c 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -7,7 +7,7 @@
use std::io::{self, BufReader};
use std::process::{Child, Command, ExitStatus, Output, Stdio};
use std::sync::Arc;
-use std::{env, iter, str};
+use std::{env, fmt, iter, str};
use build_helper::fs::remove_and_create_dir_all;
use camino::{Utf8Path, Utf8PathBuf};
@@ -21,15 +21,13 @@
UI_WINDOWS_SVG, expected_output_path, incremental_dir, output_base_dir, output_base_name,
output_testname_unique,
};
-use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
use crate::directives::TestProps;
use crate::errors::{Error, ErrorKind, load_errors};
use crate::read2::{Truncated, read2_abbreviated};
-use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex};
+use crate::runtest::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
+use crate::util::{Utf8PathBufExt, add_dylib_path, static_regex};
use crate::{ColorConfig, help, json, stamp_file_path, warning};
-mod debugger;
-
// Helper modules that implement test running logic for each test suite.
// tidy-alphabetical-start
mod assembly;
@@ -48,6 +46,8 @@
mod ui;
// tidy-alphabetical-end
+mod compute_diff;
+mod debugger;
#[cfg(test)]
mod tests;
@@ -412,7 +412,7 @@ fn run_command_to_procres(&self, cmd: &mut Command) -> ProcRes {
cmdline: format!("{cmd:?}"),
};
self.dump_output(
- self.config.verbose,
+ self.config.verbose || !proc_res.status.success(),
&cmd.get_program().to_string_lossy(),
&proc_res.stdout,
&proc_res.stderr,
@@ -1459,7 +1459,7 @@ fn compose_and_run(
) -> ProcRes {
let cmdline = {
let cmdline = self.make_cmdline(&command, lib_path);
- logv(self.config, format!("executing {}", cmdline));
+ self.logv(format_args!("executing {cmdline}"));
cmdline
};
@@ -1486,7 +1486,7 @@ fn compose_and_run(
};
self.dump_output(
- self.config.verbose,
+ self.config.verbose || (!result.status.success() && self.config.mode != TestMode::Ui),
&command.get_program().to_string_lossy(),
&result.stdout,
&result.stderr,
@@ -2006,6 +2006,18 @@ fn output_base_name(&self) -> Utf8PathBuf {
output_base_name(self.config, self.testpaths, self.safe_revision())
}
+ /// Prints a message to (captured) stdout if `config.verbose` is true.
+ /// The message is also logged to `tracing::debug!` regardles of verbosity.
+ ///
+ /// Use `format_args!` as the argument to perform formatting if required.
+ fn logv(&self, message: impl fmt::Display) {
+ debug!("{message}");
+ if self.config.verbose {
+ // Note: `./x test ... --verbose --no-capture` is needed to see this print.
+ println!("{message}");
+ }
+ }
+
/// Prefix to print before error messages. Normally just `error`, but also
/// includes the revision name for tests that use revisions.
#[must_use]
@@ -2222,7 +2234,7 @@ fn compare_to_default_rustdoc(&self, out_dir: &Utf8Path) {
.env("PAGER", "")
.stdin(File::open(&diff_filename).unwrap())
// Capture output and print it explicitly so it will in turn be
- // captured by libtest.
+ // captured by output-capture.
.output()
.unwrap();
assert!(output.status.success());
@@ -2666,8 +2678,8 @@ fn normalize_platform_differences(output: &str) -> String {
//
// It's not possible to detect paths in the error messages generally, but this is a
// decent enough heuristic.
- static_regex!(
- r#"(?x)
+ let re = static_regex!(
+ r#"(?x)
(?:
# Match paths that don't include spaces.
(?:\\[\pL\pN\.\-_']+)+\.\pL+
@@ -2675,11 +2687,8 @@ fn normalize_platform_differences(output: &str) -> String {
# If the path starts with a well-known root, then allow spaces and no file extension.
\$(?:DIR|SRC_DIR|TEST_BUILD_DIR|BUILD_DIR|LIB_DIR)(?:\\[\pL\pN\.\-_'\ ]+)+
)"#
- )
- .replace_all(&output, |caps: &Captures<'_>| {
- println!("{}", &caps[0]);
- caps[0].replace(r"\", "/")
- })
+ );
+ re.replace_all(&output, |caps: &Captures<'_>| caps[0].replace(r"\", "/"))
.replace("\r\n", "\n")
}
@@ -2754,7 +2763,11 @@ fn compare_output(
// Wrapper tools set by `runner` might provide extra output on failure,
// for example a WebAssembly runtime might print the stack trace of an
// `unreachable` instruction by default.
- let compare_output_by_lines = self.config.runner.is_some();
+ //
+ // Also, some tests like `ui/parallel-rustc` have non-deterministic
+ // orders of output, so we need to compare by lines.
+ let compare_output_by_lines =
+ self.props.compare_output_by_lines || self.config.runner.is_some();
let tmp;
let (expected, actual): (&str, &str) = if compare_output_by_lines {
@@ -2983,6 +2996,7 @@ struct ProcArgs {
args: Vec<OsString>,
}
+#[derive(Debug)]
pub struct ProcRes {
status: ExitStatus,
stdout: String,
diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/runtest/compute_diff.rs
similarity index 100%
rename from src/tools/compiletest/src/compute_diff.rs
rename to src/tools/compiletest/src/runtest/compute_diff.rs
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index 6114afd..88d022b 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -10,7 +10,6 @@
use super::{Debugger, Emit, ProcRes, TestCx, Truncated, WillExecute};
use crate::common::Config;
use crate::debuggers::{extract_gdb_version, is_android_gdb_target};
-use crate::util::logv;
impl TestCx<'_> {
pub(super) fn run_debuginfo_test(&self) {
@@ -234,7 +233,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
gdb.args(debugger_opts);
// FIXME(jieyouxu): don't pass an empty Path
let cmdline = self.make_cmdline(&gdb, Utf8Path::new(""));
- logv(self.config, format!("executing {}", cmdline));
+ self.logv(format_args!("executing {cmdline}"));
cmdline
};
@@ -395,6 +394,35 @@ fn run_debuginfo_lldb_test_no_opt(&self) {
// We don't want to hang when calling `quit` while the process is still running
let mut script_str = String::from("settings set auto-confirm true\n");
+ // macOS has a system for restricting access to files and peripherals
+ // called Transparency, Consent, and Control (TCC), which can be
+ // configured using the "Security & Privacy" tab in your settings.
+ //
+ // This system is provenance-based: if Terminal.app is given access to
+ // your Desktop, and you launch a binary within Terminal.app, the new
+ // binary also has access to the files on your Desktop.
+ //
+ // By default though, LLDB launches binaries in very isolated
+ // contexts. This includes resetting any TCC grants that might
+ // otherwise have been inherited.
+ //
+ // In effect, this means that if the developer has placed the rust
+ // repository under one of the system-protected folders, they will get
+ // a pop-up _for each binary_ asking for permissions to access the
+ // folder - quite annoying.
+ //
+ // To avoid this, we tell LLDB to spawn processes with TCC grants
+ // inherited from the parent process.
+ //
+ // Setting this also avoids unnecessary overhead from XprotectService
+ // when running with the Developer Tool grant.
+ //
+ // TIP: If you want to allow launching `lldb ~/Desktop/my_binary`
+ // without being prompted, you can put this in your `~/.lldbinit` too.
+ if self.config.host.contains("darwin") {
+ script_str.push_str("settings set target.inherit-tcc true\n");
+ }
+
// Make LLDB emit its version, so we have it documented in the test output
script_str.push_str("version\n");
diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs
index efdb131..55043bf 100644
--- a/src/tools/compiletest/src/runtest/mir_opt.rs
+++ b/src/tools/compiletest/src/runtest/mir_opt.rs
@@ -6,7 +6,7 @@
use tracing::debug;
use super::{Emit, TestCx, WillExecute};
-use crate::compute_diff::write_diff;
+use crate::runtest::compute_diff::write_diff;
impl TestCx<'_> {
pub(super) fn run_mir_opt_test(&self) {
diff --git a/src/tools/compiletest/src/runtest/pretty.rs b/src/tools/compiletest/src/runtest/pretty.rs
index e3b07f1..2655772 100644
--- a/src/tools/compiletest/src/runtest/pretty.rs
+++ b/src/tools/compiletest/src/runtest/pretty.rs
@@ -1,14 +1,13 @@
use std::fs;
use super::{ProcRes, ReadFrom, TestCx};
-use crate::util::logv;
impl TestCx<'_> {
pub(super) fn run_pretty_test(&self) {
if self.props.pp_exact.is_some() {
- logv(self.config, "testing for exact pretty-printing".to_owned());
+ self.logv("testing for exact pretty-printing");
} else {
- logv(self.config, "testing for converging pretty-printing".to_owned());
+ self.logv("testing for converging pretty-printing");
}
let rounds = match self.props.pp_exact {
@@ -21,10 +20,7 @@ pub(super) fn run_pretty_test(&self) {
let mut round = 0;
while round < rounds {
- logv(
- self.config,
- format!("pretty-printing round {} revision {:?}", round, self.revision),
- );
+ self.logv(format_args!("pretty-printing round {round} revision {:?}", self.revision));
let read_from =
if round == 0 { ReadFrom::Path } else { ReadFrom::Stdin(srcs[round].to_owned()) };
diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
index c8d5190..8a0e45c 100644
--- a/src/tools/compiletest/src/runtest/run_make.rs
+++ b/src/tools/compiletest/src/runtest/run_make.rs
@@ -308,7 +308,7 @@ pub(super) fn run_rmake_test(&self) {
let stdout = String::from_utf8_lossy(&stdout).into_owned();
let stderr = String::from_utf8_lossy(&stderr).into_owned();
// This conditions on `status.success()` so we don't print output twice on error.
- // NOTE: this code is called from a libtest thread, so it's hidden by default unless --nocapture is passed.
+ // NOTE: this code is called from an executor thread, so it's hidden by default unless --no-capture is passed.
self.dump_output(status.success(), &cmd.get_program().to_string_lossy(), &stdout, &stderr);
if !status.success() {
let res = ProcRes { status, stdout, stderr, truncated, cmdline: format!("{:?}", cmd) };
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index fb04754..1f16a67 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -2,9 +2,6 @@
use std::process::Command;
use camino::{Utf8Path, Utf8PathBuf};
-use tracing::*;
-
-use crate::common::Config;
#[cfg(test)]
mod tests;
@@ -26,14 +23,6 @@ fn path_div() -> &'static str {
";"
}
-pub fn logv(config: &Config, s: String) {
- debug!("{}", s);
- if config.verbose {
- // Note: `./x test ... --verbose --no-capture` is needed to see this print.
- println!("{}", s);
- }
-}
-
pub trait Utf8PathBufExt {
/// Append an extension to the path, even if it already has one.
fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf;
diff --git a/src/tools/coverage-dump/Cargo.toml b/src/tools/coverage-dump/Cargo.toml
index 36a66f1..e491804 100644
--- a/src/tools/coverage-dump/Cargo.toml
+++ b/src/tools/coverage-dump/Cargo.toml
@@ -7,9 +7,9 @@
[dependencies]
anyhow = "1.0.71"
-itertools = "0.12"
+itertools.workspace = true
leb128 = "0.2.5"
md5 = { package = "md-5" , version = "0.10.5" }
miniz_oxide = "0.8.8"
regex = "1.8.4"
-rustc-demangle = "0.1.23"
+rustc-demangle.workspace = true
diff --git a/src/tools/features-status-dump/Cargo.toml b/src/tools/features-status-dump/Cargo.toml
index b2976f1..d72555d 100644
--- a/src/tools/features-status-dump/Cargo.toml
+++ b/src/tools/features-status-dump/Cargo.toml
@@ -8,5 +8,5 @@
anyhow = { version = "1" }
clap = { version = "4", features = ["derive"] }
serde = { version = "1.0.125", features = [ "derive" ] }
-serde_json = "1.0.59"
+serde_json.workspace = true
tidy = { path = "../tidy", features = ["build-metrics"] }
diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml
index bcb3165..5edf1f3 100644
--- a/src/tools/generate-copyright/Cargo.toml
+++ b/src/tools/generate-copyright/Cargo.toml
@@ -11,5 +11,5 @@
askama = "0.14.0"
cargo_metadata = "0.21"
serde = { version = "1.0.147", features = ["derive"] }
-serde_json = "1.0.85"
+serde_json.workspace = true
thiserror = "1"
diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml
index 80fc26c..92fde36 100644
--- a/src/tools/jsondocck/Cargo.toml
+++ b/src/tools/jsondocck/Cargo.toml
@@ -8,5 +8,5 @@
getopts = "0.2"
regex = "1.4"
shlex = "1.0"
-serde_json = "1.0"
+serde_json.workspace = true
fs-err = "2.5.0"
diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml
index cc8ecef..44beaf2 100644
--- a/src/tools/jsondoclint/Cargo.toml
+++ b/src/tools/jsondoclint/Cargo.toml
@@ -9,7 +9,7 @@
anyhow = "1.0.62"
clap = { version = "4.0.15", features = ["derive"] }
fs-err = "2.8.1"
-rustc-hash = "2.0.0"
+rustc-hash.workspace = true
rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" }
serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0.85"
+serde_json.workspace = true
diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs
index 5114683..e273863 100644
--- a/src/tools/jsondoclint/src/item_kind.rs
+++ b/src/tools/jsondoclint/src/item_kind.rs
@@ -26,6 +26,7 @@ pub(crate) enum Kind {
AssocType,
Primitive,
Keyword,
+ Attribute,
// Not in ItemKind
ProcMacro,
}
@@ -53,6 +54,7 @@ pub fn can_appear_in_mod(self) -> bool {
ExternType => true,
// FIXME(adotinthevoid): I'm not sure if these are correct
+ Attribute => false,
Keyword => false,
ProcAttribute => false,
ProcDerive => false,
@@ -109,6 +111,7 @@ pub fn can_appear_in_trait(self) -> bool {
Kind::Primitive => false,
Kind::Keyword => false,
Kind::ProcMacro => false,
+ Kind::Attribute => false,
}
}
@@ -163,6 +166,7 @@ pub fn from_summary(s: &ItemSummary) -> Self {
match s.kind {
ItemKind::AssocConst => AssocConst,
ItemKind::AssocType => AssocType,
+ ItemKind::Attribute => Attribute,
ItemKind::Constant => Constant,
ItemKind::Enum => Enum,
ItemKind::ExternCrate => ExternCrate,
diff --git a/src/tools/lint-docs/Cargo.toml b/src/tools/lint-docs/Cargo.toml
index 6e1ab84..acafe17 100644
--- a/src/tools/lint-docs/Cargo.toml
+++ b/src/tools/lint-docs/Cargo.toml
@@ -8,6 +8,6 @@
[dependencies]
rustc-literal-escaper = "0.0.5"
-serde_json = "1.0.57"
-tempfile = "3.1.0"
+serde_json.workspace = true
+tempfile.workspace = true
walkdir = "2.3.1"
diff --git a/src/tools/llvm-bitcode-linker/Cargo.toml b/src/tools/llvm-bitcode-linker/Cargo.toml
index a9210b5..f78f8b6 100644
--- a/src/tools/llvm-bitcode-linker/Cargo.toml
+++ b/src/tools/llvm-bitcode-linker/Cargo.toml
@@ -8,7 +8,7 @@
[dependencies]
anyhow = "1.0"
-tracing = "0.1"
-tracing-subscriber = {version = "0.3.0", features = ["std"] }
+tracing.workspace = true
+tracing-subscriber = { version = "0.3.0", features = ["std"] }
clap = { version = "4.3", features = ["derive"] }
thiserror = "1.0.24"
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index d9e374c..ae1b25f 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -279,7 +279,7 @@ fn config(&mut self, config: &mut Config) {
return None;
}
let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
- if codegen_fn_attrs.contains_extern_indicator(tcx, local_def_id.into())
+ if codegen_fn_attrs.contains_extern_indicator()
|| codegen_fn_attrs
.flags
.contains(CodegenFnAttrFlags::USED_COMPILER)
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 1b5d9d5..e0c077e 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -134,8 +134,7 @@ pub fn iter_exported_symbols<'tcx>(
for def_id in crate_items.definitions() {
let exported = tcx.def_kind(def_id).has_codegen_attrs() && {
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
- codegen_attrs.contains_extern_indicator(tcx, def_id.into())
- || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
+ codegen_attrs.contains_extern_indicator()
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
};
diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs
index e2a0bdb..74b9b70 100644
--- a/src/tools/miri/src/shims/native_lib/mod.rs
+++ b/src/tools/miri/src/shims/native_lib/mod.rs
@@ -242,14 +242,9 @@ fn tracing_apply_accesses(&mut self, events: MemEvents) -> InterpResult<'tcx> {
match evt {
AccessEvent::Read(_) => {
- // FIXME: ProvenanceMap should have something like get_range().
- let p_map = alloc.provenance();
- for idx in overlap {
- // If a provenance was read by the foreign code, expose it.
- if let Some((prov, _idx)) = p_map.get_byte(Size::from_bytes(idx), this)
- {
- this.expose_provenance(prov)?;
- }
+ // If a provenance was read by the foreign code, expose it.
+ for prov in alloc.provenance().get_range(this, overlap.into()) {
+ this.expose_provenance(prov)?;
}
}
AccessEvent::Write(_, certain) => {
diff --git a/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs b/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
index 2b861e5..7147813 100644
--- a/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
+++ b/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
@@ -1,3 +1,5 @@
+#![allow(integer_to_ptr_transmutes)]
+
use std::mem::transmute;
#[cfg(target_pointer_width = "32")]
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
index b91a41d..744d64b 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
@@ -1,3 +1,5 @@
+//! Ensure we detect aliasing of two in-place arguments for the tricky case where they do not
+//! live in memory.
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows
// Validation forces more things into memory, which we can't have here.
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs
new file mode 100644
index 0000000..dff724f
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs
@@ -0,0 +1,34 @@
+//! Ensure we detect aliasing of a in-place argument with the return place for the tricky case where
+//! they do not live in memory.
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+// Validation forces more things into memory, which we can't have here.
+//@compile-flags: -Zmiri-disable-validation
+#![feature(custom_mir, core_intrinsics)]
+use std::intrinsics::mir::*;
+
+#[allow(unused)]
+pub struct S(i32);
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+fn main() {
+ mir! {
+ let _unit: ();
+ {
+ let staging = S(42); // This forces `staging` into memory...
+ let _non_copy = staging; // ... so we move it to a non-inmemory local here.
+ // This specifically uses a type with scalar representation to tempt Miri to use the
+ // efficient way of storing local variables (outside adressable memory).
+ Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+ //~[stack]^ ERROR: not granting access
+ //~[tree]| ERROR: /reborrow .* forbidden/
+ }
+ after_call = {
+ Return()
+ }
+ }
+}
+
+pub fn callee(x: S) -> S {
+ x
+}
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr
new file mode 100644
index 0000000..fcd5b87
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr
@@ -0,0 +1,25 @@
+error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
+ --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+ |
+LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+ |
+ = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
+ = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
+help: <TAG> was created here, as the root tag for ALLOC
+ --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+ |
+LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: <TAG> is this argument
+ --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+ |
+LL | x
+ | ^
+ = note: BACKTRACE (of the first span):
+ = note: inside `main` at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr
new file mode 100644
index 0000000..b7f514d
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr
@@ -0,0 +1,34 @@
+error: Undefined Behavior: reborrow through <TAG> (root of the allocation) at ALLOC[0x0] is forbidden
+ --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+ |
+LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+ |
+ = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+ = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
+ = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
+ = help: this reborrow (acting as a foreign read access) would cause the protected tag <TAG> (currently Active) to become Disabled
+ = help: protected tags must never be Disabled
+help: the accessed tag <TAG> was created here
+ --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+ |
+LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: the protected tag <TAG> was created here, in the initial state Reserved
+ --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+ |
+LL | x
+ | ^
+help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4]
+ --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+ |
+LL | x
+ | ^
+ = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
+ = note: BACKTRACE (of the first span):
+ = note: inside `main` at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/provenance_transmute.rs b/src/tools/miri/tests/fail/provenance/provenance_transmute.rs
index d72f105..60cb9a7 100644
--- a/src/tools/miri/tests/fail/provenance/provenance_transmute.rs
+++ b/src/tools/miri/tests/fail/provenance/provenance_transmute.rs
@@ -1,5 +1,7 @@
//@compile-flags: -Zmiri-permissive-provenance
+#![allow(integer_to_ptr_transmutes)]
+
use std::mem;
// This is the example from
diff --git a/src/tools/miri/tests/fail/validity/dangling_ref1.rs b/src/tools/miri/tests/fail/validity/dangling_ref1.rs
index fc3a9f3..57ba111 100644
--- a/src/tools/miri/tests/fail/validity/dangling_ref1.rs
+++ b/src/tools/miri/tests/fail/validity/dangling_ref1.rs
@@ -1,5 +1,8 @@
// Make sure we catch this even without Stacked Borrows
//@compile-flags: -Zmiri-disable-stacked-borrows
+
+#![allow(integer_to_ptr_transmutes)]
+
use std::mem;
fn main() {
diff --git a/src/tools/miri/tests/panic/transmute_fat2.rs b/src/tools/miri/tests/panic/transmute_fat2.rs
index e695ff2..7441f25 100644
--- a/src/tools/miri/tests/panic/transmute_fat2.rs
+++ b/src/tools/miri/tests/panic/transmute_fat2.rs
@@ -1,3 +1,5 @@
+#![allow(integer_to_ptr_transmutes)]
+
fn main() {
#[cfg(all(target_endian = "little", target_pointer_width = "64"))]
let bad = unsafe { std::mem::transmute::<u128, &[u8]>(42) };
diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs
index 3de34e5..d8ac511 100644
--- a/src/tools/miri/tests/pass/atomic.rs
+++ b/src/tools/miri/tests/pass/atomic.rs
@@ -2,7 +2,6 @@
//@[tree]compile-flags: -Zmiri-tree-borrows
//@compile-flags: -Zmiri-strict-provenance
-#![feature(strict_provenance_atomic_ptr)]
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
#![allow(static_mut_refs)]
diff --git a/src/tools/miri/tests/pass/binops.rs b/src/tools/miri/tests/pass/binops.rs
index 0aff7ac..fcbe6c8 100644
--- a/src/tools/miri/tests/pass/binops.rs
+++ b/src/tools/miri/tests/pass/binops.rs
@@ -32,6 +32,7 @@ fn test_bool() {
assert_eq!(true ^ true, false);
}
+#[allow(integer_to_ptr_transmutes)]
fn test_ptr() {
unsafe {
let p1: *const u8 = ::std::mem::transmute(0_usize);
diff --git a/src/tools/miri/tests/pass/too-large-primval-write-problem.rs b/src/tools/miri/tests/pass/too-large-primval-write-problem.rs
index f4c418b..00882b7 100644
--- a/src/tools/miri/tests/pass/too-large-primval-write-problem.rs
+++ b/src/tools/miri/tests/pass/too-large-primval-write-problem.rs
@@ -7,6 +7,8 @@
//
// This is just intended as a regression test to make sure we don't reintroduce this problem.
+#![allow(integer_to_ptr_transmutes)]
+
#[cfg(target_pointer_width = "32")]
fn main() {
use std::mem::transmute;
diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml
index f4051ae..b2833a9 100644
--- a/src/tools/opt-dist/Cargo.toml
+++ b/src/tools/opt-dist/Cargo.toml
@@ -15,9 +15,9 @@
camino = "1"
tar = "0.4"
xz = { version = "0.1", package = "xz2" }
-serde_json = "1"
+serde_json.workspace = true
glob = "0.3"
-tempfile = "3.5"
+tempfile.workspace = true
derive_builder = "0.20"
clap = { version = "4", features = ["derive"] }
tabled = { version = "0.15", default-features = false, features = ["std"] }
diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs
index a8d4c93..a3935f9 100644
--- a/src/tools/opt-dist/src/exec.rs
+++ b/src/tools/opt-dist/src/exec.rs
@@ -189,6 +189,12 @@ pub fn avoid_rustc_rebuild(mut self) -> Self {
self
}
+ /// Rebuild rustc in case of statically linked LLVM
+ pub fn rustc_rebuild(mut self) -> Self {
+ self.cmd = self.cmd.arg("--keep-stage").arg("0");
+ self
+ }
+
pub fn run(self, timer: &mut TimerSection) -> anyhow::Result<()> {
self.cmd.run()?;
let metrics = load_metrics(&self.metrics_path)?;
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index 19706b4..339c255 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -375,8 +375,14 @@ fn execute_pipeline(
let mut dist = Bootstrap::dist(env, &dist_args)
.llvm_pgo_optimize(llvm_pgo_profile.as_ref())
- .rustc_pgo_optimize(&rustc_pgo_profile)
- .avoid_rustc_rebuild();
+ .rustc_pgo_optimize(&rustc_pgo_profile);
+
+ // if LLVM is not built we'll have PGO optimized rustc
+ dist = if env.supports_shared_llvm() || !env.build_llvm() {
+ dist.avoid_rustc_rebuild()
+ } else {
+ dist.rustc_rebuild()
+ };
for bolt_profile in bolt_profiles {
dist = dist.with_bolt_profile(bolt_profile);
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index 250e0f6..86ac4b9 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -12,10 +12,10 @@
# tidy-alphabetical-start
bstr = "1.12"
gimli = "0.32"
-libc = "0.2"
+libc.workspace = true
object = "0.37"
regex = "1.11"
-serde_json = "1.0"
+serde_json.workspace = true
similar = "2.7"
wasmparser = { version = "0.236", default-features = false, features = ["std", "features", "validate"] }
# tidy-alphabetical-end
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index e42f266..cd7ee6f 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -97,9 +97,9 @@
[[package]]
name = "anyhow"
-version = "1.0.98"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
+checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
[[package]]
name = "autocfg"
@@ -124,9 +124,9 @@
[[package]]
name = "bitflags"
-version = "2.9.1"
+version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
[[package]]
name = "block-buffer"
@@ -156,9 +156,9 @@
[[package]]
name = "cc"
-version = "1.2.32"
+version = "1.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e"
+checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
dependencies = [
"shlex",
]
@@ -185,9 +185,9 @@
[[package]]
name = "clap"
-version = "4.5.43"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50fd97c9dc2399518aa331917ac6f274280ec5eb34e555dd291899745c48ec6f"
+checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
dependencies = [
"clap_builder",
"clap_derive",
@@ -195,9 +195,9 @@
[[package]]
name = "clap_builder"
-version = "4.5.43"
+version = "4.5.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c35b5830294e1fa0462034af85cc95225a4cb07092c088c55bda3147cfcd8f65"
+checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
dependencies = [
"anstream",
"anstyle",
@@ -208,18 +208,18 @@
[[package]]
name = "clap_complete"
-version = "4.5.56"
+version = "4.5.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67e4efcbb5da11a92e8a609233aa1e8a7d91e38de0be865f016d14700d45a7fd"
+checksum = "4d9501bd3f5f09f7bbee01da9a511073ed30a80cd7a509f1214bb74eadea71ad"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
-version = "4.5.41"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
+checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
dependencies = [
"heck",
"proc-macro2",
@@ -559,7 +559,7 @@
"pest_derive",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.15",
]
[[package]]
@@ -1035,7 +1035,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"libc",
"once_cell",
"onig_sys",
@@ -1104,7 +1104,7 @@
checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323"
dependencies = [
"memchr",
- "thiserror 2.0.12",
+ "thiserror 2.0.15",
"ucd-trie",
]
@@ -1240,9 +1240,9 @@
[[package]]
name = "proc-macro2"
-version = "1.0.95"
+version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
@@ -1253,7 +1253,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"memchr",
"pulldown-cmark-escape 0.10.1",
"unicase",
@@ -1265,7 +1265,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"getopts",
"memchr",
"pulldown-cmark-escape 0.11.0",
@@ -1347,7 +1347,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
]
[[package]]
@@ -1385,6 +1385,7 @@
dependencies = [
"clap",
"env_logger",
+ "libc",
"mdbook",
"mdbook-i18n-helpers",
"mdbook-spec",
@@ -1397,7 +1398,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"errno",
"libc",
"linux-raw-sys",
@@ -1546,9 +1547,9 @@
[[package]]
name = "syn"
-version = "2.0.104"
+version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
@@ -1612,12 +1613,12 @@
[[package]]
name = "terminal_size"
-version = "0.4.2"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
+checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
dependencies = [
"rustix",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -1637,11 +1638,11 @@
[[package]]
name = "thiserror"
-version = "2.0.12"
+version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850"
dependencies = [
- "thiserror-impl 2.0.12",
+ "thiserror-impl 2.0.15",
]
[[package]]
@@ -1657,9 +1658,9 @@
[[package]]
name = "thiserror-impl"
-version = "2.0.12"
+version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0"
dependencies = [
"proc-macro2",
"quote",
@@ -2116,7 +2117,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
]
[[package]]
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index c7c6e39f..b34c39c 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -10,6 +10,9 @@
[dependencies]
clap = "4.0.32"
env_logger = "0.11"
+# FIXME: Remove this pin once this rustix issue is resolved
+# https://github.com/bytecodealliance/rustix/issues/1496
+libc = "=0.2.174"
mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" }
mdbook-i18n-helpers = "0.3.3"
mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index e497b79..6392ffb 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -40,7 +40,7 @@
clap = { version = "4.4.2", features = ["derive"] }
clap-cargo = "0.12.0"
diff = "0.1"
-dirs = "5.0"
+dirs = "6.0"
getopts = "0.2"
ignore = "0.4"
itertools = "0.12"
diff --git a/src/tools/rustfmt/tests/source/frontmatter_compact.rs b/src/tools/rustfmt/tests/source/frontmatter_compact.rs
new file mode 100644
index 0000000..21d4c6f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/frontmatter_compact.rs
@@ -0,0 +1,8 @@
+#!/usr/bin/env cargo
+---identifier
+[dependencies]
+regex = "1"
+---
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/source/frontmatter_escaped.rs b/src/tools/rustfmt/tests/source/frontmatter_escaped.rs
new file mode 100644
index 0000000..0d02637
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/frontmatter_escaped.rs
@@ -0,0 +1,13 @@
+#!/usr/bin/env cargo
+------------
+package.description = """
+Header
+-----
+
+Body
+"""
+------------
+
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/source/frontmatter_spaced.rs b/src/tools/rustfmt/tests/source/frontmatter_spaced.rs
new file mode 100644
index 0000000..ee0bb81
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/frontmatter_spaced.rs
@@ -0,0 +1,16 @@
+#!/usr/bin/env cargo
+
+
+--- identifier
+[dependencies]
+regex = "1"
+
+---
+
+
+
+
+
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/target/frontmatter_compact.rs b/src/tools/rustfmt/tests/target/frontmatter_compact.rs
new file mode 100644
index 0000000..21d4c6f
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/frontmatter_compact.rs
@@ -0,0 +1,8 @@
+#!/usr/bin/env cargo
+---identifier
+[dependencies]
+regex = "1"
+---
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/target/frontmatter_escaped.rs b/src/tools/rustfmt/tests/target/frontmatter_escaped.rs
new file mode 100644
index 0000000..0d02637
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/frontmatter_escaped.rs
@@ -0,0 +1,13 @@
+#!/usr/bin/env cargo
+------------
+package.description = """
+Header
+-----
+
+Body
+"""
+------------
+
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/target/frontmatter_spaced.rs b/src/tools/rustfmt/tests/target/frontmatter_spaced.rs
new file mode 100644
index 0000000..ee0bb81
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/frontmatter_spaced.rs
@@ -0,0 +1,16 @@
+#!/usr/bin/env cargo
+
+
+--- identifier
+[dependencies]
+regex = "1"
+
+---
+
+
+
+
+
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index c1f27de..f437336 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -14,7 +14,7 @@
semver = "1.0"
serde = { version = "1.0.125", features = ["derive"], optional = true }
termcolor = "1.1.3"
-rustc-hash = "2.0.0"
+rustc-hash.workspace = true
fluent-syntax = "0.12"
similar = "2.5.0"
toml = "0.7.8"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 80b6d54..6974ede 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -287,14 +287,12 @@
"gimli",
"gsgdt",
"hashbrown",
+ "icu_collections",
"icu_list",
- "icu_list_data",
- "icu_locid",
- "icu_locid_transform",
- "icu_locid_transform_data",
+ "icu_locale",
+ "icu_locale_core",
+ "icu_locale_data",
"icu_provider",
- "icu_provider_adapters",
- "icu_provider_macros",
"ident_case",
"indexmap",
"intl-memoizer",
@@ -332,6 +330,7 @@
"polonius-engine",
"portable-atomic", // dependency for platforms doesn't support `AtomicU64` in std
"portable-atomic-util",
+ "potential_utf",
"ppv-lite86",
"proc-macro-hack",
"proc-macro2",
@@ -361,7 +360,6 @@
"scoped-tls",
"scopeguard",
"self_cell",
- "semver",
"serde",
"serde_derive",
"serde_json",
@@ -448,6 +446,7 @@
"zerocopy-derive",
"zerofrom",
"zerofrom-derive",
+ "zerotrie",
"zerovec",
"zerovec-derive",
// tidy-alphabetical-end
diff --git a/src/tools/tidy/src/gcc_submodule.rs b/src/tools/tidy/src/gcc_submodule.rs
index 5d726c3..217eaf1 100644
--- a/src/tools/tidy/src/gcc_submodule.rs
+++ b/src/tools/tidy/src/gcc_submodule.rs
@@ -24,6 +24,12 @@ pub fn check(root_path: &Path, compiler_path: &Path, bad: &mut bool) {
.output()
.expect("Cannot determine git SHA of the src/gcc checkout");
+ // Git is not available or we are in a tarball
+ if !git_output.status.success() {
+ eprintln!("Cannot figure out the SHA of the GCC submodule");
+ return;
+ }
+
// This can return e.g.
// -e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc
// e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc (master-e607be166673a8de9fc07f6f02c60426e556c5f2.e607be)
diff --git a/src/tools/tidy/src/unit_tests.rs b/src/tools/tidy/src/unit_tests.rs
index 3d14a46..7396310 100644
--- a/src/tools/tidy/src/unit_tests.rs
+++ b/src/tools/tidy/src/unit_tests.rs
@@ -61,6 +61,7 @@ pub fn check(root_path: &Path, stdlib: bool, bad: &mut bool) {
|| path.ends_with("library/alloc/src/collections/linked_list/tests.rs")
|| path.ends_with("library/alloc/src/collections/vec_deque/tests.rs")
|| path.ends_with("library/alloc/src/raw_vec/tests.rs")
+ || path.ends_with("library/alloc/src/wtf8/tests.rs")
}
};
diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml
index ce71890..23dc869 100644
--- a/src/tools/wasm-component-ld/Cargo.toml
+++ b/src/tools/wasm-component-ld/Cargo.toml
@@ -10,4 +10,4 @@
path = "src/main.rs"
[dependencies]
-wasm-component-ld = "0.5.14"
+wasm-component-ld = "0.5.16"
diff --git a/tests/assembly-llvm/reg-struct-return.rs b/tests/assembly-llvm/reg-struct-return.rs
new file mode 100644
index 0000000..b251d79
--- /dev/null
+++ b/tests/assembly-llvm/reg-struct-return.rs
@@ -0,0 +1,143 @@
+//! Tests that -Zreg-struct-return changes ABI for small struct returns
+//! from hidden-pointer convention to register-return on x86_32.
+//! This test covers:
+//! * Callee side, verifying that the structs are correctly loaded into registers when
+//! `-Zreg-struct-return` is activated
+//! * Caller side, verifying callers do receive returned structs in registers when
+//! `-Zreg-struct-return` is activated
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: -O --target=i686-unknown-linux-gnu -Crelocation-model=static
+//@ revisions: WITH WITHOUT
+//@[WITH] compile-flags: -Zreg-struct-return
+//@ needs-llvm-components: x86
+
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// Verifies ABI changes for small structs, where both fields fit into one register.
+// WITH is expected to use register return, WITHOUT should use hidden pointer.
+mod Small {
+ struct SmallStruct {
+ a: i8,
+ b: i8,
+ }
+
+ unsafe extern "C" {
+ fn small() -> SmallStruct;
+ }
+
+ #[unsafe(no_mangle)]
+ pub unsafe extern "C" fn small_callee() -> SmallStruct {
+ // (42 << 8) | 42 = 10794
+
+ // WITH-LABEL: small_callee
+ // WITH: movw $10794, %ax
+ // WITH: retl
+
+ // WITHOUT-LABEL: small_callee
+ // WITHOUT: movl 4(%esp), %e{{.*}}
+ // WITHOUT: movw $10794, (%e{{.*}})
+ // WITHOUT: retl $4
+ SmallStruct { a: 42, b: 42 }
+ }
+
+ #[unsafe(no_mangle)]
+ pub unsafe extern "C" fn small_caller(dst: &mut SmallStruct) {
+ // WITH-LABEL: small_caller
+ // WITH: calll small
+ // WITH: movw %ax, (%e{{.*}})
+
+ // WITHOUT-LABEL: small_caller
+ // WITHOUT: calll small
+ // WITHOUT: movzwl {{.*}}(%esp), %e[[TMP:..]]
+ // WITHOUT: movw %[[TMP]], (%e{{..}})
+ *dst = small();
+ }
+}
+
+// Verifies ABI changes for a struct of size 8, which is the maximum size
+// for reg-struct-return.
+// WITH is expected to still use register return, WITHOUT should use hidden
+// pointer.
+mod Pivot {
+ struct PivotStruct {
+ a: i32,
+ b: i32,
+ }
+
+ unsafe extern "C" {
+ fn pivot() -> PivotStruct;
+ }
+
+ #[unsafe(no_mangle)]
+ pub unsafe extern "C" fn pivot_callee() -> PivotStruct {
+ // WITH-LABEL: pivot_callee
+ // WITH: movl $42, %e{{.*}}
+ // WITH: movl $42, %e{{.*}}
+ // WITH: retl
+
+ // WITHOUT-LABEL: pivot_callee
+ // WITHOUT: movl 4(%esp), %e{{.*}}
+ // WITHOUT-DAG: movl $42, (%e{{.*}})
+ // WITHOUT-DAG: movl $42, 4(%e{{.*}})
+ // WITHOUT: retl $4
+ PivotStruct { a: 42, b: 42 }
+ }
+
+ #[unsafe(no_mangle)]
+ pub unsafe extern "C" fn pivot_caller(dst: &mut PivotStruct) {
+ // WITH-LABEL: pivot_caller
+ // WITH: calll pivot
+ // WITH-DAG: movl %e{{.*}}, 4(%e{{.*}})
+ // WITH-DAG: movl %e{{.*}}, (%e{{.*}})
+
+ // WITHOUT-LABEL: pivot_caller
+ // WITHOUT: calll pivot
+ // WITHOUT: movsd {{.*}}(%esp), %[[TMP:xmm.]]
+ // WITHOUT: movsd %[[TMP]], (%e{{..}})
+ *dst = pivot();
+ }
+}
+
+// Verifies ABI changes for a struct of size 12, which is larger than the
+// maximum size for reg-struct-return (8 bytes).
+// Here, the hidden pointer convention should be used even when `-Zreg-struct-return` is set.
+mod Large {
+ struct LargeStruct {
+ a: i32,
+ b: i32,
+ c: i32,
+ }
+
+ unsafe extern "C" {
+ fn large() -> LargeStruct;
+ }
+
+ #[unsafe(no_mangle)]
+ pub unsafe extern "C" fn large_callee() -> LargeStruct {
+ // CHECK-LABEL: large_callee
+ // CHECK: movl 4(%esp), %e{{.*}}
+ // CHECK-DAG: movl $42, (%e{{.*}})
+ // CHECK-DAG: movl $42, 4(%e{{.*}})
+ // CHECK-DAG: movl $42, 8(%e{{.*}})
+ // CHECK: retl $4
+ LargeStruct { a: 42, b: 42, c: 42 }
+ }
+
+ #[unsafe(no_mangle)]
+ pub unsafe extern "C" fn large_caller(dst: &mut LargeStruct) {
+ // CHECK-LABEL: large_caller
+ // CHECK: calll large
+ // CHECK-DAG: movl {{.*}}(%esp), %[[TMP1:e..]]
+ // CHECK-DAG: movl %[[TMP1]], {{.*}}(%e{{..}})
+ // CHECK-DAG: movsd {{.*}}(%esp), %[[TMP2:xmm.]]
+ // CHECK-DAG: movsd %[[TMP2]], {{.*}}(%e{{..}})
+ *dst = large();
+ }
+}
diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs
index 79347d0..c935a75 100644
--- a/tests/assembly-llvm/targets/targets-elf.rs
+++ b/tests/assembly-llvm/targets/targets-elf.rs
@@ -10,6 +10,9 @@
//@ revisions: aarch64_be_unknown_linux_gnu_ilp32
//@ [aarch64_be_unknown_linux_gnu_ilp32] compile-flags: --target aarch64_be-unknown-linux-gnu_ilp32
//@ [aarch64_be_unknown_linux_gnu_ilp32] needs-llvm-components: aarch64
+//@ revisions: aarch64_be_unknown_linux_musl
+//@ [aarch64_be_unknown_linux_musl] compile-flags: --target aarch64_be-unknown-linux-musl
+//@ [aarch64_be_unknown_linux_musl] needs-llvm-components: aarch64
//@ revisions: aarch64_be_unknown_netbsd
//@ [aarch64_be_unknown_netbsd] compile-flags: --target aarch64_be-unknown-netbsd
//@ [aarch64_be_unknown_netbsd] needs-llvm-components: aarch64
@@ -481,6 +484,9 @@
//@ revisions: riscv64gc_unknown_linux_gnu
//@ [riscv64gc_unknown_linux_gnu] compile-flags: --target riscv64gc-unknown-linux-gnu
//@ [riscv64gc_unknown_linux_gnu] needs-llvm-components: riscv
+//@ revisions: riscv64a23_unknown_linux_gnu
+//@ [riscv64a23_unknown_linux_gnu] compile-flags: --target riscv64a23-unknown-linux-gnu
+//@ [riscv64a23_unknown_linux_gnu] needs-llvm-components: riscv
//@ revisions: riscv64gc_unknown_linux_musl
//@ [riscv64gc_unknown_linux_musl] compile-flags: --target riscv64gc-unknown-linux-musl
//@ [riscv64gc_unknown_linux_musl] needs-llvm-components: riscv
diff --git a/tests/assembly-llvm/x86_64-mcount.rs b/tests/assembly-llvm/x86_64-mcount.rs
new file mode 100644
index 0000000..0428272
--- /dev/null
+++ b/tests/assembly-llvm/x86_64-mcount.rs
@@ -0,0 +1,24 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Zinstrument-mcount=y -Cllvm-args=-x86-asm-syntax=intel
+
+//@ revisions: x86_64-linux
+//@[x86_64-linux] compile-flags: --target=x86_64-unknown-linux-gnu
+//@[x86_64-linux] needs-llvm-components: x86
+//@[x86_64-linux] only-x86_64-unknown-linux-gnu
+
+//@ revisions: x86_64-darwin
+//@[x86_64-darwin] compile-flags: --target=x86_64-apple-darwin
+//@[x86_64-darwin] needs-llvm-components: x86
+//@[x86_64-darwin] only-x86_64-apple-darwin
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: mcount_func:
+#[no_mangle]
+pub fn mcount_func() {
+ // CHECK: call mcount
+
+ std::hint::black_box(());
+
+ // CHECK: ret
+}
diff --git a/tests/codegen-llvm/addr-of-mutate.rs b/tests/codegen-llvm/addr-of-mutate.rs
index 7166906..36d6bf5 100644
--- a/tests/codegen-llvm/addr-of-mutate.rs
+++ b/tests/codegen-llvm/addr-of-mutate.rs
@@ -5,7 +5,7 @@
// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
// See <https://github.com/rust-lang/rust/issues/111502>.
-// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 1{{( captures\(none\))?}} dereferenceable(128) %x)
+// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias noundef align 1{{( captures\(address\))?}} dereferenceable(128) %x)
#[no_mangle]
pub fn foo(x: [u8; 128]) -> u8 {
let ptr = core::ptr::addr_of!(x).cast_mut();
@@ -15,7 +15,7 @@
x[0]
}
-// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias noundef align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
#[no_mangle]
pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
@@ -24,7 +24,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
}
// If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
-// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias noundef readonly align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
#[no_mangle]
pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
diff --git a/tests/codegen-llvm/atomicptr.rs b/tests/codegen-llvm/atomicptr.rs
index ce6c4aa..9d5e618 100644
--- a/tests/codegen-llvm/atomicptr.rs
+++ b/tests/codegen-llvm/atomicptr.rs
@@ -6,7 +6,6 @@
//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes
#![crate_type = "lib"]
-#![feature(strict_provenance_atomic_ptr)]
use std::ptr::without_provenance_mut;
use std::sync::atomic::AtomicPtr;
diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs
index db50868..a0744e4 100644
--- a/tests/codegen-llvm/function-arguments.rs
+++ b/tests/codegen-llvm/function-arguments.rs
@@ -134,7 +134,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {}
#[no_mangle]
pub fn notunpin_borrow(_: &NotUnpin) {}
-// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align 4{{( captures\(none\))?}} dereferenceable(32) %_1)
+// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias noundef readonly align 4{{( captures\(address\))?}} dereferenceable(32) %_1)
#[no_mangle]
pub fn indirect_struct(_: S) {}
@@ -197,7 +197,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
x
}
-// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(none\))?}} dereferenceable(32){{( %_0)?}})
+// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(address\))?}} dereferenceable(32){{( %_0)?}})
#[no_mangle]
pub fn struct_return() -> S {
S { _field: [0, 0, 0, 0, 0, 0, 0, 0] }
diff --git a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs
index 4666342..7ea08a1 100644
--- a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs
+++ b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs
@@ -256,11 +256,11 @@ pub struct IntDoubleInt {
c: i32,
}
-// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 8{{( captures\(none\))?}} dereferenceable(24) %a)
+// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias noundef align 8{{( captures\(address\))?}} dereferenceable(24) %a)
#[no_mangle]
pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
-// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(none\))?}} dereferenceable(24) %_0)
+// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(address\))?}} dereferenceable(24) %_0)
#[no_mangle]
pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
IntDoubleInt { a: 1, b: 2., c: 3 }
diff --git a/tests/crashes/120175.rs b/tests/crashes/120175.rs
index c6e7203..e441454 100644
--- a/tests/crashes/120175.rs
+++ b/tests/crashes/120175.rs
@@ -2,8 +2,9 @@
//@ needs-rustc-debug-assertions
#![feature(extern_types)]
+#![feature(raw_dylib_elf)]
-#[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")]
+#[link(name = "bar", kind = "raw-dylib")]
extern "C" {
pub type CrossCrate;
}
diff --git a/tests/crashes/124352.rs b/tests/crashes/124352.rs
deleted file mode 100644
index e9eb441..0000000
--- a/tests/crashes/124352.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #124352
-#![rustc_never_type_options(: Unsize<U> = "hi")]
-
-fn main() {}
diff --git a/tests/crashes/137580.rs b/tests/crashes/137580.rs
deleted file mode 100644
index 246c80e..0000000
--- a/tests/crashes/137580.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #137580
-fn main() {
- println!("%65536$", 1);
-}
diff --git a/tests/debuginfo/basic-stepping.rs b/tests/debuginfo/basic-stepping.rs
index e7a70c8..f639981 100644
--- a/tests/debuginfo/basic-stepping.rs
+++ b/tests/debuginfo/basic-stepping.rs
@@ -4,6 +4,7 @@
//@ ignore-aarch64: Doesn't work yet.
//@ ignore-loongarch64: Doesn't work yet.
+//@ ignore-riscv64: Doesn't work yet.
//@ compile-flags: -g
// gdb-command: run
diff --git a/tests/mir-opt/building/async_await.rs b/tests/mir-opt/building/async_await.rs
index 6c44570..2d14a1f 100644
--- a/tests/mir-opt/building/async_await.rs
+++ b/tests/mir-opt/building/async_await.rs
@@ -4,7 +4,7 @@
// related to `yield` are `&mut Context`, and its return type is `Poll`.
//@ edition:2018
-//@ compile-flags: -C panic=abort
+//@ compile-flags: -Zmir-opt-level=0 -C panic=abort
#![crate_type = "lib"]
diff --git a/tests/mir-opt/building/dump_mir_cycle.rs b/tests/mir-opt/building/dump_mir_cycle.rs
index 8e13420..ab0f2ea 100644
--- a/tests/mir-opt/building/dump_mir_cycle.rs
+++ b/tests/mir-opt/building/dump_mir_cycle.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Zmir-opt-level=0
+
#[derive(Debug)]
pub struct Thing {
pub next: &'static Thing,
diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs
index eaf5537..07025f5 100644
--- a/tests/mir-opt/building/enum_cast.rs
+++ b/tests/mir-opt/building/enum_cast.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
// EMIT_MIR enum_cast.foo.built.after.mir
// EMIT_MIR enum_cast.bar.built.after.mir
diff --git a/tests/mir-opt/building/eq_never_type.rs b/tests/mir-opt/building/eq_never_type.rs
index 90e2e69..486e2f9 100644
--- a/tests/mir-opt/building/eq_never_type.rs
+++ b/tests/mir-opt/building/eq_never_type.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
#![feature(never_type)]
#![allow(unreachable_code)]
diff --git a/tests/mir-opt/building/index_array_and_slice.rs b/tests/mir-opt/building/index_array_and_slice.rs
index 42ede66..47d8255 100644
--- a/tests/mir-opt/building/index_array_and_slice.rs
+++ b/tests/mir-opt/building/index_array_and_slice.rs
@@ -1,36 +1,42 @@
-//@ compile-flags: -C opt-level=0
+//@ compile-flags: -Zmir-opt-level=0 -C opt-level=0
// EMIT_MIR index_array_and_slice.index_array.built.after.mir
fn index_array(array: &[i32; 7], index: usize) -> &i32 {
// CHECK: bb0:
- // CHECK: [[LT:_.+]] = Lt(copy _2, const 7_usize);
- // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const 7_usize, copy _2) -> [success: bb1, unwind
+ // CHECK: _3 = copy _2;
+ // CHECK: [[LT:_.+]] = Lt(copy _3, const 7_usize);
+ // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const 7_usize, copy _3) -> [success: bb1, unwind
// CHECK: bb1:
- // CHECK: _0 = &(*_1)[_2];
+ // CHECK: _5 = &(*_1)[_3];
+ // CHECK: _0 = &(*_5);
&array[index]
}
// EMIT_MIR index_array_and_slice.index_const_generic_array.built.after.mir
fn index_const_generic_array<const N: usize>(array: &[i32; N], index: usize) -> &i32 {
// CHECK: bb0:
- // CHECK: [[LT:_.+]] = Lt(copy _2, const N);
- // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const N, copy _2) -> [success: bb1, unwind
+ // CHECK: _3 = copy _2;
+ // CHECK: [[LT:_.+]] = Lt(copy _3, const N);
+ // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const N, copy _3) -> [success: bb1, unwind
// CHECK: bb1:
- // CHECK: _0 = &(*_1)[_2];
+ // CHECK: _5 = &(*_1)[_3];
+ // CHECK: _0 = &(*_5);
&array[index]
}
// EMIT_MIR index_array_and_slice.index_slice.built.after.mir
fn index_slice(slice: &[i32], index: usize) -> &i32 {
// CHECK: bb0:
+ // CHECK: _3 = copy _2;
// CHECK: [[LEN:_.+]] = PtrMetadata(copy _1);
- // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
- // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+ // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]);
+ // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1,
// CHECK: bb1:
- // CHECK: _0 = &(*_1)[_2];
+ // CHECK: _6 = &(*_1)[_3];
+ // CHECK: _0 = &(*_6);
&slice[index]
}
@@ -40,12 +46,15 @@ fn index_mut_slice(slice: &mut [i32], index: usize) -> &i32 {
// This cannot `copy _1` in the *built* MIR, only in the *runtime* MIR.
// CHECK: bb0:
- // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1);
- // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
- // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+ // CHECK: _3 = copy _2;
+ // CHECK: _4 = &raw const (fake) (*_1);
+ // CHECK: [[LEN:_.+]] = PtrMetadata(move _4);
+ // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]);
+ // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1,
// CHECK: bb1:
- // CHECK: _0 = &(*_1)[_2];
+ // CHECK: _7 = &(*_1)[_3];
+ // CHECK: _0 = &(*_7);
&slice[index]
}
@@ -54,13 +63,15 @@ fn index_mut_slice(slice: &mut [i32], index: usize) -> &i32 {
// EMIT_MIR index_array_and_slice.index_custom.built.after.mir
fn index_custom(custom: &WithSliceTail, index: usize) -> &i32 {
// CHECK: bb0:
+ // CHECK: _3 = copy _2;
// CHECK: [[PTR:_.+]] = &raw const (fake) ((*_1).1: [i32]);
- // CHECK: [[LEN:_.+]] = PtrMetadata(copy [[PTR]]);
- // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
- // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+ // CHECK: [[LEN:_.+]] = PtrMetadata(move [[PTR]]);
+ // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]);
+ // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1,
// CHECK: bb1:
- // CHECK: _0 = &((*_1).1: [i32])[_2];
+ // CHECK: _7 = &((*_1).1: [i32])[_3];
+ // CHECK: _0 = &(*_7);
&custom.1[index]
}
diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir
index 8a36c90..fa35658 100644
--- a/tests/mir-opt/building/issue_101867.main.built.after.mir
+++ b/tests/mir-opt/building/issue_101867.main.built.after.mir
@@ -1,8 +1,8 @@
// MIR for `main` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
-| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
+| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8>
+| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8>
|
fn main() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/issue_101867.rs b/tests/mir-opt/building/issue_101867.rs
index f8a531e..a00bc13 100644
--- a/tests/mir-opt/building/issue_101867.rs
+++ b/tests/mir-opt/building/issue_101867.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
// EMIT_MIR issue_101867.main.built.after.mir
fn main() {
diff --git a/tests/mir-opt/building/issue_110508.rs b/tests/mir-opt/building/issue_110508.rs
index e597cd5..aa8a7b1 100644
--- a/tests/mir-opt/building/issue_110508.rs
+++ b/tests/mir-opt/building/issue_110508.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
// EMIT_MIR issue_110508.{impl#0}-BAR.built.after.mir
// EMIT_MIR issue_110508.{impl#0}-SELF_BAR.built.after.mir
diff --git "a/tests/mir-opt/building/issue_110508.\173impl\0430\175-BAR.built.after.mir" "b/tests/mir-opt/building/issue_110508.\173impl\0430\175-BAR.built.after.mir"
index c3d28fa..0cefb9c 100644
--- "a/tests/mir-opt/building/issue_110508.\173impl\0430\175-BAR.built.after.mir"
+++ "b/tests/mir-opt/building/issue_110508.\173impl\0430\175-BAR.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `<impl at $DIR/issue_110508.rs:9:1: 9:9>::BAR` after built
+// MIR for `<impl at $DIR/issue_110508.rs:10:1: 10:9>::BAR` after built
-const <impl at $DIR/issue_110508.rs:9:1: 9:9>::BAR: Foo = {
+const <impl at $DIR/issue_110508.rs:10:1: 10:9>::BAR: Foo = {
let mut _0: Foo;
let mut _1: ();
diff --git "a/tests/mir-opt/building/issue_110508.\173impl\0430\175-SELF_BAR.built.after.mir" "b/tests/mir-opt/building/issue_110508.\173impl\0430\175-SELF_BAR.built.after.mir"
index 177518c..0e0e914 100644
--- "a/tests/mir-opt/building/issue_110508.\173impl\0430\175-SELF_BAR.built.after.mir"
+++ "b/tests/mir-opt/building/issue_110508.\173impl\0430\175-SELF_BAR.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `<impl at $DIR/issue_110508.rs:9:1: 9:9>::SELF_BAR` after built
+// MIR for `<impl at $DIR/issue_110508.rs:10:1: 10:9>::SELF_BAR` after built
-const <impl at $DIR/issue_110508.rs:9:1: 9:9>::SELF_BAR: Foo = {
+const <impl at $DIR/issue_110508.rs:10:1: 10:9>::SELF_BAR: Foo = {
let mut _0: Foo;
let mut _1: ();
diff --git a/tests/mir-opt/building/issue_49232.rs b/tests/mir-opt/building/issue_49232.rs
index ac06e02..f17e3e9 100644
--- a/tests/mir-opt/building/issue_49232.rs
+++ b/tests/mir-opt/building/issue_49232.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
// We must mark a variable whose initialization fails due to an
// abort statement as StorageDead.
diff --git a/tests/mir-opt/building/logical_or_in_conditional.rs b/tests/mir-opt/building/logical_or_in_conditional.rs
index 249ccf7..d1c1ea2 100644
--- a/tests/mir-opt/building/logical_or_in_conditional.rs
+++ b/tests/mir-opt/building/logical_or_in_conditional.rs
@@ -1,5 +1,5 @@
// skip-filecheck
-//@ compile-flags: -Z validate-mir
+//@ compile-flags: -Zmir-opt-level=0 -Z validate-mir
//@ edition: 2024
struct Droppy(u8);
impl Drop for Droppy {
diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
index 744553c..5cf182c 100644
--- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
+++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
@@ -1,10 +1,10 @@
// MIR for `main` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
-| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
+| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:16:14: 16:23, inferred_ty: *mut Test
+| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:16:14: 16:23, inferred_ty: *mut Test
+| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:20:18: 20:31, inferred_ty: &&&&*mut Test
+| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:20:18: 20:31, inferred_ty: &&&&*mut Test
|
fn main() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/receiver_ptr_mutability.rs b/tests/mir-opt/building/receiver_ptr_mutability.rs
index 1ddb8b7..37b142f 100644
--- a/tests/mir-opt/building/receiver_ptr_mutability.rs
+++ b/tests/mir-opt/building/receiver_ptr_mutability.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
// EMIT_MIR receiver_ptr_mutability.main.built.after.mir
diff --git a/tests/mir-opt/building/shifts.rs b/tests/mir-opt/building/shifts.rs
index d7747bb..165b388 100644
--- a/tests/mir-opt/building/shifts.rs
+++ b/tests/mir-opt/building/shifts.rs
@@ -1,5 +1,5 @@
// skip-filecheck
-//@ compile-flags: -C debug-assertions=yes
+//@ compile-flags: -Zmir-opt-level=0 -C debug-assertions=yes
// EMIT_MIR shifts.shift_signed.built.after.mir
fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) {
diff --git a/tests/mir-opt/building/storage_live_dead_in_statics.rs b/tests/mir-opt/building/storage_live_dead_in_statics.rs
index 7cb74ac..868f4a8 100644
--- a/tests/mir-opt/building/storage_live_dead_in_statics.rs
+++ b/tests/mir-opt/building/storage_live_dead_in_statics.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
// Check that when we compile the static `XXX` into MIR, we do not
// generate `StorageStart` or `StorageEnd` statements.
diff --git a/tests/mir-opt/building/uniform_array_move_out.rs b/tests/mir-opt/building/uniform_array_move_out.rs
index aff5996..3624527 100644
--- a/tests/mir-opt/building/uniform_array_move_out.rs
+++ b/tests/mir-opt/building/uniform_array_move_out.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
#![feature(liballoc_internals, rustc_attrs)]
diff --git a/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir
index 3d26fe2..bbf504d 100644
--- a/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir
@@ -1,8 +1,8 @@
// MIR for `let_else` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char)
-| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:36:20: 36:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:36:20: 36:45, inferred_ty: (u32, u64, &char)
|
fn let_else() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir
index b2a06ae..7bf2551 100644
--- a/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir
@@ -1,8 +1,8 @@
// MIR for `let_else_bindless` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char)
-| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:41:20: 41:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:41:20: 41:45, inferred_ty: (u32, u64, &char)
|
fn let_else_bindless() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir
index d1b8f82..0cf681d 100644
--- a/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir
@@ -1,8 +1,8 @@
// MIR for `let_init` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char)
-| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:26:20: 26:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:26:20: 26:45, inferred_ty: (u32, u64, &char)
|
fn let_init() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir
index 6702f93..968813c 100644
--- a/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir
@@ -1,8 +1,8 @@
// MIR for `let_init_bindless` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char)
-| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:31:20: 31:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:31:20: 31:45, inferred_ty: (u32, u64, &char)
|
fn let_init_bindless() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir
index 76b5938..b6fdc4f 100644
--- a/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir
@@ -1,7 +1,7 @@
// MIR for `let_uninit` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:15:20: 15:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:16:20: 16:45, inferred_ty: (u32, u64, &char)
|
fn let_uninit() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir
index 0cd1255..472dbfb 100644
--- a/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir
@@ -1,7 +1,7 @@
// MIR for `let_uninit_bindless` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:20:20: 20:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:21:20: 21:45, inferred_ty: (u32, u64, &char)
|
fn let_uninit_bindless() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir
index c0ce6f1..ff4b0bf 100644
--- a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir
@@ -1,8 +1,8 @@
// MIR for `match_assoc_const` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32
|
fn match_assoc_const() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir
index 3a6aa5b..4cc433f 100644
--- a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir
@@ -1,10 +1,10 @@
// MIR for `match_assoc_const_range` after built
| User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32
-| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32
-| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32
+| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32
+| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32
|
fn match_assoc_const_range() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.rs b/tests/mir-opt/building/user_type_annotations.rs
index d55c678..527bf62 100644
--- a/tests/mir-opt/building/user_type_annotations.rs
+++ b/tests/mir-opt/building/user_type_annotations.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
//@ edition: 2024
// skip-filecheck
diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout
index 506f135..badbc0b 100644
--- a/tests/run-make/rustdoc-default-output/output-default.stdout
+++ b/tests/run-make/rustdoc-default-output/output-default.stdout
@@ -194,6 +194,9 @@
--disable-minification
disable the minification of CSS/JS files
(perma-unstable, do not use with cached files)
+ --generate-macro-expansion
+ Add possibility to expand macros in the HTML source
+ code pages
--plugin-path DIR
removed, see issue #44136
<https://github.com/rust-lang/rust/issues/44136> for
diff --git a/tests/rustdoc-gui/links-color.goml b/tests/rustdoc-gui/links-color.goml
index f11920c..a363175 100644
--- a/tests/rustdoc-gui/links-color.goml
+++ b/tests/rustdoc-gui/links-color.goml
@@ -9,7 +9,7 @@
define-function: (
"check-colors",
[theme, mod, macro, struct, enum, trait, fn, type, union, keyword,
- sidebar, sidebar_current, sidebar_current_background],
+ attribute, sidebar, sidebar_current, sidebar_current_background],
block {
call-function: ("switch-theme", {"theme": |theme|})
// Checking results colors.
@@ -22,6 +22,7 @@
assert-css: (".item-table .type", {"color": |type|}, ALL)
assert-css: (".item-table .union", {"color": |union|}, ALL)
assert-css: (".item-table .keyword", {"color": |keyword|}, ALL)
+ assert-css: (".item-table .attribute", {"color": |attribute|}, ALL)
// Checking sidebar elements.
assert-css: (
".sidebar-elems li:not(.current) a",
@@ -58,6 +59,7 @@
"type": "#ffa0a5",
"union": "#ffa0a5",
"keyword": "#39afd7",
+ "attribute": "#39afd7",
"sidebar": "#53b1db",
"sidebar_current": "#ffb44c",
"sidebar_current_background": "transparent",
@@ -76,6 +78,7 @@
"type": "#2dbfb8",
"union": "#2dbfb8",
"keyword": "#d2991d",
+ "attribute": "#d2991d",
"sidebar": "#fdbf35",
"sidebar_current": "#fdbf35",
"sidebar_current_background": "#444",
@@ -94,6 +97,7 @@
"type": "#ad378a",
"union": "#ad378a",
"keyword": "#3873ad",
+ "attribute": "#3873ad",
"sidebar": "#356da4",
"sidebar_current": "#356da4",
"sidebar_current_background": "#fff",
diff --git a/tests/rustdoc-gui/macro-expansion.goml b/tests/rustdoc-gui/macro-expansion.goml
new file mode 100644
index 0000000..b87d0e4
--- /dev/null
+++ b/tests/rustdoc-gui/macro-expansion.goml
@@ -0,0 +1,126 @@
+// This test ensures that the macro expansion is generated and working as expected.
+go-to: "file://" + |DOC_PATH| + "/src/macro_expansion/lib.rs.html"
+
+define-function: (
+ "check-expansion",
+ [line, original_content],
+ block {
+ assert-text: ("a[id='" + |line| + "'] + .expansion .original", |original_content|)
+ // The "original" content should be expanded.
+ assert-css: ("a[id='" + |line| + "'] + .expansion .original", {"display": "inline"})
+ // The expanded macro should be hidden.
+ assert-css: ("a[id='" + |line| + "'] + .expansion .expanded", {"display": "none"})
+
+ // We "expand" the macro.
+ click: "a[id='" + |line| + "'] + .expansion input[type=checkbox]"
+ // The "original" content is hidden.
+ assert-css: ("a[id='" + |line| + "'] + .expansion .original", {"display": "none"})
+ // The expanded macro is visible.
+ assert-css: ("a[id='" + |line| + "'] + .expansion .expanded", {"display": "inline"})
+
+ // We collapse the macro.
+ click: "a[id='" + |line| + "'] + .expansion input[type=checkbox]"
+ // The "original" content is expanded.
+ assert-css: ("a[id='" + |line| + "'] + .expansion .original", {"display": "inline"})
+ // The expanded macro is hidden.
+ assert-css: ("a[id='" + |line| + "'] + .expansion .expanded", {"display": "none"})
+ }
+)
+
+// First we check the derive macro expansion at line 33.
+call-function: ("check-expansion", {"line": 35, "original_content": "Debug"})
+// Then we check the `bar` macro expansion at line 41.
+call-function: ("check-expansion", {"line": 43, "original_content": "bar!(y)"})
+// Then we check the `println` macro expansion at line 42-44.
+call-function: ("check-expansion", {"line": 44, "original_content": 'println!("
+45 {y}
+46 ")'})
+
+// Then finally we check when there are two macro calls on a same line.
+assert-count: ("#expand-52 ~ .original", 2)
+assert-count: ("#expand-52 ~ .expanded", 2)
+
+store-value: (repeat_o, '/following-sibling::*[@class="original"]')
+store-value: (repeat_e, '/following-sibling::*[@class="expanded"]')
+store-value: (expand_id, "expand-52")
+assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, "stringify!(foo)")
+assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, "stringify!(bar)")
+assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, '"foo"')
+assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, '"bar"')
+
+// The "original" content should be expanded.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "inline"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "inline"})
+// The expanded macro should be hidden.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "none"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "none"})
+
+// We "expand" the macro (because the line starts with a string, the label is not at the "top
+// level" of the `<code>`, so we need to use a different selector).
+click: "#" + |expand_id|
+// The "original" content is hidden.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "none"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "none"})
+// The expanded macro is visible.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "inline"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "inline"})
+
+// We collapse the macro.
+click: "#" + |expand_id|
+// The "original" content is expanded.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "inline"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "inline"})
+// The expanded macro is hidden.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "none"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "none"})
+
+// Checking the line 48 `println` which needs to be handled differently because the line number is
+// inside a "comment" span.
+store-value: (expand_id, "expand-48")
+assert-text: ("#" + |expand_id| + " ~ .original", 'println!("
+49 {y}
+50 ")')
+// The "original" content should be expanded.
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"})
+// The expanded macro should be hidden.
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"})
+
+// We "expand" the macro.
+click: "#" + |expand_id|
+// The "original" content is hidden.
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"})
+// The expanded macro is visible.
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"})
+
+// We collapse the macro.
+click: "#" + |expand_id|
+// The "original" content is expanded.
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"})
+// The expanded macro is hidden.
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"})
+
+// Ensure that the toggles are focusable and can be interacted with keyboard.
+focus: "//a[@id='29']"
+press-key: "Tab"
+store-value: (expand_id, "expand-29")
+assert: "#" + |expand_id| + ":focus"
+assert-css: ("#" + |expand_id| +" ~ .expanded", {"display": "none"})
+assert-css: ("#" + |expand_id| +" ~ .original", {"display": "inline"})
+// We now expand the macro.
+press-key: "Space"
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"})
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"})
+// We collapse the macro.
+press-key: "Space"
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"})
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"})
+
+// Now we check a macro coming from another file.
+store-value: (expand_id, "expand-55")
+// We "expand" the macro.
+click: "#" + |expand_id|
+// The "original" content is hidden.
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"})
+// The expanded macro is visible.
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"})
+assert-text: ("#" + |expand_id| + " ~ .expanded", "{ y += 2; };")
diff --git a/tests/rustdoc-gui/module-items-font.goml b/tests/rustdoc-gui/module-items-font.goml
index 0e6dd81..bed95b3 100644
--- a/tests/rustdoc-gui/module-items-font.goml
+++ b/tests/rustdoc-gui/module-items-font.goml
@@ -65,3 +65,12 @@
"#keywords + .item-table dd",
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
)
+// attributes
+assert-css: (
+ "#attributes + .item-table dt a",
+ {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
+)
+assert-css: (
+ "#attributes + .item-table dd",
+ {"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
+)
diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml
index e136eab..fe0f640 100644
--- a/tests/rustdoc-gui/search-result-color.goml
+++ b/tests/rustdoc-gui/search-result-color.goml
@@ -7,7 +7,8 @@
[
theme, count_color, desc_color, path_color, bottom_border_color, keyword_color,
struct_color, associatedtype_color, tymethod_color, method_color, structfield_color,
- structfield_hover_color, macro_color, fn_color, hover_path_color, hover_background, grey
+ structfield_hover_color, macro_color, fn_color, hover_path_color, hover_background,
+ attribute_color, grey
],
block {
call-function: ("switch-theme", {"theme": |theme|})
@@ -47,6 +48,11 @@
"hover_color": |keyword_color|,
})
call-function: ("check-result-color", {
+ "result_kind": "attribute",
+ "color": |attribute_color|,
+ "hover_color": |attribute_color|,
+ })
+ call-function: ("check-result-color", {
"result_kind": "struct",
"color": |struct_color|,
"hover_color": |struct_color|,
@@ -155,6 +161,7 @@
"path_color": "#0096cf",
"bottom_border_color": "#aaa3",
"keyword_color": "#39afd7",
+ "attribute_color": "#39afd7",
"struct_color": "#ffa0a5",
"associatedtype_color": "#39afd7",
"tymethod_color": "#fdd687",
@@ -176,6 +183,7 @@
"path_color": "#ddd",
"bottom_border_color": "#aaa3",
"keyword_color": "#d2991d",
+ "attribute_color": "#d2991d",
"struct_color": "#2dbfb8",
"associatedtype_color": "#d2991d",
"tymethod_color": "#2bab63",
@@ -197,6 +205,7 @@
"path_color": "#000",
"bottom_border_color": "#aaa3",
"keyword_color": "#3873ad",
+ "attribute_color": "#3873ad",
"struct_color": "#ad378a",
"associatedtype_color": "#3873ad",
"tymethod_color": "#ad7c37",
diff --git a/tests/rustdoc-gui/sidebar-links-color.goml b/tests/rustdoc-gui/sidebar-links-color.goml
index 57c4555..9a39865 100644
--- a/tests/rustdoc-gui/sidebar-links-color.goml
+++ b/tests/rustdoc-gui/sidebar-links-color.goml
@@ -12,6 +12,7 @@
enum_hover_background, union, union_hover, union_hover_background, trait, trait_hover,
trait_hover_background, fn, fn_hover, fn_hover_background, type, type_hover,
type_hover_background, keyword, keyword_hover, keyword_hover_background,
+ attribute, attribute_hover, attribute_hover_background,
],
block {
call-function: ("switch-theme", {"theme": |theme|})
@@ -85,6 +86,16 @@
".sidebar .block.keyword a:hover",
{"color": |keyword_hover|, "background-color": |keyword_hover_background|},
)
+ // Attribute
+ assert-css: (
+ ".sidebar .block.attribute a",
+ {"color": |attribute|, "background-color": "rgba(0, 0, 0, 0)"},
+ )
+ move-cursor-to: ".sidebar .block.attribute a"
+ assert-css: (
+ ".sidebar .block.attribute a:hover",
+ {"color": |attribute_hover|, "background-color": |attribute_hover_background|},
+ )
}
)
@@ -113,6 +124,9 @@
"keyword": "#53b1db",
"keyword_hover": "#ffb44c",
"keyword_hover_background": "transparent",
+ "attribute": "#53b1db",
+ "attribute_hover": "#ffb44c",
+ "attribute_hover_background": "transparent",
}
)
call-function: (
@@ -140,6 +154,9 @@
"keyword": "#fdbf35",
"keyword_hover": "#fdbf35",
"keyword_hover_background": "#444",
+ "attribute": "#fdbf35",
+ "attribute_hover": "#fdbf35",
+ "attribute_hover_background": "#444",
}
)
call-function: (
@@ -167,5 +184,8 @@
"keyword": "#356da4",
"keyword_hover": "#356da4",
"keyword_hover_background": "#fff",
+ "attribute": "#356da4",
+ "attribute_hover": "#356da4",
+ "attribute_hover_background": "#fff",
}
)
diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml
index 0ac8861..3f6914a 100644
--- a/tests/rustdoc-gui/sidebar-source-code.goml
+++ b/tests/rustdoc-gui/sidebar-source-code.goml
@@ -71,7 +71,7 @@
// Only "another_folder" should be "open" in "lib2".
assert: "//*[@class='dir-entry' and not(@open)]/*[normalize-space()='another_mod']"
// All other trees should be collapsed.
-assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 11)
+assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 12)
// We now switch to mobile mode.
set-window-size: (600, 600)
diff --git a/tests/rustdoc-gui/src/macro_expansion/Cargo.lock b/tests/rustdoc-gui/src/macro_expansion/Cargo.lock
new file mode 100644
index 0000000..9c5cee8
--- /dev/null
+++ b/tests/rustdoc-gui/src/macro_expansion/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "macro_expansion"
+version = "0.1.0"
diff --git a/tests/rustdoc-gui/src/macro_expansion/Cargo.toml b/tests/rustdoc-gui/src/macro_expansion/Cargo.toml
new file mode 100644
index 0000000..6d36285
--- /dev/null
+++ b/tests/rustdoc-gui/src/macro_expansion/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "macro_expansion"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+path = "lib.rs"
diff --git a/tests/rustdoc-gui/src/macro_expansion/lib.rs b/tests/rustdoc-gui/src/macro_expansion/lib.rs
new file mode 100644
index 0000000..62a92d5d
--- /dev/null
+++ b/tests/rustdoc-gui/src/macro_expansion/lib.rs
@@ -0,0 +1,56 @@
+// Test crate used to check the `--generate-macro-expansion` option.
+//@ compile-flags: -Zunstable-options --generate-macro-expansion --generate-link-to-definition
+
+mod other;
+
+#[macro_export]
+macro_rules! bar {
+ ($x:ident) => {{
+ $x += 2;
+ $x *= 2;
+ }}
+}
+
+macro_rules! bar2 {
+ () => {
+ fn foo2() -> impl std::fmt::Display {
+ String::new()
+ }
+ }
+}
+
+macro_rules! bar3 {
+ () => {
+ fn foo3() {}
+ fn foo4() -> String { String::new() }
+ }
+}
+
+bar2!();
+bar3!();
+
+#[derive(Debug, PartialEq)]
+pub struct Bar;
+
+#[derive(Debug
+)]
+pub struct Bar2;
+
+fn y_f(_: &str, _: &str, _: &str) {}
+
+fn foo() {
+ let mut y = 0;
+ bar!(y);
+ println!("
+ {y}
+ ");
+ // comment
+ println!("
+ {y}
+ ");
+ let s = y_f("\
+bla", stringify!(foo), stringify!(bar));
+
+ // Macro from another file.
+ other_macro!(y);
+}
diff --git a/tests/rustdoc-gui/src/macro_expansion/other.rs b/tests/rustdoc-gui/src/macro_expansion/other.rs
new file mode 100644
index 0000000..8661b01
--- /dev/null
+++ b/tests/rustdoc-gui/src/macro_expansion/other.rs
@@ -0,0 +1,6 @@
+#[macro_export]
+macro_rules! other_macro {
+ ($x:ident) => {{
+ $x += 2;
+ }}
+}
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 623f5b3..42f2fbd 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -161,6 +161,10 @@ pub enum AnEnum {
/// Some keyword.
pub mod keyword {}
+#[doc(attribute = "forbid")]
+/// Some attribute.
+pub mod repr {}
+
/// Just some type alias.
pub type SomeType = u32;
diff --git a/tests/rustdoc-json/doc_attribute.rs b/tests/rustdoc-json/doc_attribute.rs
new file mode 100644
index 0000000..9e1a711
--- /dev/null
+++ b/tests/rustdoc-json/doc_attribute.rs
@@ -0,0 +1,18 @@
+// Doc attributes (`#[doc(attribute = "...")]` should not be generated in rustdoc JSON output
+// and this test ensures it.
+
+#![feature(rustdoc_internals)]
+#![no_std]
+
+//@ !has "$.index[?(@.name=='repr')]"
+//@ has "$.index[?(@.name=='foo')]"
+
+#[doc(attribute = "repr")]
+/// this is a test!
+pub mod foo {}
+
+//@ !has "$.index[?(@.name=='forbid')]"
+//@ !has "$.index[?(@.name=='bar')]"
+#[doc(attribute = "forbid")]
+/// hello
+mod bar {}
diff --git a/tests/rustdoc-ui/doc-attribute-unsupported.rs b/tests/rustdoc-ui/doc-attribute-unsupported.rs
new file mode 100644
index 0000000..3bd1531
--- /dev/null
+++ b/tests/rustdoc-ui/doc-attribute-unsupported.rs
@@ -0,0 +1,7 @@
+// This is currently not supported but should be!
+
+#![feature(rustdoc_internals)]
+
+#[doc(attribute = "diagnostic::do_not_recommend")] //~ ERROR
+/// bla
+mod yup {}
diff --git a/tests/rustdoc-ui/doc-attribute-unsupported.stderr b/tests/rustdoc-ui/doc-attribute-unsupported.stderr
new file mode 100644
index 0000000..e2480a5
--- /dev/null
+++ b/tests/rustdoc-ui/doc-attribute-unsupported.stderr
@@ -0,0 +1,10 @@
+error: nonexistent builtin attribute `diagnostic::do_not_recommend` used in `#[doc(attribute = "...")]`
+ --> $DIR/doc-attribute-unsupported.rs:5:19
+ |
+LL | #[doc(attribute = "diagnostic::do_not_recommend")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: only existing builtin attributes are allowed in core/std
+
+error: aborting due to 1 previous error
+
diff --git a/tests/rustdoc-ui/invalid-attribute.rs b/tests/rustdoc-ui/invalid-attribute.rs
new file mode 100644
index 0000000..2fc7be2
--- /dev/null
+++ b/tests/rustdoc-ui/invalid-attribute.rs
@@ -0,0 +1,10 @@
+// Testing the output when an invalid builtin attribute is passed as value
+// to `doc(attribute = "...")`.
+
+#![feature(rustdoc_internals)]
+
+#[doc(attribute = "foo df")] //~ ERROR
+mod foo {}
+
+#[doc(attribute = "fooyi")] //~ ERROR
+mod foo2 {}
diff --git a/tests/rustdoc-ui/invalid-attribute.stderr b/tests/rustdoc-ui/invalid-attribute.stderr
new file mode 100644
index 0000000..66e68ce
--- /dev/null
+++ b/tests/rustdoc-ui/invalid-attribute.stderr
@@ -0,0 +1,18 @@
+error: nonexistent builtin attribute `foo df` used in `#[doc(attribute = "...")]`
+ --> $DIR/invalid-attribute.rs:6:19
+ |
+LL | #[doc(attribute = "foo df")]
+ | ^^^^^^^^
+ |
+ = help: only existing builtin attributes are allowed in core/std
+
+error: nonexistent builtin attribute `fooyi` used in `#[doc(attribute = "...")]`
+ --> $DIR/invalid-attribute.rs:9:19
+ |
+LL | #[doc(attribute = "fooyi")]
+ | ^^^^^^^
+ |
+ = help: only existing builtin attributes are allowed in core/std
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/rustdoc-ui/lints/invalid-html-tags.rs b/tests/rustdoc-ui/lints/invalid-html-tags.rs
index 317f1fd..8003e5e 100644
--- a/tests/rustdoc-ui/lints/invalid-html-tags.rs
+++ b/tests/rustdoc-ui/lints/invalid-html-tags.rs
@@ -43,7 +43,7 @@ pub fn b() {}
/// <h3>
//~^ ERROR unclosed HTML tag `h3`
/// <script
-//~^ ERROR unclosed HTML tag `script`
+//~^ ERROR incomplete HTML tag `script`
pub fn c() {}
// Unclosed tags shouldn't warn if they are nested inside a <script> elem.
@@ -72,6 +72,7 @@ pub fn e() {}
/// <div></div >
/// <div></div
//~^ ERROR unclosed HTML tag `div`
+//~| ERROR incomplete HTML tag `div`
pub fn f() {}
/// <!---->
@@ -105,7 +106,7 @@ pub fn j() {}
/// uiapp.run(&env::args().collect::<Vec<_>>());
/// ```
///
-/// <Vec<_> shouldn't warn!
+// <Vec<_> shouldn't warn!
/// ``````
pub fn k() {}
@@ -121,3 +122,92 @@ pub fn no_error_1() {}
/// backslashed \<<a href="">
//~^ ERROR unclosed HTML tag `a`
pub fn p() {}
+
+/// <svg width="512" height="512" viewBox="0 0 512" fill="none" xmlns="http://www.w3.org/2000/svg">
+/// <rect
+/// width="256"
+/// height="256"
+/// fill="#5064C8"
+/// stroke="black"
+/// />
+/// </svg>
+pub fn no_error_2() {}
+
+/// <div>
+/// <img
+/// src="https://example.com/ferris.png"
+/// width="512"
+/// height="512"
+/// />
+/// </div>
+pub fn no_error_3() {}
+
+/// > <div
+/// > class="foo">
+/// > </div>
+pub fn no_error_4() {}
+
+/// unfinished ALLOWED_UNCLOSED
+///
+/// note: CommonMark doesn't allow an html block to start with a multiline tag,
+/// so we use `<br>` a bunch to force these to be parsed as html blocks.
+///
+/// <br>
+/// <img
+//~^ ERROR incomplete HTML tag `img`
+pub fn q() {}
+
+/// nested unfinished ALLOWED_UNCLOSED
+/// <p><img</p>
+//~^ ERROR incomplete HTML tag `img`
+pub fn r() {}
+
+/// > <br>
+/// > <img
+//~^ ERROR incomplete HTML tag `img`
+/// > href="#broken"
+pub fn s() {}
+
+/// <br>
+/// <br<br>
+//~^ ERROR incomplete HTML tag `br`
+pub fn t() {}
+
+/// <br>
+/// <br
+//~^ ERROR incomplete HTML tag `br`
+pub fn u() {}
+
+/// <a href=">" alt="<">html5 allows this</a>
+pub fn no_error_5() {}
+
+/// <br>
+/// <img title="
+/// html5
+/// allows
+/// multiline
+/// attr
+/// values
+/// these are just text, not tags:
+/// </div>
+/// <p/>
+/// <div>
+/// ">
+pub fn no_error_6() {}
+
+/// <br>
+/// <a href="data:text/html,<!DOCTYPE>
+/// <html>
+/// <body><b>this is allowed for some reason</b></body>
+/// </html>
+/// ">what</a>
+pub fn no_error_7() {}
+
+/// Technically this is allowed per the html5 spec,
+/// but there's basically no legitemate reason to do it,
+/// so we don't allow it.
+///
+/// <p <!-->foobar</p>
+//~^ ERROR Unclosed HTML comment
+//~| ERROR incomplete HTML tag `p`
+pub fn v() {}
diff --git a/tests/rustdoc-ui/lints/invalid-html-tags.stderr b/tests/rustdoc-ui/lints/invalid-html-tags.stderr
index 9c2bfcf..b6ec22c 100644
--- a/tests/rustdoc-ui/lints/invalid-html-tags.stderr
+++ b/tests/rustdoc-ui/lints/invalid-html-tags.stderr
@@ -52,6 +52,12 @@
LL | /// <br/> <p>
| ^^^
+error: incomplete HTML tag `script`
+ --> $DIR/invalid-html-tags.rs:45:5
+ |
+LL | /// <script
+ | ^^^^^^^
+
error: unclosed HTML tag `div`
--> $DIR/invalid-html-tags.rs:41:5
|
@@ -64,11 +70,11 @@
LL | /// <h3>
| ^^^^
-error: unclosed HTML tag `script`
- --> $DIR/invalid-html-tags.rs:45:5
+error: incomplete HTML tag `div`
+ --> $DIR/invalid-html-tags.rs:73:10
|
-LL | /// <script
- | ^^^^^^
+LL | /// <div></div
+ | ^^^^^
error: unclosed HTML tag `div`
--> $DIR/invalid-html-tags.rs:73:5
@@ -77,28 +83,73 @@
| ^^^^^
error: Unclosed HTML comment
- --> $DIR/invalid-html-tags.rs:87:5
+ --> $DIR/invalid-html-tags.rs:88:5
|
LL | /// <!--
- | ^^^
+ | ^^^^
error: unopened HTML tag `unopened-tag`
- --> $DIR/invalid-html-tags.rs:114:26
+ --> $DIR/invalid-html-tags.rs:115:26
|
LL | /// Web Components style </unopened-tag>
| ^^^^^^^^^^^^^^^
error: unclosed HTML tag `dashed-tags`
- --> $DIR/invalid-html-tags.rs:112:26
+ --> $DIR/invalid-html-tags.rs:113:26
|
LL | /// Web Components style <dashed-tags>
| ^^^^^^^^^^^^^
error: unclosed HTML tag `a`
- --> $DIR/invalid-html-tags.rs:121:19
+ --> $DIR/invalid-html-tags.rs:122:19
|
LL | /// backslashed \<<a href="">
| ^^
-error: aborting due to 16 previous errors
+error: incomplete HTML tag `img`
+ --> $DIR/invalid-html-tags.rs:156:5
+ |
+LL | /// <img
+ | ^^^^
+
+error: incomplete HTML tag `img`
+ --> $DIR/invalid-html-tags.rs:161:8
+ |
+LL | /// <p><img</p>
+ | ^^^^
+
+error: incomplete HTML tag `img`
+ --> $DIR/invalid-html-tags.rs:166:7
+ |
+LL | /// > <img
+ | _______^
+LL | |
+LL | | /// > href="#broken"
+ | |____________________^
+
+error: incomplete HTML tag `br`
+ --> $DIR/invalid-html-tags.rs:172:5
+ |
+LL | /// <br<br>
+ | ^^^
+
+error: incomplete HTML tag `br`
+ --> $DIR/invalid-html-tags.rs:177:5
+ |
+LL | /// <br
+ | ^^^
+
+error: incomplete HTML tag `p`
+ --> $DIR/invalid-html-tags.rs:210:5
+ |
+LL | /// <p <!-->foobar</p>
+ | ^^^
+
+error: Unclosed HTML comment
+ --> $DIR/invalid-html-tags.rs:210:8
+ |
+LL | /// <p <!-->foobar</p>
+ | ^^^^
+
+error: aborting due to 24 previous errors
diff --git a/tests/rustdoc/attribute-rendering.rs b/tests/rustdoc/attribute-rendering.rs
index bf9b810..fb40d0a 100644
--- a/tests/rustdoc/attribute-rendering.rs
+++ b/tests/rustdoc/attribute-rendering.rs
@@ -1,7 +1,8 @@
#![crate_name = "foo"]
//@ has 'foo/fn.f.html'
-//@ has - //*[@'class="rust item-decl"]' '#[unsafe(export_name = "f")] pub fn f()'
+//@ has - //*[@'class="code-attribute"]' '#[unsafe(export_name = "f")]'
+//@ has - //*[@'class="rust item-decl"]' 'pub fn f()'
#[unsafe(export_name = "\
f")]
pub fn f() {}
diff --git a/tests/rustdoc/attributes.rs b/tests/rustdoc/attributes.rs
index 34487a8..33e4e31 100644
--- a/tests/rustdoc/attributes.rs
+++ b/tests/rustdoc/attributes.rs
@@ -1,18 +1,81 @@
//@ edition: 2024
#![crate_name = "foo"]
-//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]'
+//@ has foo/fn.f.html '//*[@class="code-attribute"]' '#[unsafe(no_mangle)]'
#[unsafe(no_mangle)]
pub extern "C" fn f() {}
-//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "bar")]'
+//@ has foo/fn.g.html '//*[@class="code-attribute"]' '#[unsafe(export_name = "bar")]'
#[unsafe(export_name = "bar")]
pub extern "C" fn g() {}
-//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".text")]'
+//@ has foo/fn.example.html '//*[@class="code-attribute"]' '#[unsafe(link_section = ".text")]'
#[unsafe(link_section = ".text")]
pub extern "C" fn example() {}
-//@ has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]'
+//@ has foo/struct.Repr.html '//*[@class="code-attribute"]' '#[repr(C, align(8))]'
#[repr(C, align(8))]
pub struct Repr;
+
+//@ has foo/macro.macro_rule.html '//*[@class="code-attribute"]' '#[unsafe(link_section = ".text")]'
+#[unsafe(link_section = ".text")]
+#[macro_export]
+macro_rules! macro_rule {
+ () => {};
+}
+
+//@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "enum")]'
+#[unsafe(link_section = "enum")]
+pub enum Enum {
+ //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "a")]'
+ //@ has - '//*[@class="variants"]//*[@class="code-attribute"]' '#[unsafe(link_section = "a")]'
+ #[unsafe(link_section = "a")]
+ A,
+ //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "quz")]'
+ //@ has - '//*[@class="variants"]//*[@class="code-attribute"]' '#[unsafe(link_section = "quz")]'
+ #[unsafe(link_section = "quz")]
+ Quz {
+ //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "b")]'
+ //@ has - '//*[@class="variants"]//*[@class="code-attribute"]' '#[unsafe(link_section = "b")]'
+ #[unsafe(link_section = "b")]
+ b: (),
+ },
+}
+
+//@ has 'foo/trait.Trait.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "trait")]'
+#[unsafe(link_section = "trait")]
+pub trait Trait {
+ //@ has 'foo/trait.Trait.html'
+ //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]/*[@class="code-attribute"]' '#[unsafe(link_section = "bar")]'
+ //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' 'const BAR: u32 = 0u32'
+ #[unsafe(link_section = "bar")]
+ const BAR: u32 = 0;
+
+ //@ has - '//*[@class="code-attribute"]' '#[unsafe(link_section = "foo")]'
+ #[unsafe(link_section = "foo")]
+ fn foo() {}
+}
+
+//@ has 'foo/union.Union.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "union")]'
+#[unsafe(link_section = "union")]
+pub union Union {
+ //@ has 'foo/union.Union.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "x")]'
+ #[unsafe(link_section = "x")]
+ pub x: u32,
+ y: f32,
+}
+
+//@ has 'foo/struct.Struct.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "struct")]'
+#[unsafe(link_section = "struct")]
+pub struct Struct {
+ //@ has 'foo/struct.Struct.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "x")]'
+ //@ has - '//*[@id="structfield.x"]//*[@class="code-attribute"]' '#[unsafe(link_section = "x")]'
+ #[unsafe(link_section = "x")]
+ pub x: u32,
+ y: f32,
+}
+
+// Check that the attributes from the trait items show up consistently in the impl.
+//@ has 'foo/struct.Struct.html' '//*[@id="trait-implementations-list"]//*[@class="code-attribute"]' '#[unsafe(link_section = "bar")]'
+//@ has 'foo/struct.Struct.html' '//*[@id="trait-implementations-list"]//*[@class="code-attribute"]' '#[unsafe(link_section = "foo")]'
+impl Trait for Struct {}
diff --git a/tests/rustdoc/doc-attribute.rs b/tests/rustdoc/doc-attribute.rs
new file mode 100644
index 0000000..92e603a
--- /dev/null
+++ b/tests/rustdoc/doc-attribute.rs
@@ -0,0 +1,24 @@
+// Test checking the `#[doc(attribute = "...")]` attribute.
+
+#![crate_name = "foo"]
+
+#![feature(rustdoc_internals)]
+
+//@ has foo/index.html '//h2[@id="attributes"]' 'Attributes'
+//@ has foo/index.html '//a[@href="attribute.no_mangle.html"]' 'no_mangle'
+//@ has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Attributes'
+//@ has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#attributes'
+//@ has foo/attribute.no_mangle.html '//h1' 'Attribute no_mangle'
+//@ has foo/attribute.no_mangle.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
+//@ has foo/index.html '//a/@href' '../foo/index.html'
+//@ !has foo/foo/index.html
+//@ !has-dir foo/foo
+//@ !has foo/index.html '//span' '🔒'
+#[doc(attribute = "no_mangle")]
+/// this is a test!
+mod foo{}
+
+//@ has foo/attribute.repr.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'hello'
+#[doc(attribute = "repr")]
+/// hello
+mod bar {}
diff --git a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html
index 04eea70..e8b8e93 100644
--- a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html
+++ b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html
@@ -1,4 +1,4 @@
<code>pub enum TypeAlias {
- #[non_exhaustive]
+ <div class="code-attribute">#[non_exhaustive]</div>
Variant,
-}</code>
\ No newline at end of file
+}</code>
diff --git a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html
index 6c8851e..51763c8 100644
--- a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html
+++ b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html
@@ -1,4 +1,4 @@
<code>pub enum Type {
- #[non_exhaustive]
+ <div class="code-attribute">#[non_exhaustive]</div>
Variant,
-}</code>
\ No newline at end of file
+}</code>
diff --git a/tests/rustdoc/macro/macro_expansion.rs b/tests/rustdoc/macro/macro_expansion.rs
new file mode 100644
index 0000000..c989cca
--- /dev/null
+++ b/tests/rustdoc/macro/macro_expansion.rs
@@ -0,0 +1,28 @@
+// This test checks that patterns and statements are also getting expanded.
+
+//@ compile-flags: -Zunstable-options --generate-macro-expansion
+
+#![crate_name = "foo"]
+
+//@ has 'src/foo/macro_expansion.rs.html'
+//@ count - '//span[@class="expansion"]' 2
+
+macro_rules! pat {
+ ($x:literal) => {
+ Some($x)
+ }
+}
+
+macro_rules! stmt {
+ ($x:expr) => {{
+ let _ = $x;
+ }}
+}
+
+fn bar() {
+ match Some("hello") {
+ pat!("blolb") => {}
+ _ => {}
+ }
+ stmt!(1)
+}
diff --git a/tests/rustdoc/type-alias/repr.rs b/tests/rustdoc/type-alias/repr.rs
index cf90798..884ed74 100644
--- a/tests/rustdoc/type-alias/repr.rs
+++ b/tests/rustdoc/type-alias/repr.rs
@@ -22,7 +22,8 @@ pub union Foo2 {
}
//@ has 'foo/type.Bar2.html'
-//@ matches - '//*[@class="rust item-decl"]' '#\[repr\(C\)\]\npub union Bar2 \{*'
+//@ matches - '//*[@class="code-attribute"]' '#\[repr\(C\)\]'
+//@ matches - '//*[@class="rust item-decl"]' 'pub union Bar2 \{*'
// Ensures that we see the doc comment of the type alias and not of the aliased type.
//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar'
/// bar
diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs
index 3fdd65d..965fd83 100644
--- a/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs
+++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs
@@ -8,7 +8,7 @@
use rustc_type_ir::Interner;
-fn foo<I: Interner>(cx: I, did: I::DefId) {
+fn foo<I: Interner>(cx: I, did: I::TraitId) {
let _ = cx.trait_is_unsafe(did);
//~^ ERROR do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
}
diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr
index b8d6c63..ec6b9b8 100644
--- a/tests/ui/abi/c-zst.powerpc-linux.stderr
+++ b/tests/ui/abi/c-zst.powerpc-linux.stderr
@@ -27,7 +27,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr
index b8d6c63..ec6b9b8 100644
--- a/tests/ui/abi/c-zst.s390x-linux.stderr
+++ b/tests/ui/abi/c-zst.s390x-linux.stderr
@@ -27,7 +27,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr
index b8d6c63..ec6b9b8 100644
--- a/tests/ui/abi/c-zst.sparc64-linux.stderr
+++ b/tests/ui/abi/c-zst.sparc64-linux.stderr
@@ -27,7 +27,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
index b8d6c63..ec6b9b8 100644
--- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
+++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
@@ -27,7 +27,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr
index 0fec35d..47341da 100644
--- a/tests/ui/abi/debug.generic.stderr
+++ b/tests/ui/abi/debug.generic.stderr
@@ -454,7 +454,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(32 bytes),
pointee_align: Some(
@@ -527,7 +527,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(128 bytes),
pointee_align: Some(
diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr
index ce8bd41..94a01a8 100644
--- a/tests/ui/abi/debug.loongarch64.stderr
+++ b/tests/ui/abi/debug.loongarch64.stderr
@@ -454,7 +454,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(32 bytes),
pointee_align: Some(
@@ -527,7 +527,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(128 bytes),
pointee_align: Some(
diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr
index ce8bd41..94a01a8 100644
--- a/tests/ui/abi/debug.riscv64.stderr
+++ b/tests/ui/abi/debug.riscv64.stderr
@@ -454,7 +454,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(32 bytes),
pointee_align: Some(
@@ -527,7 +527,7 @@
},
mode: Indirect {
attrs: ArgAttributes {
- regular: NoAlias | NoCapture | NonNull | NoUndef,
+ regular: NoAlias | CapturesAddress | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(128 bytes),
pointee_align: Some(
diff --git a/tests/ui/array-slice-vec/pattern-matching-fixed-length-vectors-7784.rs b/tests/ui/array-slice-vec/fixed-length-vector-pattern-matching-7784.rs
similarity index 100%
rename from tests/ui/array-slice-vec/pattern-matching-fixed-length-vectors-7784.rs
rename to tests/ui/array-slice-vec/fixed-length-vector-pattern-matching-7784.rs
diff --git a/tests/ui/array-slice-vec/matching-on-vector-slice-option-8498.rs b/tests/ui/array-slice-vec/vector-slice-matching-8498.rs
similarity index 100%
rename from tests/ui/array-slice-vec/matching-on-vector-slice-option-8498.rs
rename to tests/ui/array-slice-vec/vector-slice-matching-8498.rs
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr
index ce49126..9a5b694 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr
@@ -32,12 +32,10 @@
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: higher-ranked subtype error
- --> $DIR/issue-111404-1.rs:10:1
+ --> $DIR/issue-111404-1.rs:10:8
|
LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+ | ^
error: aborting due to 5 previous errors
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
index 3d82f57..823d8d5 100644
--- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
@@ -25,6 +25,7 @@
|
LL | match fut.as_mut().poll(ctx) {
| ^^^^ method not found in `Pin<&mut impl Future<Output = ()>>`
+ |
--> $SRC_DIR/core/src/future/future.rs:LL:COL
|
= note: the method is available for `Pin<&mut impl Future<Output = ()>>` here
diff --git a/tests/ui/attributes/attr-on-mac-call.rs b/tests/ui/attributes/attr-on-mac-call.rs
new file mode 100644
index 0000000..a23ced1
--- /dev/null
+++ b/tests/ui/attributes/attr-on-mac-call.rs
@@ -0,0 +1,73 @@
+//@ check-pass
+// Regression test for https://github.com/rust-lang/rust/issues/145779
+#![warn(unused_attributes)]
+
+fn main() {
+ #[export_name = "x"]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[unsafe(naked)]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[track_caller]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[used]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[target_feature(enable = "x")]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[deprecated]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[inline]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[link_name = "x"]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[link_section = "x"]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[link_ordinal(42)]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[non_exhaustive]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[proc_macro]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[cold]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[no_mangle]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[deprecated]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[automatically_derived]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[macro_use]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[must_use]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[no_implicit_prelude]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[path = ""]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[ignore]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ #[should_panic]
+ //~^ WARN attribute cannot be used on macro calls
+ //~| WARN previously accepted
+ unreachable!();
+}
diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr
new file mode 100644
index 0000000..a08d305
--- /dev/null
+++ b/tests/ui/attributes/attr-on-mac-call.stderr
@@ -0,0 +1,205 @@
+warning: `#[export_name]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:6:5
+ |
+LL | #[export_name = "x"]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[export_name]` can be applied to functions and statics
+note: the lint level is defined here
+ --> $DIR/attr-on-mac-call.rs:3:9
+ |
+LL | #![warn(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+
+warning: `#[naked]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:9:5
+ |
+LL | #[unsafe(naked)]
+ | ^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[naked]` can only be applied to functions
+
+warning: `#[track_caller]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:12:5
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[track_caller]` can only be applied to functions
+
+warning: `#[used]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:15:5
+ |
+LL | #[used]
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[used]` can only be applied to statics
+
+warning: `#[target_feature]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:18:5
+ |
+LL | #[target_feature(enable = "x")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[target_feature]` can only be applied to functions
+
+warning: `#[deprecated]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:21:5
+ |
+LL | #[deprecated]
+ | ^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, foreign statics, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, and crates
+
+warning: `#[inline]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:24:5
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[inline]` can only be applied to functions
+
+warning: `#[link_name]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:27:5
+ |
+LL | #[link_name = "x"]
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[link_name]` can be applied to foreign functions and foreign statics
+
+warning: `#[link_section]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:30:5
+ |
+LL | #[link_section = "x"]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[link_section]` can be applied to statics and functions
+
+warning: `#[link_ordinal]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:33:5
+ |
+LL | #[link_ordinal(42)]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[link_ordinal]` can be applied to foreign functions and foreign statics
+
+warning: `#[non_exhaustive]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:36:5
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[non_exhaustive]` can be applied to data types and enum variants
+
+warning: `#[proc_macro]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:39:5
+ |
+LL | #[proc_macro]
+ | ^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[proc_macro]` can only be applied to functions
+
+warning: `#[cold]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:42:5
+ |
+LL | #[cold]
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[cold]` can only be applied to functions
+
+warning: `#[no_mangle]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:45:5
+ |
+LL | #[no_mangle]
+ | ^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[no_mangle]` can be applied to functions and statics
+
+warning: `#[deprecated]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:48:5
+ |
+LL | #[deprecated]
+ | ^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, foreign statics, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, and crates
+
+warning: `#[automatically_derived]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:51:5
+ |
+LL | #[automatically_derived]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[macro_use]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:54:5
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[macro_use]` can be applied to modules, extern crates, and crates
+
+warning: `#[must_use]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:57:5
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[must_use]` can be applied to functions, data types, unions, and traits
+
+warning: `#[no_implicit_prelude]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:60:5
+ |
+LL | #[no_implicit_prelude]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[no_implicit_prelude]` can be applied to modules and crates
+
+warning: `#[path]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:63:5
+ |
+LL | #[path = ""]
+ | ^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[path]` can only be applied to modules
+
+warning: `#[ignore]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:66:5
+ |
+LL | #[ignore]
+ | ^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[ignore]` can only be applied to functions
+
+warning: `#[should_panic]` attribute cannot be used on macro calls
+ --> $DIR/attr-on-mac-call.rs:69:5
+ |
+LL | #[should_panic]
+ | ^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[should_panic]` can only be applied to functions
+
+warning: 22 warnings emitted
+
diff --git a/tests/ui/attributes/crate-name-empty.stderr b/tests/ui/attributes/crate-name-empty.stderr
index 509a42d..31d9dd0 100644
--- a/tests/ui/attributes/crate-name-empty.stderr
+++ b/tests/ui/attributes/crate-name-empty.stderr
@@ -1,8 +1,8 @@
error: crate name must not be empty
- --> $DIR/crate-name-empty.rs:3:1
+ --> $DIR/crate-name-empty.rs:3:17
|
LL | #![crate_name = ""]
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^
error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/crate-name-macro-call.rs b/tests/ui/attributes/crate-name-macro-call.rs
index 1aae2e5..6107634 100644
--- a/tests/ui/attributes/crate-name-macro-call.rs
+++ b/tests/ui/attributes/crate-name-macro-call.rs
@@ -1,6 +1,6 @@
// issue: rust-lang/rust#122001
// Ensure we reject macro calls inside `#![crate_name]` as their result wouldn't get honored anyway.
-#![crate_name = concat!("my", "crate")] //~ ERROR malformed `crate_name` attribute input
+#![crate_name = concat!("my", "crate")] //~ ERROR attribute value must be a literal
fn main() {}
diff --git a/tests/ui/attributes/crate-name-macro-call.stderr b/tests/ui/attributes/crate-name-macro-call.stderr
index 56827aa..e988b84 100644
--- a/tests/ui/attributes/crate-name-macro-call.stderr
+++ b/tests/ui/attributes/crate-name-macro-call.stderr
@@ -1,10 +1,8 @@
-error: malformed `crate_name` attribute input
- --> $DIR/crate-name-macro-call.rs:4:1
+error: attribute value must be a literal
+ --> $DIR/crate-name-macro-call.rs:4:17
|
LL | #![crate_name = concat!("my", "crate")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
- |
- = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
+ | ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/crate-name-mismatch.stderr b/tests/ui/attributes/crate-name-mismatch.stderr
index 4021fbe..6416ad2 100644
--- a/tests/ui/attributes/crate-name-mismatch.stderr
+++ b/tests/ui/attributes/crate-name-mismatch.stderr
@@ -1,8 +1,8 @@
error: `--crate-name` and `#[crate_name]` are required to match, but `foo` != `bar`
- --> $DIR/crate-name-mismatch.rs:5:1
+ --> $DIR/crate-name-mismatch.rs:5:17
|
LL | #![crate_name = "bar"]
- | ^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/crate-only-as-outer.rs b/tests/ui/attributes/crate-only-as-outer.rs
new file mode 100644
index 0000000..5a7d916
--- /dev/null
+++ b/tests/ui/attributes/crate-only-as-outer.rs
@@ -0,0 +1,10 @@
+#![deny(unused)]
+#[crate_name = "owo"]
+//~^ ERROR: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+
+fn main() {}
+
+mod inner {
+ #![crate_name = "iwi"]
+ //~^ ERROR: the `#![crate_name]` attribute can only be used at the crate root
+}
diff --git a/tests/ui/attributes/crate-only-as-outer.stderr b/tests/ui/attributes/crate-only-as-outer.stderr
new file mode 100644
index 0000000..270f02a
--- /dev/null
+++ b/tests/ui/attributes/crate-only-as-outer.stderr
@@ -0,0 +1,26 @@
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+ --> $DIR/crate-only-as-outer.rs:2:1
+ |
+LL | #[crate_name = "owo"]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: This attribute does not have an `!`, which means it is applied to this function
+ --> $DIR/crate-only-as-outer.rs:5:1
+ |
+LL | fn main() {}
+ | ^^^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/crate-only-as-outer.rs:1:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
+
+error: the `#![crate_name]` attribute can only be used at the crate root
+ --> $DIR/crate-only-as-outer.rs:8:5
+ |
+LL | #![crate_name = "iwi"]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs
index 90ca007..932aaf7 100644
--- a/tests/ui/attributes/malformed-attrs.rs
+++ b/tests/ui/attributes/malformed-attrs.rs
@@ -81,8 +81,7 @@
#[export_stable = 1]
//~^ ERROR malformed
#[link]
-//~^ ERROR valid forms for the attribute are
-//~| WARN this was previously accepted by the compiler
+//~^ ERROR malformed
#[link_name]
//~^ ERROR malformed
#[link_section]
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index 98ff578..b85864b 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -1,5 +1,5 @@
error[E0539]: malformed `cfg` attribute input
- --> $DIR/malformed-attrs.rs:102:1
+ --> $DIR/malformed-attrs.rs:101:1
|
LL | #[cfg]
| ^^^^^^
@@ -10,7 +10,7 @@
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>
error: malformed `cfg_attr` attribute input
- --> $DIR/malformed-attrs.rs:104:1
+ --> $DIR/malformed-attrs.rs:103:1
|
LL | #[cfg_attr]
| ^^^^^^^^^^^
@@ -22,7 +22,7 @@
| ++++++++++++++++++++++++++++++++++++++++++++
error[E0463]: can't find crate for `wloop`
- --> $DIR/malformed-attrs.rs:211:1
+ --> $DIR/malformed-attrs.rs:210:1
|
LL | extern crate wloop;
| ^^^^^^^^^^^^^^^^^^^ can't find crate
@@ -41,34 +41,8 @@
LL | #![windows_subsystem = "windows"]
| +++++++++++
-error: malformed `crate_name` attribute input
- --> $DIR/malformed-attrs.rs:74:1
- |
-LL | #[crate_name]
- | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]`
- |
- = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
-
-error: malformed `sanitize` attribute input
- --> $DIR/malformed-attrs.rs:92:1
- |
-LL | #[sanitize]
- | ^^^^^^^^^^^
- |
-help: the following are the possible correct uses
- |
-LL | #[sanitize(address = "on|off")]
- | ++++++++++++++++++++
-LL | #[sanitize(cfi = "on|off")]
- | ++++++++++++++++
-LL | #[sanitize(hwaddress = "on|off")]
- | ++++++++++++++++++++++
-LL | #[sanitize(kcfi = "on|off")]
- | +++++++++++++++++
- = and 5 other candidates
-
error: malformed `instruction_set` attribute input
- --> $DIR/malformed-attrs.rs:106:1
+ --> $DIR/malformed-attrs.rs:105:1
|
LL | #[instruction_set]
| ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]`
@@ -76,13 +50,13 @@
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute>
error: malformed `patchable_function_entry` attribute input
- --> $DIR/malformed-attrs.rs:108:1
+ --> $DIR/malformed-attrs.rs:107:1
|
LL | #[patchable_function_entry]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
error: malformed `must_not_suspend` attribute input
- --> $DIR/malformed-attrs.rs:132:1
+ --> $DIR/malformed-attrs.rs:131:1
|
LL | #[must_not_suspend()]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -97,13 +71,13 @@
|
error: malformed `cfi_encoding` attribute input
- --> $DIR/malformed-attrs.rs:134:1
+ --> $DIR/malformed-attrs.rs:133:1
|
LL | #[cfi_encoding]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
error: malformed `allow` attribute input
- --> $DIR/malformed-attrs.rs:178:1
+ --> $DIR/malformed-attrs.rs:177:1
|
LL | #[allow]
| ^^^^^^^^
@@ -119,7 +93,7 @@
| +++++++++++++++++++++++++++++++++++++
error: malformed `expect` attribute input
- --> $DIR/malformed-attrs.rs:180:1
+ --> $DIR/malformed-attrs.rs:179:1
|
LL | #[expect]
| ^^^^^^^^^
@@ -135,7 +109,7 @@
| +++++++++++++++++++++++++++++++++++++
error: malformed `warn` attribute input
- --> $DIR/malformed-attrs.rs:182:1
+ --> $DIR/malformed-attrs.rs:181:1
|
LL | #[warn]
| ^^^^^^^
@@ -151,7 +125,7 @@
| +++++++++++++++++++++++++++++++++++++
error: malformed `deny` attribute input
- --> $DIR/malformed-attrs.rs:184:1
+ --> $DIR/malformed-attrs.rs:183:1
|
LL | #[deny]
| ^^^^^^^
@@ -167,7 +141,7 @@
| +++++++++++++++++++++++++++++++++++++
error: malformed `forbid` attribute input
- --> $DIR/malformed-attrs.rs:186:1
+ --> $DIR/malformed-attrs.rs:185:1
|
LL | #[forbid]
| ^^^^^^^^^
@@ -183,7 +157,7 @@
| +++++++++++++++++++++++++++++++++++++
error: malformed `debugger_visualizer` attribute input
- --> $DIR/malformed-attrs.rs:188:1
+ --> $DIR/malformed-attrs.rs:187:1
|
LL | #[debugger_visualizer]
| ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]`
@@ -191,13 +165,13 @@
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute>
error: malformed `thread_local` attribute input
- --> $DIR/malformed-attrs.rs:203:1
+ --> $DIR/malformed-attrs.rs:202:1
|
LL | #[thread_local()]
| ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]`
error: malformed `no_link` attribute input
- --> $DIR/malformed-attrs.rs:207:1
+ --> $DIR/malformed-attrs.rs:206:1
|
LL | #[no_link()]
| ^^^^^^^^^^^^ help: must be of the form: `#[no_link]`
@@ -205,7 +179,7 @@
= note: for more information, visit <https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute>
error: malformed `macro_export` attribute input
- --> $DIR/malformed-attrs.rs:214:1
+ --> $DIR/malformed-attrs.rs:213:1
|
LL | #[macro_export = 18]
| ^^^^^^^^^^^^^^^^^^^^
@@ -221,25 +195,25 @@
|
error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
- --> $DIR/malformed-attrs.rs:99:1
+ --> $DIR/malformed-attrs.rs:98:1
|
LL | #[proc_macro = 18]
| ^^^^^^^^^^^^^^^^^^
error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type
- --> $DIR/malformed-attrs.rs:116:1
+ --> $DIR/malformed-attrs.rs:115:1
|
LL | #[proc_macro_attribute = 19]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
- --> $DIR/malformed-attrs.rs:123:1
+ --> $DIR/malformed-attrs.rs:122:1
|
LL | #[proc_macro_derive]
| ^^^^^^^^^^^^^^^^^^^^
error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint
- --> $DIR/malformed-attrs.rs:216:1
+ --> $DIR/malformed-attrs.rs:215:1
|
LL | #[allow_internal_unsafe = 1]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -268,18 +242,8 @@
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html>
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
- --> $DIR/malformed-attrs.rs:83:1
- |
-LL | #[link]
- | ^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
- = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-
error: invalid argument
- --> $DIR/malformed-attrs.rs:188:1
+ --> $DIR/malformed-attrs.rs:187:1
|
LL | #[debugger_visualizer]
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -496,6 +460,12 @@
|
= help: `#[used]` can only be applied to statics
+error[E0539]: malformed `crate_name` attribute input
+ --> $DIR/malformed-attrs.rs:74:1
+ |
+LL | #[crate_name]
+ | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]`
+
error[E0539]: malformed `target_feature` attribute input
--> $DIR/malformed-attrs.rs:79:1
|
@@ -514,8 +484,27 @@
| | didn't expect any arguments here
| help: must be of the form: `#[export_stable]`
+error[E0539]: malformed `link` attribute input
+ --> $DIR/malformed-attrs.rs:83:1
+ |
+LL | #[link]
+ | ^^^^^^^ expected this to be a list
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL | #[link(name = "...")]
+ | ++++++++++++++
+LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...")]
+ | +++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ = and 1 other candidate
+
error[E0539]: malformed `link_name` attribute input
- --> $DIR/malformed-attrs.rs:86:1
+ --> $DIR/malformed-attrs.rs:85:1
|
LL | #[link_name]
| ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]`
@@ -523,7 +512,7 @@
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute>
error[E0539]: malformed `link_section` attribute input
- --> $DIR/malformed-attrs.rs:88:1
+ --> $DIR/malformed-attrs.rs:87:1
|
LL | #[link_section]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]`
@@ -531,7 +520,7 @@
= note: for more information, visit <https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute>
error[E0539]: malformed `coverage` attribute input
- --> $DIR/malformed-attrs.rs:90:1
+ --> $DIR/malformed-attrs.rs:89:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -543,8 +532,26 @@
LL | #[coverage(on)]
| ++++
+error[E0539]: malformed `sanitize` attribute input
+ --> $DIR/malformed-attrs.rs:91:1
+ |
+LL | #[sanitize]
+ | ^^^^^^^^^^^ expected this to be a list
+ |
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL | #[sanitize(address = "on|off")]
+ | ++++++++++++++++++++
+LL | #[sanitize(cfi = "on|off")]
+ | ++++++++++++++++
+LL | #[sanitize(hwaddress = "on|off")]
+ | ++++++++++++++++++++++
+LL | #[sanitize(kcfi = "on|off")]
+ | +++++++++++++++++
+ = and 5 other candidates
+
error[E0565]: malformed `no_implicit_prelude` attribute input
- --> $DIR/malformed-attrs.rs:97:1
+ --> $DIR/malformed-attrs.rs:96:1
|
LL | #[no_implicit_prelude = 23]
| ^^^^^^^^^^^^^^^^^^^^^^----^
@@ -553,7 +560,7 @@
| help: must be of the form: `#[no_implicit_prelude]`
error[E0565]: malformed `proc_macro` attribute input
- --> $DIR/malformed-attrs.rs:99:1
+ --> $DIR/malformed-attrs.rs:98:1
|
LL | #[proc_macro = 18]
| ^^^^^^^^^^^^^----^
@@ -562,7 +569,7 @@
| help: must be of the form: `#[proc_macro]`
error[E0565]: malformed `coroutine` attribute input
- --> $DIR/malformed-attrs.rs:111:5
+ --> $DIR/malformed-attrs.rs:110:5
|
LL | #[coroutine = 63] || {}
| ^^^^^^^^^^^^----^
@@ -571,7 +578,7 @@
| help: must be of the form: `#[coroutine]`
error[E0565]: malformed `proc_macro_attribute` attribute input
- --> $DIR/malformed-attrs.rs:116:1
+ --> $DIR/malformed-attrs.rs:115:1
|
LL | #[proc_macro_attribute = 19]
| ^^^^^^^^^^^^^^^^^^^^^^^----^
@@ -580,7 +587,7 @@
| help: must be of the form: `#[proc_macro_attribute]`
error[E0539]: malformed `must_use` attribute input
- --> $DIR/malformed-attrs.rs:119:1
+ --> $DIR/malformed-attrs.rs:118:1
|
LL | #[must_use = 1]
| ^^^^^^^^^^^^^-^
@@ -598,7 +605,7 @@
|
error[E0539]: malformed `proc_macro_derive` attribute input
- --> $DIR/malformed-attrs.rs:123:1
+ --> $DIR/malformed-attrs.rs:122:1
|
LL | #[proc_macro_derive]
| ^^^^^^^^^^^^^^^^^^^^ expected this to be a list
@@ -612,7 +619,7 @@
| ++++++++++++++++++++++++++++++++++++++++++
error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input
- --> $DIR/malformed-attrs.rs:128:1
+ --> $DIR/malformed-attrs.rs:127:1
|
LL | #[rustc_layout_scalar_valid_range_start]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -621,7 +628,7 @@
| help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]`
error[E0539]: malformed `rustc_layout_scalar_valid_range_end` attribute input
- --> $DIR/malformed-attrs.rs:130:1
+ --> $DIR/malformed-attrs.rs:129:1
|
LL | #[rustc_layout_scalar_valid_range_end]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -630,7 +637,7 @@
| help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]`
error[E0565]: malformed `marker` attribute input
- --> $DIR/malformed-attrs.rs:155:1
+ --> $DIR/malformed-attrs.rs:154:1
|
LL | #[marker = 3]
| ^^^^^^^^^---^
@@ -639,7 +646,7 @@
| help: must be of the form: `#[marker]`
error[E0565]: malformed `fundamental` attribute input
- --> $DIR/malformed-attrs.rs:157:1
+ --> $DIR/malformed-attrs.rs:156:1
|
LL | #[fundamental()]
| ^^^^^^^^^^^^^--^
@@ -648,7 +655,7 @@
| help: must be of the form: `#[fundamental]`
error[E0565]: malformed `ffi_pure` attribute input
- --> $DIR/malformed-attrs.rs:165:5
+ --> $DIR/malformed-attrs.rs:164:5
|
LL | #[unsafe(ffi_pure = 1)]
| ^^^^^^^^^^^^^^^^^^---^^
@@ -657,7 +664,7 @@
| help: must be of the form: `#[ffi_pure]`
error[E0539]: malformed `link_ordinal` attribute input
- --> $DIR/malformed-attrs.rs:167:5
+ --> $DIR/malformed-attrs.rs:166:5
|
LL | #[link_ordinal]
| ^^^^^^^^^^^^^^^
@@ -668,7 +675,7 @@
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute>
error[E0565]: malformed `ffi_const` attribute input
- --> $DIR/malformed-attrs.rs:171:5
+ --> $DIR/malformed-attrs.rs:170:5
|
LL | #[unsafe(ffi_const = 1)]
| ^^^^^^^^^^^^^^^^^^^---^^
@@ -677,7 +684,7 @@
| help: must be of the form: `#[ffi_const]`
error[E0539]: malformed `linkage` attribute input
- --> $DIR/malformed-attrs.rs:173:5
+ --> $DIR/malformed-attrs.rs:172:5
|
LL | #[linkage]
| ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
@@ -695,7 +702,7 @@
= and 5 other candidates
error[E0565]: malformed `automatically_derived` attribute input
- --> $DIR/malformed-attrs.rs:191:1
+ --> $DIR/malformed-attrs.rs:190:1
|
LL | #[automatically_derived = 18]
| ^^^^^^^^^^^^^^^^^^^^^^^^----^
@@ -704,7 +711,7 @@
| help: must be of the form: `#[automatically_derived]`
error[E0565]: malformed `non_exhaustive` attribute input
- --> $DIR/malformed-attrs.rs:197:1
+ --> $DIR/malformed-attrs.rs:196:1
|
LL | #[non_exhaustive = 1]
| ^^^^^^^^^^^^^^^^^---^
@@ -713,13 +720,13 @@
| help: must be of the form: `#[non_exhaustive]`
error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
- --> $DIR/malformed-attrs.rs:209:1
+ --> $DIR/malformed-attrs.rs:208:1
|
LL | #[macro_use = 1]
| ^^^^^^^^^^^^^^^^
error[E0565]: malformed `allow_internal_unsafe` attribute input
- --> $DIR/malformed-attrs.rs:216:1
+ --> $DIR/malformed-attrs.rs:215:1
|
LL | #[allow_internal_unsafe = 1]
| ^^^^^^^^^^^^^^^^^^^^^^^^---^
@@ -728,7 +735,7 @@
| help: must be of the form: `#[allow_internal_unsafe]`
error[E0565]: malformed `type_const` attribute input
- --> $DIR/malformed-attrs.rs:143:5
+ --> $DIR/malformed-attrs.rs:142:5
|
LL | #[type_const = 1]
| ^^^^^^^^^^^^^---^
@@ -761,7 +768,7 @@
| ^^^^^^^
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
- --> $DIR/malformed-attrs.rs:149:1
+ --> $DIR/malformed-attrs.rs:148:1
|
LL | #[diagnostic::do_not_recommend()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -769,7 +776,7 @@
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
warning: missing options for `on_unimplemented` attribute
- --> $DIR/malformed-attrs.rs:138:1
+ --> $DIR/malformed-attrs.rs:137:1
|
LL | #[diagnostic::on_unimplemented]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -777,7 +784,7 @@
= help: at least one of the `message`, `note` and `label` options are expected
warning: malformed `on_unimplemented` attribute
- --> $DIR/malformed-attrs.rs:140:1
+ --> $DIR/malformed-attrs.rs:139:1
|
LL | #[diagnostic::on_unimplemented = 1]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -794,7 +801,7 @@
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
- --> $DIR/malformed-attrs.rs:94:1
+ --> $DIR/malformed-attrs.rs:93:1
|
LL | #[ignore()]
| ^^^^^^^^^^^
@@ -803,7 +810,7 @@
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
- --> $DIR/malformed-attrs.rs:223:1
+ --> $DIR/malformed-attrs.rs:222:1
|
LL | #[ignore = 1]
| ^^^^^^^^^^^^^
@@ -812,7 +819,7 @@
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
error[E0308]: mismatched types
- --> $DIR/malformed-attrs.rs:111:23
+ --> $DIR/malformed-attrs.rs:110:23
|
LL | fn test() {
| - help: a return type might be missing here: `-> _`
@@ -820,7 +827,7 @@
| ^^^^^ expected `()`, found coroutine
|
= note: expected unit type `()`
- found coroutine `{coroutine@$DIR/malformed-attrs.rs:111:23: 111:25}`
+ found coroutine `{coroutine@$DIR/malformed-attrs.rs:110:23: 110:25}`
error: aborting due to 77 previous errors; 3 warnings emitted
@@ -851,18 +858,6 @@
= note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
- --> $DIR/malformed-attrs.rs:83:1
- |
-LL | #[link]
- | ^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
- = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
- = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
--> $DIR/malformed-attrs.rs:52:1
|
@@ -875,7 +870,7 @@
Future breakage diagnostic:
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
- --> $DIR/malformed-attrs.rs:94:1
+ --> $DIR/malformed-attrs.rs:93:1
|
LL | #[ignore()]
| ^^^^^^^^^^^
@@ -886,7 +881,7 @@
Future breakage diagnostic:
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
- --> $DIR/malformed-attrs.rs:223:1
+ --> $DIR/malformed-attrs.rs:222:1
|
LL | #[ignore = 1]
| ^^^^^^^^^^^^^
diff --git a/tests/ui/attributes/malformed-never-type-options.rs b/tests/ui/attributes/malformed-never-type-options.rs
new file mode 100644
index 0000000..0c384be
--- /dev/null
+++ b/tests/ui/attributes/malformed-never-type-options.rs
@@ -0,0 +1,8 @@
+//! Regression test for #124352
+//! The `rustc_*` attribute is malformed, but ICEing without a `feature(rustc_attrs)` is still bad.
+
+#![rustc_never_type_options(: Unsize<U> = "hi")]
+//~^ ERROR expected unsuffixed literal, found `:`
+//~| ERROR use of an internal attribute
+
+fn main() {}
diff --git a/tests/ui/attributes/malformed-never-type-options.stderr b/tests/ui/attributes/malformed-never-type-options.stderr
new file mode 100644
index 0000000..0d2ff48
--- /dev/null
+++ b/tests/ui/attributes/malformed-never-type-options.stderr
@@ -0,0 +1,19 @@
+error: expected unsuffixed literal, found `:`
+ --> $DIR/malformed-never-type-options.rs:4:29
+ |
+LL | #![rustc_never_type_options(: Unsize<U> = "hi")]
+ | ^
+
+error[E0658]: use of an internal attribute
+ --> $DIR/malformed-never-type-options.rs:4:1
+ |
+LL | #![rustc_never_type_options(: Unsize<U> = "hi")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
+ = note: the `#[rustc_never_type_options]` attribute is an internal implementation detail that will never be stable
+ = note: `rustc_never_type_options` is used to experiment with never type fallback and work on never type stabilization
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/pattern/match-with-at-binding-8391.rs b/tests/ui/binding/match-with-at-binding-8391.rs
similarity index 100%
rename from tests/ui/pattern/match-with-at-binding-8391.rs
rename to tests/ui/binding/match-with-at-binding-8391.rs
diff --git a/tests/ui/issues/issue-7092.rs b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.rs
similarity index 85%
rename from tests/ui/issues/issue-7092.rs
rename to tests/ui/binding/method-call-nonsensical-pattern-binding-7092.rs
index fab18bd..4cb04cd 100644
--- a/tests/ui/issues/issue-7092.rs
+++ b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/7092
enum Whatever {
}
diff --git a/tests/ui/issues/issue-7092.stderr b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.stderr
similarity index 85%
rename from tests/ui/issues/issue-7092.stderr
rename to tests/ui/binding/method-call-nonsensical-pattern-binding-7092.stderr
index e2e5748..1f8ff2d 100644
--- a/tests/ui/issues/issue-7092.stderr
+++ b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/issue-7092.rs:6:9
+ --> $DIR/method-call-nonsensical-pattern-binding-7092.rs:7:9
|
LL | match x {
| - this expression has type `Whatever`
diff --git a/tests/ui/pattern/ref-in-function-parameter-patterns-8860.rs b/tests/ui/binding/ref-pattern-drop-behavior-8860.rs
similarity index 100%
rename from tests/ui/pattern/ref-in-function-parameter-patterns-8860.rs
rename to tests/ui/binding/ref-pattern-drop-behavior-8860.rs
diff --git a/tests/ui/binop/binops.rs b/tests/ui/binop/binops.rs
index 7142190..702e9a6 100644
--- a/tests/ui/binop/binops.rs
+++ b/tests/ui/binop/binops.rs
@@ -35,6 +35,7 @@ fn test_bool() {
assert_eq!(true ^ true, false);
}
+#[allow(integer_to_ptr_transmutes)]
fn test_ptr() {
unsafe {
let p1: *const u8 = ::std::mem::transmute(0_usize);
diff --git a/tests/ui/issues/issue-6738.rs b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.rs
similarity index 79%
rename from tests/ui/issues/issue-6738.rs
rename to tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.rs
index a2f8dfe..856caa2 100644
--- a/tests/ui/issues/issue-6738.rs
+++ b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/6738
struct Foo<T> {
x: T,
}
diff --git a/tests/ui/issues/issue-6738.stderr b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.stderr
similarity index 85%
rename from tests/ui/issues/issue-6738.stderr
rename to tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.stderr
index f22d6a2..060d330 100644
--- a/tests/ui/issues/issue-6738.stderr
+++ b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.stderr
@@ -1,5 +1,5 @@
error[E0368]: binary assignment operation `+=` cannot be applied to type `T`
- --> $DIR/issue-6738.rs:6:9
+ --> $DIR/struct-field-generic-type-binary-assignment-error-6738.rs:7:9
|
LL | self.x += v.x;
| ------^^^^^^^
diff --git a/tests/ui/issues/auxiliary/issue-5518.rs b/tests/ui/borrowck/auxiliary/aux-5518.rs
similarity index 100%
rename from tests/ui/issues/auxiliary/issue-5518.rs
rename to tests/ui/borrowck/auxiliary/aux-5518.rs
diff --git a/tests/ui/issues/issue-5884.rs b/tests/ui/borrowck/borrowed-pointer-in-struct-5884.rs
similarity index 81%
rename from tests/ui/issues/issue-5884.rs
rename to tests/ui/borrowck/borrowed-pointer-in-struct-5884.rs
index 559b897..d2f17cf 100644
--- a/tests/ui/issues/issue-5884.rs
+++ b/tests/ui/borrowck/borrowed-pointer-in-struct-5884.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5884
//@ build-pass
#![allow(dead_code)]
diff --git a/tests/ui/issues/issue-5550.rs b/tests/ui/borrowck/incorrect-loan-error-on-local-update-5550.rs
similarity index 78%
rename from tests/ui/issues/issue-5550.rs
rename to tests/ui/borrowck/incorrect-loan-error-on-local-update-5550.rs
index 41de8ee..2258d76 100644
--- a/tests/ui/issues/issue-5550.rs
+++ b/tests/ui/borrowck/incorrect-loan-error-on-local-update-5550.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5550
//@ run-pass
#![allow(unused_assignments)]
diff --git a/tests/ui/issues/issue-5708.rs b/tests/ui/borrowck/struct-with-reference-to-trait-5708.rs
similarity index 94%
rename from tests/ui/issues/issue-5708.rs
rename to tests/ui/borrowck/struct-with-reference-to-trait-5708.rs
index 6fa3cfa..5157a3b 100644
--- a/tests/ui/issues/issue-5708.rs
+++ b/tests/ui/borrowck/struct-with-reference-to-trait-5708.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5708
//@ run-pass
#![allow(unused_variables)]
/*
@@ -10,7 +11,6 @@ struct with that reference results in an ICE.
to traits.
*/
-
// original
trait Inner {
fn print(&self);
@@ -38,7 +38,6 @@ pub fn main() {
outer.inner.print();
}
-
// minimal
pub trait MyTrait<T> {
fn dummy(&self, t: T) -> T { panic!() }
diff --git a/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs b/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs
new file mode 100644
index 0000000..f254030
--- /dev/null
+++ b/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs
@@ -0,0 +1,7 @@
+// https://github.com/rust-lang/rust/issues/5518
+//@ run-pass
+//@ aux-build:aux-5518.rs
+
+extern crate aux_5518 as other;
+
+fn main() {}
diff --git a/tests/ui/issues/issue-6557.rs b/tests/ui/box/box-patterns-feature-usage-6557.rs
similarity index 71%
rename from tests/ui/issues/issue-6557.rs
rename to tests/ui/box/box-patterns-feature-usage-6557.rs
index 64a025a..e0d9b25 100644
--- a/tests/ui/issues/issue-6557.rs
+++ b/tests/ui/box/box-patterns-feature-usage-6557.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/6557
//@ check-pass
#![allow(dead_code)]
diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr
index dc323f9..3bf8b7b 100644
--- a/tests/ui/c-variadic/issue-86053-1.stderr
+++ b/tests/ui/c-variadic/issue-86053-1.stderr
@@ -57,10 +57,10 @@
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^
+ |
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
= note: similarly named trait `Fn` defined here
- |
help: a trait with a similar name exists
|
LL | self , ... , self , self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) {
diff --git a/tests/ui/issues/issue-54094.rs b/tests/ui/cast/associated-type-bounds-cast-54094.rs
similarity index 76%
rename from tests/ui/issues/issue-54094.rs
rename to tests/ui/cast/associated-type-bounds-cast-54094.rs
index 4ca7d1d..c9f307e 100644
--- a/tests/ui/issues/issue-54094.rs
+++ b/tests/ui/cast/associated-type-bounds-cast-54094.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/54094
//@ check-pass
trait Zoo {
type X;
diff --git a/tests/ui/issues/issue-6318.rs b/tests/ui/cast/owned-struct-to-trait-cast-6318.rs
similarity index 83%
rename from tests/ui/issues/issue-6318.rs
rename to tests/ui/cast/owned-struct-to-trait-cast-6318.rs
index d3f0828..8cfc77c 100644
--- a/tests/ui/issues/issue-6318.rs
+++ b/tests/ui/cast/owned-struct-to-trait-cast-6318.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/6318
//@ run-pass
pub enum Thing {
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index f644814..258f213 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -243,6 +243,7 @@
`relax`
`relaxed-simd`
`rtm`
+`rva23u64`
`sb`
`scq`
`sha`
@@ -304,6 +305,7 @@
`ssve-fp8dot2`
`ssve-fp8dot4`
`ssve-fp8fma`
+`supm`
`sve`
`sve-b16b16`
`sve2`
diff --git a/tests/ui/issues/issue-6153.rs b/tests/ui/closures/closure-mut-argument-6153.rs
similarity index 83%
rename from tests/ui/issues/issue-6153.rs
rename to tests/ui/closures/closure-mut-argument-6153.rs
index cd78c85..ac19c2b 100644
--- a/tests/ui/issues/issue-6153.rs
+++ b/tests/ui/closures/closure-mut-argument-6153.rs
@@ -1,6 +1,6 @@
+// https://github.com/rust-lang/rust/issues/6153
//@ run-pass
-
fn swap<F>(f: F) -> Vec<isize> where F: FnOnce(Vec<isize>) -> Vec<isize> {
let x = vec![1, 2, 3];
f(x)
diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr
index 3e95fab..987625d 100644
--- a/tests/ui/closures/issue-78720.stderr
+++ b/tests/ui/closures/issue-78720.stderr
@@ -9,10 +9,10 @@
|
LL | _func: F,
| ^
+ |
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
= note: similarly named trait `Fn` defined here
- |
help: a trait with a similar name exists
|
LL | _func: Fn,
diff --git a/tests/ui/closures/issue-90871.stderr b/tests/ui/closures/issue-90871.stderr
index ef1cb21..1202022 100644
--- a/tests/ui/closures/issue-90871.stderr
+++ b/tests/ui/closures/issue-90871.stderr
@@ -3,6 +3,7 @@
|
LL | type_ascribe!(2, n([u8; || 1]))
| ^ help: a trait with a similar name exists: `Fn`
+ |
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
= note: similarly named trait `Fn` defined here
diff --git a/tests/ui/codegen/indirect-nocapture.rs b/tests/ui/codegen/indirect-nocapture.rs
new file mode 100644
index 0000000..78024a9
--- /dev/null
+++ b/tests/ui/codegen/indirect-nocapture.rs
@@ -0,0 +1,15 @@
+// Regression test for issue #137668 where an indirect argument have been marked as nocapture
+// despite the fact that callee did in fact capture the address.
+//
+//@ run-pass
+//@ compile-flags: -Copt-level=2
+
+#[inline(never)]
+pub fn f(a: [u32; 64], b: [u32; 64]) -> bool {
+ &a as *const _ as usize != &b as *const _ as usize
+}
+
+fn main() {
+ static S: [u32; 64] = [0; 64];
+ assert!(f(S, S));
+}
diff --git a/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs b/tests/ui/codegen/matrix-row-swap-54462.rs
similarity index 93%
rename from tests/ui/issues/issue-54462-mutable-noalias-correctness.rs
rename to tests/ui/codegen/matrix-row-swap-54462.rs
index 70d0bee..6bfc600 100644
--- a/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs
+++ b/tests/ui/codegen/matrix-row-swap-54462.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/54462
//@ run-pass
//
//@ compile-flags: -Ccodegen-units=1 -O
diff --git a/tests/ui/issues/issue-7012.rs b/tests/ui/codegen/static-array-comparison-7012.rs
similarity index 91%
rename from tests/ui/issues/issue-7012.rs
rename to tests/ui/codegen/static-array-comparison-7012.rs
index 69b881e..c08b1c0 100644
--- a/tests/ui/issues/issue-7012.rs
+++ b/tests/ui/codegen/static-array-comparison-7012.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/7012
//@ run-pass
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
diff --git a/tests/ui/coercion/mut-trait-coercion-8248.rs b/tests/ui/coercion/coerce-mut-trait-object-8248.rs
similarity index 100%
rename from tests/ui/coercion/mut-trait-coercion-8248.rs
rename to tests/ui/coercion/coerce-mut-trait-object-8248.rs
diff --git a/tests/ui/coercion/mut-trait-coercion-8248.stderr b/tests/ui/coercion/coerce-mut-trait-object-8248.stderr
similarity index 83%
rename from tests/ui/coercion/mut-trait-coercion-8248.stderr
rename to tests/ui/coercion/coerce-mut-trait-object-8248.stderr
index 0c7d5f9..c3b35a7 100644
--- a/tests/ui/coercion/mut-trait-coercion-8248.stderr
+++ b/tests/ui/coercion/coerce-mut-trait-object-8248.stderr
@@ -1,5 +1,5 @@
warning: method `dummy` is never used
- --> $DIR/mut-trait-coercion-8248.rs:5:8
+ --> $DIR/coerce-mut-trait-object-8248.rs:5:8
|
LL | trait A {
| - method in this trait
diff --git a/tests/ui/coercion/fake-sized-ptr-cast.rs b/tests/ui/coercion/fake-sized-ptr-cast.rs
new file mode 100644
index 0000000..4b6bf0e
--- /dev/null
+++ b/tests/ui/coercion/fake-sized-ptr-cast.rs
@@ -0,0 +1,16 @@
+// Make sure borrowck doesn't ICE because it thinks a pointer cast is a metadata-preserving
+// wide-to-wide ptr cast when it's actually (falsely) a wide-to-thin ptr cast due to an
+// impossible dyn sized bound.
+
+//@ check-pass
+
+trait Trait<T> {}
+
+fn func<'a>(x: *const (dyn Trait<()> + 'a))
+where
+ dyn Trait<u8> + 'a: Sized,
+{
+ let _x: *const dyn Trait<u8> = x as _;
+}
+
+fn main() {}
diff --git a/tests/ui/issues/issue-54477-reduced-2.rs b/tests/ui/collections/vecdeque-append-operation-54477.rs
similarity index 93%
rename from tests/ui/issues/issue-54477-reduced-2.rs
rename to tests/ui/collections/vecdeque-append-operation-54477.rs
index 5f65e54..7680fd0 100644
--- a/tests/ui/issues/issue-54477-reduced-2.rs
+++ b/tests/ui/collections/vecdeque-append-operation-54477.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/54477
//@ run-pass
// rust-lang/rust#54477: runtime bug in the VecDeque library that was
// exposed by this test case, derived from test suite of crates.io
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
index 4c8a5e4..c05584e 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
@@ -32,8 +32,9 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
help: use parentheses to call this closure
|
-LL | check(|| {}());
- | ++
+LL - check(|| {});
+LL + check((|| {})());
+ |
error[E0277]: `fn()` can't be used as a const parameter type
--> $DIR/const_param_ty_bad.rs:9:11
diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr
index b9db746..c9c8115 100644
--- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr
@@ -3,10 +3,10 @@
|
LL | let f: F = async { 1 };
| ^
+ |
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
= note: similarly named trait `Fn` defined here
- |
help: a trait with a similar name exists
|
LL | let f: Fn = async { 1 };
diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr
index 32fa46b..299ae68 100644
--- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr
+++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr
@@ -1,8 +1,8 @@
warning: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/issue-71348.rs:18:40
+ --> $DIR/issue-71348.rs:18:56
|
LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target
- | ^^ -- ------------------------ the same lifetime is hidden here
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| | |
| | the same lifetime is named here
| the lifetime is named here
diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr
index 56025e0..5008a2e 100644
--- a/tests/ui/consts/issue-89088.stderr
+++ b/tests/ui/consts/issue-89088.stderr
@@ -6,6 +6,7 @@
...
LL | FOO => todo!(),
| ^^^ constant of non-structural type
+ |
--> $SRC_DIR/alloc/src/borrow.rs:LL:COL
|
= note: `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
diff --git a/tests/ui/consts/ptr_comparisons.rs b/tests/ui/consts/ptr_comparisons.rs
index e142ab3..b8d8094 100644
--- a/tests/ui/consts/ptr_comparisons.rs
+++ b/tests/ui/consts/ptr_comparisons.rs
@@ -1,43 +1,205 @@
//@ compile-flags: --crate-type=lib
//@ check-pass
+//@ edition: 2024
+#![feature(const_raw_ptr_comparison)]
+#![feature(fn_align)]
+// Generally:
+// For any `Some` return, `None` would also be valid, unless otherwise noted.
+// For any `None` return, only `None` is valid, unless otherwise noted.
-#![feature(
- core_intrinsics,
- const_raw_ptr_comparison,
-)]
-
-const FOO: &usize = &42;
-
-macro_rules! check {
- (eq, $a:expr, $b:expr) => {
- pub const _: () =
- assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 1);
- };
- (ne, $a:expr, $b:expr) => {
- pub const _: () =
- assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 0);
- };
- (!, $a:expr, $b:expr) => {
- pub const _: () =
- assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 2);
+macro_rules! do_test {
+ ($a:expr, $b:expr, $expected:pat) => {
+ const _: () = {
+ let a: *const _ = $a;
+ let b: *const _ = $b;
+ assert!(matches!(<*const u8>::guaranteed_eq(a.cast(), b.cast()), $expected));
+ };
};
}
-check!(eq, 0, 0);
-check!(ne, 0, 1);
-check!(ne, FOO as *const _, 0);
-check!(ne, unsafe { (FOO as *const usize).offset(1) }, 0);
-check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0);
+#[repr(align(2))]
+struct T(#[allow(unused)] u16);
-// We want pointers to be equal to themselves, but aren't checking this yet because
-// there are some open questions (e.g. whether function pointers to the same function
-// compare equal: they don't necessarily do at runtime).
-check!(!, FOO as *const _, FOO as *const _);
+#[repr(align(2))]
+struct AlignedZst;
+
+static A: T = T(42);
+static B: T = T(42);
+static mut MUT_STATIC: T = T(42);
+static ZST: () = ();
+static ALIGNED_ZST: AlignedZst = AlignedZst;
+static LARGE_WORD_ALIGNED: [usize; 2] = [0, 1];
+static mut MUT_LARGE_WORD_ALIGNED: [usize; 2] = [0, 1];
+
+const FN_PTR: *const () = {
+ fn foo() {}
+ unsafe { std::mem::transmute(foo as fn()) }
+};
+
+const ALIGNED_FN_PTR: *const () = {
+ #[rustc_align(2)]
+ fn aligned_foo() {}
+ unsafe { std::mem::transmute(aligned_foo as fn()) }
+};
+
+trait Trait {
+ #[allow(unused)]
+ fn method(&self) -> u8;
+}
+impl Trait for u32 {
+ fn method(&self) -> u8 { 1 }
+}
+impl Trait for i32 {
+ fn method(&self) -> u8 { 2 }
+}
+
+const VTABLE_PTR_1: *const () = {
+ let [_data, vtable] = unsafe {
+ std::mem::transmute::<&dyn Trait, [*const (); 2]>(&42_u32 as &dyn Trait)
+ };
+ vtable
+};
+const VTABLE_PTR_2: *const () = {
+ let [_data, vtable] = unsafe {
+ std::mem::transmute::<&dyn Trait, [*const (); 2]>(&42_i32 as &dyn Trait)
+ };
+ vtable
+};
+
+// Cannot be `None`: `is_null` is stable with strong guarantees about integer-valued pointers.
+do_test!(0 as *const u8, 0 as *const u8, Some(true));
+do_test!(0 as *const u8, 1 as *const u8, Some(false));
+
+// Integer-valued pointers can always be compared.
+do_test!(1 as *const u8, 1 as *const u8, Some(true));
+do_test!(1 as *const u8, 2 as *const u8, Some(false));
+
+// Cannot be `None`: `static`s' addresses, references, (and within and one-past-the-end of those),
+// and `fn` pointers cannot be null, and `is_null` is stable with strong guarantees, and
+// `is_null` is implemented using `guaranteed_cmp`.
+do_test!(&A, 0 as *const u8, Some(false));
+do_test!((&raw const A).cast::<u8>().wrapping_add(1), 0 as *const u8, Some(false));
+do_test!((&raw const A).wrapping_add(1), 0 as *const u8, Some(false));
+do_test!(&ZST, 0 as *const u8, Some(false));
+do_test!(&(), 0 as *const u8, Some(false));
+do_test!(const { &() }, 0 as *const u8, Some(false));
+do_test!(FN_PTR, 0 as *const u8, Some(false));
+
+// This pointer is out-of-bounds, but still cannot be equal to 0 because of alignment.
+do_test!((&raw const A).cast::<u8>().wrapping_add(size_of::<T>() + 1), 0 as *const u8, Some(false));
// aside from 0, these pointers might end up pretty much anywhere.
-check!(!, FOO as *const _, 1); // this one could be `ne` by taking into account alignment
-check!(!, FOO as *const _, 1024);
+do_test!(&A, align_of::<T>() as *const u8, None);
+do_test!((&raw const A).wrapping_byte_add(1), (align_of::<T>() + 1) as *const u8, None);
+
+// except that they must still be aligned
+do_test!(&A, 1 as *const u8, Some(false));
+do_test!((&raw const A).wrapping_byte_add(1), align_of::<T>() as *const u8, Some(false));
+
+// If `ptr.wrapping_sub(int)` cannot be null (because it is in-bounds or one-past-the-end of
+// `ptr`'s allocation, or because it is misaligned from `ptr`'s allocation), then we know that
+// `ptr != int`, even if `ptr` itself is out-of-bounds or one-past-the-end of its allocation.
+do_test!((&raw const A).wrapping_byte_add(1), 1 as *const u8, Some(false));
+do_test!((&raw const A).wrapping_byte_add(2), 2 as *const u8, Some(false));
+do_test!((&raw const A).wrapping_byte_add(3), 1 as *const u8, Some(false));
+do_test!((&raw const ZST).wrapping_byte_add(1), 1 as *const u8, Some(false));
+do_test!(VTABLE_PTR_1.wrapping_byte_add(1), 1 as *const u8, Some(false));
+do_test!(FN_PTR.wrapping_byte_add(1), 1 as *const u8, Some(false));
+do_test!(&A, size_of::<T>().wrapping_neg() as *const u8, Some(false));
+do_test!(&LARGE_WORD_ALIGNED, size_of::<usize>().wrapping_neg() as *const u8, Some(false));
+// (`ptr - int != 0` due to misalignment)
+do_test!((&raw const A).wrapping_byte_add(2), 1 as *const u8, Some(false));
+do_test!((&raw const ALIGNED_ZST).wrapping_byte_add(2), 1 as *const u8, Some(false));
// When pointers go out-of-bounds, they *might* become null, so these comparions cannot work.
-check!(!, unsafe { (FOO as *const usize).wrapping_add(2) }, 0);
-check!(!, unsafe { (FOO as *const usize).wrapping_sub(1) }, 0);
+do_test!((&raw const A).wrapping_add(2), 0 as *const u8, None);
+do_test!((&raw const A).wrapping_sub(1), 0 as *const u8, None);
+
+// Statics cannot be duplicated
+do_test!(&A, &A, Some(true));
+
+// Two non-ZST statics cannot have the same address
+do_test!(&A, &B, Some(false));
+do_test!(&A, &raw const MUT_STATIC, Some(false));
+
+// One-past-the-end of one static can be equal to the address of another static.
+do_test!(&A, (&raw const B).wrapping_add(1), None);
+
+// Cannot know if ZST static is at the same address with anything non-null (if alignment allows).
+do_test!(&A, &ZST, None);
+do_test!(&A, &ALIGNED_ZST, None);
+
+// Unclear if ZST statics can be placed "in the middle of" non-ZST statics.
+// For now, we conservatively say they could, and return None here.
+do_test!(&ZST, (&raw const A).wrapping_byte_add(1), None);
+
+// As per https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness
+// immutable statics are allowed to overlap with const items and promoteds.
+do_test!(&A, &T(42), None);
+do_test!(&A, const { &T(42) }, None);
+do_test!(&A, { const X: T = T(42); &X }, None);
+
+// These could return Some(false), since only immutable statics can overlap with const items
+// and promoteds.
+do_test!(&raw const MUT_STATIC, &T(42), None);
+do_test!(&raw const MUT_STATIC, const { &T(42) }, None);
+do_test!(&raw const MUT_STATIC, { const X: T = T(42); &X }, None);
+
+// An odd offset from a 2-aligned allocation can never be equal to an even offset from a
+// 2-aligned allocation, even if the offsets are out-of-bounds.
+do_test!(&A, (&raw const B).wrapping_byte_add(1), Some(false));
+do_test!(&A, (&raw const B).wrapping_byte_add(5), Some(false));
+do_test!(&A, (&raw const ALIGNED_ZST).wrapping_byte_add(1), Some(false));
+do_test!(&ALIGNED_ZST, (&raw const A).wrapping_byte_add(1), Some(false));
+do_test!(&A, (&T(42) as *const T).wrapping_byte_add(1), Some(false));
+do_test!(&A, (const { &T(42) } as *const T).wrapping_byte_add(1), Some(false));
+do_test!(&A, ({ const X: T = T(42); &X } as *const T).wrapping_byte_add(1), Some(false));
+
+// We could return `Some(false)` for these, as pointers to different statics can never be equal if
+// that would require the statics to overlap, even if the pointers themselves are offset out of
+// bounds or one-past-the-end. We currently only check strictly in-bounds pointers when comparing
+// pointers to different statics, however.
+do_test!((&raw const A).wrapping_add(1), (&raw const B).wrapping_add(1), None);
+do_test!(
+ (&raw const LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(2),
+ (&raw const MUT_LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1),
+ None
+);
+
+// Pointers into the same static are equal if and only if their offset is the same,
+// even if either is out-of-bounds.
+do_test!(&A, &A, Some(true));
+do_test!(&A, &A.0, Some(true));
+do_test!(&A, (&raw const A).wrapping_byte_add(1), Some(false));
+do_test!(&A, (&raw const A).wrapping_byte_add(2), Some(false));
+do_test!(&A, (&raw const A).wrapping_byte_add(51), Some(false));
+do_test!((&raw const A).wrapping_byte_add(51), (&raw const A).wrapping_byte_add(51), Some(true));
+
+// Pointers to the same fn may be unequal, since `fn`s can be duplicated.
+do_test!(FN_PTR, FN_PTR, None);
+do_test!(ALIGNED_FN_PTR, ALIGNED_FN_PTR, None);
+
+// Pointers to different fns may be equal, since `fn`s can be deduplicated.
+do_test!(FN_PTR, ALIGNED_FN_PTR, None);
+
+// Pointers to the same vtable may be unequal, since vtables can be duplicated.
+do_test!(VTABLE_PTR_1, VTABLE_PTR_1, None);
+
+// Pointers to different vtables may be equal, since vtables can be deduplicated.
+do_test!(VTABLE_PTR_1, VTABLE_PTR_2, None);
+
+// Function pointers to aligned function allocations are not necessarily actually aligned,
+// due to platform-specific semantics.
+// See https://github.com/rust-lang/rust/issues/144661
+// FIXME: This could return `Some` on platforms where function pointers' addresses actually
+// correspond to function addresses including alignment, or on platforms where all functions
+// are aligned to some amount (e.g. ARM where a32 function pointers are at least 4-aligned,
+// and t32 function pointers are 2-aligned-offset-by-1).
+do_test!(ALIGNED_FN_PTR, ALIGNED_FN_PTR.wrapping_byte_offset(1), None);
+
+// Conservatively say we don't know.
+do_test!(FN_PTR, VTABLE_PTR_1, None);
+do_test!((&raw const LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1), VTABLE_PTR_1, None);
+do_test!((&raw const MUT_LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1), VTABLE_PTR_1, None);
+do_test!((&raw const LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1), FN_PTR, None);
+do_test!((&raw const MUT_LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1), FN_PTR, None);
diff --git a/tests/ui/issues/auxiliary/issue-7178.rs b/tests/ui/cross-crate/auxiliary/aux-7178.rs
similarity index 100%
rename from tests/ui/issues/auxiliary/issue-7178.rs
rename to tests/ui/cross-crate/auxiliary/aux-7178.rs
diff --git a/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs b/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs
new file mode 100644
index 0000000..3888d3b
--- /dev/null
+++ b/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs
@@ -0,0 +1,9 @@
+// https://github.com/rust-lang/rust/issues/7178
+//@ run-pass
+//@ aux-build:aux-7178.rs
+
+extern crate aux_7178 as cross_crate_self;
+
+pub fn main() {
+ let _ = cross_crate_self::Foo::new(&1);
+}
diff --git a/tests/ui/cross-crate/static-regions-in-cross-crate-8259.rs b/tests/ui/cross-crate/static-with-cross-crate-regions-8259.rs
similarity index 100%
rename from tests/ui/cross-crate/static-regions-in-cross-crate-8259.rs
rename to tests/ui/cross-crate/static-with-cross-crate-regions-8259.rs
diff --git a/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs b/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs
new file mode 100644
index 0000000..ce3ea7d
--- /dev/null
+++ b/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs
@@ -0,0 +1,10 @@
+// https://github.com/rust-lang/rust/issues/7899
+//@ run-pass
+#![allow(unused_variables)]
+//@ aux-build:aux-7899.rs
+
+extern crate aux_7899 as testcrate;
+
+fn main() {
+ let f = testcrate::V2(1.0f32, 2.0f32);
+}
diff --git a/tests/ui/derives/deriving-meta-unknown-trait.stderr b/tests/ui/derives/deriving-meta-unknown-trait.stderr
index 28753b8..7ee90ae 100644
--- a/tests/ui/derives/deriving-meta-unknown-trait.stderr
+++ b/tests/ui/derives/deriving-meta-unknown-trait.stderr
@@ -3,6 +3,7 @@
|
LL | #[derive(Eqr)]
| ^^^ help: a derive macro with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named derive macro `Eq` defined here
@@ -12,6 +13,7 @@
|
LL | #[derive(Eqr)]
| ^^^ help: a derive macro with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named derive macro `Eq` defined here
diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.rs b/tests/ui/diagnostic-flags/colored-session-opt-error.rs
index e850345..1c41104 100644
--- a/tests/ui/diagnostic-flags/colored-session-opt-error.rs
+++ b/tests/ui/diagnostic-flags/colored-session-opt-error.rs
@@ -1,4 +1,8 @@
//@ check-pass
//@ ignore-windows
//@ compile-flags: -Cremark=foo --error-format=human --color=always
+
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
fn main() {}
diff --git a/tests/ui/did_you_mean/println-typo.stderr b/tests/ui/did_you_mean/println-typo.stderr
index a1e0b1f..7dd6fbb 100644
--- a/tests/ui/did_you_mean/println-typo.stderr
+++ b/tests/ui/did_you_mean/println-typo.stderr
@@ -3,6 +3,7 @@
|
LL | prinltn!();
| ^^^^^^^ help: a macro with a similar name exists: `println`
+ |
--> $SRC_DIR/std/src/macros.rs:LL:COL
|
= note: similarly named macro `println` defined here
diff --git a/tests/ui/issues/issue-5900.rs b/tests/ui/enum/enum-referred-by-submodule-5900.rs
similarity index 77%
rename from tests/ui/issues/issue-5900.rs
rename to tests/ui/enum/enum-referred-by-submodule-5900.rs
index 14b7b8f..4ed0926 100644
--- a/tests/ui/issues/issue-5900.rs
+++ b/tests/ui/enum/enum-referred-by-submodule-5900.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5900
//@ check-pass
#![allow(dead_code)]
diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs b/tests/ui/enum/enum-with-generic-parameter-5997.rs
similarity index 76%
rename from tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs
rename to tests/ui/enum/enum-with-generic-parameter-5997.rs
index 7ed8819..fab7ebb 100644
--- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs
+++ b/tests/ui/enum/enum-with-generic-parameter-5997.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5997
//@ run-pass
#![allow(dead_code)]
diff --git a/tests/ui/issues/issue-6117.rs b/tests/ui/enum/match-either-enum-variants-6117.rs
similarity index 78%
rename from tests/ui/issues/issue-6117.rs
rename to tests/ui/enum/match-either-enum-variants-6117.rs
index 3ccf67b..7b39506 100644
--- a/tests/ui/issues/issue-6117.rs
+++ b/tests/ui/enum/match-either-enum-variants-6117.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/6117
//@ run-pass
#![allow(dead_code)]
diff --git a/tests/ui/error-codes/E0458.rs b/tests/ui/error-codes/E0458.rs
index 35e7e84..0e35ba4 100644
--- a/tests/ui/error-codes/E0458.rs
+++ b/tests/ui/error-codes/E0458.rs
@@ -1,4 +1,4 @@
-#[link(kind = "wonderful_unicorn")] extern "C" {} //~ ERROR E0458
+#[link(kind = "wonderful_unicorn")] extern "C" {} //~ ERROR malformed `link` attribute input [E0539]
//~| ERROR E0459
fn main() {
diff --git a/tests/ui/error-codes/E0458.stderr b/tests/ui/error-codes/E0458.stderr
index c13ae4e..524765e 100644
--- a/tests/ui/error-codes/E0458.stderr
+++ b/tests/ui/error-codes/E0458.stderr
@@ -1,8 +1,27 @@
-error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib, link-arg
- --> $DIR/E0458.rs:1:15
+error[E0539]: malformed `link` attribute input
+ --> $DIR/E0458.rs:1:1
|
LL | #[link(kind = "wonderful_unicorn")] extern "C" {}
- | ^^^^^^^^^^^^^^^^^^^ unknown link kind
+ | ^^^^^^^^^^^^^^-------------------^^
+ | |
+ | valid arguments are "static", "dylib", "framework", "raw-dylib" or "link-arg"
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(kind = "wonderful_unicorn")] extern "C" {}
+LL + #[link(name = "...")] extern "C" {}
+ |
+LL - #[link(kind = "wonderful_unicorn")] extern "C" {}
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] extern "C" {}
+ |
+LL - #[link(kind = "wonderful_unicorn")] extern "C" {}
+LL + #[link(name = "...", kind = "dylib|static|...")] extern "C" {}
+ |
+LL - #[link(kind = "wonderful_unicorn")] extern "C" {}
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] extern "C" {}
+ |
+ = and 1 other candidate
error[E0459]: `#[link]` attribute requires a `name = "string"` argument
--> $DIR/E0458.rs:1:1
@@ -12,5 +31,5 @@
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0458, E0459.
-For more information about an error, try `rustc --explain E0458`.
+Some errors have detailed explanations: E0459, E0539.
+For more information about an error, try `rustc --explain E0459`.
diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs
index 57d6b59..0ad3b2a 100644
--- a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs
+++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs
@@ -2,6 +2,10 @@
/// wonderful
mod foo {}
+#[doc(attribute = "repr")] //~ ERROR: `#[doc(attribute)]` is meant for internal use only
+/// wonderful
+mod foo2 {}
+
trait Mine {}
#[doc(fake_variadic)] //~ ERROR: `#[doc(fake_variadic)]` is meant for internal use only
diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr
index f3c00a2..5a6d4d3 100644
--- a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr
+++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr
@@ -8,8 +8,18 @@
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+error[E0658]: `#[doc(attribute)]` is meant for internal use only
+ --> $DIR/feature-gate-rustdoc_internals.rs:5:1
+ |
+LL | #[doc(attribute = "repr")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
+ = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
error[E0658]: `#[doc(fake_variadic)]` is meant for internal use only
- --> $DIR/feature-gate-rustdoc_internals.rs:7:1
+ --> $DIR/feature-gate-rustdoc_internals.rs:11:1
|
LL | #[doc(fake_variadic)]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +29,7 @@
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `#[doc(search_unbox)]` is meant for internal use only
- --> $DIR/feature-gate-rustdoc_internals.rs:10:1
+ --> $DIR/feature-gate-rustdoc_internals.rs:14:1
|
LL | #[doc(search_unbox)]
| ^^^^^^^^^^^^^^^^^^^^
@@ -28,6 +38,6 @@
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index 6066648..e5dae4c 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -69,7 +69,7 @@
//~| WARN previously accepted
//~| HELP can only be applied to
//~| HELP remove the attribute
-#![link()] //~ WARN attribute should be applied to an `extern` block
+#![link(name = "x")] //~ WARN attribute should be applied to an `extern` block
//~^ WARN this was previously accepted
#![link_name = "1900"]
//~^ WARN attribute cannot be used on
@@ -482,21 +482,26 @@ mod inner { #![no_implicit_prelude] }
#[reexport_test_harness_main = "2900"]
//~^ WARN crate-level attribute should be
+//~| HELP add a `!`
mod reexport_test_harness_main {
mod inner { #![reexport_test_harness_main="2900"] }
//~^ WARN crate-level attribute should be
#[reexport_test_harness_main = "2900"] fn f() { }
//~^ WARN crate-level attribute should be
+ //~| HELP add a `!`
#[reexport_test_harness_main = "2900"] struct S;
//~^ WARN crate-level attribute should be
+ //~| HELP add a `!`
#[reexport_test_harness_main = "2900"] type T = S;
//~^ WARN crate-level attribute should be
+ //~| HELP add a `!`
#[reexport_test_harness_main = "2900"] impl S { }
//~^ WARN crate-level attribute should be
+ //~| HELP add a `!`
}
// Cannot feed "2700" to `#[macro_escape]` without signaling an error.
@@ -534,21 +539,26 @@ mod inner { #![macro_escape] }
#[no_std]
//~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
mod no_std {
mod inner { #![no_std] }
//~^ WARN crate-level attribute should be in the root module
#[no_std] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_std] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_std] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_std] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
}
// At time of authorship, #[proc_macro_derive = "2500"] signals error
@@ -682,38 +692,38 @@ mod inner { #![link_section="1800"] }
// Note that this is a `check-pass` test, so it will never invoke the linker.
-#[link()]
+#[link(name = "x")]
//~^ WARN attribute should be applied to an `extern` block
//~| WARN this was previously accepted
mod link {
//~^ NOTE not an `extern` block
- mod inner { #![link()] }
+ mod inner { #![link(name = "x")] }
//~^ WARN attribute should be applied to an `extern` block
//~| WARN this was previously accepted
//~| NOTE not an `extern` block
- #[link()] fn f() { }
+ #[link(name = "x")] fn f() { }
//~^ WARN attribute should be applied to an `extern` block
//~| WARN this was previously accepted
//~| NOTE not an `extern` block
- #[link()] struct S;
+ #[link(name = "x")] struct S;
//~^ WARN attribute should be applied to an `extern` block
//~| WARN this was previously accepted
//~| NOTE not an `extern` block
- #[link()] type T = S;
+ #[link(name = "x")] type T = S;
//~^ WARN attribute should be applied to an `extern` block
//~| WARN this was previously accepted
//~| NOTE not an `extern` block
- #[link()] impl S { }
+ #[link(name = "x")] impl S { }
//~^ WARN attribute should be applied to an `extern` block
//~| WARN this was previously accepted
//~| NOTE not an `extern` block
- #[link()] extern "Rust" {}
+ #[link(name = "x")] extern "Rust" {}
//~^ WARN attribute should be applied to an `extern` block
//~| WARN this was previously accepted
}
@@ -760,21 +770,26 @@ mod inner { #![must_use] } //~ WARN attribute cannot be used on
#[windows_subsystem = "windows"]
//~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
mod windows_subsystem {
mod inner { #![windows_subsystem="windows"] }
//~^ WARN crate-level attribute should be in the root module
#[windows_subsystem = "windows"] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[windows_subsystem = "windows"] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[windows_subsystem = "windows"] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[windows_subsystem = "windows"] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
}
// BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
@@ -782,135 +797,170 @@ mod inner { #![windows_subsystem="windows"] }
#[crate_name = "0900"]
//~^ WARN crate-level attribute should be an inner attribute
mod crate_name {
+//~^ NOTE This attribute does not have an `!`, which means it is applied to this module
mod inner { #![crate_name="0900"] }
-//~^ WARN crate-level attribute should be in the root module
+//~^ WARN the `#![crate_name]` attribute can only be used at the crate root
#[crate_name = "0900"] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| NOTE This attribute does not have an `!`, which means it is applied to this function
#[crate_name = "0900"] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| NOTE This attribute does not have an `!`, which means it is applied to this struct
#[crate_name = "0900"] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| NOTE This attribute does not have an `!`, which means it is applied to this type alias
#[crate_name = "0900"] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| NOTE This attribute does not have an `!`, which means it is applied to this implementation block
}
#[crate_type = "0800"]
//~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
mod crate_type {
mod inner { #![crate_type="0800"] }
//~^ WARN crate-level attribute should be in the root module
#[crate_type = "0800"] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[crate_type = "0800"] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[crate_type = "0800"] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[crate_type = "0800"] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
}
#[feature(x0600)]
//~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
mod feature {
mod inner { #![feature(x0600)] }
//~^ WARN crate-level attribute should be in the root module
#[feature(x0600)] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[feature(x0600)] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[feature(x0600)] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[feature(x0600)] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
}
#[no_main]
//~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
mod no_main_1 {
mod inner { #![no_main] }
//~^ WARN crate-level attribute should be in the root module
#[no_main] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_main] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_main] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_main] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
}
#[no_builtins]
//~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
mod no_builtins {
mod inner { #![no_builtins] }
//~^ WARN crate-level attribute should be in the root module
#[no_builtins] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_builtins] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_builtins] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[no_builtins] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
}
#[recursion_limit="0200"]
//~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
mod recursion_limit {
mod inner { #![recursion_limit="0200"] }
//~^ WARN crate-level attribute should be in the root module
#[recursion_limit="0200"] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[recursion_limit="0200"] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[recursion_limit="0200"] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[recursion_limit="0200"] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
}
#[type_length_limit="0100"]
//~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
mod type_length_limit {
mod inner { #![type_length_limit="0100"] }
//~^ WARN crate-level attribute should be in the root module
#[type_length_limit="0100"] fn f() { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[type_length_limit="0100"] struct S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[type_length_limit="0100"] type T = S;
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
#[type_length_limit="0100"] impl S { }
//~^ WARN crate-level attribute should be an inner attribute
+ //~| HELP add a `!`
}
fn main() {}
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index 7488c68..ef74a00 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -1,5 +1,5 @@
warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:506:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:511:17
|
LL | mod inner { #![macro_escape] }
| ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@
= help: try an outer attribute: `#[macro_use]`
warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:1
|
LL | #[macro_escape]
| ^^^^^^^^^^^^^^^
@@ -198,87 +198,126 @@
LL | #![warn(unused_attributes, unknown_lints)]
| ^^^^^^^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+warning: crate-level attribute should be an inner attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:1
|
LL | #[reexport_test_harness_main = "2900"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![reexport_test_harness_main = "2900"]
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:1
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:1
|
LL | #[no_std]
| ^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_std]
+ | +
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:1
|
-LL | #[link()]
- | ^^^^^^^^^
+LL | #[link(name = "x")]
+ | ^^^^^^^^^^^^^^^^^^^
...
LL | / mod link {
LL | |
LL | |
-LL | | mod inner { #![link()] }
+LL | | mod inner { #![link(name = "x")] }
... |
LL | | }
| |_- not an `extern` block
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:1
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:1
|
LL | #[windows_subsystem = "windows"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:1
|
-LL | #[crate_name = "0900"]
- | ^^^^^^^^^^^^^^^^^^^^^^
+help: add a `!`
+ |
+LL | #![windows_subsystem = "windows"]
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:1
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
|
LL | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![crate_type = "0800"]
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:820:1
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:845:1
|
LL | #[feature(x0600)]
| ^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![feature(x0600)]
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:840:1
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:870:1
|
LL | #[no_main]
| ^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_main]
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:859:1
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:894:1
|
LL | #[no_builtins]
| ^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_builtins]
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:878:1
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:918:1
|
LL | #[recursion_limit="0200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![recursion_limit="0200"]
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:897:1
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:942:1
|
LL | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![type_length_limit="0100"]
+ | +
warning: attribute should be applied to an `extern` block with non-Rust ABI
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
|
-LL | #![link()]
- | ^^^^^^^^^^ not an `extern` block
+LL | #![link(name = "x")]
+ | ^^^^^^^^^^^^^^^^^^^^ not an `extern` block
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
@@ -321,352 +360,502 @@
| ^^^^^^^^^^^^^^^
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:17
|
LL | mod inner { #![reexport_test_harness_main="2900"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:490:5
|
LL | #[reexport_test_harness_main = "2900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![reexport_test_harness_main = "2900"] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:494:5
|
LL | #[reexport_test_harness_main = "2900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![reexport_test_harness_main = "2900"] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:498:5
|
LL | #[reexport_test_harness_main = "2900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![reexport_test_harness_main = "2900"] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:498:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
|
LL | #[reexport_test_harness_main = "2900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![reexport_test_harness_main = "2900"] impl S { }
+ | +
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:17
|
LL | mod inner { #![no_std] }
| ^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
|
LL | #[no_std] fn f() { }
| ^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_std] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:5
|
LL | #[no_std] struct S;
| ^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_std] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:5
|
LL | #[no_std] type T = S;
| ^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_std] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:550:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
|
LL | #[no_std] impl S { }
| ^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_std] impl S { }
+ | +
warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:17
|
-LL | mod inner { #![link()] }
- | ------------^^^^^^^^^^-- not an `extern` block
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
- |
-LL | #[link()] fn f() { }
- | ^^^^^^^^^ ---------- not an `extern` block
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to an `extern` block with non-Rust ABI
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5
- |
-LL | #[link()] struct S;
- | ^^^^^^^^^ --------- not an `extern` block
+LL | mod inner { #![link(name = "x")] }
+ | ------------^^^^^^^^^^^^^^^^^^^^-- not an `extern` block
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
|
-LL | #[link()] type T = S;
- | ^^^^^^^^^ ----------- not an `extern` block
+LL | #[link(name = "x")] fn f() { }
+ | ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
|
-LL | #[link()] impl S { }
- | ^^^^^^^^^ ---------- not an `extern` block
+LL | #[link(name = "x")] struct S;
+ | ^^^^^^^^^^^^^^^^^^^ --------- not an `extern` block
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to an `extern` block with non-Rust ABI
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5
|
-LL | #[link()] extern "Rust" {}
- | ^^^^^^^^^
+LL | #[link(name = "x")] type T = S;
+ | ^^^^^^^^^^^^^^^^^^^ ----------- not an `extern` block
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+warning: attribute should be applied to an `extern` block with non-Rust ABI
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
+ |
+LL | #[link(name = "x")] impl S { }
+ | ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+warning: attribute should be applied to an `extern` block with non-Rust ABI
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5
+ |
+LL | #[link(name = "x")] extern "Rust" {}
+ | ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775:17
|
LL | mod inner { #![windows_subsystem="windows"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:5
|
LL | #[windows_subsystem = "windows"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![windows_subsystem = "windows"] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5
|
LL | #[windows_subsystem = "windows"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![windows_subsystem = "windows"] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5
|
LL | #[windows_subsystem = "windows"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![windows_subsystem = "windows"] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5
|
LL | #[windows_subsystem = "windows"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![windows_subsystem = "windows"] impl S { }
+ | +
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:17
- |
-LL | mod inner { #![crate_name="0900"] }
- | ^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:5
- |
-LL | #[crate_name = "0900"] fn f() { }
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
- |
-LL | #[crate_name = "0900"] struct S;
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:794:5
- |
-LL | #[crate_name = "0900"] type T = S;
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5
- |
-LL | #[crate_name = "0900"] impl S { }
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
|
LL | mod inner { #![crate_type="0800"] }
| ^^^^^^^^^^^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:807:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:828:5
|
LL | #[crate_type = "0800"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![crate_type = "0800"] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:832:5
|
LL | #[crate_type = "0800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![crate_type = "0800"] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:5
|
LL | #[crate_type = "0800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![crate_type = "0800"] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:840:5
|
LL | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![crate_type = "0800"] impl S { }
+ | +
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:849:17
|
LL | mod inner { #![feature(x0600)] }
| ^^^^^^^^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:852:5
|
LL | #[feature(x0600)] fn f() { }
| ^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![feature(x0600)] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:856:5
|
LL | #[feature(x0600)] struct S;
| ^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![feature(x0600)] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:832:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:860:5
|
LL | #[feature(x0600)] type T = S;
| ^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![feature(x0600)] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:864:5
|
LL | #[feature(x0600)] impl S { }
| ^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![feature(x0600)] impl S { }
+ | +
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:874:17
|
LL | mod inner { #![no_main] }
| ^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:5
|
LL | #[no_main] fn f() { }
| ^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_main] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:849:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:881:5
|
LL | #[no_main] struct S;
| ^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_main] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:852:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:885:5
|
LL | #[no_main] type T = S;
| ^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_main] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:855:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:889:5
|
LL | #[no_main] impl S { }
| ^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_main] impl S { }
+ | +
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:898:17
|
LL | mod inner { #![no_builtins] }
| ^^^^^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:865:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:901:5
|
LL | #[no_builtins] fn f() { }
| ^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_builtins] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:868:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:905:5
|
LL | #[no_builtins] struct S;
| ^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_builtins] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:871:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:5
|
LL | #[no_builtins] type T = S;
| ^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_builtins] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:874:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:913:5
|
LL | #[no_builtins] impl S { }
| ^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![no_builtins] impl S { }
+ | +
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:881:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:922:17
|
LL | mod inner { #![recursion_limit="0200"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:884:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:925:5
|
LL | #[recursion_limit="0200"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![recursion_limit="0200"] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:887:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:929:5
|
LL | #[recursion_limit="0200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![recursion_limit="0200"] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:890:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:933:5
|
LL | #[recursion_limit="0200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![recursion_limit="0200"] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:893:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:937:5
|
LL | #[recursion_limit="0200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![recursion_limit="0200"] impl S { }
+ | +
warning: crate-level attribute should be in the root module
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:900:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:946:17
|
LL | mod inner { #![type_length_limit="0100"] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:903:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:949:5
|
LL | #[type_length_limit="0100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![type_length_limit="0100"] fn f() { }
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:906:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:953:5
|
LL | #[type_length_limit="0100"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![type_length_limit="0100"] struct S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:957:5
|
LL | #[type_length_limit="0100"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![type_length_limit="0100"] type T = S;
+ | +
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:912:5
+warning: crate-level attribute should be an inner attribute
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:961:5
|
LL | #[type_length_limit="0100"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![type_length_limit="0100"] impl S { }
+ | +
warning: `#[macro_use]` attribute cannot be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5
@@ -993,7 +1182,7 @@
= help: `#[no_implicit_prelude]` can be applied to modules and crates
warning: `#[macro_escape]` attribute cannot be used on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:5
|
LL | #[macro_escape] fn f() { }
| ^^^^^^^^^^^^^^^
@@ -1002,7 +1191,7 @@
= help: `#[macro_escape]` can be applied to modules, extern crates, and crates
warning: `#[macro_escape]` attribute cannot be used on structs
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:5
|
LL | #[macro_escape] struct S;
| ^^^^^^^^^^^^^^^
@@ -1011,7 +1200,7 @@
= help: `#[macro_escape]` can be applied to modules, extern crates, and crates
warning: `#[macro_escape]` attribute cannot be used on type aliases
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
|
LL | #[macro_escape] type T = S;
| ^^^^^^^^^^^^^^^
@@ -1020,7 +1209,7 @@
= help: `#[macro_escape]` can be applied to modules, extern crates, and crates
warning: `#[macro_escape]` attribute cannot be used on inherent impl blocks
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:533:5
|
LL | #[macro_escape] impl S { }
| ^^^^^^^^^^^^^^^
@@ -1029,7 +1218,7 @@
= help: `#[macro_escape]` can be applied to modules, extern crates, and crates
warning: `#[cold]` attribute cannot be used on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:581:1
|
LL | #[cold]
| ^^^^^^^
@@ -1038,7 +1227,7 @@
= help: `#[cold]` can only be applied to functions
warning: `#[cold]` attribute cannot be used on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:578:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:588:17
|
LL | mod inner { #![cold] }
| ^^^^^^^^
@@ -1047,7 +1236,7 @@
= help: `#[cold]` can only be applied to functions
warning: `#[cold]` attribute cannot be used on structs
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:586:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:596:5
|
LL | #[cold] struct S;
| ^^^^^^^
@@ -1056,7 +1245,7 @@
= help: `#[cold]` can only be applied to functions
warning: `#[cold]` attribute cannot be used on type aliases
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:592:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:602:5
|
LL | #[cold] type T = S;
| ^^^^^^^
@@ -1065,7 +1254,7 @@
= help: `#[cold]` can only be applied to functions
warning: `#[cold]` attribute cannot be used on inherent impl blocks
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:598:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:608:5
|
LL | #[cold] impl S { }
| ^^^^^^^
@@ -1074,7 +1263,7 @@
= help: `#[cold]` can only be applied to functions
warning: `#[link_name]` attribute cannot be used on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:605:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:615:1
|
LL | #[link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -1083,7 +1272,7 @@
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on foreign modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:621:5
|
LL | #[link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -1092,7 +1281,7 @@
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:618:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:628:17
|
LL | mod inner { #![link_name="1900"] }
| ^^^^^^^^^^^^^^^^^^^^
@@ -1101,7 +1290,7 @@
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on functions
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:634:5
|
LL | #[link_name = "1900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^
@@ -1110,7 +1299,7 @@
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on structs
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:640:5
|
LL | #[link_name = "1900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^
@@ -1119,7 +1308,7 @@
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on type aliases
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5
|
LL | #[link_name = "1900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^
@@ -1128,7 +1317,7 @@
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on inherent impl blocks
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:5
|
LL | #[link_name = "1900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^
@@ -1137,7 +1326,7 @@
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_section]` attribute cannot be used on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:649:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1
|
LL | #[link_section = "1800"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1146,7 +1335,7 @@
= help: `#[link_section]` can be applied to statics and functions
warning: `#[link_section]` attribute cannot be used on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:17
|
LL | mod inner { #![link_section="1800"] }
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -1155,7 +1344,7 @@
= help: `#[link_section]` can be applied to statics and functions
warning: `#[link_section]` attribute cannot be used on structs
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5
|
LL | #[link_section = "1800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1164,7 +1353,7 @@
= help: `#[link_section]` can be applied to statics and functions
warning: `#[link_section]` attribute cannot be used on type aliases
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
|
LL | #[link_section = "1800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1173,7 +1362,7 @@
= help: `#[link_section]` can be applied to statics and functions
warning: `#[link_section]` attribute cannot be used on inherent impl blocks
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5
|
LL | #[link_section = "1800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1182,7 +1371,7 @@
= help: `#[link_section]` can be applied to statics and functions
warning: `#[must_use]` attribute cannot be used on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:1
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -1191,7 +1380,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
warning: `#[must_use]` attribute cannot be used on modules
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:17
|
LL | mod inner { #![must_use] }
| ^^^^^^^^^^^^
@@ -1200,7 +1389,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
warning: `#[must_use]` attribute cannot be used on type aliases
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5
|
LL | #[must_use] type T = S;
| ^^^^^^^^^^^
@@ -1209,7 +1398,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
warning: `#[must_use]` attribute cannot be used on inherent impl blocks
- --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
|
LL | #[must_use] impl S { }
| ^^^^^^^^^^^
@@ -1217,6 +1406,76 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:1
+ |
+LL | #[crate_name = "0900"]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: This attribute does not have an `!`, which means it is applied to this module
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:1
+ |
+LL | / mod crate_name {
+LL | |
+LL | | mod inner { #![crate_name="0900"] }
+... |
+LL | | }
+ | |_^
+
+warning: the `#![crate_name]` attribute can only be used at the crate root
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:17
+ |
+LL | mod inner { #![crate_name="0900"] }
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:5
+ |
+LL | #[crate_name = "0900"] fn f() { }
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: This attribute does not have an `!`, which means it is applied to this function
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:28
+ |
+LL | #[crate_name = "0900"] fn f() { }
+ | ^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:5
+ |
+LL | #[crate_name = "0900"] struct S;
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: This attribute does not have an `!`, which means it is applied to this struct
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:28
+ |
+LL | #[crate_name = "0900"] struct S;
+ | ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:812:5
+ |
+LL | #[crate_name = "0900"] type T = S;
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: This attribute does not have an `!`, which means it is applied to this type alias
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:812:28
+ |
+LL | #[crate_name = "0900"] type T = S;
+ | ^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:5
+ |
+LL | #[crate_name = "0900"] impl S { }
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: This attribute does not have an `!`, which means it is applied to this implementation block
+ --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:28
+ |
+LL | #[crate_name = "0900"] impl S { }
+ | ^^^^^^^^^^
+
warning: `#[should_panic]` attribute cannot be used on crates
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:1
|
diff --git a/tests/ui/issues/issue-54696.rs b/tests/ui/function-pointer/function-pointer-comparison-54696.rs
similarity index 82%
rename from tests/ui/issues/issue-54696.rs
rename to tests/ui/function-pointer/function-pointer-comparison-54696.rs
index 63ffbe4..2e28dfe 100644
--- a/tests/ui/issues/issue-54696.rs
+++ b/tests/ui/function-pointer/function-pointer-comparison-54696.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/54696
//@ run-pass
#![allow(unpredictable_function_pointer_comparisons)]
diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr
index d624fb1..d6294ef 100644
--- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr
+++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr
@@ -1,30 +1,14 @@
-error[E0283]: type annotations needed
- --> $DIR/ambig-hr-projection-issue-93340.rs:17:5
+error[E0282]: type annotations needed
+ --> $DIR/ambig-hr-projection-issue-93340.rs:16:5
|
LL | cmp_eq
| ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
|
- = note: cannot satisfy `_: Scalar`
-note: required by a bound in `cmp_eq`
- --> $DIR/ambig-hr-projection-issue-93340.rs:10:22
- |
-LL | fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefType<'b>) -> O {
- | ^^^^^^ required by this bound in `cmp_eq`
help: consider specifying the generic arguments
|
LL | cmp_eq::<A, B, O>
| +++++++++++
-error[E0277]: expected a `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure, found `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
- --> $DIR/ambig-hr-projection-issue-93340.rs:14:1
- |
-LL | / fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
-LL | | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
- | |_________________________________________________^ expected an `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure, found `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
- |
- = help: the trait `for<'a, 'b> Fn(<A as Scalar>::RefType<'a>, <B as Scalar>::RefType<'b>)` is not implemented for fn item `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
+error: aborting due to 1 previous error
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0283.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr
index 4a293d4..d913b2e9 100644
--- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr
+++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr
@@ -1,5 +1,5 @@
error[E0283]: type annotations needed
- --> $DIR/ambig-hr-projection-issue-93340.rs:17:5
+ --> $DIR/ambig-hr-projection-issue-93340.rs:16:5
|
LL | cmp_eq
| ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs
index 6ba3c4c..acfebad 100644
--- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs
+++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs
@@ -13,7 +13,6 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT
fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
- //[next]~^^ ERROR expected a `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure
cmp_eq
//~^ ERROR type annotations needed
}
diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.rs
similarity index 76%
rename from tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs
rename to tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.rs
index 0b1857a..00bf66d 100644
--- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs
+++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5997
fn f<Z>() -> bool {
enum E { V(Z) }
//~^ ERROR can't use generic parameters from outer item
diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr
similarity index 85%
rename from tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr
rename to tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr
index c0b3cd6..aea0f04 100644
--- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr
+++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr
@@ -1,5 +1,5 @@
error[E0401]: can't use generic parameters from outer item
- --> $DIR/issue-5997-enum.rs:2:16
+ --> $DIR/enum-definition-with-outer-generic-parameter-5997.rs:3:16
|
LL | fn f<Z>() -> bool {
| - type parameter from outer item
diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
index d7add86..2e3fd61 100644
--- a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
+++ b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
@@ -2,7 +2,7 @@
--> $DIR/higher-ranked-lifetime-error.rs:12:5
|
LL | assert_all::<_, &String>(id);
- | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnMut` is not general enough
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnMut` is not general enough
|
= note: `for<'a> fn(&'a String) -> &'a String {id}` must implement `FnMut<(&String,)>`
= note: ...but it actually implements `FnMut<(&'0 String,)>`, for some specific lifetime `'0`
diff --git a/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr
index 916854e..6c17b1f 100644
--- a/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr
@@ -2,7 +2,7 @@
--> $DIR/due-to-where-clause.rs:2:5
|
LL | test::<FooS>(&mut 42);
- | ^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ | ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`...
= note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1`
diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
index 5caf0eb..7170efc 100644
--- a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
@@ -1,17 +1,9 @@
-error[E0283]: type annotations needed
+error[E0282]: type annotations needed
--> $DIR/auto-trait-selection-freeze.rs:19:16
|
LL | if false { is_trait(foo()) } else { Default::default() }
- | ^^^^^^^^ ----- type must be known at this point
- | |
- | cannot infer type of the type parameter `T` declared on the function `is_trait`
+ | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_trait`
|
- = note: cannot satisfy `_: Trait<_>`
-note: required by a bound in `is_trait`
- --> $DIR/auto-trait-selection-freeze.rs:11:16
- |
-LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
- | ^^^^^^^^ required by this bound in `is_trait`
help: consider specifying the generic arguments
|
LL | if false { is_trait::<T, U>(foo()) } else { Default::default() }
@@ -19,4 +11,4 @@
error: aborting due to 1 previous error
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr
index d34fdcc..0f33aca 100644
--- a/tests/ui/impl-trait/auto-trait-selection.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr
@@ -1,17 +1,9 @@
-error[E0283]: type annotations needed
+error[E0282]: type annotations needed
--> $DIR/auto-trait-selection.rs:15:16
|
LL | if false { is_trait(foo()) } else { Default::default() }
- | ^^^^^^^^ ----- type must be known at this point
- | |
- | cannot infer type of the type parameter `T` declared on the function `is_trait`
+ | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_trait`
|
- = note: cannot satisfy `_: Trait<_>`
-note: required by a bound in `is_trait`
- --> $DIR/auto-trait-selection.rs:7:16
- |
-LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
- | ^^^^^^^^ required by this bound in `is_trait`
help: consider specifying the generic arguments
|
LL | if false { is_trait::<T, U>(foo()) } else { Default::default() }
@@ -19,4 +11,4 @@
error: aborting due to 1 previous error
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_without_import.no_import.stderr b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
index dbac74b..2ca79aa 100644
--- a/tests/ui/impl-trait/call_method_without_import.no_import.stderr
+++ b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
@@ -3,6 +3,7 @@
|
LL | x.fmt(f);
| ^^^ method not found in `impl Debug`
+ |
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
= note: the method is available for `impl Debug` here
diff --git a/tests/ui/impl-trait/impl-generic-mismatch.stderr b/tests/ui/impl-trait/impl-generic-mismatch.stderr
index 18347bd..d7fff4c 100644
--- a/tests/ui/impl-trait/impl-generic-mismatch.stderr
+++ b/tests/ui/impl-trait/impl-generic-mismatch.stderr
@@ -48,6 +48,7 @@
|
LL | fn hash(&self, hasher: &mut impl Hasher) {}
| ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
+ |
--> $SRC_DIR/core/src/hash/mod.rs:LL:COL
|
= note: declaration in trait here
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
index 080c328..11a88b0 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
@@ -11,7 +11,7 @@
| ^^^^^^^^^^
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-in-exhaustiveness.rs:39:23
+ --> $DIR/recursive-in-exhaustiveness.rs:37:23
|
LL | fn build3<T>(x: T) -> impl Sized {
| ^^^^^^^^^^
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
index db57be7..45df8cc 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
@@ -1,80 +1,21 @@
-error[E0284]: type annotations needed: cannot normalize `build<_>::{opaque#0}`
- --> $DIR/recursive-in-exhaustiveness.rs:20:5
+error[E0282]: type annotations needed
+ --> $DIR/recursive-in-exhaustiveness.rs:19:17
|
-LL | build(x)
- | ^^^^^^^^ cannot normalize `build<_>::{opaque#0}`
+LL | let (x,) = (build(x),);
+ | ^^^^^^^^ cannot infer type
-error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
- --> $DIR/recursive-in-exhaustiveness.rs:30:6
+error[E0282]: type annotations needed
+ --> $DIR/recursive-in-exhaustiveness.rs:29:17
|
-LL | (build2(x),)
- | ^^^^^^^^^ types differ
+LL | let (x,) = (build2(x),);
+ | ^^^^^^^^^ cannot infer type
-error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
- --> $DIR/recursive-in-exhaustiveness.rs:30:5
+error[E0282]: type annotations needed
+ --> $DIR/recursive-in-exhaustiveness.rs:40:5
|
-LL | (build2(x),)
- | ^^^^^^^^^^^^ types differ
+LL | build3(x)
+ | ^^^^^^^^^ cannot infer type
-error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
- --> $DIR/recursive-in-exhaustiveness.rs:30:5
- |
-LL | (build2(x),)
- | ^^^^^^^^^^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `(impl Sized,)`
- = note: tuples must have a statically known size to be initialized
+error: aborting due to 3 previous errors
-error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
- --> $DIR/recursive-in-exhaustiveness.rs:41:17
- |
-LL | let (x,) = (build3((x,)),);
- | ^^^^^^^^^^^^ types differ
-
-error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
- --> $DIR/recursive-in-exhaustiveness.rs:41:16
- |
-LL | let (x,) = (build3((x,)),);
- | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `(impl Sized,)`
- = note: tuples must have a statically known size to be initialized
-
-error[E0308]: mismatched types
- --> $DIR/recursive-in-exhaustiveness.rs:41:16
- |
-LL | fn build3<T>(x: T) -> impl Sized {
- | ---------- the found opaque type
-LL |
-LL | let (x,) = (build3((x,)),);
- | ^^^^^^^^^^^^^^^ types differ
- |
- = note: expected type `_`
- found tuple `(impl Sized,)`
-
-error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
- --> $DIR/recursive-in-exhaustiveness.rs:41:17
- |
-LL | let (x,) = (build3((x,)),);
- | ^^^^^^^^^^^^ types differ
- |
- = note: the return type of a function must have a statically known size
-
-error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
- --> $DIR/recursive-in-exhaustiveness.rs:41:16
- |
-LL | let (x,) = (build3((x,)),);
- | ^^^^^^^^^^^^^^^ types differ
-
-error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
- --> $DIR/recursive-in-exhaustiveness.rs:41:17
- |
-LL | let (x,) = (build3((x,)),);
- | ^^^^^^^^^^^^ types differ
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 10 previous errors
-
-Some errors have detailed explanations: E0271, E0277, E0284, E0308.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
index dabef22..7aee8a6 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
@@ -17,8 +17,8 @@
fn build<T>(x: T) -> impl Sized {
//[current]~^ ERROR cannot resolve opaque type
let (x,) = (build(x),);
+ //[next]~^ ERROR type annotations needed
build(x)
- //[next]~^ ERROR type annotations needed: cannot normalize `build<_>::{opaque#0}`
}
// Opaque<T> = (Opaque<T>,)
@@ -27,10 +27,8 @@ fn build<T>(x: T) -> impl Sized {
fn build2<T>(x: T) -> impl Sized {
//[current]~^ ERROR cannot resolve opaque type
let (x,) = (build2(x),);
+ //[next]~^ ERROR type annotations needed
(build2(x),)
- //[next]~^ ERROR type mismatch resolving
- //[next]~| ERROR type mismatch resolving
- //[next]~| ERROR the size for values of type
}
// Opaque<T> = Opaque<(T,)>
@@ -39,13 +37,8 @@ fn build2<T>(x: T) -> impl Sized {
fn build3<T>(x: T) -> impl Sized {
//[current]~^ ERROR cannot resolve opaque type
let (x,) = (build3((x,)),);
- //[next]~^ ERROR type mismatch resolving
- //[next]~| ERROR type mismatch resolving
- //[next]~| ERROR type mismatch resolving
- //[next]~| ERROR type mismatch resolving
- //[next]~| ERROR the size for values of type
- //[next]~| ERROR mismatched types
build3(x)
+ //[next]~^ ERROR type annotations needed
}
fn main() {}
diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
index 3651226..7a9254b 100644
--- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
+++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
@@ -1,8 +1,8 @@
warning: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:31
+ --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:82
|
LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &u32)> {
- | ^^ the lifetime is named here ---- the same lifetime is elided here
+ | -- the lifetime is named here ^^^^ the same lifetime is elided here
|
= help: the same lifetime is referred to in inconsistent ways, making the signature confusing
= note: `#[warn(mismatched_lifetime_syntaxes)]` on by default
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
index fac4776..785e5fd 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
@@ -1,9 +1,15 @@
error[E0282]: type annotations needed
- --> $DIR/two_tait_defining_each_other2.rs:12:11
+ --> $DIR/two_tait_defining_each_other2.rs:12:8
|
LL | fn muh(x: A) -> B {
- | ^ cannot infer type
+ | ^ cannot infer type
-error: aborting due to 1 previous error
+error[E0282]: type annotations needed
+ --> $DIR/two_tait_defining_each_other2.rs:14:5
+ |
+LL | x // B's hidden type is A (opaquely)
+ | ^ cannot infer type
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
index ec29632..99262f4 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -12,7 +12,8 @@ trait Foo {}
fn muh(x: A) -> B {
//[next]~^ ERROR: type annotations needed
x // B's hidden type is A (opaquely)
- //[current]~^ ERROR opaque type's hidden type cannot be another opaque type
+ //[next]~^ ERROR: type annotations needed
+ //[current]~^^ ERROR opaque type's hidden type cannot be another opaque type
}
struct Bar;
diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr
index 5d0bf9b..c91ea8a 100644
--- a/tests/ui/imports/suggest-remove-issue-121315.stderr
+++ b/tests/ui/imports/suggest-remove-issue-121315.stderr
@@ -3,10 +3,10 @@
|
LL | use std::convert::TryFrom;
| ^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `TryFrom` is already defined here
- |
note: the lint level is defined here
--> $DIR/suggest-remove-issue-121315.rs:2:25
|
@@ -18,6 +18,7 @@
|
LL | use std::convert::{TryFrom, TryInto};
| ^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `TryFrom` is already defined here
@@ -27,6 +28,7 @@
|
LL | use std::convert::{TryFrom, TryInto};
| ^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `TryInto` is already defined here
@@ -48,6 +50,7 @@
|
LL | use std::convert::{AsMut, Into};
| ^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `Into` is already defined here
diff --git a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs
index c7f3c2c..62f1f6c 100644
--- a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs
+++ b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs
@@ -2,4 +2,4 @@
// See also <https://github.com/rust-lang/rust/issues/122001>.
//@ compile-flags: --print=crate-name
-#![crate_name = concat!("wrapped")] //~ ERROR malformed `crate_name` attribute input
+#![crate_name = concat!("wrapped")] //~ ERROR attribute value must be a literal
diff --git a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr
index b773f7c..fab38da 100644
--- a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr
+++ b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr
@@ -1,10 +1,8 @@
-error: malformed `crate_name` attribute input
- --> $DIR/print-crate-name-request-malformed-crate-name.rs:5:1
+error: attribute value must be a literal
+ --> $DIR/print-crate-name-request-malformed-crate-name.rs:5:17
|
LL | #![crate_name = concat!("wrapped")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
- |
- = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
+ | ^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr
index 64e38ed..d3e6094 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr
@@ -1,10 +1,9 @@
-error: malformed `crate_name` attribute input
+error[E0539]: malformed `crate_name` attribute input
--> $DIR/print-file-names-request-malformed-crate-name-1.rs:4:1
|
LL | #![crate_name]
| ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
- |
- = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs
index 13c9d1e..1ac1208 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs
@@ -4,4 +4,4 @@
//@ compile-flags: --print=file-names
#![crate_name = "this_one_is_okay"]
-#![crate_name = concat!("this_one_is_not")] //~ ERROR malformed `crate_name` attribute input
+#![crate_name = concat!("this_one_is_not")] //~ ERROR attribute value must be a literal
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr
index e9a5b58..1571521 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr
@@ -1,10 +1,8 @@
-error: malformed `crate_name` attribute input
- --> $DIR/print-file-names-request-malformed-crate-name-2.rs:7:1
+error: attribute value must be a literal
+ --> $DIR/print-file-names-request-malformed-crate-name-2.rs:7:17
|
LL | #![crate_name = concat!("this_one_is_not")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
- |
- = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs
index 5fe8bd7..6441017 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs
@@ -2,4 +2,4 @@
// See also <https://github.com/rust-lang/rust/issues/122001>.
//@ compile-flags: --print=file-names
-#![crate_name = concat!("wrapped")] //~ ERROR malformed `crate_name` attribute input
+#![crate_name = concat!("wrapped")] //~ ERROR attribute value must be a literal
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr
index e63525c..155e2e5 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr
@@ -1,10 +1,8 @@
-error: malformed `crate_name` attribute input
- --> $DIR/print-file-names-request-malformed-crate-name.rs:5:1
+error: attribute value must be a literal
+ --> $DIR/print-file-names-request-malformed-crate-name.rs:5:17
|
LL | #![crate_name = concat!("wrapped")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
- |
- = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
+ | ^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/issues/issue-17546.stderr b/tests/ui/issues/issue-17546.stderr
index 25a94dd..5bae738 100644
--- a/tests/ui/issues/issue-17546.stderr
+++ b/tests/ui/issues/issue-17546.stderr
@@ -3,10 +3,10 @@
|
LL | fn new() -> NoResult<MyEnum, String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/core/src/result.rs:LL:COL
|
= note: similarly named enum `Result` defined here
- |
help: try using the variant's enum
|
LL - fn new() -> NoResult<MyEnum, String> {
@@ -57,10 +57,10 @@
|
LL | fn newer() -> NoResult<foo::MyEnum, String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/core/src/result.rs:LL:COL
|
= note: similarly named enum `Result` defined here
- |
help: try using the variant's enum
|
LL - fn newer() -> NoResult<foo::MyEnum, String> {
diff --git a/tests/ui/issues/issue-27033.stderr b/tests/ui/issues/issue-27033.stderr
index 7a0ca88..129870f 100644
--- a/tests/ui/issues/issue-27033.stderr
+++ b/tests/ui/issues/issue-27033.stderr
@@ -3,6 +3,7 @@
|
LL | None @ _ => {}
| ^^^^ cannot be named the same as a unit variant
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the unit variant `None` is defined here
diff --git a/tests/ui/issues/issue-29466.rs b/tests/ui/issues/issue-29466.rs
index dbc3750..3962940 100644
--- a/tests/ui/issues/issue-29466.rs
+++ b/tests/ui/issues/issue-29466.rs
@@ -2,6 +2,9 @@
//
//@ run-pass
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
#![allow(unused_variables)]
macro_rules! m(
diff --git a/tests/ui/issues/issue-54410.rs b/tests/ui/issues/issue-54410.rs
deleted file mode 100644
index e3e8ca9..0000000
--- a/tests/ui/issues/issue-54410.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-extern "C" {
- pub static mut symbol: [i8];
- //~^ ERROR the size for values of type `[i8]` cannot be known at compilation time
-}
-
-fn main() {
- println!("{:p}", unsafe { &symbol });
-}
diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr
deleted file mode 100644
index cb68ada..0000000
--- a/tests/ui/issues/issue-54410.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
- --> $DIR/issue-54410.rs:2:5
- |
-LL | pub static mut symbol: [i8];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `[i8]`
- = note: statics and constants must have a statically known size
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/issues/issue-5518.rs b/tests/ui/issues/issue-5518.rs
deleted file mode 100644
index 333185c..0000000
--- a/tests/ui/issues/issue-5518.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ run-pass
-//@ aux-build:issue-5518.rs
-
-
-extern crate issue_5518 as other;
-
-fn main() {}
diff --git a/tests/ui/issues/issue-5844.rs b/tests/ui/issues/issue-5844.rs
deleted file mode 100644
index 2302120..0000000
--- a/tests/ui/issues/issue-5844.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@aux-build:issue-5844-aux.rs
-
-extern crate issue_5844_aux;
-
-fn main() {
- issue_5844_aux::rand(); //~ ERROR: requires unsafe
-}
diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs
deleted file mode 100644
index 19d994b..0000000
--- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-fn f<T>() -> bool {
- struct S(T); //~ ERROR can't use generic parameters from outer item
-
- true
-}
-
-fn main() {
- let b = f::<isize>();
- assert!(b);
-}
diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr
deleted file mode 100644
index 670a548..0000000
--- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0401]: can't use generic parameters from outer item
- --> $DIR/issue-5997-struct.rs:2:14
- |
-LL | fn f<T>() -> bool {
- | - type parameter from outer item
-LL | struct S(T);
- | -^ use of generic parameter from outer item
- | |
- | help: try introducing a local generic parameter here: `<T>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/tests/ui/issues/issue-6344-match.rs b/tests/ui/issues/issue-6344-match.rs
deleted file mode 100644
index 9251e27..0000000
--- a/tests/ui/issues/issue-6344-match.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//@ run-pass
-#![allow(non_shorthand_field_patterns)]
-
-struct A { x: usize }
-
-impl Drop for A {
- fn drop(&mut self) {}
-}
-
-pub fn main() {
- let a = A { x: 0 };
-
- match a {
- A { x : ref x } => {
- println!("{}", x)
- }
- }
-}
diff --git a/tests/ui/issues/issue-7178.rs b/tests/ui/issues/issue-7178.rs
deleted file mode 100644
index 408ce0b..0000000
--- a/tests/ui/issues/issue-7178.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ run-pass
-//@ aux-build:issue-7178.rs
-
-
-extern crate issue_7178 as cross_crate_self;
-
-pub fn main() {
- let _ = cross_crate_self::Foo::new(&1);
-}
diff --git a/tests/ui/issues/issue-53419.rs b/tests/ui/lifetimes/dyn-trait-function-pointer-53419.rs
similarity index 64%
rename from tests/ui/issues/issue-53419.rs
rename to tests/ui/lifetimes/dyn-trait-function-pointer-53419.rs
index 55d41f2..b1017b1 100644
--- a/tests/ui/issues/issue-53419.rs
+++ b/tests/ui/lifetimes/dyn-trait-function-pointer-53419.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/53419
//@ check-pass
struct Foo {
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr
index 5a7a5a6..2b7d6a6 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr
@@ -1,8 +1,8 @@
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/example-from-issue48686.rs:6:21
+ --> $DIR/example-from-issue48686.rs:6:50
|
LL | pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
- | ^^^^^^^ ------- the same lifetime is elided here
+ | ------- ^^^^^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr
index af56a0a..c4d6e78d 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr
@@ -1,8 +1,8 @@
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/missing-lifetime-kind.rs:3:22
+ --> $DIR/missing-lifetime-kind.rs:3:32
|
LL | fn ampersand<'a>(x: &'a u8) -> &u8 {
- | ^^ --- the same lifetime is elided here
+ | -- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -18,10 +18,10 @@
| ++
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/missing-lifetime-kind.rs:10:21
+ --> $DIR/missing-lifetime-kind.rs:10:31
|
LL | fn brackets<'a>(x: &'a u8) -> Brackets {
- | ^^ -------- the same lifetime is hidden here
+ | -- ^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -32,10 +32,10 @@
| ++++
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/missing-lifetime-kind.rs:17:18
+ --> $DIR/missing-lifetime-kind.rs:17:28
|
LL | fn comma<'a>(x: &'a u8) -> Comma<u8> {
- | ^^ --------- the same lifetime is hidden here
+ | -- ^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -46,10 +46,10 @@
| +++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/missing-lifetime-kind.rs:22:23
+ --> $DIR/missing-lifetime-kind.rs:22:34
|
LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 {
- | ^^ -- the same lifetime is elided here
+ | -- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr
index cf0a296..28de809 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr
@@ -1,8 +1,8 @@
warning: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/not-tied-to-crate.rs:8:16
+ --> $DIR/not-tied-to-crate.rs:8:31
|
LL | fn bar(x: &'static u8) -> &u8 {
- | ^^^^^^^ --- the same lifetime is elided here
+ | ------- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -18,10 +18,10 @@
| +++++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/not-tied-to-crate.rs:14:16
+ --> $DIR/not-tied-to-crate.rs:14:31
|
LL | fn baz(x: &'static u8) -> &u8 {
- | ^^^^^^^ --- the same lifetime is elided here
+ | ------- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr
index d60bec6..5f21a28 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr
@@ -1,8 +1,8 @@
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/static.rs:16:18
+ --> $DIR/static.rs:16:33
|
LL | fn ampersand(x: &'static u8) -> &u8 {
- | ^^^^^^^ --- the same lifetime is elided here
+ | ------- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -18,10 +18,10 @@
| +++++++
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/static.rs:23:17
+ --> $DIR/static.rs:23:32
|
LL | fn brackets(x: &'static u8) -> Brackets {
- | ^^^^^^^ -------- the same lifetime is hidden here
+ | ------- ^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -32,10 +32,10 @@
| +++++++++
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/static.rs:30:14
+ --> $DIR/static.rs:30:29
|
LL | fn comma(x: &'static u8) -> Comma<u8> {
- | ^^^^^^^ --------- the same lifetime is hidden here
+ | ------- ^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -46,10 +46,10 @@
| ++++++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/static.rs:35:19
+ --> $DIR/static.rs:35:35
|
LL | fn underscore(x: &'static u8) -> &'_ u8 {
- | ^^^^^^^ -- the same lifetime is elided here
+ | ------- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs
index f6260c4..f404c41 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs
@@ -36,8 +36,8 @@ fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> Contains
fn explicit_bound_path_to_explicit_anonymous_path<'a>(
v: ContainsLifetime<'a>,
- //~^ ERROR eliding a lifetime that's named elsewhere is confusing
) -> ContainsLifetime<'_> {
+ //~^ ERROR eliding a lifetime that's named elsewhere is confusing
v
}
@@ -188,8 +188,8 @@ fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) -> impl
fn explicit_bound_path_to_impl_trait_precise_capture<'a>(
v: ContainsLifetime<'a>,
- //~^ ERROR eliding a lifetime that's named elsewhere is confusing
) -> impl FnOnce() + use<'_> {
+ //~^ ERROR eliding a lifetime that's named elsewhere is confusing
move || _ = v
}
}
@@ -208,8 +208,8 @@ fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box<dyn Iterator<Item
fn explicit_bound_path_to_dyn_trait_bound<'a>(
v: ContainsLifetime<'a>,
- //~^ ERROR hiding a lifetime that's named elsewhere is confusing
) -> Box<dyn Iterator<Item = ContainsLifetime> + '_> {
+ //~^ ERROR hiding a lifetime that's named elsewhere is confusing
Box::new(iter::once(v))
}
}
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr
index 20b7561..89768fc 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr
@@ -1,8 +1,8 @@
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:10:47
+ --> $DIR/mismatched-lifetime-syntaxes.rs:10:57
|
LL | fn explicit_bound_ref_to_implicit_ref<'a>(v: &'a u8) -> &u8 {
- | ^^ --- the same lifetime is elided here
+ | -- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -18,10 +18,10 @@
| ++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:15:57
+ --> $DIR/mismatched-lifetime-syntaxes.rs:15:68
|
LL | fn explicit_bound_ref_to_explicit_anonymous_ref<'a>(v: &'a u8) -> &'_ u8 {
- | ^^ -- the same lifetime is elided here
+ | -- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -36,7 +36,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:22:48
|
LL | fn implicit_path_to_explicit_anonymous_path(v: ContainsLifetime) -> ContainsLifetime<'_> {
- | ^^^^^^^^^^^^^^^^ -- the same lifetime is elided here
+ | ^^^^^^^^^^^^^^^^ ^^ the same lifetime is elided here
| |
| the lifetime is hidden here
|
@@ -50,7 +50,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:27:65
|
LL | fn explicit_anonymous_path_to_implicit_path(v: ContainsLifetime<'_>) -> ContainsLifetime {
- | ^^ ---------------- the same lifetime is hidden here
+ | ^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
@@ -61,10 +61,10 @@
| ++++
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:32:65
+ --> $DIR/mismatched-lifetime-syntaxes.rs:32:73
|
LL | fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> ContainsLifetime {
- | ^^ ---------------- the same lifetime is hidden here
+ | -- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -75,13 +75,12 @@
| ++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:38:25
+ --> $DIR/mismatched-lifetime-syntaxes.rs:39:23
|
LL | v: ContainsLifetime<'a>,
- | ^^ the lifetime is named here
-LL |
+ | -- the lifetime is named here
LL | ) -> ContainsLifetime<'_> {
- | -- the same lifetime is elided here
+ | ^^ the same lifetime is elided here
|
= help: the same lifetime is referred to in inconsistent ways, making the signature confusing
help: consistently use `'a`
@@ -94,7 +93,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:46:37
|
LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime {
- | ^^^ ---------------- the same lifetime is hidden here
+ | ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
@@ -108,7 +107,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:51:48
|
LL | fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime {
- | ^^ ---------------- the same lifetime is hidden here
+ | ^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
@@ -119,10 +118,10 @@
| ++++
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:56:48
+ --> $DIR/mismatched-lifetime-syntaxes.rs:56:58
|
LL | fn explicit_bound_ref_to_implicit_path<'a>(v: &'a u8) -> ContainsLifetime {
- | ^^ ---------------- the same lifetime is hidden here
+ | -- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -133,10 +132,10 @@
| ++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:61:58
+ --> $DIR/mismatched-lifetime-syntaxes.rs:61:85
|
LL | fn explicit_bound_ref_to_explicit_anonymous_path<'a>(v: &'a u8) -> ContainsLifetime<'_> {
- | ^^ -- the same lifetime is elided here
+ | -- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -151,7 +150,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:68:37
|
LL | fn implicit_path_to_implicit_ref(v: ContainsLifetime) -> &u8 {
- | ^^^^^^^^^^^^^^^^ --- the same lifetime is elided here
+ | ^^^^^^^^^^^^^^^^ ^^^ the same lifetime is elided here
| |
| the lifetime is hidden here
|
@@ -165,7 +164,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:73:47
|
LL | fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime) -> &'_ u8 {
- | ^^^^^^^^^^^^^^^^ -- the same lifetime is elided here
+ | ^^^^^^^^^^^^^^^^ ^^ the same lifetime is elided here
| |
| the lifetime is hidden here
|
@@ -176,10 +175,10 @@
| ++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:78:64
+ --> $DIR/mismatched-lifetime-syntaxes.rs:78:72
|
LL | fn explicit_bound_path_to_implicit_ref<'a>(v: ContainsLifetime<'a>) -> &u8 {
- | ^^ --- the same lifetime is elided here
+ | -- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -190,10 +189,10 @@
| ++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:83:74
+ --> $DIR/mismatched-lifetime-syntaxes.rs:83:83
|
LL | fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a>) -> &'_ u8 {
- | ^^ -- the same lifetime is elided here
+ | -- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -205,10 +204,10 @@
|
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:89:55
+ --> $DIR/mismatched-lifetime-syntaxes.rs:89:67
|
LL | fn method_explicit_bound_ref_to_implicit_ref<'a>(&'a self) -> &u8 {
- | ^^ --- the same lifetime is elided here
+ | -- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -219,10 +218,10 @@
| ++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:94:65
+ --> $DIR/mismatched-lifetime-syntaxes.rs:94:78
|
LL | fn method_explicit_bound_ref_to_explicit_anonymous_ref<'a>(&'a self) -> &'_ u8 {
- | ^^ -- the same lifetime is elided here
+ | -- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -237,7 +236,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:101:56
|
LL | fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> ContainsLifetime {
- | ^^ ---------------- the same lifetime is hidden here
+ | ^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
@@ -248,10 +247,10 @@
| ++++
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:106:56
+ --> $DIR/mismatched-lifetime-syntaxes.rs:106:68
|
LL | fn method_explicit_bound_ref_to_implicit_path<'a>(&'a self) -> ContainsLifetime {
- | ^^ ---------------- the same lifetime is hidden here
+ | -- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -262,10 +261,10 @@
| ++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:111:66
+ --> $DIR/mismatched-lifetime-syntaxes.rs:111:95
|
LL | fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) -> ContainsLifetime<'_> {
- | ^^ -- the same lifetime is elided here
+ | -- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -277,10 +276,10 @@
|
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:126:39
+ --> $DIR/mismatched-lifetime-syntaxes.rs:126:54
|
LL | fn static_ref_to_implicit_ref(v: &'static u8) -> &u8 {
- | ^^^^^^^ --- the same lifetime is elided here
+ | ------- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -291,10 +290,10 @@
| +++++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:131:49
+ --> $DIR/mismatched-lifetime-syntaxes.rs:131:65
|
LL | fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'_ u8 {
- | ^^^^^^^ -- the same lifetime is elided here
+ | ------- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -306,10 +305,10 @@
|
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:136:40
+ --> $DIR/mismatched-lifetime-syntaxes.rs:136:55
|
LL | fn static_ref_to_implicit_path(v: &'static u8) -> ContainsLifetime {
- | ^^^^^^^ ---------------- the same lifetime is hidden here
+ | ------- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -320,10 +319,10 @@
| +++++++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:141:50
+ --> $DIR/mismatched-lifetime-syntaxes.rs:141:82
|
LL | fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLifetime<'_> {
- | ^^^^^^^ -- the same lifetime is elided here
+ | ------- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -335,10 +334,10 @@
|
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:147:40
+ --> $DIR/mismatched-lifetime-syntaxes.rs:147:57
|
LL | fn static_ref_to_implicit_ref(&'static self) -> &u8 {
- | ^^^^^^^ --- the same lifetime is elided here
+ | ------- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -349,10 +348,10 @@
| +++++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:152:50
+ --> $DIR/mismatched-lifetime-syntaxes.rs:152:68
|
LL | fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'_ u8 {
- | ^^^^^^^ -- the same lifetime is elided here
+ | ------- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -364,10 +363,10 @@
|
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:157:41
+ --> $DIR/mismatched-lifetime-syntaxes.rs:157:58
|
LL | fn static_ref_to_implicit_path(&'static self) -> ContainsLifetime {
- | ^^^^^^^ ---------------- the same lifetime is hidden here
+ | ------- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is named here
|
@@ -378,10 +377,10 @@
| +++++++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:162:51
+ --> $DIR/mismatched-lifetime-syntaxes.rs:162:85
|
LL | fn static_ref_to_explicit_anonymous_path(&'static self) -> ContainsLifetime<'_> {
- | ^^^^^^^ -- the same lifetime is elided here
+ | ------- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -393,10 +392,10 @@
|
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:174:55
+ --> $DIR/mismatched-lifetime-syntaxes.rs:174:81
|
LL | fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce() + '_ {
- | ^^ -- the same lifetime is elided here
+ | -- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -408,10 +407,10 @@
|
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:179:65
+ --> $DIR/mismatched-lifetime-syntaxes.rs:179:95
|
LL | fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> impl FnOnce() + use<'_> {
- | ^^ the lifetime is named here -- the same lifetime is elided here
+ | -- the lifetime is named here ^^ the same lifetime is elided here
|
= help: the same lifetime is referred to in inconsistent ways, making the signature confusing
help: consistently use `'a`
@@ -421,10 +420,10 @@
|
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:184:72
+ --> $DIR/mismatched-lifetime-syntaxes.rs:184:96
|
LL | fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) -> impl FnOnce() + '_ {
- | ^^ -- the same lifetime is elided here
+ | -- ^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -436,13 +435,12 @@
|
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:190:29
+ --> $DIR/mismatched-lifetime-syntaxes.rs:191:30
|
LL | v: ContainsLifetime<'a>,
- | ^^ the lifetime is named here
-LL |
+ | -- the lifetime is named here
LL | ) -> impl FnOnce() + use<'_> {
- | -- the same lifetime is elided here
+ | ^^ the same lifetime is elided here
|
= help: the same lifetime is referred to in inconsistent ways, making the signature confusing
help: consistently use `'a`
@@ -452,10 +450,10 @@
|
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:204:54
+ --> $DIR/mismatched-lifetime-syntaxes.rs:204:88
|
LL | fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box<dyn Iterator<Item = &u8> + '_> {
- | ^^ the lifetime is named here --- the same lifetime is elided here
+ | -- the lifetime is named here ^^^ the same lifetime is elided here
|
= help: the same lifetime is referred to in inconsistent ways, making the signature confusing
help: consistently use `'a`
@@ -464,13 +462,12 @@
| ++
error: hiding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:210:29
+ --> $DIR/mismatched-lifetime-syntaxes.rs:211:34
|
LL | v: ContainsLifetime<'a>,
- | ^^ the lifetime is named here
-LL |
+ | -- the lifetime is named here
LL | ) -> Box<dyn Iterator<Item = ContainsLifetime> + '_> {
- | ---------------- the same lifetime is hidden here
+ | ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
|
= help: the same lifetime is referred to in inconsistent ways, making the signature confusing
help: consistently use `'a`
@@ -479,10 +476,10 @@
| ++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:222:33
+ --> $DIR/mismatched-lifetime-syntaxes.rs:222:52
|
LL | fn multiple_inputs<'a>(v: (&'a u8, &'a u8)) -> &u8 {
- | ^^ ^^ --- the same lifetime is elided here
+ | -- -- ^^^ the same lifetime is elided here
| | |
| | the lifetime is named here
| the lifetime is named here
@@ -494,10 +491,10 @@
| ++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:227:33
+ --> $DIR/mismatched-lifetime-syntaxes.rs:227:44
|
LL | fn multiple_outputs<'a>(v: &'a u8) -> (&u8, &u8) {
- | ^^ --- --- the same lifetime is elided here
+ | -- ^^^ ^^^ the same lifetime is elided here
| | |
| | the same lifetime is elided here
| the lifetime is named here
@@ -509,10 +506,10 @@
| ++ ++
error: hiding or eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:232:53
+ --> $DIR/mismatched-lifetime-syntaxes.rs:232:62
|
LL | fn all_three_categories<'a>(v: ContainsLifetime<'a>) -> (&u8, ContainsLifetime) {
- | ^^ --- ---------------- the same lifetime is hidden here
+ | -- ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| | |
| | the same lifetime is elided here
| the lifetime is named here
@@ -524,10 +521,10 @@
| ++ ++++
error: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/mismatched-lifetime-syntaxes.rs:237:38
+ --> $DIR/mismatched-lifetime-syntaxes.rs:237:49
|
LL | fn explicit_bound_output<'a>(v: &'a u8) -> (&u8, &'a u8, ContainsLifetime<'a>) {
- | ^^ --- -- -- the same lifetime is named here
+ | -- ^^^ -- -- the same lifetime is named here
| | | |
| | | the same lifetime is named here
| | the same lifetime is elided here
@@ -543,7 +540,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:250:45
|
LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime;
- | ^^^ ---------------- the same lifetime is hidden here
+ | ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
@@ -557,7 +554,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:253:49
|
LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime;
- | ^^^^^ ---------------- the same lifetime is hidden here
+ | ^^^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
@@ -571,7 +568,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:258:45
|
LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime {
- | ^^^ ---------------- the same lifetime is hidden here
+ | ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
@@ -585,7 +582,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:263:49
|
LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime {
- | ^^^^^ ---------------- the same lifetime is hidden here
+ | ^^^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
@@ -599,7 +596,7 @@
--> $DIR/mismatched-lifetime-syntaxes.rs:277:45
|
LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime;
- | ^^^ ---------------- the same lifetime is hidden here
+ | ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
| |
| the lifetime is elided here
|
diff --git a/tests/ui/issues/issue-7268.rs b/tests/ui/lifetimes/static-bound-fulfillment-with-pointer-7268.rs
similarity index 70%
rename from tests/ui/issues/issue-7268.rs
rename to tests/ui/lifetimes/static-bound-fulfillment-with-pointer-7268.rs
index a3bc1bc..8ec58e6 100644
--- a/tests/ui/issues/issue-7268.rs
+++ b/tests/ui/lifetimes/static-bound-fulfillment-with-pointer-7268.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/7268
//@ check-pass
#![allow(dead_code)]
diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.full-debuginfo.stderr
similarity index 85%
rename from tests/ui/limits/huge-enum.stderr
rename to tests/ui/limits/huge-enum.full-debuginfo.stderr
index 18168b3..4b179d5 100644
--- a/tests/ui/limits/huge-enum.stderr
+++ b/tests/ui/limits/huge-enum.full-debuginfo.stderr
@@ -1,5 +1,5 @@
error: values of the type `Option<TYPE>` are too big for the target architecture
- --> $DIR/huge-enum.rs:12:9
+ --> $DIR/huge-enum.rs:17:9
|
LL | let big: BIG = None;
| ^^^
diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.no-debuginfo.stderr
similarity index 85%
copy from tests/ui/limits/huge-enum.stderr
copy to tests/ui/limits/huge-enum.no-debuginfo.stderr
index 18168b3..4b179d5 100644
--- a/tests/ui/limits/huge-enum.stderr
+++ b/tests/ui/limits/huge-enum.no-debuginfo.stderr
@@ -1,5 +1,5 @@
error: values of the type `Option<TYPE>` are too big for the target architecture
- --> $DIR/huge-enum.rs:12:9
+ --> $DIR/huge-enum.rs:17:9
|
LL | let big: BIG = None;
| ^^^
diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs
index 66c5be2..9395bee 100644
--- a/tests/ui/limits/huge-enum.rs
+++ b/tests/ui/limits/huge-enum.rs
@@ -1,6 +1,11 @@
+// FIXME(#61117): Remove revisions once x86_64-gnu-debug CI job sets rust.debuginfo-level-tests=2
+// NOTE: The .stderr for both revisions shall be identical.
+//@ revisions: no-debuginfo full-debuginfo
//@ build-fail
//@ normalize-stderr: "std::option::Option<\[u32; \d+\]>" -> "TYPE"
//@ normalize-stderr: "\[u32; \d+\]" -> "TYPE"
+//@[no-debuginfo] compile-flags: -Cdebuginfo=0
+//@[full-debuginfo] compile-flags: -Cdebuginfo=2
#[cfg(target_pointer_width = "32")]
type BIG = Option<[u32; (1<<29)-1]>;
diff --git a/tests/ui/link-native-libs/issue-43925.rs b/tests/ui/link-native-libs/issue-43925.rs
index 1a21088..e3ce713 100644
--- a/tests/ui/link-native-libs/issue-43925.rs
+++ b/tests/ui/link-native-libs/issue-43925.rs
@@ -1,4 +1,6 @@
-#[link(name = "foo", cfg("rlib"))] //~ ERROR link cfg must have a single predicate argument
+#[link(name = "foo", cfg("rlib"))]
+//~^ ERROR link cfg is unstable
+//~| ERROR `cfg` predicate key must be an identifier
extern "C" {}
fn main() {}
diff --git a/tests/ui/link-native-libs/issue-43925.stderr b/tests/ui/link-native-libs/issue-43925.stderr
index 7cc347c..82d2042 100644
--- a/tests/ui/link-native-libs/issue-43925.stderr
+++ b/tests/ui/link-native-libs/issue-43925.stderr
@@ -1,8 +1,18 @@
-error: link cfg must have a single predicate argument
+error[E0658]: link cfg is unstable
--> $DIR/issue-43925.rs:1:22
|
LL | #[link(name = "foo", cfg("rlib"))]
| ^^^^^^^^^^^
+ |
+ = help: add `#![feature(link_cfg)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error: aborting due to 1 previous error
+error: `cfg` predicate key must be an identifier
+ --> $DIR/issue-43925.rs:1:26
+ |
+LL | #[link(name = "foo", cfg("rlib"))]
+ | ^^^^^^
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/link-native-libs/issue-43926.rs b/tests/ui/link-native-libs/issue-43926.rs
index 6d30035..293ad3f 100644
--- a/tests/ui/link-native-libs/issue-43926.rs
+++ b/tests/ui/link-native-libs/issue-43926.rs
@@ -1,4 +1,4 @@
-#[link(name = "foo", cfg())] //~ ERROR link cfg must have a single predicate argument
+#[link(name = "foo", cfg())] //~ ERROR malformed `link` attribute input
extern "C" {}
fn main() {}
diff --git a/tests/ui/link-native-libs/issue-43926.stderr b/tests/ui/link-native-libs/issue-43926.stderr
index 7c5c50a..9e3ec21 100644
--- a/tests/ui/link-native-libs/issue-43926.stderr
+++ b/tests/ui/link-native-libs/issue-43926.stderr
@@ -1,8 +1,28 @@
-error: link cfg must have a single predicate argument
- --> $DIR/issue-43926.rs:1:22
+error[E0805]: malformed `link` attribute input
+ --> $DIR/issue-43926.rs:1:1
|
LL | #[link(name = "foo", cfg())]
- | ^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^-----^^
+ | |
+ | expected a single argument here
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "foo", cfg())]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "foo", cfg())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "foo", cfg())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "foo", cfg())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0805`.
diff --git a/tests/ui/link-native-libs/link-attr-validation-early.rs b/tests/ui/link-native-libs/link-attr-validation-early.rs
index a7dd80f..89a34ac 100644
--- a/tests/ui/link-native-libs/link-attr-validation-early.rs
+++ b/tests/ui/link-native-libs/link-attr-validation-early.rs
@@ -1,8 +1,6 @@
// Top-level ill-formed
-#[link] //~ ERROR valid forms for the attribute are
- //~| WARN this was previously accepted
-#[link = "foo"] //~ ERROR valid forms for the attribute are
- //~| WARN this was previously accepted
+#[link] //~ ERROR malformed
+#[link = "foo"] //~ ERROR malformed
extern "C" {}
fn main() {}
diff --git a/tests/ui/link-native-libs/link-attr-validation-early.stderr b/tests/ui/link-native-libs/link-attr-validation-early.stderr
index d4fc2e2..e4799b1 100644
--- a/tests/ui/link-native-libs/link-attr-validation-early.stderr
+++ b/tests/ui/link-native-libs/link-attr-validation-early.stderr
@@ -1,47 +1,45 @@
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
+error[E0539]: malformed `link` attribute input
--> $DIR/link-attr-validation-early.rs:2:1
|
LL | #[link]
- | ^^^^^^^
+ | ^^^^^^^ expected this to be a list
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
- = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL | #[link(name = "...")]
+ | ++++++++++++++
+LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...")]
+ | +++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ = and 1 other candidate
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
- --> $DIR/link-attr-validation-early.rs:4:1
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-early.rs:3:1
|
LL | #[link = "foo"]
- | ^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^ expected this to be a list
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link = "foo"]
+LL + #[link(name = "...")]
+ |
+LL - #[link = "foo"]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link = "foo"]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link = "foo"]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: aborting due to 2 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
- --> $DIR/link-attr-validation-early.rs:2:1
- |
-LL | #[link]
- | ^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
- = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
- = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
- --> $DIR/link-attr-validation-early.rs:4:1
- |
-LL | #[link = "foo"]
- | ^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
- = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
- = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.rs b/tests/ui/link-native-libs/link-attr-validation-late.rs
index 4eeb8ba..d2947b5 100644
--- a/tests/ui/link-native-libs/link-attr-validation-late.rs
+++ b/tests/ui/link-native-libs/link-attr-validation-late.rs
@@ -1,38 +1,36 @@
#![feature(link_cfg)]
// Top-level ill-formed
-#[link(name = "...", "literal")] //~ ERROR unexpected `#[link]` argument
-#[link(name = "...", unknown)] //~ ERROR unexpected `#[link]` argument
+#[link(name = "...", "literal")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", unknown)] //~ ERROR malformed `link` attribute input
extern "C" {}
// Duplicate arguments
-#[link(name = "foo", name = "bar")] //~ ERROR multiple `name` arguments
-#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR multiple `kind` arguments
-#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR multiple `modifiers` arguments
-#[link(name = "...", cfg(false), cfg(false))] //~ ERROR multiple `cfg` arguments
-#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR multiple `wasm_import_module` arguments
+#[link(name = "foo", name = "bar")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", cfg(false), cfg(false))] //~ ERROR malformed `link` attribute input
+#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR malformed `link` attribute input
extern "C" {}
// Ill-formed arguments
-#[link(name)] //~ ERROR link name must be of the form `name = "string"`
- //~| ERROR `#[link]` attribute requires a `name = "string"` argument
-#[link(name())] //~ ERROR link name must be of the form `name = "string"`
- //~| ERROR `#[link]` attribute requires a `name = "string"` argument
-#[link(name = "...", kind)] //~ ERROR link kind must be of the form `kind = "string"`
-#[link(name = "...", kind())] //~ ERROR link kind must be of the form `kind = "string"`
-#[link(name = "...", modifiers)] //~ ERROR link modifiers must be of the form `modifiers = "string"`
-#[link(name = "...", modifiers())] //~ ERROR link modifiers must be of the form `modifiers = "string"`
-#[link(name = "...", cfg)] //~ ERROR link cfg must be of the form `cfg(/* predicate */)`
-#[link(name = "...", cfg = "literal")] //~ ERROR link cfg must be of the form `cfg(/* predicate */)`
-#[link(name = "...", cfg("literal"))] //~ ERROR link cfg must have a single predicate argument
-#[link(name = "...", wasm_import_module)] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"`
-#[link(name = "...", wasm_import_module())] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"`
+#[link(name)] //~ ERROR malformed `link` attribute input
+#[link(name())] //~ ERROR malformed `link` attribute input
+#[link(name = "...", kind)] //~ ERROR malformed `link` attribute input
+#[link(name = "...", kind())] //~ ERROR malformed `link` attribute input
+#[link(name = "...", modifiers)] //~ ERROR malformed `link` attribute input
+#[link(name = "...", modifiers())] //~ ERROR malformed `link` attribute input
+#[link(name = "...", cfg)] //~ ERROR malformed `link` attribute input
+#[link(name = "...", cfg = "literal")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", cfg("literal"))] //~ ERROR `cfg` predicate key must be an identifier
+#[link(name = "...", wasm_import_module)] //~ ERROR malformed `link` attribute input
+#[link(name = "...", wasm_import_module())] //~ ERROR malformed `link` attribute input
extern "C" {}
// Basic modifier validation
#[link(name = "...", modifiers = "")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix
#[link(name = "...", modifiers = "no-plus-minus")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix
-#[link(name = "...", modifiers = "+unknown")] //~ ERROR unknown linking modifier `unknown`
+#[link(name = "...", modifiers = "+unknown")] //~ ERROR malformed `link` attribute input
#[link(name = "...", modifiers = "+verbatim,+verbatim")] //~ ERROR multiple `verbatim` modifiers
extern "C" {}
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr
index f3989c0..834dca0 100644
--- a/tests/ui/link-native-libs/link-attr-validation-late.stderr
+++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr
@@ -1,147 +1,472 @@
-error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
- --> $DIR/link-attr-validation-late.rs:4:22
+error[E0565]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:4:1
|
LL | #[link(name = "...", "literal")]
- | ^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^---------^^
+ | |
+ | didn't expect a literal here
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", "literal")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", "literal")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", "literal")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", "literal")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
- --> $DIR/link-attr-validation-late.rs:5:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:5:1
|
LL | #[link(name = "...", unknown)]
- | ^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^-------^^
+ | |
+ | valid arguments are "name", "kind", "modifiers", "cfg", "wasm_import_module" or "import_name_type"
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", unknown)]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", unknown)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", unknown)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", unknown)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: multiple `name` arguments in a single `#[link]` attribute
- --> $DIR/link-attr-validation-late.rs:9:22
+error[E0538]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:9:1
|
LL | #[link(name = "foo", name = "bar")]
- | ^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^------------^^
+ | |
+ | found `name` used as a key more than once
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "foo", name = "bar")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "foo", name = "bar")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "foo", name = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "foo", name = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: multiple `kind` arguments in a single `#[link]` attribute
- --> $DIR/link-attr-validation-late.rs:10:38
+error[E0538]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:10:1
|
LL | #[link(name = "...", kind = "dylib", kind = "bar")]
- | ^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------^^
+ | |
+ | found `kind` used as a key more than once
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", kind = "dylib", kind = "bar")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", kind = "dylib", kind = "bar")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", kind = "dylib", kind = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", kind = "dylib", kind = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: multiple `modifiers` arguments in a single `#[link]` attribute
- --> $DIR/link-attr-validation-late.rs:11:47
+error[E0538]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:11:1
|
LL | #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
- | ^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^
+ | |
+ | found `modifiers` used as a key more than once
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: multiple `cfg` arguments in a single `#[link]` attribute
- --> $DIR/link-attr-validation-late.rs:12:34
+error[E0538]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:12:1
|
LL | #[link(name = "...", cfg(false), cfg(false))]
- | ^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------^^
+ | |
+ | found `cfg` used as a key more than once
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", cfg(false), cfg(false))]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", cfg(false), cfg(false))]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", cfg(false), cfg(false))]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", cfg(false), cfg(false))]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: multiple `wasm_import_module` arguments in a single `#[link]` attribute
- --> $DIR/link-attr-validation-late.rs:13:36
+error[E0538]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:13:1
|
LL | #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: link name must be of the form `name = "string"`
- --> $DIR/link-attr-validation-late.rs:17:8
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------^^
+ | |
+ | found `wasm_import_module` used as a key more than once
|
-LL | #[link(name)]
- | ^^^^
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error[E0459]: `#[link]` attribute requires a `name = "string"` argument
+error[E0539]: malformed `link` attribute input
--> $DIR/link-attr-validation-late.rs:17:1
|
LL | #[link(name)]
- | ^^^^^^^^^^^^^ missing `name` argument
+ | ^^^^^^^----^^
+ | |
+ | expected this to be of the form `name = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL | #[link(name = "...")]
+ | +++++++
+LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...")]
+ | ++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ = and 1 other candidate
-error: link name must be of the form `name = "string"`
- --> $DIR/link-attr-validation-late.rs:19:8
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:18:1
|
LL | #[link(name())]
- | ^^^^^^
+ | ^^^^^^^------^^
+ | |
+ | expected this to be of the form `name = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name())]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error[E0459]: `#[link]` attribute requires a `name = "string"` argument
+error[E0539]: malformed `link` attribute input
--> $DIR/link-attr-validation-late.rs:19:1
|
-LL | #[link(name())]
- | ^^^^^^^^^^^^^^^ missing `name` argument
-
-error: link kind must be of the form `kind = "string"`
- --> $DIR/link-attr-validation-late.rs:21:22
- |
LL | #[link(name = "...", kind)]
- | ^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^----^^
+ | |
+ | expected this to be of the form `kind = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", kind)]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", kind)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL | #[link(name = "...", kind = "dylib|static|...")]
+ | ++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ = and 1 other candidate
-error: link kind must be of the form `kind = "string"`
- --> $DIR/link-attr-validation-late.rs:22:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:20:1
|
LL | #[link(name = "...", kind())]
- | ^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^------^^
+ | |
+ | expected this to be of the form `kind = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", kind())]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", kind())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", kind())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", kind())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: link modifiers must be of the form `modifiers = "string"`
- --> $DIR/link-attr-validation-late.rs:23:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:21:1
|
LL | #[link(name = "...", modifiers)]
- | ^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^---------^^
+ | |
+ | expected this to be of the form `modifiers = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", modifiers)]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", modifiers)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", modifiers)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", modifiers)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: link modifiers must be of the form `modifiers = "string"`
- --> $DIR/link-attr-validation-late.rs:24:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:22:1
|
LL | #[link(name = "...", modifiers())]
- | ^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^-----------^^
+ | |
+ | expected this to be of the form `modifiers = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", modifiers())]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", modifiers())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", modifiers())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", modifiers())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: link cfg must be of the form `cfg(/* predicate */)`
- --> $DIR/link-attr-validation-late.rs:25:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:23:1
|
LL | #[link(name = "...", cfg)]
- | ^^^
+ | ^^^^^^^^^^^^^^^^^^^^^---^^
+ | |
+ | expected this to be a list
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", cfg)]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", cfg)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", cfg)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", cfg)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: link cfg must be of the form `cfg(/* predicate */)`
- --> $DIR/link-attr-validation-late.rs:26:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:24:1
|
LL | #[link(name = "...", cfg = "literal")]
- | ^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^---------------^^
+ | |
+ | expected this to be a list
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", cfg = "literal")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", cfg = "literal")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", cfg = "literal")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", cfg = "literal")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: link cfg must have a single predicate argument
- --> $DIR/link-attr-validation-late.rs:27:22
+error: `cfg` predicate key must be an identifier
+ --> $DIR/link-attr-validation-late.rs:25:26
|
LL | #[link(name = "...", cfg("literal"))]
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^^^
-error: wasm import module must be of the form `wasm_import_module = "string"`
- --> $DIR/link-attr-validation-late.rs:28:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:26:1
|
LL | #[link(name = "...", wasm_import_module)]
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^------------------^^
+ | |
+ | expected this to be of the form `wasm_import_module = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: wasm import module must be of the form `wasm_import_module = "string"`
- --> $DIR/link-attr-validation-late.rs:29:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:27:1
|
LL | #[link(name = "...", wasm_import_module())]
- | ^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^--------------------^^
+ | |
+ | expected this to be of the form `wasm_import_module = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
- --> $DIR/link-attr-validation-late.rs:33:34
+ --> $DIR/link-attr-validation-late.rs:31:34
|
LL | #[link(name = "...", modifiers = "")]
| ^^
error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
- --> $DIR/link-attr-validation-late.rs:34:34
+ --> $DIR/link-attr-validation-late.rs:32:34
|
LL | #[link(name = "...", modifiers = "no-plus-minus")]
| ^^^^^^^^^^^^^^^
-error: unknown linking modifier `unknown`, expected one of: bundle, verbatim, whole-archive, as-needed
- --> $DIR/link-attr-validation-late.rs:35:34
+error[E0539]: malformed `link` attribute input
+ --> $DIR/link-attr-validation-late.rs:33:1
|
LL | #[link(name = "...", modifiers = "+unknown")]
- | ^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------^^
+ | |
+ | valid arguments are "bundle", "verbatim", "whole-archive" or "as-needed"
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", modifiers = "+unknown")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", modifiers = "+unknown")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", modifiers = "+unknown")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", modifiers = "+unknown")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: multiple `verbatim` modifiers in a single `modifiers` argument
- --> $DIR/link-attr-validation-late.rs:36:34
+ --> $DIR/link-attr-validation-late.rs:34:34
|
LL | #[link(name = "...", modifiers = "+verbatim,+verbatim")]
| ^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 24 previous errors
+error: aborting due to 22 previous errors
-For more information about this error, try `rustc --explain E0459`.
+Some errors have detailed explanations: E0538, E0539, E0565.
+For more information about an error, try `rustc --explain E0538`.
diff --git a/tests/ui/link-native-libs/modifiers-override-4.rs b/tests/ui/link-native-libs/modifiers-override-4.rs
new file mode 100644
index 0000000..cc5b07e
--- /dev/null
+++ b/tests/ui/link-native-libs/modifiers-override-4.rs
@@ -0,0 +1,12 @@
+#[link(name = "foo")]
+#[link(
+//~^ ERROR malformed `link` attribute input
+ name = "bar",
+ kind = "static",
+ modifiers = "+whole-archive,-whole-archive",
+ //~^ ERROR multiple `whole-archive` modifiers in a single `modifiers` argument
+ modifiers = "+bundle"
+)]
+extern "C" {}
+
+fn main() {}
diff --git a/tests/ui/link-native-libs/modifiers-override-4.stderr b/tests/ui/link-native-libs/modifiers-override-4.stderr
new file mode 100644
index 0000000..317e89c
--- /dev/null
+++ b/tests/ui/link-native-libs/modifiers-override-4.stderr
@@ -0,0 +1,67 @@
+error[E0538]: malformed `link` attribute input
+ --> $DIR/modifiers-override-4.rs:2:1
+ |
+LL | / #[link(
+LL | |
+LL | | name = "bar",
+LL | | kind = "static",
+... |
+LL | | modifiers = "+bundle"
+ | | --------------------- found `modifiers` used as a key more than once
+LL | | )]
+ | |__^
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(
+LL -
+LL - name = "bar",
+LL - kind = "static",
+LL - modifiers = "+whole-archive,-whole-archive",
+LL -
+LL - modifiers = "+bundle"
+LL - )]
+LL + #[link(name = "...")]
+ |
+LL - #[link(
+LL -
+LL - name = "bar",
+LL - kind = "static",
+LL - modifiers = "+whole-archive,-whole-archive",
+LL -
+LL - modifiers = "+bundle"
+LL - )]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(
+LL -
+LL - name = "bar",
+LL - kind = "static",
+LL - modifiers = "+whole-archive,-whole-archive",
+LL -
+LL - modifiers = "+bundle"
+LL - )]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(
+LL -
+LL - name = "bar",
+LL - kind = "static",
+LL - modifiers = "+whole-archive,-whole-archive",
+LL -
+LL - modifiers = "+bundle"
+LL - )]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
+
+error: multiple `whole-archive` modifiers in a single `modifiers` argument
+ --> $DIR/modifiers-override-4.rs:6:17
+ |
+LL | modifiers = "+whole-archive,-whole-archive",
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0538`.
diff --git a/tests/ui/link-native-libs/modifiers-override.rs b/tests/ui/link-native-libs/modifiers-override.rs
index cd2d003..a44b7d3 100644
--- a/tests/ui/link-native-libs/modifiers-override.rs
+++ b/tests/ui/link-native-libs/modifiers-override.rs
@@ -4,13 +4,8 @@
#[link(
name = "bar",
kind = "static",
- modifiers = "+whole-archive,-whole-archive",
- //~^ ERROR multiple `whole-archive` modifiers in a single `modifiers` argument
- modifiers = "+bundle"
- //~^ ERROR multiple `modifiers` arguments in a single `#[link]` attribute
)]
extern "C" {}
//~^ ERROR overriding linking modifiers from command line is not supported
-//~| ERROR overriding linking modifiers from command line is not supported
fn main() {}
diff --git a/tests/ui/link-native-libs/modifiers-override.stderr b/tests/ui/link-native-libs/modifiers-override.stderr
index 6442765..3cc99c9 100644
--- a/tests/ui/link-native-libs/modifiers-override.stderr
+++ b/tests/ui/link-native-libs/modifiers-override.stderr
@@ -1,28 +1,8 @@
-error: multiple `modifiers` arguments in a single `#[link]` attribute
- --> $DIR/modifiers-override.rs:9:5
- |
-LL | modifiers = "+bundle"
- | ^^^^^^^^^^^^^^^^^^^^^
-
-error: multiple `whole-archive` modifiers in a single `modifiers` argument
- --> $DIR/modifiers-override.rs:7:17
- |
-LL | modifiers = "+whole-archive,-whole-archive",
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
error: overriding linking modifiers from command line is not supported
- --> $DIR/modifiers-override.rs:12:1
+ --> $DIR/modifiers-override.rs:8:1
|
LL | extern "C" {}
| ^^^^^^^^^^^^^
-error: overriding linking modifiers from command line is not supported
- --> $DIR/modifiers-override.rs:12:1
- |
-LL | extern "C" {}
- | ^^^^^^^^^^^^^
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs
index 50ad8a1..542f34b 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs
@@ -1,7 +1,10 @@
-//@ only-windows
-//@ only-x86
-#[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
-//~^ ERROR import name type must be of the form `import_name_type = "string"`
-extern "C" { }
+//@ add-core-stubs
+//@ compile-flags: --target i686-pc-windows-msvc
+//@ needs-llvm-components: x86
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
-fn main() {}
+#[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+//~^ ERROR malformed
+extern "C" { }
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr
index d2cf7a0..6121762 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr
@@ -1,8 +1,28 @@
-error: import name type must be of the form `import_name_type = "string"`
- --> $DIR/import-name-type-invalid-format.rs:3:42
+error[E0539]: malformed `link` attribute input
+ --> $DIR/import-name-type-invalid-format.rs:8:1
|
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
- | ^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------^^
+ | |
+ | expected this to be of the form `import_name_type = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs
index cf456b9..e241864 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs
@@ -1,8 +1,11 @@
// ignore-tidy-linelength
-//@ only-windows
-//@ only-x86
-#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
-//~^ ERROR multiple `import_name_type` arguments in a single `#[link]` attribute
-extern "C" { }
+//@ add-core-stubs
+//@ compile-flags: --target i686-pc-windows-msvc
+//@ needs-llvm-components: x86
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
-fn main() {}
+#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+//~^ ERROR malformed
+extern "C" { }
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr
index 8e65baf..adfe915 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr
@@ -1,8 +1,28 @@
-error: multiple `import_name_type` arguments in a single `#[link]` attribute
- --> $DIR/import-name-type-multiple.rs:4:74
+error[E0538]: malformed `link` attribute input
+ --> $DIR/import-name-type-multiple.rs:9:1
|
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------^^
+ | |
+ | found `import_name_type` used as a key more than once
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0538`.
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs
index b3859ba..174e868 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs
@@ -1,7 +1,10 @@
-//@ only-windows
-//@ only-x86
-#[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
-//~^ ERROR unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
-extern "C" { }
+//@ add-core-stubs
+//@ compile-flags: --target i686-pc-windows-msvc
+//@ needs-llvm-components: x86
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
-fn main() {}
+#[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+//~^ ERROR malformed
+extern "C" { }
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr
index 4b8b90e..fc24a6b 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr
@@ -1,8 +1,28 @@
-error: unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
- --> $DIR/import-name-type-unknown-value.rs:3:42
+error[E0539]: malformed `link` attribute input
+ --> $DIR/import-name-type-unknown-value.rs:8:1
|
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------^^
+ | |
+ | valid arguments are "decorated", "noprefix" or "undecorated"
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs
index 3ead5cb..ca6aef7 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs
@@ -1,5 +1,10 @@
-//@ only-windows
-//@ only-x86
+//@ add-core-stubs
+//@ compile-flags: --target i686-pc-windows-msvc
+//@ needs-llvm-components: x86
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
#[link(name = "foo", import_name_type = "decorated")]
//~^ ERROR import name type can only be used with link kind `raw-dylib`
extern "C" { }
@@ -11,5 +16,3 @@
// Specifying `import_name_type` before `kind` shouldn't raise an error.
#[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")]
extern "C" { }
-
-fn main() {}
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr
index 75cadc4..075e4ff 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr
@@ -1,11 +1,11 @@
error: import name type can only be used with link kind `raw-dylib`
- --> $DIR/import-name-type-unsupported-link-kind.rs:3:22
+ --> $DIR/import-name-type-unsupported-link-kind.rs:8:22
|
LL | #[link(name = "foo", import_name_type = "decorated")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: import name type can only be used with link kind `raw-dylib`
- --> $DIR/import-name-type-unsupported-link-kind.rs:7:39
+ --> $DIR/import-name-type-unsupported-link-kind.rs:12:39
|
LL | #[link(name = "bar", kind = "static", import_name_type = "decorated")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs
index ab0dcda..5f1410f 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs
@@ -1,7 +1,10 @@
-//@ only-windows
-//@ ignore-x86
+//@ add-core-stubs
+//@ compile-flags: --target aarch64-pc-windows-msvc
+//@ needs-llvm-components: aarch64
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
//~^ ERROR import name type is only supported on x86
extern "C" { }
-
-fn main() {}
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr
index 757f1f7..ad3b9f7 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr
@@ -1,5 +1,5 @@
error: import name type is only supported on x86
- --> $DIR/import-name-type-x86-only.rs:3:42
+ --> $DIR/import-name-type-x86-only.rs:8:42
|
LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
index 301e690..8651a4e 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
@@ -10,7 +10,7 @@ fn test() {}
//~^ ERROR attribute cannot be used on
static mut imported_val: i32 = 123;
-#[link(name = "exporter", kind = "raw-dylib")]
+#[link(name = "exporter")]
extern "C" {
#[link_ordinal(13)]
fn imported_function();
diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs
index d345cbc..c2ccba7 100644
--- a/tests/ui/lint/inert-attr-macro.rs
+++ b/tests/ui/lint/inert-attr-macro.rs
@@ -1,6 +1,5 @@
//@ check-pass
-#![feature(rustc_attrs)]
#![warn(unused)]
macro_rules! foo {
@@ -8,16 +7,18 @@ macro_rules! foo {
}
fn main() {
- #[rustc_dummy] foo!(); //~ WARN unused attribute `rustc_dummy`
+ #[inline] foo!(); //~ WARN `#[inline]` attribute cannot be used on macro calls
+ //~^ WARN previously accepted
// This does nothing, since `#[allow(warnings)]` is itself
// an inert attribute on a macro call
- #[allow(warnings)] #[rustc_dummy] foo!(); //~ WARN unused attribute `allow`
- //~^ WARN unused attribute `rustc_dummy`
+ #[allow(warnings)] #[inline] foo!(); //~ WARN unused attribute `allow`
+ //~^ WARN `#[inline]` attribute cannot be used on macro calls
+ //~| WARN previously accepted
// This does work, since the attribute is on a parent
// of the macro invocation.
- #[allow(warnings)] { #[rustc_dummy] foo!(); }
+ #[allow(warnings)] { #[inline] foo!(); }
// Ok, `cfg` and `cfg_attr` are expanded eagerly and do not warn.
#[cfg(true)] foo!();
diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr
index fc02ee3..9ab6e3d 100644
--- a/tests/ui/lint/inert-attr-macro.stderr
+++ b/tests/ui/lint/inert-attr-macro.stderr
@@ -1,16 +1,13 @@
-warning: unused attribute `rustc_dummy`
- --> $DIR/inert-attr-macro.rs:11:5
+warning: `#[inline]` attribute cannot be used on macro calls
+ --> $DIR/inert-attr-macro.rs:10:5
|
-LL | #[rustc_dummy] foo!();
- | ^^^^^^^^^^^^^^
+LL | #[inline] foo!();
+ | ^^^^^^^^^
|
-note: the built-in attribute `rustc_dummy` will be ignored, since it's applied to the macro invocation `foo`
- --> $DIR/inert-attr-macro.rs:11:20
- |
-LL | #[rustc_dummy] foo!();
- | ^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[inline]` can only be applied to functions
note: the lint level is defined here
- --> $DIR/inert-attr-macro.rs:4:9
+ --> $DIR/inert-attr-macro.rs:3:9
|
LL | #![warn(unused)]
| ^^^^^^
@@ -19,26 +16,23 @@
warning: unused attribute `allow`
--> $DIR/inert-attr-macro.rs:15:5
|
-LL | #[allow(warnings)] #[rustc_dummy] foo!();
+LL | #[allow(warnings)] #[inline] foo!();
| ^^^^^^^^^^^^^^^^^^
|
note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
- --> $DIR/inert-attr-macro.rs:15:39
+ --> $DIR/inert-attr-macro.rs:15:34
|
-LL | #[allow(warnings)] #[rustc_dummy] foo!();
- | ^^^
+LL | #[allow(warnings)] #[inline] foo!();
+ | ^^^
-warning: unused attribute `rustc_dummy`
+warning: `#[inline]` attribute cannot be used on macro calls
--> $DIR/inert-attr-macro.rs:15:24
|
-LL | #[allow(warnings)] #[rustc_dummy] foo!();
- | ^^^^^^^^^^^^^^
+LL | #[allow(warnings)] #[inline] foo!();
+ | ^^^^^^^^^
|
-note: the built-in attribute `rustc_dummy` will be ignored, since it's applied to the macro invocation `foo`
- --> $DIR/inert-attr-macro.rs:15:39
- |
-LL | #[allow(warnings)] #[rustc_dummy] foo!();
- | ^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[inline]` can only be applied to functions
warning: 3 warnings emitted
diff --git a/tests/ui/lint/int_to_ptr-unsized.rs b/tests/ui/lint/int_to_ptr-unsized.rs
new file mode 100644
index 0000000..bbdc247
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr-unsized.rs
@@ -0,0 +1,23 @@
+// Checks for the `integer_to_pointer_transmutes` lint with unsized types
+//
+// Related to https://github.com/rust-lang/rust/issues/145935
+
+//@ check-pass
+
+#![allow(non_camel_case_types)]
+#![allow(unused_unsafe)]
+
+#[cfg(target_pointer_width = "64")]
+type usizemetadata = i128;
+
+#[cfg(target_pointer_width = "32")]
+type usizemetadata = i64;
+
+unsafe fn unsized_type(a: usize) {
+ let _ref = unsafe { std::mem::transmute::<usizemetadata, &'static str>(0xff) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr = unsafe { std::mem::transmute::<usizemetadata, *const [u8]>(0xff) };
+ //~^ WARN transmuting an integer to a pointer
+}
+
+fn main() {}
diff --git a/tests/ui/lint/int_to_ptr-unsized.stderr b/tests/ui/lint/int_to_ptr-unsized.stderr
new file mode 100644
index 0000000..9799af8
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr-unsized.stderr
@@ -0,0 +1,27 @@
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr-unsized.rs:17:25
+ |
+LL | let _ref = unsafe { std::mem::transmute::<usizemetadata, &'static str>(0xff) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+ = note: `#[warn(integer_to_ptr_transmutes)]` on by default
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr-unsized.rs:19:25
+ |
+LL | let _ptr = unsafe { std::mem::transmute::<usizemetadata, *const [u8]>(0xff) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/lint/int_to_ptr.fixed b/tests/ui/lint/int_to_ptr.fixed
new file mode 100644
index 0000000..8f37349
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr.fixed
@@ -0,0 +1,47 @@
+// Checks for the `integer_to_pointer_transmutes` lint
+
+//@ check-pass
+//@ run-rustfix
+
+#![allow(unused_unsafe)]
+#![allow(dead_code)]
+
+unsafe fn should_lint(a: usize) {
+ let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+
+ let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
+ //~^ WARN transmuting an integer to a pointer
+}
+
+const unsafe fn should_lintin_const(a: usize) {
+ let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+
+ let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
+ //~^ WARN transmuting an integer to a pointer
+}
+
+unsafe fn should_not_lint(a: usize) {
+ let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(0usize) }; // linted by other lints
+ let _ptr = unsafe { std::mem::transmute::<usize, *const ()>(a) }; // inner type is a ZST
+ let _ptr = unsafe { std::mem::transmute::<usize, fn()>(a) }; // omit fn-ptr for now
+}
+
+fn main() {}
diff --git a/tests/ui/lint/int_to_ptr.rs b/tests/ui/lint/int_to_ptr.rs
new file mode 100644
index 0000000..7f60da4
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr.rs
@@ -0,0 +1,47 @@
+// Checks for the `integer_to_pointer_transmutes` lint
+
+//@ check-pass
+//@ run-rustfix
+
+#![allow(unused_unsafe)]
+#![allow(dead_code)]
+
+unsafe fn should_lint(a: usize) {
+ let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+
+ let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+ //~^ WARN transmuting an integer to a pointer
+}
+
+const unsafe fn should_lintin_const(a: usize) {
+ let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+ //~^ WARN transmuting an integer to a pointer
+
+ let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+ //~^ WARN transmuting an integer to a pointer
+ let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+ //~^ WARN transmuting an integer to a pointer
+}
+
+unsafe fn should_not_lint(a: usize) {
+ let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(0usize) }; // linted by other lints
+ let _ptr = unsafe { std::mem::transmute::<usize, *const ()>(a) }; // inner type is a ZST
+ let _ptr = unsafe { std::mem::transmute::<usize, fn()>(a) }; // omit fn-ptr for now
+}
+
+fn main() {}
diff --git a/tests/ui/lint/int_to_ptr.stderr b/tests/ui/lint/int_to_ptr.stderr
new file mode 100644
index 0000000..4035bda
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr.stderr
@@ -0,0 +1,207 @@
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:10:36
+ |
+LL | let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+ = note: `#[warn(integer_to_ptr_transmutes)]` on by default
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+ |
+LL - let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+LL + let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:12:34
+ |
+LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance
+ |
+LL - let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+LL + let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:14:38
+ |
+LL | let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+ |
+LL - let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+LL + let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:16:42
+ |
+LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance
+ |
+LL - let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+LL + let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:19:25
+ |
+LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+ |
+LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:21:25
+ |
+LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+ |
+LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:26:36
+ |
+LL | let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+ |
+LL - let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+LL + let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:28:34
+ |
+LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance
+ |
+LL - let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+LL + let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:30:38
+ |
+LL | let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+ |
+LL - let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+LL + let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:32:42
+ |
+LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance
+ |
+LL - let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+LL + let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:35:25
+ |
+LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+ |
+LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
+ |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+ --> $DIR/int_to_ptr.rs:37:25
+ |
+LL | let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+ = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+ = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+ = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+ = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+ |
+LL - let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
+ |
+
+warning: 12 warnings emitted
+
diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr
index c678562..ae5f6b3 100644
--- a/tests/ui/lint/linker-warning.stderr
+++ b/tests/ui/lint/linker-warning.stderr
@@ -1,4 +1,4 @@
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+warning: crate-level attribute should be an inner attribute
--> $DIR/linker-warning.rs:7:1
|
LL | #[allow(linker_messages)]
@@ -9,6 +9,10 @@
|
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
+help: add a `!`
+ |
+LL | #![allow(linker_messages)]
+ | +
warning: unused attribute
--> $DIR/linker-warning.rs:4:1
diff --git a/tests/ui/lint/lint-misplaced-attr.stderr b/tests/ui/lint/lint-misplaced-attr.stderr
index abaf462..bcfda17 100644
--- a/tests/ui/lint/lint-misplaced-attr.stderr
+++ b/tests/ui/lint/lint-misplaced-attr.stderr
@@ -10,11 +10,16 @@
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+error: crate-level attribute should be an inner attribute
--> $DIR/lint-misplaced-attr.rs:10:1
|
LL | #[crate_type = "bin"] fn main() {}
| ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a `!`
+ |
+LL | #![crate_type = "bin"] fn main() {}
+ | +
error: aborting due to 2 previous errors
diff --git a/tests/ui/lint/unused/concat-in-crate-deprecated-issue-137687.rs b/tests/ui/lint/unused/concat-in-crate-deprecated-issue-137687.rs
new file mode 100644
index 0000000..22dd55f
--- /dev/null
+++ b/tests/ui/lint/unused/concat-in-crate-deprecated-issue-137687.rs
@@ -0,0 +1,6 @@
+//@ check-pass
+#[deprecated = concat !()]
+macro_rules! a {
+ () => {};
+}
+fn main() {}
diff --git a/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs
new file mode 100644
index 0000000..c507b65
--- /dev/null
+++ b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs
@@ -0,0 +1,9 @@
+#![deny(unused)]
+
+#[crate_name = concat !()]
+//~^ ERROR crate-level attribute should be an inner attribute
+macro_rules! a {
+ //~^ ERROR unused macro definition
+ () => {};
+}
+fn main() {}
diff --git a/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr
new file mode 100644
index 0000000..b06e65a
--- /dev/null
+++ b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr
@@ -0,0 +1,31 @@
+error: unused macro definition: `a`
+ --> $DIR/concat-in-crate-name-issue-137687.rs:5:14
+ |
+LL | macro_rules! a {
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/concat-in-crate-name-issue-137687.rs:1:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_macros)]` implied by `#[deny(unused)]`
+
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+ --> $DIR/concat-in-crate-name-issue-137687.rs:3:1
+ |
+LL | #[crate_name = concat !()]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: This attribute does not have an `!`, which means it is applied to this macro def
+ --> $DIR/concat-in-crate-name-issue-137687.rs:5:1
+ |
+LL | / macro_rules! a {
+LL | |
+LL | | () => {};
+LL | | }
+ | |_^
+ = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs
index cfa6c2b..a334c49 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.rs
+++ b/tests/ui/lint/unused/unused-attr-duplicate.rs
@@ -11,8 +11,12 @@
// - no_main: extra setup
#![deny(unused_attributes)]
#![crate_name = "unused_attr_duplicate"]
-#![crate_name = "unused_attr_duplicate2"] //~ ERROR unused attribute
-//~^ WARN this was previously accepted
+#![crate_name = "unused_attr_duplicate2"]
+//~^ ERROR unused attribute
+//~| WARN this was previously accepted
+//~| ERROR unused attribute
+//~| WARN this was previously accepted
+// FIXME(jdonszelmann) this error is given twice now. I'll look at this in the future
#![recursion_limit = "128"]
#![recursion_limit = "256"] //~ ERROR unused attribute
//~^ WARN this was previously accepted
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr
index 6c44e88..203211d 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.stderr
+++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr
@@ -1,14 +1,15 @@
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:33:1
+ --> $DIR/unused-attr-duplicate.rs:14:1
|
-LL | #[no_link]
- | ^^^^^^^^^^ help: remove this attribute
+LL | #![crate_name = "unused_attr_duplicate2"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:32:1
+ --> $DIR/unused-attr-duplicate.rs:13:1
|
-LL | #[no_link]
- | ^^^^^^^^^^
+LL | #![crate_name = "unused_attr_duplicate"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
note: the lint level is defined here
--> $DIR/unused-attr-duplicate.rs:12:9
|
@@ -16,6 +17,280 @@
| ^^^^^^^^^^^^^^^^^
error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:37:1
+ |
+LL | #[no_link]
+ | ^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:36:1
+ |
+LL | #[no_link]
+ | ^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:21:1
+ |
+LL | #![recursion_limit = "256"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:20:1
+ |
+LL | #![recursion_limit = "128"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:24:1
+ |
+LL | #![type_length_limit = "1"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:23:1
+ |
+LL | #![type_length_limit = "1048576"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:27:1
+ |
+LL | #![no_std]
+ | ^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:26:1
+ |
+LL | #![no_std]
+ | ^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:31:1
+ |
+LL | #![windows_subsystem = "windows"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:30:1
+ |
+LL | #![windows_subsystem = "console"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:34:1
+ |
+LL | #![no_builtins]
+ | ^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:33:1
+ |
+LL | #![no_builtins]
+ | ^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:44:5
+ |
+LL | #[macro_export]
+ | ^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:43:5
+ |
+LL | #[macro_export]
+ | ^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:41:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:40:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:51:1
+ |
+LL | #[path = "bar.rs"]
+ | ^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:50:1
+ |
+LL | #[path = "auxiliary/lint_unused_extern_crate.rs"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:57:1
+ |
+LL | #[ignore = "some text"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:56:1
+ |
+LL | #[ignore]
+ | ^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:59:1
+ |
+LL | #[should_panic(expected = "values don't match")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:58:1
+ |
+LL | #[should_panic]
+ | ^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:64:1
+ |
+LL | #[must_use = "some message"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:63:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:70:1
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:69:1
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:76:1
+ |
+LL | #[automatically_derived]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:75:1
+ |
+LL | #[automatically_derived]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:80:1
+ |
+LL | #[inline(never)]
+ | ^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:79:1
+ |
+LL | #[inline(always)]
+ | ^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:83:1
+ |
+LL | #[cold]
+ | ^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:82:1
+ |
+LL | #[cold]
+ | ^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:85:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:84:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:92:5
+ |
+LL | #[link_name = "this_does_not_exist"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:94:5
+ |
+LL | #[link_name = "rust_dbg_extern_identity_u32"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:98:1
+ |
+LL | #[export_name = "exported_symbol_name"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:100:1
+ |
+LL | #[export_name = "exported_symbol_name2"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:104:1
+ |
+LL | #[no_mangle]
+ | ^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:103:1
+ |
+LL | #[no_mangle]
+ | ^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:108:1
+ |
+LL | #[used]
+ | ^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:107:1
+ |
+LL | #[used]
+ | ^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:111:1
+ |
+LL | #[link_section = ".text"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:114:1
+ |
+LL | #[link_section = ".bss"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
--> $DIR/unused-attr-duplicate.rs:14:1
|
LL | #![crate_name = "unused_attr_duplicate2"]
@@ -27,280 +302,19 @@
LL | #![crate_name = "unused_attr_duplicate"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:17:1
- |
-LL | #![recursion_limit = "256"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:16:1
- |
-LL | #![recursion_limit = "128"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:20:1
- |
-LL | #![type_length_limit = "1"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:19:1
- |
-LL | #![type_length_limit = "1048576"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:23:1
- |
-LL | #![no_std]
- | ^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:22:1
- |
-LL | #![no_std]
- | ^^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:27:1
- |
-LL | #![windows_subsystem = "windows"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:26:1
- |
-LL | #![windows_subsystem = "console"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:30:1
- |
-LL | #![no_builtins]
- | ^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:29:1
|
-LL | #![no_builtins]
- | ^^^^^^^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:40:5
- |
-LL | #[macro_export]
- | ^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:39:5
- |
-LL | #[macro_export]
- | ^^^^^^^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:37:1
- |
-LL | #[macro_use]
- | ^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:36:1
- |
-LL | #[macro_use]
- | ^^^^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:47:1
- |
-LL | #[path = "bar.rs"]
- | ^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:46:1
- |
-LL | #[path = "auxiliary/lint_unused_extern_crate.rs"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:53:1
- |
-LL | #[ignore = "some text"]
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:52:1
- |
-LL | #[ignore]
- | ^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:55:1
- |
-LL | #[should_panic(expected = "values don't match")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:54:1
- |
-LL | #[should_panic]
- | ^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:60:1
- |
-LL | #[must_use = "some message"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:59:1
- |
-LL | #[must_use]
- | ^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:66:1
- |
-LL | #[non_exhaustive]
- | ^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:65:1
- |
-LL | #[non_exhaustive]
- | ^^^^^^^^^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:72:1
- |
-LL | #[automatically_derived]
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:71:1
- |
-LL | #[automatically_derived]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:76:1
- |
-LL | #[inline(never)]
- | ^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:75:1
- |
-LL | #[inline(always)]
- | ^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:79:1
- |
-LL | #[cold]
- | ^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:78:1
- |
-LL | #[cold]
- | ^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:81:1
- |
-LL | #[track_caller]
- | ^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:80:1
- |
-LL | #[track_caller]
- | ^^^^^^^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:88:5
- |
-LL | #[link_name = "this_does_not_exist"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:90:5
- |
-LL | #[link_name = "rust_dbg_extern_identity_u32"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:94:1
- |
-LL | #[export_name = "exported_symbol_name"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:96:1
- |
-LL | #[export_name = "exported_symbol_name2"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:100:1
- |
-LL | #[no_mangle]
- | ^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:99:1
- |
-LL | #[no_mangle]
- | ^^^^^^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:104:1
- |
-LL | #[used]
- | ^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:103:1
- |
-LL | #[used]
- | ^^^^^^^
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:107:1
- |
-LL | #[link_section = ".text"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:110:1
- |
-LL | #[link_section = ".bss"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error: unused attribute
- --> $DIR/unused-attr-duplicate.rs:25:1
- |
LL | #![no_implicit_prelude]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
- --> $DIR/unused-attr-duplicate.rs:24:1
+ --> $DIR/unused-attr-duplicate.rs:28:1
|
LL | #![no_implicit_prelude]
| ^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 24 previous errors
+error: aborting due to 25 previous errors
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
index 9d61120..af64be8 100644
--- a/tests/ui/lint/unused/unused-attr-macro-rules.stderr
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
@@ -1,4 +1,4 @@
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+error: crate-level attribute should be an inner attribute
--> $DIR/unused-attr-macro-rules.rs:11:1
|
LL | #[recursion_limit="1"]
@@ -9,6 +9,10 @@
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
+help: add a `!`
+ |
+LL | #![recursion_limit="1"]
+ | +
error: `#[macro_use]` attribute cannot be used on macro defs
--> $DIR/unused-attr-macro-rules.rs:7:1
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.fixed b/tests/ui/lint/unused/unused_attributes-must_use.fixed
index 2e800cb..fa596da 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.fixed
+++ b/tests/ui/lint/unused/unused_attributes-must_use.fixed
@@ -65,7 +65,8 @@
fn foreign_foo() -> i64;
}
- //~ ERROR unused attribute
+//~^ ERROR `#[must_use]` attribute cannot be used on macro calls
+//~| WARN this was previously accepted by the compiler but is being phased out
global_asm!("");
//~ ERROR attribute cannot be used on
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.rs b/tests/ui/lint/unused/unused_attributes-must_use.rs
index c41c6c1..3e72dd1 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.rs
+++ b/tests/ui/lint/unused/unused_attributes-must_use.rs
@@ -65,7 +65,9 @@ fn foo() -> i64 {
fn foreign_foo() -> i64;
}
-#[must_use] //~ ERROR unused attribute
+#[must_use]
+//~^ ERROR `#[must_use]` attribute cannot be used on macro calls
+//~| WARN this was previously accepted by the compiler but is being phased out
global_asm!("");
#[must_use] //~ ERROR attribute cannot be used on
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr
index 03baea3..001ec52 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.stderr
+++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr
@@ -1,14 +1,11 @@
-error: unused attribute `must_use`
+error: `#[must_use]` attribute cannot be used on macro calls
--> $DIR/unused_attributes-must_use.rs:68:1
|
LL | #[must_use]
| ^^^^^^^^^^^
|
-note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm`
- --> $DIR/unused_attributes-must_use.rs:69:1
- |
-LL | global_asm!("");
- | ^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = help: `#[must_use]` can be applied to functions, data types, unions, and traits
note: the lint level is defined here
--> $DIR/unused_attributes-must_use.rs:4:9
|
@@ -88,7 +85,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on type aliases
- --> $DIR/unused_attributes-must_use.rs:71:1
+ --> $DIR/unused_attributes-must_use.rs:73:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -97,7 +94,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on function params
- --> $DIR/unused_attributes-must_use.rs:75:8
+ --> $DIR/unused_attributes-must_use.rs:77:8
|
LL | fn qux<#[must_use] T>(_: T) {}
| ^^^^^^^^^^^
@@ -106,7 +103,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on associated consts
- --> $DIR/unused_attributes-must_use.rs:80:5
+ --> $DIR/unused_attributes-must_use.rs:82:5
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -115,7 +112,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on associated types
- --> $DIR/unused_attributes-must_use.rs:83:5
+ --> $DIR/unused_attributes-must_use.rs:85:5
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -124,7 +121,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on trait impl blocks
- --> $DIR/unused_attributes-must_use.rs:93:1
+ --> $DIR/unused_attributes-must_use.rs:95:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -133,7 +130,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on trait methods in impl blocks
- --> $DIR/unused_attributes-must_use.rs:98:5
+ --> $DIR/unused_attributes-must_use.rs:100:5
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -142,7 +139,7 @@
= help: `#[must_use]` can be applied to data types, functions, unions, required trait methods, provided trait methods, inherent methods, foreign functions, and traits
error: `#[must_use]` attribute cannot be used on trait aliases
- --> $DIR/unused_attributes-must_use.rs:105:1
+ --> $DIR/unused_attributes-must_use.rs:107:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -151,7 +148,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on macro defs
- --> $DIR/unused_attributes-must_use.rs:109:1
+ --> $DIR/unused_attributes-must_use.rs:111:1
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -160,7 +157,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on statements
- --> $DIR/unused_attributes-must_use.rs:118:5
+ --> $DIR/unused_attributes-must_use.rs:120:5
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -169,7 +166,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on closures
- --> $DIR/unused_attributes-must_use.rs:123:13
+ --> $DIR/unused_attributes-must_use.rs:125:13
|
LL | let x = #[must_use]
| ^^^^^^^^^^^
@@ -178,7 +175,7 @@
= help: `#[must_use]` can be applied to methods, data types, functions, unions, foreign functions, and traits
error: `#[must_use]` attribute cannot be used on match arms
- --> $DIR/unused_attributes-must_use.rs:146:9
+ --> $DIR/unused_attributes-must_use.rs:148:9
|
LL | #[must_use]
| ^^^^^^^^^^^
@@ -187,7 +184,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on struct fields
- --> $DIR/unused_attributes-must_use.rs:155:28
+ --> $DIR/unused_attributes-must_use.rs:157:28
|
LL | let s = PatternField { #[must_use] foo: 123 };
| ^^^^^^^^^^^
@@ -196,7 +193,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on pattern fields
- --> $DIR/unused_attributes-must_use.rs:157:24
+ --> $DIR/unused_attributes-must_use.rs:159:24
|
LL | let PatternField { #[must_use] foo } = s;
| ^^^^^^^^^^^
@@ -205,7 +202,7 @@
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: unused `X` that must be used
- --> $DIR/unused_attributes-must_use.rs:128:5
+ --> $DIR/unused_attributes-must_use.rs:130:5
|
LL | X;
| ^
@@ -221,7 +218,7 @@
| +++++++
error: unused `Y` that must be used
- --> $DIR/unused_attributes-must_use.rs:129:5
+ --> $DIR/unused_attributes-must_use.rs:131:5
|
LL | Y::Z;
| ^^^^
@@ -232,7 +229,7 @@
| +++++++
error: unused `U` that must be used
- --> $DIR/unused_attributes-must_use.rs:130:5
+ --> $DIR/unused_attributes-must_use.rs:132:5
|
LL | U { unit: () };
| ^^^^^^^^^^^^^^
@@ -243,7 +240,7 @@
| +++++++
error: unused return value of `U::method` that must be used
- --> $DIR/unused_attributes-must_use.rs:131:5
+ --> $DIR/unused_attributes-must_use.rs:133:5
|
LL | U::method();
| ^^^^^^^^^^^
@@ -254,7 +251,7 @@
| +++++++
error: unused return value of `foo` that must be used
- --> $DIR/unused_attributes-must_use.rs:132:5
+ --> $DIR/unused_attributes-must_use.rs:134:5
|
LL | foo();
| ^^^^^
@@ -265,7 +262,7 @@
| +++++++
error: unused return value of `foreign_foo` that must be used
- --> $DIR/unused_attributes-must_use.rs:135:9
+ --> $DIR/unused_attributes-must_use.rs:137:9
|
LL | foreign_foo();
| ^^^^^^^^^^^^^
@@ -276,7 +273,7 @@
| +++++++
error: unused return value of `Use::get_four` that must be used
- --> $DIR/unused_attributes-must_use.rs:143:5
+ --> $DIR/unused_attributes-must_use.rs:145:5
|
LL | ().get_four();
| ^^^^^^^^^^^^^
diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
index c14ab9e..8a5c243 100644
--- a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
+++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
@@ -3,10 +3,10 @@
|
LL | use std::string::String;
| ^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `String` is already defined here
- |
note: the lint level is defined here
--> $DIR/use-redundant-issue-71450.rs:3:9
|
diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr
index 48d5c27..71bc7d3 100644
--- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr
+++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr
@@ -3,10 +3,10 @@
|
LL | use std::option::Option::Some;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `Some` is already defined here
- |
note: the lint level is defined here
--> $DIR/use-redundant-prelude-rust-2015.rs:3:9
|
@@ -18,6 +18,7 @@
|
LL | use std::option::Option::None;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `None` is already defined here
@@ -27,6 +28,7 @@
|
LL | use std::result::Result::Ok;
| ^^^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `Ok` is already defined here
@@ -36,6 +38,7 @@
|
LL | use std::result::Result::Err;
| ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `Err` is already defined here
diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr
index 526771c..f9b7af2 100644
--- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr
+++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr
@@ -3,10 +3,10 @@
|
LL | use std::convert::TryFrom;
| ^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `TryFrom` is already defined here
- |
note: the lint level is defined here
--> $DIR/use-redundant-prelude-rust-2021.rs:3:9
|
@@ -18,6 +18,7 @@
|
LL | use std::convert::TryInto;
| ^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `TryInto` is already defined here
diff --git a/tests/ui/issues/issue-5741.rs b/tests/ui/loops/unreachable-while-loop-5741.rs
similarity index 69%
rename from tests/ui/issues/issue-5741.rs
rename to tests/ui/loops/unreachable-while-loop-5741.rs
index af4702e..bc69df0 100644
--- a/tests/ui/issues/issue-5741.rs
+++ b/tests/ui/loops/unreachable-while-loop-5741.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5741
//@ run-pass
#![allow(while_true)]
#![allow(unreachable_code)]
diff --git a/tests/ui/macros/format-foreign-dollar-without-spec.rs b/tests/ui/macros/format-foreign-dollar-without-spec.rs
new file mode 100644
index 0000000..c57c138
--- /dev/null
+++ b/tests/ui/macros/format-foreign-dollar-without-spec.rs
@@ -0,0 +1,5 @@
+// https://github.com/rust-lang/rust/issues/137580
+fn main() {
+ println!("%65536$", 1);
+ //~^ ERROR never used
+}
diff --git a/tests/ui/macros/format-foreign-dollar-without-spec.stderr b/tests/ui/macros/format-foreign-dollar-without-spec.stderr
new file mode 100644
index 0000000..d5a07c5
--- /dev/null
+++ b/tests/ui/macros/format-foreign-dollar-without-spec.stderr
@@ -0,0 +1,16 @@
+error: argument never used
+ --> $DIR/format-foreign-dollar-without-spec.rs:3:25
+ |
+LL | println!("%65536$", 1);
+ | ^ argument never used
+ |
+note: format specifiers use curly braces, and the conversion specifier `
+ ` is unknown or unsupported
+ --> $DIR/format-foreign-dollar-without-spec.rs:3:15
+ |
+LL | println!("%65536$", 1);
+ | ^^^^^^^^
+ = note: printf formatting is not supported; see the documentation for `std::fmt`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/macro-name-typo.stderr b/tests/ui/macros/macro-name-typo.stderr
index 9059b10..1cc7ea6 100644
--- a/tests/ui/macros/macro-name-typo.stderr
+++ b/tests/ui/macros/macro-name-typo.stderr
@@ -3,6 +3,7 @@
|
LL | printlx!("oh noes!");
| ^^^^^^^ help: a macro with a similar name exists: `println`
+ |
--> $SRC_DIR/std/src/macros.rs:LL:COL
|
= note: similarly named macro `println` defined here
diff --git a/tests/ui/macros/macro-path-prelude-fail-3.stderr b/tests/ui/macros/macro-path-prelude-fail-3.stderr
index 485d7b7..3d0a074 100644
--- a/tests/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/tests/ui/macros/macro-path-prelude-fail-3.stderr
@@ -3,6 +3,7 @@
|
LL | inline!();
| ^^^^^^ help: a macro with a similar name exists: `line`
+ |
--> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
= note: similarly named macro `line` defined here
diff --git a/tests/ui/issues/issue-5554.rs b/tests/ui/macros/macro-variable-declaration-with-bounds-5554.rs
similarity index 90%
rename from tests/ui/issues/issue-5554.rs
rename to tests/ui/macros/macro-variable-declaration-with-bounds-5554.rs
index 7d219a0..8ccf8e8 100644
--- a/tests/ui/issues/issue-5554.rs
+++ b/tests/ui/macros/macro-variable-declaration-with-bounds-5554.rs
@@ -1,7 +1,7 @@
+// https://github.com/rust-lang/rust/issues/5554
//@ run-pass
#![allow(dead_code)]
-
pub struct X<T> {
a: T,
}
diff --git a/tests/ui/issues/issue-5718.rs b/tests/ui/macros/macro-variable-unused-reporting-5718.rs
similarity index 87%
rename from tests/ui/issues/issue-5718.rs
rename to tests/ui/macros/macro-variable-unused-reporting-5718.rs
index 234fb2e..55da925 100644
--- a/tests/ui/issues/issue-5718.rs
+++ b/tests/ui/macros/macro-variable-unused-reporting-5718.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5718
//@ run-pass
struct Element;
diff --git a/tests/ui/macros/missing-writer-issue-139830.stderr b/tests/ui/macros/missing-writer-issue-139830.stderr
index 34dd613..0a1c6f6 100644
--- a/tests/ui/macros/missing-writer-issue-139830.stderr
+++ b/tests/ui/macros/missing-writer-issue-139830.stderr
@@ -3,10 +3,10 @@
|
LL | let _ = write!(buf, "foo");
| ^^^
+ |
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
= note: the method is available for `String` here
- |
note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
--> $DIR/missing-writer-issue-139830.rs:7:20
|
diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs
index 99f0fc9..407920c 100644
--- a/tests/ui/malformed/malformed-regressions.rs
+++ b/tests/ui/malformed/malformed-regressions.rs
@@ -4,9 +4,7 @@
//~^ WARN this was previously accepted
#[inline = ""] //~ ERROR valid forms for the attribute are
//~^ WARN this was previously accepted
-#[link] //~ ERROR valid forms for the attribute are
-//~^ WARN this was previously accepted
-#[link = ""] //~ ERROR valid forms for the attribute are
-//~^ WARN this was previously accepted
+#[link] //~ ERROR malformed
+#[link = ""] //~ ERROR malformed
fn main() {}
diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr
index cab347a..850bcb6c 100644
--- a/tests/ui/malformed/malformed-regressions.stderr
+++ b/tests/ui/malformed/malformed-regressions.stderr
@@ -9,25 +9,47 @@
= note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html>
= note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
+error[E0539]: malformed `link` attribute input
--> $DIR/malformed-regressions.rs:7:1
|
LL | #[link]
- | ^^^^^^^
+ | ^^^^^^^ expected this to be a list
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL | #[link(name = "...")]
+ | ++++++++++++++
+LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...")]
+ | +++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ = and 1 other candidate
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
- --> $DIR/malformed-regressions.rs:9:1
+error[E0539]: malformed `link` attribute input
+ --> $DIR/malformed-regressions.rs:8:1
|
LL | #[link = ""]
- | ^^^^^^^^^^^^
+ | ^^^^^^^^^^^^ expected this to be a list
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link = ""]
+LL + #[link(name = "...")]
+ |
+LL - #[link = ""]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link = ""]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link = ""]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
--> $DIR/malformed-regressions.rs:3:1
@@ -49,6 +71,7 @@
error: aborting due to 5 previous errors
+For more information about this error, try `rustc --explain E0539`.
Future incompatibility report: Future breakage diagnostic:
error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]`
--> $DIR/malformed-regressions.rs:1:1
@@ -62,30 +85,6 @@
= note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
- --> $DIR/malformed-regressions.rs:7:1
- |
-LL | #[link]
- | ^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
- = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
- = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
- --> $DIR/malformed-regressions.rs:9:1
- |
-LL | #[link = ""]
- | ^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
- = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
- = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
--> $DIR/malformed-regressions.rs:3:1
|
diff --git a/tests/ui/issues/issue-5358-1.rs b/tests/ui/match/mismatched-types-in-match-5358.rs
similarity index 60%
rename from tests/ui/issues/issue-5358-1.rs
rename to tests/ui/match/mismatched-types-in-match-5358.rs
index 281f219..d096bf3 100644
--- a/tests/ui/issues/issue-5358-1.rs
+++ b/tests/ui/match/mismatched-types-in-match-5358.rs
@@ -1,8 +1,13 @@
-enum Either<T, U> { Left(T), Right(U) }
+// https://github.com/rust-lang/rust/issues/5358
+enum Either<T, U> {
+ Left(T),
+ Right(U),
+}
struct S(Either<usize, usize>);
fn main() {
- match S(Either::Left(5)) { //~ NOTE this expression has type `S`
+ match S(Either::Left(5)) {
+ //~^ NOTE this expression has type `S`
Either::Right(_) => {}
//~^ ERROR mismatched types
//~| NOTE expected `S`, found `Either<_, _>`
diff --git a/tests/ui/issues/issue-5358-1.stderr b/tests/ui/match/mismatched-types-in-match-5358.stderr
similarity index 92%
rename from tests/ui/issues/issue-5358-1.stderr
rename to tests/ui/match/mismatched-types-in-match-5358.stderr
index e68db86..6a6cf3e 100644
--- a/tests/ui/issues/issue-5358-1.stderr
+++ b/tests/ui/match/mismatched-types-in-match-5358.stderr
@@ -1,8 +1,9 @@
error[E0308]: mismatched types
- --> $DIR/issue-5358-1.rs:6:9
+ --> $DIR/mismatched-types-in-match-5358.rs:11:9
|
LL | match S(Either::Left(5)) {
| ------------------ this expression has type `S`
+LL |
LL | Either::Right(_) => {}
| ^^^^^^^^^^^^^^^^ expected `S`, found `Either<_, _>`
|
diff --git a/tests/ui/match/mismatched-types-in-match-pattern-7867.rs b/tests/ui/match/mismatched-types-in-match-7867.rs
similarity index 100%
rename from tests/ui/match/mismatched-types-in-match-pattern-7867.rs
rename to tests/ui/match/mismatched-types-in-match-7867.rs
diff --git a/tests/ui/match/mismatched-types-in-match-pattern-7867.stderr b/tests/ui/match/mismatched-types-in-match-7867.stderr
similarity index 88%
rename from tests/ui/match/mismatched-types-in-match-pattern-7867.stderr
rename to tests/ui/match/mismatched-types-in-match-7867.stderr
index 8997f36..e41a61e 100644
--- a/tests/ui/match/mismatched-types-in-match-pattern-7867.stderr
+++ b/tests/ui/match/mismatched-types-in-match-7867.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/mismatched-types-in-match-pattern-7867.rs:10:9
+ --> $DIR/mismatched-types-in-match-7867.rs:10:9
|
LL | enum A { B, C }
| - unit variant defined here
diff --git a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr
index a87c47a..cc8bd18 100644
--- a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr
+++ b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -14,6 +14,7 @@
|
LL | 0.clone::<'a>();
| ^^
+ |
--> $SRC_DIR/core/src/clone.rs:LL:COL
|
= note: the late bound lifetime parameter is introduced here
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.rs b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.rs
new file mode 100644
index 0000000..8363ec1
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.rs
@@ -0,0 +1,17 @@
+// Regression test for <github.com/rust-lang/rust/issues/145185>.
+
+mod module {
+ pub trait Trait {
+ fn method(&self);
+ }
+}
+
+// Note that we do not import Trait
+use std::ops::Deref;
+
+fn foo(x: impl Deref<Target: module::Trait>) {
+ x.method();
+ //~^ ERROR no method named `method` found for type parameter
+}
+
+fn main() {}
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr
new file mode 100644
index 0000000..433cab9
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `method` found for type parameter `impl Deref<Target : module::Trait>` in the current scope
+ --> $DIR/rigid-alias-bound-is-not-inherent-2.rs:13:7
+ |
+LL | fn foo(x: impl Deref<Target: module::Trait>) {
+ | --------------------------------- method `method` not found for this type parameter
+LL | x.method();
+ | ^^^^^^ method not found in `impl Deref<Target : module::Trait>`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: trait `Trait` which provides `method` is implemented but not in scope; perhaps you want to import it
+ |
+LL + use module::Trait;
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.rs b/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.rs
new file mode 100644
index 0000000..bb316ee
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.rs
@@ -0,0 +1,26 @@
+use std::ops::Deref;
+
+trait Trait1 {
+ fn call_me(&self) {}
+}
+
+impl<T> Trait1 for T {}
+
+trait Trait2 {
+ fn call_me(&self) {}
+}
+
+impl<T> Trait2 for T {}
+
+pub fn foo<T, U>(x: T)
+where
+ T: Deref<Target = U>,
+ U: Trait1,
+{
+ // This should be ambiguous. The fact that there's an inherent where-bound
+ // candidate for `U` should not impact the candidates for `T`
+ x.call_me();
+ //~^ ERROR multiple applicable items in scope
+}
+
+fn main() {}
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.stderr
new file mode 100644
index 0000000..466ad4d
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/rigid-alias-bound-is-not-inherent-3.rs:22:7
+ |
+LL | x.call_me();
+ | ^^^^^^^ multiple `call_me` found
+ |
+note: candidate #1 is defined in an impl of the trait `Trait1` for the type `T`
+ --> $DIR/rigid-alias-bound-is-not-inherent-3.rs:4:5
+ |
+LL | fn call_me(&self) {}
+ | ^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T`
+ --> $DIR/rigid-alias-bound-is-not-inherent-3.rs:10:5
+ |
+LL | fn call_me(&self) {}
+ | ^^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+ |
+LL - x.call_me();
+LL + Trait1::call_me(&x);
+ |
+help: disambiguate the method for candidate #2
+ |
+LL - x.call_me();
+LL + Trait2::call_me(&x);
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr
new file mode 100644
index 0000000..4652bf5
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/rigid-alias-bound-is-not-inherent.rs:42:7
+ |
+LL | x.method();
+ | ^^^^^^ multiple `method` found
+ |
+note: candidate #1 is defined in the trait `Trait1`
+ --> $DIR/rigid-alias-bound-is-not-inherent.rs:21:5
+ |
+LL | fn method(&self) {
+ | ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T`
+ --> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
+ |
+LL | fn method(&self) {
+ | ^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+ |
+LL - x.method();
+LL + Trait1::method(&x);
+ |
+help: disambiguate the method for candidate #2
+ |
+LL - x.method();
+LL + Trait2::method(&x);
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr
new file mode 100644
index 0000000..afacb3a
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/rigid-alias-bound-is-not-inherent.rs:42:7
+ |
+LL | x.method();
+ | ^^^^^^ multiple `method` found
+ |
+note: candidate #1 is defined in the trait `Trait1`
+ --> $DIR/rigid-alias-bound-is-not-inherent.rs:21:5
+ |
+LL | fn method(&self) {
+ | ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `Trait2`
+ --> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
+ |
+LL | fn method(&self) {
+ | ^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+ |
+LL - x.method();
+LL + Trait1::method(&x);
+ |
+help: disambiguate the method for candidate #2
+ |
+LL - x.method();
+LL + Trait2::method(&x);
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs b/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs
new file mode 100644
index 0000000..3dd63df
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs
@@ -0,0 +1,46 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// See the code below.
+//
+// We were using `DeepRejectCtxt` to ensure that `assemble_inherent_candidates_from_param`
+// did not rely on the param-env being eagerly normalized. Since aliases unify with all
+// types, this meant that a rigid param-env candidate like `<T as Deref>::Target: Trait1`
+// would be registered as a "WhereClauseCandidate", which is treated as inherent. Since
+// we evaluate these candidates for all self types in the deref chain, this candidate
+// would be satisfied for `<T as Deref>::Target`, meaning that it would be preferred over
+// an "extension" candidate like `<T as Deref>::Target: Trait2` even though it holds.
+// This is problematic, since it causes ambiguities to be broken somewhat arbitrarily.
+// And as a side-effect, it also caused our computation of "used" traits to be miscalculated
+// since inherent candidates don't count as an import usage.
+
+use std::ops::Deref;
+
+trait Trait1 {
+ fn method(&self) {
+ println!("1");
+ }
+}
+
+trait Trait2 {
+ fn method(&self) {
+ println!("2");
+ }
+}
+impl<T: Other + ?Sized> Trait2 for T {}
+
+trait Other {}
+
+fn foo<T>(x: T)
+where
+ T: Deref,
+ <T as Deref>::Target: Trait1 + Other,
+{
+ // Make sure that we don't prefer methods from where clauses for rigid aliases,
+ // just for params. We could revisit this behavior, but it would be a lang change.
+ x.method();
+ //~^ ERROR multiple applicable items in scope
+}
+
+fn main() {}
diff --git a/tests/ui/methods/trait-method-self-param-error-7575.rs b/tests/ui/methods/trait-method-resolution-7575.rs
similarity index 100%
rename from tests/ui/methods/trait-method-self-param-error-7575.rs
rename to tests/ui/methods/trait-method-resolution-7575.rs
diff --git a/tests/ui/methods/trait-method-self-param-error-7575.stderr b/tests/ui/methods/trait-method-resolution-7575.stderr
similarity index 77%
rename from tests/ui/methods/trait-method-self-param-error-7575.stderr
rename to tests/ui/methods/trait-method-resolution-7575.stderr
index 656db30..8bbc360 100644
--- a/tests/ui/methods/trait-method-self-param-error-7575.stderr
+++ b/tests/ui/methods/trait-method-resolution-7575.stderr
@@ -1,5 +1,5 @@
warning: trait `Foo` is never used
- --> $DIR/trait-method-self-param-error-7575.rs:4:7
+ --> $DIR/trait-method-resolution-7575.rs:4:7
|
LL | trait Foo {
| ^^^
diff --git a/tests/ui/mir/validate/ice-zst-as-discr-145786.rs b/tests/ui/mir/validate/ice-zst-as-discr-145786.rs
new file mode 100644
index 0000000..616736b
--- /dev/null
+++ b/tests/ui/mir/validate/ice-zst-as-discr-145786.rs
@@ -0,0 +1,14 @@
+// Do not attempt to take the discriminant as the source
+// converted to a `u128`, that won't work for ZST.
+//
+//@ compile-flags: -Zvalidate-mir
+
+enum A {
+ B,
+ C,
+}
+
+fn main() {
+ let _: A = unsafe { std::mem::transmute(()) };
+ //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
diff --git a/tests/ui/mir/validate/ice-zst-as-discr-145786.stderr b/tests/ui/mir/validate/ice-zst-as-discr-145786.stderr
new file mode 100644
index 0000000..b0bca1e
--- /dev/null
+++ b/tests/ui/mir/validate/ice-zst-as-discr-145786.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> $DIR/ice-zst-as-discr-145786.rs:12:25
+ |
+LL | let _: A = unsafe { std::mem::transmute(()) };
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `()` (0 bits)
+ = note: target type: `A` (8 bits)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr b/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr
index a2cec97..6bda784 100644
--- a/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr
+++ b/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr
@@ -2,7 +2,7 @@
--> $DIR/hr-projection-mismatch.rs:20:5
|
LL | wrap::<_, Thing>();
- | ^^^^^^^^^^^^^^^^ one type is more general than the other
+ | ^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected reference `&'a _`
found reference `&_`
diff --git a/tests/ui/issues/issue-5950.rs b/tests/ui/modules/pub-use-module-alias-5950.rs
similarity index 62%
rename from tests/ui/issues/issue-5950.rs
rename to tests/ui/modules/pub-use-module-alias-5950.rs
index 6015560..91d3f9b 100644
--- a/tests/ui/issues/issue-5950.rs
+++ b/tests/ui/modules/pub-use-module-alias-5950.rs
@@ -1,6 +1,6 @@
+// https://github.com/rust-lang/rust/issues/5950
//@ check-pass
-
pub use local as local_alias;
pub mod local { }
diff --git a/tests/ui/resolve/module-import-resolution-7663.rs b/tests/ui/modules/use-statement-duplicate-check-7663.rs
similarity index 100%
rename from tests/ui/resolve/module-import-resolution-7663.rs
rename to tests/ui/modules/use-statement-duplicate-check-7663.rs
diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr
index ead4d49..0edbd7b 100644
--- a/tests/ui/nll/ice-106874.stderr
+++ b/tests/ui/nll/ice-106874.stderr
@@ -17,15 +17,6 @@
= note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-error: implementation of `Fn` is not general enough
- --> $DIR/ice-106874.rs:8:7
- |
-LL | A(B(C::new(D::new(move |st| f(st)))))
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
- |
- = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
- = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
-
error: implementation of `FnOnce` is not general enough
--> $DIR/ice-106874.rs:8:7
|
@@ -43,48 +34,58 @@
|
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: implementation of `FnOnce` is not general enough
- --> $DIR/ice-106874.rs:8:9
+ --> $DIR/ice-106874.rs:8:7
|
LL | A(B(C::new(D::new(move |st| f(st)))))
- | ^^^^^^ implementation of `FnOnce` is not general enough
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: implementation of `Fn` is not general enough
- --> $DIR/ice-106874.rs:8:9
+ --> $DIR/ice-106874.rs:8:7
|
LL | A(B(C::new(D::new(move |st| f(st)))))
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: implementation of `FnOnce` is not general enough
- --> $DIR/ice-106874.rs:8:9
+ --> $DIR/ice-106874.rs:8:7
|
LL | A(B(C::new(D::new(move |st| f(st)))))
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
-
-error: higher-ranked subtype error
- --> $DIR/ice-106874.rs:8:41
- |
-LL | A(B(C::new(D::new(move |st| f(st)))))
- | ^
-
-error: higher-ranked subtype error
- --> $DIR/ice-106874.rs:8:41
- |
-LL | A(B(C::new(D::new(move |st| f(st)))))
- | ^
- |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+error: implementation of `Fn` is not general enough
+ --> $DIR/ice-106874.rs:8:7
+ |
+LL | A(B(C::new(D::new(move |st| f(st)))))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
+ |
+ = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
+ = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: higher-ranked subtype error
+ --> $DIR/ice-106874.rs:8:7
+ |
+LL | A(B(C::new(D::new(move |st| f(st)))))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+ --> $DIR/ice-106874.rs:8:41
+ |
+LL | A(B(C::new(D::new(move |st| f(st)))))
+ | ^
+
error: aborting due to 10 previous errors
diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
index 26ad1ef..c2e91ed 100644
--- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr
+++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
@@ -38,18 +38,16 @@
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: higher-ranked subtype error
- --> $DIR/missing-universe-cause-issue-114907.rs:33:21
+ --> $DIR/missing-universe-cause-issue-114907.rs:33:5
|
LL | accept(callback);
- | ^
+ | ^^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/missing-universe-cause-issue-114907.rs:33:21
|
LL | accept(callback);
| ^
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 6 previous errors
diff --git a/tests/ui/issues/issue-6130.rs b/tests/ui/numeric/type-limit-comparisons-6130.rs
similarity index 77%
rename from tests/ui/issues/issue-6130.rs
rename to tests/ui/numeric/type-limit-comparisons-6130.rs
index c675a8a..54b3f63 100644
--- a/tests/ui/issues/issue-6130.rs
+++ b/tests/ui/numeric/type-limit-comparisons-6130.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/6130
//@ run-pass
pub fn main() {
diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs
index 5999e04..9c0b264 100644
--- a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs
+++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs
@@ -7,11 +7,11 @@ fn main() {
(0 | 1, 2 | 3) => {}
}
match ((0u8,),) {
- //~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX))`
+ //~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX,),)`
((0 | 1,) | (2 | 3,),) => {}
}
match (Some(0u8),) {
- //~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX))`
+ //~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX),)`
(None | Some(0 | 1),) => {}
}
}
diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
index 9f691ae..fe3a4aa 100644
--- a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
+++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
@@ -11,30 +11,30 @@
LL + (2_u8..=u8::MAX, _) => todo!()
|
-error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX))` not covered
+error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX,),)` not covered
--> $DIR/exhaustiveness-non-exhaustive.rs:9:11
|
LL | match ((0u8,),) {
- | ^^^^^^^^^ pattern `((4_u8..=u8::MAX))` not covered
+ | ^^^^^^^^^ pattern `((4_u8..=u8::MAX,),)` not covered
|
= note: the matched value is of type `((u8,),)`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ ((0 | 1,) | (2 | 3,),) => {},
-LL + ((4_u8..=u8::MAX)) => todo!()
+LL + ((4_u8..=u8::MAX,),) => todo!()
|
-error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` not covered
+error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX),)` not covered
--> $DIR/exhaustiveness-non-exhaustive.rs:13:11
|
LL | match (Some(0u8),) {
- | ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX))` not covered
+ | ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX),)` not covered
|
= note: the matched value is of type `(Option<u8>,)`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ (None | Some(0 | 1),) => {},
-LL + (Some(2_u8..=u8::MAX)) => todo!()
+LL + (Some(2_u8..=u8::MAX),) => todo!()
|
error: aborting due to 3 previous errors
diff --git a/tests/ui/panics/issue-47429-short-backtraces.rs b/tests/ui/panics/issue-47429-short-backtraces.rs
index 378ade6..21428d8 100644
--- a/tests/ui/panics/issue-47429-short-backtraces.rs
+++ b/tests/ui/panics/issue-47429-short-backtraces.rs
@@ -6,6 +6,9 @@
//@ check-run-results
//@ exec-env:RUST_BACKTRACE=1
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
// This is needed to avoid test output differences across std being built with v0 symbols vs legacy
// symbols.
//@ normalize-stderr: "begin_panic::<&str>" -> "begin_panic"
diff --git a/tests/ui/panics/issue-47429-short-backtraces.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.run.stderr
index 13b59a7..32aa6a3 100644
--- a/tests/ui/panics/issue-47429-short-backtraces.run.stderr
+++ b/tests/ui/panics/issue-47429-short-backtraces.run.stderr
@@ -1,5 +1,5 @@
-thread 'main' ($TID) panicked at $DIR/issue-47429-short-backtraces.rs:24:5:
+thread 'main' ($TID) panicked at $DIR/issue-47429-short-backtraces.rs:27:5:
explicit panic
stack backtrace:
0: std::panicking::begin_panic
diff --git a/tests/ui/panics/runtime-switch.rs b/tests/ui/panics/runtime-switch.rs
index 7d5b416..61c07a97 100644
--- a/tests/ui/panics/runtime-switch.rs
+++ b/tests/ui/panics/runtime-switch.rs
@@ -6,6 +6,9 @@
//@ check-run-results
//@ exec-env:RUST_BACKTRACE=0
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
// This is needed to avoid test output differences across std being built with v0 symbols vs legacy
// symbols.
//@ normalize-stderr: "begin_panic::<&str>" -> "begin_panic"
diff --git a/tests/ui/panics/runtime-switch.run.stderr b/tests/ui/panics/runtime-switch.run.stderr
index f3f6044..48a12b5 100644
--- a/tests/ui/panics/runtime-switch.run.stderr
+++ b/tests/ui/panics/runtime-switch.run.stderr
@@ -1,5 +1,5 @@
-thread 'main' ($TID) panicked at $DIR/runtime-switch.rs:28:5:
+thread 'main' ($TID) panicked at $DIR/runtime-switch.rs:31:5:
explicit panic
stack backtrace:
0: std::panicking::begin_panic
diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs
index 73d1730..a357040 100644
--- a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs
+++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs
@@ -1,16 +1,18 @@
+// Test for #111528, the ice issue cause waiting on a query that panicked
+//
//@ compile-flags: -Z threads=16
//@ build-fail
+//@ compare-output-by-lines
-#![crate_type="rlib"]
+#![crate_type = "rlib"]
#![allow(warnings)]
-#[export_name="fail"]
-pub fn a() {
-}
+#[export_name = "fail"]
+pub fn a() {}
-#[export_name="fail"]
+#[export_name = "fail"]
pub fn b() {
-//~^ ERROR symbol `fail` is already defined
+ //~^ ERROR symbol `fail` is already defined
}
fn main() {}
diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr
index 7963165..80f6373 100644
--- a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr
+++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr
@@ -1,5 +1,5 @@
error: symbol `fail` is already defined
- --> $DIR/cache-after-waiting-issue-111528.rs:12:1
+ --> $DIR/cache-after-waiting-issue-111528.rs:14:1
|
LL | pub fn b() {
| ^^^^^^^^^^
diff --git a/tests/ui/parallel-rustc/cycle_crash-issue-135870.rs b/tests/ui/parallel-rustc/cycle_crash-issue-135870.rs
new file mode 100644
index 0000000..4407e3a
--- /dev/null
+++ b/tests/ui/parallel-rustc/cycle_crash-issue-135870.rs
@@ -0,0 +1,8 @@
+// Test for #135870, which causes a deadlock bug
+//
+//@ compile-flags: -Z threads=2
+//@ compare-output-by-lines
+
+const FOO: usize = FOO; //~ ERROR cycle detected when simplifying constant for the type system `FOO`
+
+fn main() {}
diff --git a/tests/ui/parallel-rustc/cycle_crash.stderr b/tests/ui/parallel-rustc/cycle_crash-issue-135870.stderr
similarity index 88%
rename from tests/ui/parallel-rustc/cycle_crash.stderr
rename to tests/ui/parallel-rustc/cycle_crash-issue-135870.stderr
index 7af3b8e..6e588d1 100644
--- a/tests/ui/parallel-rustc/cycle_crash.stderr
+++ b/tests/ui/parallel-rustc/cycle_crash-issue-135870.stderr
@@ -1,11 +1,11 @@
error[E0391]: cycle detected when simplifying constant for the type system `FOO`
- --> $DIR/cycle_crash.rs:3:1
+ --> $DIR/cycle_crash-issue-135870.rs:6:1
|
LL | const FOO: usize = FOO;
| ^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `FOO`...
- --> $DIR/cycle_crash.rs:3:20
+ --> $DIR/cycle_crash-issue-135870.rs:6:20
|
LL | const FOO: usize = FOO;
| ^^^
diff --git a/tests/ui/parallel-rustc/cycle_crash.rs b/tests/ui/parallel-rustc/cycle_crash.rs
deleted file mode 100644
index 94ae11a..0000000
--- a/tests/ui/parallel-rustc/cycle_crash.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ compile-flags: -Z threads=2
-
-const FOO: usize = FOO; //~ERROR cycle detected when simplifying constant for the type system `FOO`
-
-fn main() {}
diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs
index 024df72..523b1b2 100644
--- a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs
+++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs
@@ -1,6 +1,10 @@
+// Test for #118205, which causes a deadlock bug
+//
//@ compile-flags:-C extra-filename=-1 -Z threads=16
//@ no-prefer-dynamic
//@ build-pass
+//@ compare-output-by-lines
+
#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs
index 3ccc1ea..65f99c3 100644
--- a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs
+++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs
@@ -1,5 +1,8 @@
+// Test for #118205, which causes a deadlock bug
+//
//@ compile-flags: -Z threads=16
//@ build-pass
+//@ compare-output-by-lines
pub static GLOBAL: isize = 3;
diff --git a/tests/ui/parallel-rustc/hello_world.rs b/tests/ui/parallel-rustc/hello_world.rs
index 56698fe..57891b9 100644
--- a/tests/ui/parallel-rustc/hello_world.rs
+++ b/tests/ui/parallel-rustc/hello_world.rs
@@ -1,5 +1,8 @@
+// Test for the basic function of parallel front end
+//
//@ compile-flags: -Z threads=8
//@ run-pass
+//@ compare-output-by-lines
fn main() {
println!("Hello world!");
diff --git a/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs
index ea8ecb67..a6b37e6 100644
--- a/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs
+++ b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs
@@ -1,18 +1,21 @@
+// Test for #111520, which causes an ice bug cause of reading stolen value
+//
//@ compile-flags: -Z threads=16
//@ run-pass
+//@ compare-output-by-lines
#[repr(transparent)]
struct Sched {
i: i32,
}
impl Sched {
- extern "C" fn get(self) -> i32 { self.i }
+ extern "C" fn get(self) -> i32 {
+ self.i
+ }
}
fn main() {
let s = Sched { i: 4 };
- let f = || -> i32 {
- s.get()
- };
+ let f = || -> i32 { s.get() };
println!("f: {}", f());
}
diff --git a/tests/ui/parallel-rustc/ty-variance-issue-124423.rs b/tests/ui/parallel-rustc/ty-variance-issue-124423.rs
new file mode 100644
index 0000000..8d7f29f
--- /dev/null
+++ b/tests/ui/parallel-rustc/ty-variance-issue-124423.rs
@@ -0,0 +1,58 @@
+// Test for #124423, which causes an ice bug: only `variances_of` returns `&[ty::Variance]`
+//
+//@ compile-flags: -Z threads=16
+//@ compare-output-by-lines
+
+use std::fmt::Debug;
+
+fn elided(_: &impl Copy + 'a) -> _ { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR the placeholder `_` is not allowed within types on item signatures for return types
+
+fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR at least one trait must be specified
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+
+fn elided2( impl 'b) -> impl 'a + 'a { x }
+//~^ ERROR expected one of `:` or `|`, found `'b`
+//~| ERROR expected identifier, found keyword `impl`
+//~| ERROR at least one trait must be specified
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+
+fn explicit2<'a>(_: &'a impl Copy + 'a) -> impl Copy + 'a { x }
+//~^ ERROR ambiguous `+` in a type
+
+fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR at least one trait must be specified
+//~| ERROR use of undeclared lifetime name `'b`
+
+fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR at least one trait is required for an object type
+
+fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR at least one trait is required for an object type
+//~| ERROR no function or associated item named `u32` found for struct `Box<_, _>` in the current scope
+
+fn elided4(_: &impl Copy + 'a) -> new { x(x) }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR cannot find type `new` in this scope
+
+trait LifetimeTrait<'a> {}
+
+impl<'a> LifetimeTrait<'a> for &'a Box<dyn 'a> {}
+//~^ ERROR at least one trait is required for an object type
+
+fn main() {}
diff --git a/tests/ui/parallel-rustc/ty-variance-issue-124423.stderr b/tests/ui/parallel-rustc/ty-variance-issue-124423.stderr
new file mode 100644
index 0000000..7ba89f7
--- /dev/null
+++ b/tests/ui/parallel-rustc/ty-variance-issue-124423.stderr
@@ -0,0 +1,287 @@
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-124423.rs:8:15
+ |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn elided(_: &(impl Copy + 'a)) -> _ { x }
+ | + +
+
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-124423.rs:13:24
+ |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn explicit<'b>(_: &'a (impl Copy + 'a)) -> impl 'a { x }
+ | + +
+
+error: expected identifier, found keyword `impl`
+ --> $DIR/ty-variance-issue-124423.rs:20:13
+ |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+ | ^^^^ expected identifier, found keyword
+
+error: expected one of `:` or `|`, found `'b`
+ --> $DIR/ty-variance-issue-124423.rs:20:18
+ |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+ | ^^ expected one of `:` or `|`
+
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-124423.rs:27:25
+ |
+LL | fn explicit2<'a>(_: &'a impl Copy + 'a) -> impl Copy + 'a { x }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn explicit2<'a>(_: &'a (impl Copy + 'a)) -> impl Copy + 'a { x }
+ | + +
+
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-124423.rs:30:16
+ |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn foo<'a>(_: &(impl Copy + 'a)) -> impl 'b + 'a { x }
+ | + +
+
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-124423.rs:35:16
+ |
+LL | fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn elided3(_: &(impl Copy + 'a)) -> Box<dyn 'a> { Box::new(x) }
+ | + +
+
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-124423.rs:41:17
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn x<'b>(_: &'a (impl Copy + 'a)) -> Box<dyn 'b> { Box::u32(x) }
+ | + +
+
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-124423.rs:48:16
+ |
+LL | fn elided4(_: &impl Copy + 'a) -> new { x(x) }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn elided4(_: &(impl Copy + 'a)) -> new { x(x) }
+ | + +
+
+error: at least one trait must be specified
+ --> $DIR/ty-variance-issue-124423.rs:13:43
+ |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+ | ^^^^^^^
+
+error: at least one trait must be specified
+ --> $DIR/ty-variance-issue-124423.rs:20:25
+ |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+ | ^^^^^^^^^^^^
+
+error: at least one trait must be specified
+ --> $DIR/ty-variance-issue-124423.rs:30:35
+ |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+ | ^^^^^^^^^^^^
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:8:27
+ |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn elided<'a>(_: &impl Copy + 'a) -> _ { x }
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:13:21
+ |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn explicit<'a, 'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:13:36
+ |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn explicit<'a, 'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:13:48
+ |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn explicit<'a, 'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:20:30
+ |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn elided2<'a>( impl 'b) -> impl 'a + 'a { x }
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:20:35
+ |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn elided2<'a>( impl 'b) -> impl 'a + 'a { x }
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/ty-variance-issue-124423.rs:30:40
+ |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'b` here
+ |
+LL | fn foo<'b, 'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:35:28
+ |
+LL | fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn elided3<'a>(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:35:43
+ |
+LL | fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn elided3<'a>(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:41:14
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn x<'a, 'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:41:29
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn x<'a, 'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-124423.rs:48:28
+ |
+LL | fn elided4(_: &impl Copy + 'a) -> new { x(x) }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn elided4<'a>(_: &impl Copy + 'a) -> new { x(x) }
+ | ++++
+
+error[E0412]: cannot find type `new` in this scope
+ --> $DIR/ty-variance-issue-124423.rs:48:36
+ |
+LL | fn elided4(_: &impl Copy + 'a) -> new { x(x) }
+ | ^^^ not found in this scope
+
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/ty-variance-issue-124423.rs:35:39
+ |
+LL | fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+ | ^^^^^^
+
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/ty-variance-issue-124423.rs:41:40
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^^^^^
+
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/ty-variance-issue-124423.rs:55:40
+ |
+LL | impl<'a> LifetimeTrait<'a> for &'a Box<dyn 'a> {}
+ | ^^^^^^
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/ty-variance-issue-124423.rs:8:34
+ |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+ | ^ not allowed in type signatures
+
+error[E0599]: no function or associated item named `u32` found for struct `Box<_, _>` in the current scope
+ --> $DIR/ty-variance-issue-124423.rs:41:55
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^^ function or associated item not found in `Box<_, _>`
+ |
+note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions:
+ Box::<T>::new
+ Box::<T>::new_uninit
+ Box::<T>::new_zeroed
+ Box::<T>::try_new
+ and 22 others
+ --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+
+error: aborting due to 30 previous errors
+
+Some errors have detailed explanations: E0121, E0224, E0261, E0412, E0599.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/parallel-rustc/ty-variance-issue-127971.rs b/tests/ui/parallel-rustc/ty-variance-issue-127971.rs
new file mode 100644
index 0000000..a179168
--- /dev/null
+++ b/tests/ui/parallel-rustc/ty-variance-issue-127971.rs
@@ -0,0 +1,25 @@
+// Test for #127971, which causes an ice bug: only `variances_of` returns `&[ty::Variance]`
+//
+//@ compile-flags: -Z threads=16
+//@ compare-output-by-lines
+
+use std::fmt::Debug;
+
+fn elided(_: &impl Copy + 'a) -> _ { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR the placeholder `_` is not allowed within types on item signatures for return types
+
+fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR at least one trait must be specified
+//~| ERROR use of undeclared lifetime name `'b`
+
+fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR at least one trait is required for an object type
+//~| ERROR no function or associated item named `u32` found for struct `Box<_, _>` in the current scope
+
+fn main() {}
diff --git a/tests/ui/parallel-rustc/ty-variance-issue-127971.stderr b/tests/ui/parallel-rustc/ty-variance-issue-127971.stderr
new file mode 100644
index 0000000..9929d3e
--- /dev/null
+++ b/tests/ui/parallel-rustc/ty-variance-issue-127971.stderr
@@ -0,0 +1,113 @@
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-127971.rs:8:15
+ |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn elided(_: &(impl Copy + 'a)) -> _ { x }
+ | + +
+
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-127971.rs:13:16
+ |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn foo<'a>(_: &(impl Copy + 'a)) -> impl 'b + 'a { x }
+ | + +
+
+error: ambiguous `+` in a type
+ --> $DIR/ty-variance-issue-127971.rs:18:17
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^^^^^^^^^^^^^
+ |
+help: try adding parentheses
+ |
+LL | fn x<'b>(_: &'a (impl Copy + 'a)) -> Box<dyn 'b> { Box::u32(x) }
+ | + +
+
+error: at least one trait must be specified
+ --> $DIR/ty-variance-issue-127971.rs:13:35
+ |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+ | ^^^^^^^^^^^^
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-127971.rs:8:27
+ |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn elided<'a>(_: &impl Copy + 'a) -> _ { x }
+ | ++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/ty-variance-issue-127971.rs:13:40
+ |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'b` here
+ |
+LL | fn foo<'b, 'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-127971.rs:18:14
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn x<'a, 'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/ty-variance-issue-127971.rs:18:29
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn x<'a, 'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | +++
+
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/ty-variance-issue-127971.rs:18:40
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^^^^^
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/ty-variance-issue-127971.rs:8:34
+ |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+ | ^ not allowed in type signatures
+
+error[E0599]: no function or associated item named `u32` found for struct `Box<_, _>` in the current scope
+ --> $DIR/ty-variance-issue-127971.rs:18:55
+ |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+ | ^^^ function or associated item not found in `Box<_, _>`
+ |
+note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions:
+ Box::<T>::new
+ Box::<T>::new_uninit
+ Box::<T>::new_zeroed
+ Box::<T>::try_new
+ and 22 others
+ --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0121, E0224, E0261, E0599.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/parallel-rustc/undefined-function-issue-120760.rs b/tests/ui/parallel-rustc/undefined-function-issue-120760.rs
new file mode 100644
index 0000000..2665c30
--- /dev/null
+++ b/tests/ui/parallel-rustc/undefined-function-issue-120760.rs
@@ -0,0 +1,71 @@
+// Test for #120760, which causes an ice bug: no index for a field
+//
+//@ compile-flags: -Z threads=45
+//@ edition: 2021
+//@ compare-output-by-lines
+
+type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T>>>;
+
+fn main() {
+ let _ = f();
+}
+
+async fn f() {
+ run("dependency").await; //~ ERROR cannot find function `run` in this scope
+}
+
+struct InMemoryStorage;
+
+pub struct User<'dep> {
+ pub name: &'a str, //~ ERROR use of undeclared lifetime name `'a`
+}
+
+impl<'a> StorageRequest<InMemoryStorage> for SaveUser<'a> {
+ fn execute(&self) -> BoxFuture<Result<(), String>> {
+ todo!()
+ }
+}
+
+trait Storage {
+ type Error;
+}
+
+impl Storage for InMemoryStorage {
+ type Error = String;
+}
+
+trait StorageRequestReturnType {
+ type Output;
+}
+
+trait StorageRequest<S: Storage>: StorageRequestReturnType {
+ fn execute(
+ &self,
+ ) -> BoxFuture<Result<<SaveUser as StorageRequestReturnType>::Output, <S as Storage>::Error>>;
+}
+
+pub struct SaveUser<'a> {
+ pub name: &'a str,
+}
+
+impl<'a> StorageRequestReturnType for SaveUser<'a> {
+ type Output = ();
+}
+
+impl<'dep> User<'dep> {
+ async fn save<S>(self)
+ where
+ S: Storage,
+ for<'a> SaveUser<'a>: StorageRequest<S>,
+ {
+ let _ = run("dependency").await; //~ ERROR cannot find function `run` in this scope
+ }
+}
+
+async fn execute<S>(dep: &str)
+where
+ S: Storage,
+ for<'a> SaveUser<'a>: StorageRequest<S>,
+{
+ User { dep }.save().await; //~ ERROR struct `User<'_>` has no field named `dep`
+}
diff --git a/tests/ui/parallel-rustc/undefined-function-issue-120760.stderr b/tests/ui/parallel-rustc/undefined-function-issue-120760.stderr
new file mode 100644
index 0000000..87af537
--- /dev/null
+++ b/tests/ui/parallel-rustc/undefined-function-issue-120760.stderr
@@ -0,0 +1,35 @@
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/undefined-function-issue-120760.rs:20:16
+ |
+LL | pub name: &'a str,
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | pub struct User<'a, 'dep> {
+ | +++
+
+error[E0425]: cannot find function `run` in this scope
+ --> $DIR/undefined-function-issue-120760.rs:14:5
+ |
+LL | run("dependency").await;
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find function `run` in this scope
+ --> $DIR/undefined-function-issue-120760.rs:61:17
+ |
+LL | let _ = run("dependency").await;
+ | ^^^ not found in this scope
+
+error[E0560]: struct `User<'_>` has no field named `dep`
+ --> $DIR/undefined-function-issue-120760.rs:70:12
+ |
+LL | User { dep }.save().await;
+ | ^^^ `User<'_>` does not have this field
+ |
+ = note: available fields are: `name`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0261, E0425, E0560.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/parallel-rustc/unexpected-type-issue-120601.rs b/tests/ui/parallel-rustc/unexpected-type-issue-120601.rs
new file mode 100644
index 0000000..2e215aa
--- /dev/null
+++ b/tests/ui/parallel-rustc/unexpected-type-issue-120601.rs
@@ -0,0 +1,28 @@
+// Test for #120601, which causes an ice bug cause of unexpected type
+//
+//@ compile-flags: -Z threads=40
+//@ compare-output-by-lines
+
+struct T;
+struct Tuple(i32);
+
+async fn foo() -> Result<(), ()> {
+ Unstable2(())
+}
+//~^^^ ERROR `async fn` is not permitted in Rust 2015
+//~^^^ ERROR cannot find function, tuple struct or tuple variant `Unstable2` in this scope
+
+async fn tuple() -> Tuple {
+ Tuple(1i32)
+}
+//~^^^ ERROR `async fn` is not permitted in Rust 2015
+
+async fn match_() {
+ match tuple() {
+ Tuple(_) => {}
+ }
+}
+//~^^^^^ ERROR `async fn` is not permitted in Rust 2015
+//~^^^^ ERROR mismatched types
+
+fn main() {}
diff --git a/tests/ui/parallel-rustc/unexpected-type-issue-120601.stderr b/tests/ui/parallel-rustc/unexpected-type-issue-120601.stderr
new file mode 100644
index 0000000..ed563bb
--- /dev/null
+++ b/tests/ui/parallel-rustc/unexpected-type-issue-120601.stderr
@@ -0,0 +1,52 @@
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/unexpected-type-issue-120601.rs:9:1
+ |
+LL | async fn foo() -> Result<(), ()> {
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2024` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/unexpected-type-issue-120601.rs:15:1
+ |
+LL | async fn tuple() -> Tuple {
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2024` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+ --> $DIR/unexpected-type-issue-120601.rs:20:1
+ |
+LL | async fn match_() {
+ | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+ |
+ = help: pass `--edition 2024` to `rustc`
+ = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0425]: cannot find function, tuple struct or tuple variant `Unstable2` in this scope
+ --> $DIR/unexpected-type-issue-120601.rs:10:5
+ |
+LL | Unstable2(())
+ | ^^^^^^^^^ not found in this scope
+
+error[E0308]: mismatched types
+ --> $DIR/unexpected-type-issue-120601.rs:22:9
+ |
+LL | match tuple() {
+ | ------- this expression has type `impl Future<Output = Tuple>`
+LL | Tuple(_) => {}
+ | ^^^^^^^^ expected future, found `Tuple`
+ |
+ = note: expected opaque type `impl Future<Output = Tuple>`
+ found struct `Tuple`
+help: consider `await`ing on the `Future`
+ |
+LL | match tuple().await {
+ | ++++++
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0425, E0670.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/bad-lit-suffixes.rs b/tests/ui/parser/bad-lit-suffixes.rs
index 0a01bb8..0a1ee12 100644
--- a/tests/ui/parser/bad-lit-suffixes.rs
+++ b/tests/ui/parser/bad-lit-suffixes.rs
@@ -42,5 +42,10 @@ fn g() {}
#[rustc_layout_scalar_valid_range_start(0suffix)]
//~^ ERROR invalid suffix `suffix` for number literal
-//~| ERROR malformed `rustc_layout_scalar_valid_range_start` attribute input
struct S;
+
+impl S {
+ #[rustc_confusables("blah"suffix)]
+ //~^ ERROR suffixes on string literals are invalid
+ fn woof() { }
+}
diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr
index e1a8a68..6c3dbbc 100644
--- a/tests/ui/parser/bad-lit-suffixes.stderr
+++ b/tests/ui/parser/bad-lit-suffixes.stderr
@@ -10,12 +10,6 @@
LL | "C"suffix
| ^^^^^^^^^ invalid suffix `suffix`
-error: suffixes on string literals are invalid
- --> $DIR/bad-lit-suffixes.rs:39:15
- |
-LL | #[link(name = "string"suffix)]
- | ^^^^^^^^^^^^^^ invalid suffix `suffix`
-
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/bad-lit-suffixes.rs:3:1
|
@@ -160,6 +154,12 @@
LL + #[must_use]
|
+error: suffixes on string literals are invalid
+ --> $DIR/bad-lit-suffixes.rs:39:15
+ |
+LL | #[link(name = "string"suffix)]
+ | ^^^^^^^^^^^^^^ invalid suffix `suffix`
+
error: invalid suffix `suffix` for number literal
--> $DIR/bad-lit-suffixes.rs:43:41
|
@@ -168,14 +168,11 @@
|
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
-error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input
- --> $DIR/bad-lit-suffixes.rs:43:1
+error: suffixes on string literals are invalid
+ --> $DIR/bad-lit-suffixes.rs:48:25
|
-LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^
- | | |
- | | expected an integer literal here
- | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]`
+LL | #[rustc_confusables("blah"suffix)]
+ | ^^^^^^^^^^^^ invalid suffix `suffix`
error: aborting due to 22 previous errors; 2 warnings emitted
diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr
index 21b99d6..dd33fdb 100644
--- a/tests/ui/parser/misspelled-keywords/ref.stderr
+++ b/tests/ui/parser/misspelled-keywords/ref.stderr
@@ -15,6 +15,7 @@
|
LL | Some(refe list) => println!("{list:?}"),
| ^^^^ ^^^^ expected 1 field, found 2
+ |
--> $SRC_DIR/core/src/option.rs:LL:COL
|
= note: tuple variant has 1 field
diff --git a/tests/ui/issues/issue-5572.rs b/tests/ui/parser/partial-eq-trait-bound-5572.rs
similarity index 66%
rename from tests/ui/issues/issue-5572.rs
rename to tests/ui/parser/partial-eq-trait-bound-5572.rs
index f27744e..7ee0cdc 100644
--- a/tests/ui/issues/issue-5572.rs
+++ b/tests/ui/parser/partial-eq-trait-bound-5572.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5572
//@ check-pass
#![allow(dead_code)]
diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr
index 3300002..a99f7e1 100644
--- a/tests/ui/parser/recover/recover-pat-exprs.stderr
+++ b/tests/ui/parser/recover/recover-pat-exprs.stderr
@@ -690,6 +690,7 @@
|
LL | let b = matches!(x, (x * x | x.f()) | x[0]);
| ^ expected one of `)`, `,`, `@`, `if`, or `|`
+ |
--> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
= note: while parsing argument for this `pat` macro fragment
diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr
index 21d09ec4..6d43018 100644
--- a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr
+++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr
@@ -6,6 +6,7 @@
...
LL | EMPTY => {}
| ^^^^^ constant of non-structural type
+ |
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<()>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr
index 69d1072..ed465ea 100644
--- a/tests/ui/pattern/issue-115599.stderr
+++ b/tests/ui/pattern/issue-115599.stderr
@@ -6,6 +6,7 @@
...
LL | if let CONST_STRING = empty_str {}
| ^^^^^^^^^^^^ constant of non-structural type
+ |
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<u8>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
diff --git a/tests/ui/issues/auxiliary/iss.rs b/tests/ui/privacy/auxiliary/iss-6919.rs
similarity index 100%
rename from tests/ui/issues/auxiliary/iss.rs
rename to tests/ui/privacy/auxiliary/iss-6919.rs
diff --git a/tests/ui/issues/issue-6919.rs b/tests/ui/privacy/deref-separate-compile-unit-6919.rs
similarity index 60%
rename from tests/ui/issues/issue-6919.rs
rename to tests/ui/privacy/deref-separate-compile-unit-6919.rs
index 7fb8a2f..5d89349 100644
--- a/tests/ui/issues/issue-6919.rs
+++ b/tests/ui/privacy/deref-separate-compile-unit-6919.rs
@@ -1,7 +1,7 @@
+// https://github.com/rust-lang/rust/issues/6919
//@ run-pass
#![allow(unused_attributes)]
-//@ aux-build:iss.rs
-
+//@ aux-build:iss-6919.rs
extern crate issue6919_3;
diff --git a/tests/ui/issues/issue-55376.rs b/tests/ui/privacy/pub-restricted-path-usage-55376.rs
similarity index 84%
rename from tests/ui/issues/issue-55376.rs
rename to tests/ui/privacy/pub-restricted-path-usage-55376.rs
index 5a6862b..ca4e27c 100644
--- a/tests/ui/issues/issue-55376.rs
+++ b/tests/ui/privacy/pub-restricted-path-usage-55376.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/55376
//@ run-pass
// Tests that paths in `pub(...)` don't fail HIR verification.
diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr
index 6c47b52..2b48e90 100644
--- a/tests/ui/privacy/suggest-box-new.stderr
+++ b/tests/ui/privacy/suggest-box-new.stderr
@@ -3,10 +3,10 @@
|
LL | let _ = std::collections::HashMap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
= note: `std::collections::HashMap` defined here
- |
help: you might have meant to use an associated function to build this type
|
LL | let _ = std::collections::HashMap::new();
diff --git a/tests/ui/proc-macro/parent-source-spans.stderr b/tests/ui/proc-macro/parent-source-spans.stderr
index a3b27fd..db1eed5 100644
--- a/tests/ui/proc-macro/parent-source-spans.stderr
+++ b/tests/ui/proc-macro/parent-source-spans.stderr
@@ -144,6 +144,7 @@
...
LL | one!("hello", "world");
| ---------------------- in this macro invocation
+ |
--> $SRC_DIR/core/src/result.rs:LL:COL
|
= note: similarly named tuple variant `Ok` defined here
@@ -158,6 +159,7 @@
...
LL | two!("yay", "rust");
| ------------------- in this macro invocation
+ |
--> $SRC_DIR/core/src/result.rs:LL:COL
|
= note: similarly named tuple variant `Ok` defined here
@@ -172,6 +174,7 @@
...
LL | three!("hip", "hop");
| -------------------- in this macro invocation
+ |
--> $SRC_DIR/core/src/result.rs:LL:COL
|
= note: similarly named tuple variant `Ok` defined here
diff --git a/tests/ui/proc-macro/resolve-error.stderr b/tests/ui/proc-macro/resolve-error.stderr
index 9632983..45b71a3 100644
--- a/tests/ui/proc-macro/resolve-error.stderr
+++ b/tests/ui/proc-macro/resolve-error.stderr
@@ -76,6 +76,7 @@
|
LL | #[derive(Dlone)]
| ^^^^^ help: a derive macro with a similar name exists: `Clone`
+ |
--> $SRC_DIR/core/src/clone.rs:LL:COL
|
= note: similarly named derive macro `Clone` defined here
@@ -85,6 +86,7 @@
|
LL | #[derive(Dlone)]
| ^^^^^ help: a derive macro with a similar name exists: `Clone`
+ |
--> $SRC_DIR/core/src/clone.rs:LL:COL
|
= note: similarly named derive macro `Clone` defined here
diff --git a/tests/ui/issues/issue-53728.rs b/tests/ui/repr/packed-struct-with-enum-53728.rs
similarity index 85%
rename from tests/ui/issues/issue-53728.rs
rename to tests/ui/repr/packed-struct-with-enum-53728.rs
index 3649652..6ce65ed 100644
--- a/tests/ui/issues/issue-53728.rs
+++ b/tests/ui/repr/packed-struct-with-enum-53728.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/53728
//@ run-pass
#![allow(dead_code)]
diff --git a/tests/ui/issues/issue-6936.rs b/tests/ui/resolve/duplicate-name-in-module-6936.rs
similarity index 91%
rename from tests/ui/issues/issue-6936.rs
rename to tests/ui/resolve/duplicate-name-in-module-6936.rs
index e9aa80b..ae9282c 100644
--- a/tests/ui/issues/issue-6936.rs
+++ b/tests/ui/resolve/duplicate-name-in-module-6936.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/6936
struct T;
mod t1 {
@@ -30,5 +31,4 @@ mod t6 {
impl Foo {} // ok
}
-
fn main() {}
diff --git a/tests/ui/issues/issue-6936.stderr b/tests/ui/resolve/duplicate-name-in-module-6936.stderr
similarity index 86%
rename from tests/ui/issues/issue-6936.stderr
rename to tests/ui/resolve/duplicate-name-in-module-6936.stderr
index 03cc506..76bb8f5 100644
--- a/tests/ui/issues/issue-6936.stderr
+++ b/tests/ui/resolve/duplicate-name-in-module-6936.stderr
@@ -1,5 +1,5 @@
error[E0428]: the name `Foo` is defined multiple times
- --> $DIR/issue-6936.rs:5:5
+ --> $DIR/duplicate-name-in-module-6936.rs:6:5
|
LL | type Foo = crate::T;
| -------------------- previous definition of the type `Foo` here
@@ -9,7 +9,7 @@
= note: `Foo` must be defined only once in the type namespace of this module
error[E0428]: the name `Foo` is defined multiple times
- --> $DIR/issue-6936.rs:10:5
+ --> $DIR/duplicate-name-in-module-6936.rs:11:5
|
LL | type Foo = crate::T;
| -------------------- previous definition of the type `Foo` here
@@ -19,7 +19,7 @@
= note: `Foo` must be defined only once in the type namespace of this module
error[E0428]: the name `Foo` is defined multiple times
- --> $DIR/issue-6936.rs:15:5
+ --> $DIR/duplicate-name-in-module-6936.rs:16:5
|
LL | type Foo = crate::T;
| -------------------- previous definition of the type `Foo` here
@@ -29,7 +29,7 @@
= note: `Foo` must be defined only once in the type namespace of this module
error[E0428]: the name `Bar` is defined multiple times
- --> $DIR/issue-6936.rs:25:5
+ --> $DIR/duplicate-name-in-module-6936.rs:26:5
|
LL | type Bar<T> = T;
| ---------------- previous definition of the type `Bar` here
diff --git a/tests/ui/resolve/issue-102946.rs b/tests/ui/resolve/issue-102946.rs
index c6feca6..8d90e61 100644
--- a/tests/ui/resolve/issue-102946.rs
+++ b/tests/ui/resolve/issue-102946.rs
@@ -1,7 +1,6 @@
impl Error for str::Utf8Error {
//~^ ERROR cannot find trait `Error` in this scope
//~| ERROR ambiguous associated type
- fn description(&self) {}
}
fn main() {}
diff --git a/tests/ui/resolve/levenshtein.stderr b/tests/ui/resolve/levenshtein.stderr
index cf47821..7fc5710 100644
--- a/tests/ui/resolve/levenshtein.stderr
+++ b/tests/ui/resolve/levenshtein.stderr
@@ -18,6 +18,7 @@
|
LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
| ^^^^^^ help: an enum with a similar name exists: `Option`
+ |
--> $SRC_DIR/core/src/option.rs:LL:COL
|
= note: similarly named enum `Option` defined here
diff --git a/tests/ui/resolve/path-attr-in-const-block.rs b/tests/ui/resolve/path-attr-in-const-block.rs
index 076511d..0ca356b 100644
--- a/tests/ui/resolve/path-attr-in-const-block.rs
+++ b/tests/ui/resolve/path-attr-in-const-block.rs
@@ -5,5 +5,6 @@ fn main() {
const {
#![path = foo!()]
//~^ ERROR: cannot find macro `foo` in this scope
+ //~| ERROR: attribute value must be a literal
}
}
diff --git a/tests/ui/resolve/path-attr-in-const-block.stderr b/tests/ui/resolve/path-attr-in-const-block.stderr
index 8f9e581..19d2745 100644
--- a/tests/ui/resolve/path-attr-in-const-block.stderr
+++ b/tests/ui/resolve/path-attr-in-const-block.stderr
@@ -4,5 +4,11 @@
LL | #![path = foo!()]
| ^^^
-error: aborting due to 1 previous error
+error: attribute value must be a literal
+ --> $DIR/path-attr-in-const-block.rs:6:19
+ |
+LL | #![path = foo!()]
+ | ^^^^^^
+
+error: aborting due to 2 previous errors
diff --git a/tests/ui/issues/issue-7044.rs b/tests/ui/resolve/unit-like-struct-masks-constant-7044.rs
similarity index 65%
rename from tests/ui/issues/issue-7044.rs
rename to tests/ui/resolve/unit-like-struct-masks-constant-7044.rs
index a6e22bc..f48dd69 100644
--- a/tests/ui/issues/issue-7044.rs
+++ b/tests/ui/resolve/unit-like-struct-masks-constant-7044.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/7044
static X: isize = 0;
struct X; //~ ERROR the name `X` is defined multiple times
diff --git a/tests/ui/issues/issue-7044.stderr b/tests/ui/resolve/unit-like-struct-masks-constant-7044.stderr
similarity index 87%
rename from tests/ui/issues/issue-7044.stderr
rename to tests/ui/resolve/unit-like-struct-masks-constant-7044.stderr
index 9d1fb3a..48aa6fce 100644
--- a/tests/ui/issues/issue-7044.stderr
+++ b/tests/ui/resolve/unit-like-struct-masks-constant-7044.stderr
@@ -1,5 +1,5 @@
error[E0428]: the name `X` is defined multiple times
- --> $DIR/issue-7044.rs:2:1
+ --> $DIR/unit-like-struct-masks-constant-7044.rs:3:1
|
LL | static X: isize = 0;
| -------------------- previous definition of the value `X` here
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs b/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs
index 65e61a2..7902f40 100644
--- a/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs
+++ b/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs
@@ -5,12 +5,12 @@
const fn assert_file_has_trailing_zero() {
let caller = core::panic::Location::caller();
let file_str = caller.file();
- let file_with_nul = caller.file_with_nul();
- if file_str.len() != file_with_nul.count_bytes() {
+ let file_cstr = caller.file_as_c_str();
+ if file_str.len() != file_cstr.count_bytes() {
panic!("mismatched lengths");
}
let trailing_byte: core::ffi::c_char = unsafe {
- *file_with_nul.as_ptr().offset(file_with_nul.count_bytes() as _)
+ *file_cstr.as_ptr().offset(file_cstr.count_bytes() as _)
};
if trailing_byte != 0 {
panic!("trailing byte was nonzero")
diff --git a/tests/ui/sanitize-attr/invalid-sanitize.rs b/tests/ui/sanitize-attr/invalid-sanitize.rs
index 49dc01c..957ce78 100644
--- a/tests/ui/sanitize-attr/invalid-sanitize.rs
+++ b/tests/ui/sanitize-attr/invalid-sanitize.rs
@@ -1,8 +1,7 @@
#![feature(sanitize)]
-#[sanitize(brontosaurus = "off")] //~ ERROR invalid argument
-fn main() {
-}
+#[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input
+fn main() {}
#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
#[sanitize(address = "off")]
@@ -12,11 +11,11 @@ fn multiple_consistent() {}
#[sanitize(address = "off")]
fn multiple_inconsistent() {}
-#[sanitize(address = "bogus")] //~ ERROR invalid argument for `sanitize`
+#[sanitize(address = "bogus")] //~ ERROR malformed `sanitize` attribute input
fn wrong_value() {}
#[sanitize = "off"] //~ ERROR malformed `sanitize` attribute input
-fn name_value () {}
+fn name_value() {}
#[sanitize] //~ ERROR malformed `sanitize` attribute input
fn just_word() {}
diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr
index 4bf8177..ec0a93b 100644
--- a/tests/ui/sanitize-attr/invalid-sanitize.stderr
+++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr
@@ -1,10 +1,82 @@
-error: malformed `sanitize` attribute input
- --> $DIR/invalid-sanitize.rs:18:1
+error[E0539]: malformed `sanitize` attribute input
+ --> $DIR/invalid-sanitize.rs:3:1
+ |
+LL | #[sanitize(brontosaurus = "off")]
+ | ^^^^^^^^^^^------------^^^^^^^^^^
+ | |
+ | valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread" or "hwaddress"
+ |
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[sanitize(brontosaurus = "off")]
+LL + #[sanitize(address = "on|off")]
+ |
+LL - #[sanitize(brontosaurus = "off")]
+LL + #[sanitize(cfi = "on|off")]
+ |
+LL - #[sanitize(brontosaurus = "off")]
+LL + #[sanitize(hwaddress = "on|off")]
+ |
+LL - #[sanitize(brontosaurus = "off")]
+LL + #[sanitize(kcfi = "on|off")]
+ |
+ = and 5 other candidates
+
+error: multiple `sanitize` attributes
+ --> $DIR/invalid-sanitize.rs:6:1
+ |
+LL | #[sanitize(address = "off")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/invalid-sanitize.rs:7:1
+ |
+LL | #[sanitize(address = "off")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: multiple `sanitize` attributes
+ --> $DIR/invalid-sanitize.rs:10:1
+ |
+LL | #[sanitize(address = "on")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/invalid-sanitize.rs:11:1
+ |
+LL | #[sanitize(address = "off")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0539]: malformed `sanitize` attribute input
+ --> $DIR/invalid-sanitize.rs:14:1
+ |
+LL | #[sanitize(address = "bogus")]
+ | ^^^^^^^^^^^^^^^^^^^^^-------^^
+ | |
+ | valid arguments are "on" or "off"
+ |
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[sanitize(address = "bogus")]
+LL + #[sanitize(address = "on|off")]
+ |
+LL - #[sanitize(address = "bogus")]
+LL + #[sanitize(cfi = "on|off")]
+ |
+LL - #[sanitize(address = "bogus")]
+LL + #[sanitize(hwaddress = "on|off")]
+ |
+LL - #[sanitize(address = "bogus")]
+LL + #[sanitize(kcfi = "on|off")]
+ |
+ = and 5 other candidates
+
+error[E0539]: malformed `sanitize` attribute input
+ --> $DIR/invalid-sanitize.rs:17:1
|
LL | #[sanitize = "off"]
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^ expected this to be a list
|
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
|
LL - #[sanitize = "off"]
LL + #[sanitize(address = "on|off")]
@@ -20,13 +92,13 @@
|
= and 5 other candidates
-error: malformed `sanitize` attribute input
- --> $DIR/invalid-sanitize.rs:21:1
+error[E0539]: malformed `sanitize` attribute input
+ --> $DIR/invalid-sanitize.rs:20:1
|
LL | #[sanitize]
- | ^^^^^^^^^^^
+ | ^^^^^^^^^^^ expected this to be a list
|
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
|
LL | #[sanitize(address = "on|off")]
| ++++++++++++++++++++
@@ -38,45 +110,6 @@
| +++++++++++++++++
= and 5 other candidates
-error: multiple `sanitize` attributes
- --> $DIR/invalid-sanitize.rs:7:1
- |
-LL | #[sanitize(address = "off")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/invalid-sanitize.rs:8:1
- |
-LL | #[sanitize(address = "off")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: multiple `sanitize` attributes
- --> $DIR/invalid-sanitize.rs:11:1
- |
-LL | #[sanitize(address = "on")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
- |
-note: attribute also specified here
- --> $DIR/invalid-sanitize.rs:12:1
- |
-LL | #[sanitize(address = "off")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: invalid argument for `sanitize`
- --> $DIR/invalid-sanitize.rs:3:1
- |
-LL | #[sanitize(brontosaurus = "off")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
-
-error: invalid argument for `sanitize`
- --> $DIR/invalid-sanitize.rs:15:1
- |
-LL | #[sanitize(address = "bogus")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
-
error: aborting due to 6 previous errors
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/sanitizer/cfi/no_builtins.rs b/tests/ui/sanitizer/cfi/no_builtins.rs
new file mode 100644
index 0000000..9490576
--- /dev/null
+++ b/tests/ui/sanitizer/cfi/no_builtins.rs
@@ -0,0 +1,22 @@
+// Verifies that `#![no_builtins]` crates can be built with linker-plugin-lto and CFI.
+// See Issue #142284
+//
+//@ needs-sanitizer-cfi
+//@ compile-flags: -Clinker-plugin-lto -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static
+//@ compile-flags: --crate-type rlib
+//@ build-pass
+
+#![no_builtins]
+#![no_std]
+
+pub static FUNC: fn() = initializer;
+
+pub fn initializer() {
+ call(fma_with_fma);
+}
+
+pub fn call(fn_ptr: fn()) {
+ fn_ptr();
+}
+
+pub fn fma_with_fma() {}
diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
index 7108fa1..1a5c871 100644
--- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
+++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
@@ -1,8 +1,8 @@
warning: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/ignore-non-reference-lifetimes.rs:6:30
+ --> $DIR/ignore-non-reference-lifetimes.rs:6:41
|
LL | fn a<'a>(self: Self, a: &'a str) -> &str {
- | ^^ ---- the same lifetime is elided here
+ | -- ^^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -14,10 +14,10 @@
| ++
warning: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/ignore-non-reference-lifetimes.rs:10:33
+ --> $DIR/ignore-non-reference-lifetimes.rs:10:44
|
LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str {
- | ^^ ---- the same lifetime is elided here
+ | -- ^^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr
index 43dc96a..78cc610 100644
--- a/tests/ui/self/self_lifetime-async.stderr
+++ b/tests/ui/self/self_lifetime-async.stderr
@@ -1,8 +1,8 @@
warning: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/self_lifetime-async.rs:6:29
+ --> $DIR/self_lifetime-async.rs:6:44
|
LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
- | ^^ --- the same lifetime is elided here
+ | -- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -14,10 +14,10 @@
| ++
warning: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/self_lifetime-async.rs:12:42
+ --> $DIR/self_lifetime-async.rs:12:52
|
LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
- | ^^ --- the same lifetime is elided here
+ | -- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr
index 4f9b2fc..84f6345 100644
--- a/tests/ui/self/self_lifetime.stderr
+++ b/tests/ui/self/self_lifetime.stderr
@@ -1,8 +1,8 @@
warning: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/self_lifetime.rs:7:23
+ --> $DIR/self_lifetime.rs:7:38
|
LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
- | ^^ --- the same lifetime is elided here
+ | -- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
@@ -14,10 +14,10 @@
| ++
warning: eliding a lifetime that's named elsewhere is confusing
- --> $DIR/self_lifetime.rs:13:36
+ --> $DIR/self_lifetime.rs:13:46
|
LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
- | ^^ --- the same lifetime is elided here
+ | -- ^^^ the same lifetime is elided here
| |
| the lifetime is named here
|
diff --git a/tests/ui/issues/issue-55380.rs b/tests/ui/specialization/trait-specialization-default-methods-55380.rs
similarity index 89%
rename from tests/ui/issues/issue-55380.rs
rename to tests/ui/specialization/trait-specialization-default-methods-55380.rs
index 54894cd..b3d79fb 100644
--- a/tests/ui/issues/issue-55380.rs
+++ b/tests/ui/specialization/trait-specialization-default-methods-55380.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/55380
//@ run-pass
#![feature(specialization)]
//~^ WARN the feature `specialization` is incomplete
diff --git a/tests/ui/issues/issue-55380.stderr b/tests/ui/specialization/trait-specialization-default-methods-55380.stderr
similarity index 87%
rename from tests/ui/issues/issue-55380.stderr
rename to tests/ui/specialization/trait-specialization-default-methods-55380.stderr
index 403844c..f7c1903 100644
--- a/tests/ui/issues/issue-55380.stderr
+++ b/tests/ui/specialization/trait-specialization-default-methods-55380.stderr
@@ -1,5 +1,5 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/issue-55380.rs:2:12
+ --> $DIR/trait-specialization-default-methods-55380.rs:3:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
diff --git a/tests/ui/issues/issue-7364.rs b/tests/ui/static/global-variable-promotion-error-7364.rs
similarity index 83%
rename from tests/ui/issues/issue-7364.rs
rename to tests/ui/static/global-variable-promotion-error-7364.rs
index 4ce9beb..dba4a48 100644
--- a/tests/ui/issues/issue-7364.rs
+++ b/tests/ui/static/global-variable-promotion-error-7364.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/7364
use std::cell::RefCell;
// Regression test for issue 7364
diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/static/global-variable-promotion-error-7364.stderr
similarity index 91%
rename from tests/ui/issues/issue-7364.stderr
rename to tests/ui/static/global-variable-promotion-error-7364.stderr
index a47a90c..b9d7567 100644
--- a/tests/ui/issues/issue-7364.stderr
+++ b/tests/ui/static/global-variable-promotion-error-7364.stderr
@@ -1,5 +1,5 @@
error[E0277]: `RefCell<isize>` cannot be shared between threads safely
- --> $DIR/issue-7364.rs:4:15
+ --> $DIR/global-variable-promotion-error-7364.rs:5:15
|
LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0));
| ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
@@ -12,7 +12,7 @@
= note: shared static variables must have a type that implements `Sync`
error[E0015]: cannot call non-const associated function `Box::<RefCell<isize>>::new` in statics
- --> $DIR/issue-7364.rs:4:37
+ --> $DIR/global-variable-promotion-error-7364.rs:5:37
|
LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/issues/issue-5917.rs b/tests/ui/static/static-list-initialization-5917.rs
similarity index 77%
rename from tests/ui/issues/issue-5917.rs
rename to tests/ui/static/static-list-initialization-5917.rs
index 8e91b10..c6c32f7 100644
--- a/tests/ui/issues/issue-5917.rs
+++ b/tests/ui/static/static-list-initialization-5917.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5917
//@ run-pass
#![allow(non_upper_case_globals)]
diff --git a/tests/ui/issues/issue-5688.rs b/tests/ui/static/static-struct-initialization-5688.rs
similarity index 90%
rename from tests/ui/issues/issue-5688.rs
rename to tests/ui/static/static-struct-initialization-5688.rs
index a7db1df..6a4c2f4 100644
--- a/tests/ui/issues/issue-5688.rs
+++ b/tests/ui/static/static-struct-initialization-5688.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5688
//@ run-pass
/*
# Corrupted initialization in the static struct
diff --git a/tests/ui/structs-enums/auxiliary/aux-8044.rs b/tests/ui/structs/auxiliary/aux-8044.rs
similarity index 100%
rename from tests/ui/structs-enums/auxiliary/aux-8044.rs
rename to tests/ui/structs/auxiliary/aux-8044.rs
diff --git a/tests/ui/structs-enums/struct-and-enum-usage-8044.rs b/tests/ui/structs/btree-struct-usage-8044.rs
similarity index 100%
rename from tests/ui/structs-enums/struct-and-enum-usage-8044.rs
rename to tests/ui/structs/btree-struct-usage-8044.rs
diff --git a/tests/ui/issues/issue-6344-let.rs b/tests/ui/structs/destructuring-struct-with-dtor-6344.rs
similarity index 80%
rename from tests/ui/issues/issue-6344-let.rs
rename to tests/ui/structs/destructuring-struct-with-dtor-6344.rs
index 1e1bdfa..b107a99 100644
--- a/tests/ui/issues/issue-6344-let.rs
+++ b/tests/ui/structs/destructuring-struct-with-dtor-6344.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/6344
//@ run-pass
#![allow(non_shorthand_field_patterns)]
diff --git a/tests/ui/issues/issue-5439.rs b/tests/ui/structs/nonexistent-struct-field-error-5439.rs
similarity index 86%
rename from tests/ui/issues/issue-5439.rs
rename to tests/ui/structs/nonexistent-struct-field-error-5439.rs
index 852b264..b2b3293 100644
--- a/tests/ui/issues/issue-5439.rs
+++ b/tests/ui/structs/nonexistent-struct-field-error-5439.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5439
struct Foo {
foo: isize,
}
diff --git a/tests/ui/issues/issue-5439.stderr b/tests/ui/structs/nonexistent-struct-field-error-5439.stderr
similarity index 86%
rename from tests/ui/issues/issue-5439.stderr
rename to tests/ui/structs/nonexistent-struct-field-error-5439.stderr
index 6d1d74e..b560772 100644
--- a/tests/ui/issues/issue-5439.stderr
+++ b/tests/ui/structs/nonexistent-struct-field-error-5439.stderr
@@ -1,5 +1,5 @@
error[E0560]: struct `Foo` has no field named `nonexistent`
- --> $DIR/issue-5439.rs:11:31
+ --> $DIR/nonexistent-struct-field-error-5439.rs:12:31
|
LL | return Box::new(Foo { nonexistent: self, foo: i });
| ^^^^^^^^^^^ `Foo` does not have this field
diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr
index a1a01c0..1816a27 100644
--- a/tests/ui/suggestions/attribute-typos.stderr
+++ b/tests/ui/suggestions/attribute-typos.stderr
@@ -15,6 +15,7 @@
|
LL | #[tests]
| ^^^^^ help: an attribute macro with a similar name exists: `test`
+ |
--> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
= note: similarly named attribute macro `test` defined here
diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
index 0cd6267..c81ac34 100644
--- a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
+++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
@@ -3,6 +3,7 @@
|
LL | impl result {
| ^^^^^^ help: an enum with a similar name exists: `Result`
+ |
--> $SRC_DIR/core/src/result.rs:LL:COL
|
= note: similarly named enum `Result` defined here
diff --git a/tests/ui/suggestions/enum-method-probe.stderr b/tests/ui/suggestions/enum-method-probe.stderr
index 5aa0fc4..7d97495 100644
--- a/tests/ui/suggestions/enum-method-probe.stderr
+++ b/tests/ui/suggestions/enum-method-probe.stderr
@@ -99,10 +99,10 @@
|
LL | res.len();
| ^^^ private method
+ |
--> $SRC_DIR/core/src/option.rs:LL:COL
|
= note: private method defined here
- |
note: the method `len` exists on the type `Vec<{integer}>`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
help: consider using `Option::expect` to unwrap the `Vec<{integer}>` value, panicking if the value is an `Option::None`
diff --git a/tests/ui/suggestions/import-trait-for-method-call.stderr b/tests/ui/suggestions/import-trait-for-method-call.stderr
index 58b07fe..177ab76 100644
--- a/tests/ui/suggestions/import-trait-for-method-call.stderr
+++ b/tests/ui/suggestions/import-trait-for-method-call.stderr
@@ -3,6 +3,7 @@
|
LL | h.finish()
| ^^^^^^ method not found in `DefaultHasher`
+ |
--> $SRC_DIR/core/src/hash/mod.rs:LL:COL
|
= note: the method is available for `DefaultHasher` here
diff --git a/tests/ui/suggestions/multi-suggestion.ascii.stderr b/tests/ui/suggestions/multi-suggestion.ascii.stderr
index f2a146f..1744162 100644
--- a/tests/ui/suggestions/multi-suggestion.ascii.stderr
+++ b/tests/ui/suggestions/multi-suggestion.ascii.stderr
@@ -3,10 +3,10 @@
|
LL | let _ = std::collections::HashMap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
= note: `std::collections::HashMap` defined here
- |
help: you might have meant to use an associated function to build this type
|
LL | let _ = std::collections::HashMap::new();
diff --git a/tests/ui/suggestions/multi-suggestion.unicode.stderr b/tests/ui/suggestions/multi-suggestion.unicode.stderr
index 69df481..4835c26 100644
--- a/tests/ui/suggestions/multi-suggestion.unicode.stderr
+++ b/tests/ui/suggestions/multi-suggestion.unicode.stderr
@@ -3,10 +3,10 @@
│
LL │ let _ = std::collections::HashMap();
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━
+ ╰╴
╭▸ $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
│
╰ note: `std::collections::HashMap` defined here
- ╰╴
help: you might have meant to use an associated function to build this type
╭╴
LL │ let _ = std::collections::HashMap::new();
@@ -34,7 +34,7 @@
note: constructor is not visible here due to private fields
╭▸ $SRC_DIR/alloc/src/boxed.rs:LL:COL
│
- ╰ note: private field
+ ├ note: private field
│
╰ note: private field
help: you might have meant to use an associated function to build this type
diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
index 0008b4f..8ab8a17 100644
--- a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
+++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
@@ -44,6 +44,7 @@
|
LL | let _i: i16 = 0_i32.try_into().unwrap();
| ^^^^^^^^
+ |
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
|
= note: the method is available for `i32` here
diff --git a/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.fixed b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.fixed
new file mode 100644
index 0000000..2835743
--- /dev/null
+++ b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.fixed
@@ -0,0 +1,13 @@
+//@ run-rustfix
+
+use std::fmt::Display;
+
+struct S;
+
+impl S {
+ fn call(&self, _: impl Display) {}
+}
+
+fn main() {
+ S.call((|| "hello")()); //~ ERROR [E0277]
+}
diff --git a/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.rs b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.rs
new file mode 100644
index 0000000..848629a
--- /dev/null
+++ b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.rs
@@ -0,0 +1,13 @@
+//@ run-rustfix
+
+use std::fmt::Display;
+
+struct S;
+
+impl S {
+ fn call(&self, _: impl Display) {}
+}
+
+fn main() {
+ S.call(|| "hello"); //~ ERROR [E0277]
+}
diff --git a/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr
new file mode 100644
index 0000000..cb6df5a
--- /dev/null
+++ b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr
@@ -0,0 +1,23 @@
+error[E0277]: `{closure@$DIR/use-parentheses-to-call-closure-issue-145404.rs:12:12: 12:14}` doesn't implement `std::fmt::Display`
+ --> $DIR/use-parentheses-to-call-closure-issue-145404.rs:12:12
+ |
+LL | S.call(|| "hello");
+ | ---- ^^^^^^^^^^ unsatisfied trait bound
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `std::fmt::Display` is not implemented for closure `{closure@$DIR/use-parentheses-to-call-closure-issue-145404.rs:12:12: 12:14}`
+note: required by a bound in `S::call`
+ --> $DIR/use-parentheses-to-call-closure-issue-145404.rs:8:28
+ |
+LL | fn call(&self, _: impl Display) {}
+ | ^^^^^^^ required by this bound in `S::call`
+help: use parentheses to call this closure
+ |
+LL - S.call(|| "hello");
+LL + S.call((|| "hello")());
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
index 2288bd1..40936ce1 100644
--- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
+++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -3,10 +3,10 @@
|
LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
| ^^^^^^ not a trait
+ |
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
= note: similarly named trait `ToString` defined here
- |
help: constrain the associated type to `String`
|
LL - struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
@@ -22,10 +22,10 @@
|
LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
| ^^^^^^ not a trait
+ |
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
= note: similarly named trait `ToString` defined here
- |
help: constrain the associated type to `String`
|
LL - struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
@@ -41,10 +41,10 @@
|
LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
| ^^^^^^ not a trait
+ |
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
= note: similarly named trait `ToString` defined here
- |
help: constrain the associated type to `String`
|
LL - fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
@@ -60,10 +60,10 @@
|
LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
| ^^^^^^ not a trait
+ |
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
= note: similarly named trait `ToString` defined here
- |
help: constrain the associated type to `String`
|
LL - fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
@@ -85,6 +85,7 @@
|
LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
| ^^^^^^ help: a trait with a similar name exists: `ToString`
+ |
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
= note: similarly named trait `ToString` defined here
diff --git a/tests/ui/traits/const-traits/constructor-const-fn.rs b/tests/ui/traits/const-traits/constructor-const-fn.rs
new file mode 100644
index 0000000..4a7bf53
--- /dev/null
+++ b/tests/ui/traits/const-traits/constructor-const-fn.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+#![feature(const_trait_impl)]
+const fn impls_fn<F: ~const Fn(u32) -> Foo>(_: &F) {}
+
+struct Foo(u32);
+
+const fn foo() {
+ // This previously triggered an incorrect assert
+ // when checking whether the constructor of `Foo`
+ // is const.
+ impls_fn(&Foo)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/reservation-impl-ice.rs b/tests/ui/traits/const-traits/reservation-impl-ice.rs
new file mode 100644
index 0000000..efaea1c
--- /dev/null
+++ b/tests/ui/traits/const-traits/reservation-impl-ice.rs
@@ -0,0 +1,13 @@
+//@ compile-flags: -Znext-solver
+#![feature(const_from, never_type, const_trait_impl)]
+
+const fn impls_from<T: ~const From<!>>() {}
+
+const fn foo() {
+ // This previously ICE'd when encountering the reservation impl
+ // from the standard library.
+ impls_from::<()>();
+ //~^ ERROR the trait bound `(): From<!>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/reservation-impl-ice.stderr b/tests/ui/traits/const-traits/reservation-impl-ice.stderr
new file mode 100644
index 0000000..a3fdcba
--- /dev/null
+++ b/tests/ui/traits/const-traits/reservation-impl-ice.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `(): From<!>` is not satisfied
+ --> $DIR/reservation-impl-ice.rs:9:18
+ |
+LL | impls_from::<()>();
+ | ^^ the trait `From<!>` is not implemented for `()`
+ |
+ = help: the following other types implement trait `From<T>`:
+ `(T, T)` implements `From<[T; 2]>`
+ `(T, T, T)` implements `From<[T; 3]>`
+ `(T, T, T, T)` implements `From<[T; 4]>`
+ `(T, T, T, T, T)` implements `From<[T; 5]>`
+ `(T, T, T, T, T, T)` implements `From<[T; 6]>`
+ `(T, T, T, T, T, T, T)` implements `From<[T; 7]>`
+ `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>`
+ `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>`
+ and 4 others
+note: required by a bound in `impls_from`
+ --> $DIR/reservation-impl-ice.rs:4:24
+ |
+LL | const fn impls_from<T: ~const From<!>>() {}
+ | ^^^^^^^^^^^^^^ required by this bound in `impls_from`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/issues/issue-5666.rs b/tests/ui/traits/dynamic-dispatch-trait-objects-5666.rs
similarity index 90%
rename from tests/ui/issues/issue-5666.rs
rename to tests/ui/traits/dynamic-dispatch-trait-objects-5666.rs
index 76e2f82..e335949 100644
--- a/tests/ui/issues/issue-5666.rs
+++ b/tests/ui/traits/dynamic-dispatch-trait-objects-5666.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5666
//@ run-pass
struct Dog {
@@ -14,7 +15,6 @@ fn bark(&self) -> String {
}
}
-
pub fn main() {
let snoopy = Box::new(Dog{name: "snoopy".to_string()});
let bubbles = Box::new(Dog{name: "bubbles".to_string()});
diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr
index 3b47888..e75be1e 100644
--- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr
+++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr
@@ -1,10 +1,10 @@
-error[E0283]: type annotations needed: cannot satisfy `impl Trait<'x> + Trait<'y>: Trait<'y>`
- --> $DIR/ambiguity-due-to-uniquification-2.rs:16:23
+error[E0283]: type annotations needed: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>`
+ --> $DIR/ambiguity-due-to-uniquification-2.rs:16:5
|
LL | impls_trait::<'y, _>(foo::<'x, 'y>());
- | ^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: cannot satisfy `impl Trait<'x> + Trait<'y>: Trait<'y>`
+ = note: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>`
= help: the trait `Trait<'t>` is implemented for `()`
note: required by a bound in `impls_trait`
--> $DIR/ambiguity-due-to-uniquification-2.rs:13:23
diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs
index 2a9a8b8..30df703 100644
--- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs
+++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs
@@ -14,7 +14,7 @@ fn impls_trait<'x, T: Trait<'x>>(_: T) {}
fn bar<'x, 'y>() {
impls_trait::<'y, _>(foo::<'x, 'y>());
- //[next]~^ ERROR type annotations needed: cannot satisfy `impl Trait<'x> + Trait<'y>: Trait<'y>`
+ //[next]~^ ERROR type annotations needed: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>`
}
fn main() {}
diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr
index e25f892..7fa8905 100644
--- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr
+++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr
@@ -1,12 +1,10 @@
-error[E0283]: type annotations needed: cannot satisfy `(dyn Object<&(), &()> + 'static): Trait<&()>`
- --> $DIR/ambiguity-due-to-uniquification-3.rs:28:17
+error[E0283]: type annotations needed: cannot satisfy `dyn Object<&(), &()>: Trait<&()>`
+ --> $DIR/ambiguity-due-to-uniquification-3.rs:28:5
|
LL | impls_trait(obj, t);
- | ----------- ^^^
- | |
- | required by a bound introduced by this call
+ | ^^^^^^^^^^^^^^^^^^^
|
- = note: cannot satisfy `(dyn Object<&(), &()> + 'static): Trait<&()>`
+ = note: cannot satisfy `dyn Object<&(), &()>: Trait<&()>`
= help: the trait `Trait<T>` is implemented for `()`
note: required by a bound in `impls_trait`
--> $DIR/ambiguity-due-to-uniquification-3.rs:24:19
diff --git a/tests/ui/traits/next-solver/opaques/different-bound-vars.current.stderr b/tests/ui/traits/next-solver/opaques/different-bound-vars.current.stderr
new file mode 100644
index 0000000..32e92e4
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/different-bound-vars.current.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+ --> $DIR/different-bound-vars.rs:13:37
+ |
+LL | let _: for<'b> fn(&'b ()) = foo::<U, T>(false);
+ | ^^^^^^^^^^^^^^^^^^ expected `for<'a> fn(&'a ())`, got `for<'b> fn(&'b ())`
+ |
+note: previous use here
+ --> $DIR/different-bound-vars.rs:12:37
+ |
+LL | let _: for<'a> fn(&'a ()) = foo::<T, U>(false);
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/next-solver/opaques/different-bound-vars.rs b/tests/ui/traits/next-solver/opaques/different-bound-vars.rs
new file mode 100644
index 0000000..5801a5e
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/different-bound-vars.rs
@@ -0,0 +1,20 @@
+// Check whether we support defining uses with different bound vars.
+// This needs to handle both mismatches for the same opaque type storage
+// entry, but also between different entries.
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+fn foo<T, U>(b: bool) -> impl Sized {
+ if b {
+ let _: for<'a> fn(&'a ()) = foo::<T, U>(false);
+ let _: for<'b> fn(&'b ()) = foo::<U, T>(false);
+ //[current]~^ ERROR concrete type differs from previous defining opaque type use
+ }
+
+ (|&()| ()) as for<'c> fn(&'c ())
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
index 6d2bbd8..a188629 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
@@ -1,16 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
- --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
+error[E0282]: type annotations needed
+ --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:12
|
-LL | needs_send::<Foo>();
- | ^^^
- |
- = note: cannot satisfy `Foo: Send`
-note: required by a bound in `needs_send`
- --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
- |
-LL | fn needs_send<T: Send>() {}
- | ^^^^ required by this bound in `needs_send`
+LL | fn test(_: Foo) {
+ | ^^^ cannot infer type
error: aborting due to 1 previous error
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
index 6d2bbd8..a188629 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
@@ -1,16 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
- --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
+error[E0282]: type annotations needed
+ --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:12
|
-LL | needs_send::<Foo>();
- | ^^^
- |
- = note: cannot satisfy `Foo: Send`
-note: required by a bound in `needs_send`
- --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
- |
-LL | fn needs_send<T: Send>() {}
- | ^^^^ required by this bound in `needs_send`
+LL | fn test(_: Foo) {
+ | ^^^ cannot infer type
error: aborting due to 1 previous error
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
index fddf892..8ff99d3 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
@@ -13,8 +13,8 @@ fn needs_send<T: Send>() {}
#[define_opaque(Foo)]
fn test(_: Foo) {
- needs_send::<Foo>();
//~^ ERROR type annotations needed
+ needs_send::<Foo>();
}
#[define_opaque(Foo)]
diff --git a/tests/ui/traits/next-solver/opaques/non-defining-use-hir-typeck.rs b/tests/ui/traits/next-solver/opaques/non-defining-use-hir-typeck.rs
new file mode 100644
index 0000000..a55be5f
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/non-defining-use-hir-typeck.rs
@@ -0,0 +1,28 @@
+//@ ignore-compare-mode-next-solver
+//@ compile-flags: -Znext-solver
+//@ check-pass
+#![feature(type_alias_impl_trait)]
+
+// Make sure that we support non-defining uses in HIR typeck.
+// Regression test for trait-system-refactor-initiative#135.
+
+fn non_defining_recurse<T>(b: bool) -> impl Sized {
+ if b {
+ // This results in an opaque type use `opaque<()> = ?unconstrained`
+ // during HIR typeck.
+ non_defining_recurse::<()>(false);
+ }
+}
+
+trait Eq<T, U> {}
+impl<T> Eq<T, T> for () {}
+fn is_eq<T: Eq<U, V>, U, V>() {}
+type Tait<T> = impl Sized;
+#[define_opaque(Tait)]
+fn non_defining_explicit<T>() {
+ is_eq::<(), Tait<_>, u32>(); // constrains opaque type args via hidden type
+ is_eq::<(), Tait<u64>, _>(); // constraints hidden type via args
+ is_eq::<(), Tait<T>, T>(); // actually defines
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs b/tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs
new file mode 100644
index 0000000..5e7e973
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// The recursive call to `foo` results in the opaque type use `opaque<U, T> = ?unconstrained`.
+// This needs to be supported and treated as a revealing use.
+
+fn foo<T, U>(b: bool) -> impl Sized {
+ if b {
+ foo::<U, T>(b);
+ }
+ 1u16
+}
+
+fn main() {}
diff --git a/tests/ui/issues/issue-53568.rs b/tests/ui/traits/nll-ice-custom-type-ops-53568.rs
similarity index 92%
rename from tests/ui/issues/issue-53568.rs
rename to tests/ui/traits/nll-ice-custom-type-ops-53568.rs
index 9862d4c..9b240cd 100644
--- a/tests/ui/issues/issue-53568.rs
+++ b/tests/ui/traits/nll-ice-custom-type-ops-53568.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/53568
// Regression test for an NLL-related ICE (#53568) -- we failed to
// resolve inference variables in "custom type-ops".
//
diff --git a/tests/ui/issues/issue-5883.rs b/tests/ui/traits/opaque-trait-size-error-5883.rs
similarity index 81%
rename from tests/ui/issues/issue-5883.rs
rename to tests/ui/traits/opaque-trait-size-error-5883.rs
index dd4753e..e39e24e 100644
--- a/tests/ui/issues/issue-5883.rs
+++ b/tests/ui/traits/opaque-trait-size-error-5883.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5883
trait A {}
struct Struct {
diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/traits/opaque-trait-size-error-5883.stderr
similarity index 88%
rename from tests/ui/issues/issue-5883.stderr
rename to tests/ui/traits/opaque-trait-size-error-5883.stderr
index 2ca437b..78de250 100644
--- a/tests/ui/issues/issue-5883.stderr
+++ b/tests/ui/traits/opaque-trait-size-error-5883.stderr
@@ -1,19 +1,19 @@
error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
- --> $DIR/issue-5883.rs:9:6
+ --> $DIR/opaque-trait-size-error-5883.rs:10:6
|
LL | ) -> Struct {
| ^^^^^^ doesn't have a size known at compile-time
|
= help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)`
note: required because it appears within the type `Struct`
- --> $DIR/issue-5883.rs:3:8
+ --> $DIR/opaque-trait-size-error-5883.rs:4:8
|
LL | struct Struct {
| ^^^^^^
= note: the return type of a function must have a statically known size
error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
- --> $DIR/issue-5883.rs:8:8
+ --> $DIR/opaque-trait-size-error-5883.rs:9:8
|
LL | r: dyn A + 'static
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
diff --git a/tests/ui/traits/self-implements-kinds-in-default-methods-8171.rs b/tests/ui/traits/self-not-send-in-default-method-8171.rs
similarity index 100%
rename from tests/ui/traits/self-implements-kinds-in-default-methods-8171.rs
rename to tests/ui/traits/self-not-send-in-default-method-8171.rs
diff --git a/tests/ui/issues/issue-6898.rs b/tests/ui/traits/trait-implementation-generic-access-6898.rs
similarity index 92%
rename from tests/ui/issues/issue-6898.rs
rename to tests/ui/traits/trait-implementation-generic-access-6898.rs
index c810aca..e9437b1 100644
--- a/tests/ui/issues/issue-6898.rs
+++ b/tests/ui/traits/trait-implementation-generic-access-6898.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/6898
//@ check-pass
use std::mem;
diff --git a/tests/ui/issues/issue-5988.rs b/tests/ui/traits/trait-implementation-restriction-5988.rs
similarity index 79%
rename from tests/ui/issues/issue-5988.rs
rename to tests/ui/traits/trait-implementation-restriction-5988.rs
index b7527d9..d3a5b10 100644
--- a/tests/ui/issues/issue-5988.rs
+++ b/tests/ui/traits/trait-implementation-restriction-5988.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/5988
//@ run-pass
trait B {
diff --git a/tests/ui/traits/trait-implementation-and-usage-7563.rs b/tests/ui/traits/trait-object-lifetime-bounds-7563.rs
similarity index 100%
rename from tests/ui/traits/trait-implementation-and-usage-7563.rs
rename to tests/ui/traits/trait-object-lifetime-bounds-7563.rs
diff --git a/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr
new file mode 100644
index 0000000..d90a786
--- /dev/null
+++ b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr
@@ -0,0 +1,16 @@
+error: vtable entries: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<dyn OneTwo as One>::one - shim(reify)),
+ Method(<dyn OneTwo as Two>::two - shim(reify)),
+ TraitVPtr(<dyn OneTwo as Two>),
+ TraitVPtr(<dyn OneTwo as TwoAgain>),
+ ]
+ --> $DIR/empty-supertrait-with-nonempty-supersupertrait.rs:40:1
+ |
+LL | type T = dyn OneTwo;
+ | ^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs
new file mode 100644
index 0000000..507cda6
--- /dev/null
+++ b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs
@@ -0,0 +1,49 @@
+//@ revisions: run dump
+//@[run] run-pass
+//@[dump] check-fail
+//! Regression test for #145752
+//! Ensure that `OneTwo` contains a vptr for `TwoAgain`
+#![allow(unused)]
+#![cfg_attr(dump, feature(rustc_attrs))]
+
+trait One {
+ fn one(&self) {
+ panic!("don't call this");
+ }
+}
+impl One for () {}
+
+trait Two {
+ fn two(&self) {
+ println!("good");
+ }
+}
+impl Two for () {}
+
+trait TwoAgain: Two {}
+impl<T: Two> TwoAgain for T {}
+
+trait OneTwo: One + TwoAgain {}
+impl<T: One + Two> OneTwo for T {}
+
+fn main() {
+ (&()).two();
+ (&() as &dyn OneTwo).two();
+ (&() as &dyn OneTwo as &dyn Two).two();
+
+ // these two used to panic because they called `one` due to #145752
+ (&() as &dyn OneTwo as &dyn TwoAgain).two();
+ (&() as &dyn OneTwo as &dyn TwoAgain as &dyn Two).two();
+}
+
+#[cfg_attr(dump, rustc_dump_vtable)]
+type T = dyn OneTwo;
+//[dump]~^ ERROR vtable entries: [
+//[dump]~| ERROR MetadataDropInPlace,
+//[dump]~| ERROR MetadataSize,
+//[dump]~| ERROR MetadataAlign,
+//[dump]~| ERROR Method(<dyn OneTwo as One>::one - shim(reify)),
+//[dump]~| ERROR Method(<dyn OneTwo as Two>::two - shim(reify)),
+//[dump]~| ERROR TraitVPtr(<dyn OneTwo as Two>),
+//[dump]~| ERROR TraitVPtr(<dyn OneTwo as TwoAgain>),
+//[dump]~| ERROR ]
diff --git a/tests/ui/traits/vtable/multiple-auto.rs b/tests/ui/traits/vtable/multiple-auto.rs
new file mode 100644
index 0000000..87ee865
--- /dev/null
+++ b/tests/ui/traits/vtable/multiple-auto.rs
@@ -0,0 +1,50 @@
+// Related to <https://github.com/rust-lang/rust/issues/113840>
+//
+// This test makes sure that multiple auto traits can reuse the
+// same pointer for upcasting (e.g. `Send`/`Sync`)
+
+#![crate_type = "lib"]
+#![feature(rustc_attrs, auto_traits)]
+
+// Markers
+auto trait M0 {}
+auto trait M1 {}
+auto trait M2 {}
+
+// Just a trait with a method
+trait T {
+ fn method(&self) {}
+}
+
+trait A: M0 + M1 + M2 + T {}
+
+trait B: M0 + M1 + T + M2 {}
+
+trait C: M0 + T + M1 + M2 {}
+
+trait D: T + M0 + M1 + M2 {}
+
+struct S;
+
+impl M0 for S {}
+impl M1 for S {}
+impl M2 for S {}
+impl T for S {}
+
+#[rustc_dump_vtable]
+impl A for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
+impl B for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
+impl C for S {}
+//~^ ERROR vtable entries
+
+#[rustc_dump_vtable]
+impl D for S {}
+//~^ ERROR vtable entries
+
+fn main() {}
diff --git a/tests/ui/traits/vtable/multiple-auto.stderr b/tests/ui/traits/vtable/multiple-auto.stderr
new file mode 100644
index 0000000..0a7c3eb
--- /dev/null
+++ b/tests/ui/traits/vtable/multiple-auto.stderr
@@ -0,0 +1,46 @@
+error: vtable entries: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as T>::method),
+ ]
+ --> $DIR/multiple-auto.rs:35:1
+ |
+LL | impl A for S {}
+ | ^^^^^^^^^^^^
+
+error: vtable entries: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as T>::method),
+ ]
+ --> $DIR/multiple-auto.rs:39:1
+ |
+LL | impl B for S {}
+ | ^^^^^^^^^^^^
+
+error: vtable entries: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as T>::method),
+ ]
+ --> $DIR/multiple-auto.rs:43:1
+ |
+LL | impl C for S {}
+ | ^^^^^^^^^^^^
+
+error: vtable entries: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<S as T>::method),
+ ]
+ --> $DIR/multiple-auto.rs:47:1
+ |
+LL | impl D for S {}
+ | ^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
index 72a253c..b50d1b6 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
@@ -1,24 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
- --> $DIR/constrain_in_projection2.rs:28:14
+error[E0282]: type annotations needed
+ --> $DIR/constrain_in_projection2.rs:28:13
|
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
- | ^^^
- |
-note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
- --> $DIR/constrain_in_projection2.rs:18:1
- |
-LL | impl Trait<()> for Foo {
- | ^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | impl Trait<u32> for Foo {
- | ^^^^^^^^^^^^^^^^^^^^^^^
- = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
-help: use the fully qualified path to an implementation
- |
-LL - let x = <Foo as Trait<Bar>>::Assoc::default();
-LL + let x = <<Type as Trait>::Assoc as Trait<Bar>>::Assoc::default();
- |
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
error: aborting due to 1 previous error
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
index 61773cf..c4aa6f3 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
@@ -26,7 +26,7 @@ impl Trait<u32> for Foo {
#[define_opaque(Bar)]
fn bop() {
let x = <Foo as Trait<Bar>>::Assoc::default();
- //[next]~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
+ //[next]~^ ERROR: type annotations needed
//[current]~^^ ERROR: `Foo: Trait<Bar>` is not satisfied
//[current]~| ERROR: `Foo: Trait<Bar>` is not satisfied
}
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.current.stderr
similarity index 87%
rename from tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
rename to tests/ui/type-alias-impl-trait/generic_nondefining_use.current.stderr
index 71e4152..2a78860 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.current.stderr
@@ -1,5 +1,5 @@
error[E0792]: expected generic type parameter, found `u32`
- --> $DIR/generic_nondefining_use.rs:16:21
+ --> $DIR/generic_nondefining_use.rs:20:21
|
LL | type OneTy<T> = impl Debug;
| - this generic parameter must be used with a generic type parameter
@@ -8,7 +8,7 @@
| ^^^^^^^^^^
error[E0792]: expected generic lifetime parameter, found `'static`
- --> $DIR/generic_nondefining_use.rs:23:5
+ --> $DIR/generic_nondefining_use.rs:29:5
|
LL | type OneLifetime<'a> = impl Debug;
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
@@ -17,7 +17,7 @@
| ^^^^
error[E0792]: expected generic constant parameter, found `123`
- --> $DIR/generic_nondefining_use.rs:28:24
+ --> $DIR/generic_nondefining_use.rs:35:24
|
LL | type OneConst<const X: usize> = impl Debug;
| -------------- this generic parameter must be used with a generic constant parameter
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.next.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.next.stderr
new file mode 100644
index 0000000..2b53614
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.next.stderr
@@ -0,0 +1,44 @@
+error: item does not constrain `OneTy::{opaque#0}`
+ --> $DIR/generic_nondefining_use.rs:20:4
+ |
+LL | fn concrete_ty() -> OneTy<u32> {
+ | ^^^^^^^^^^^
+ |
+ = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+ --> $DIR/generic_nondefining_use.rs:11:17
+ |
+LL | type OneTy<T> = impl Debug;
+ | ^^^^^^^^^^
+note: this use of `OneTy<u32>` does not have unique universal generic arguments
+ --> $DIR/generic_nondefining_use.rs:23:5
+ |
+LL | 5u32
+ | ^^^^
+
+error: non-defining use of `OneLifetime<'_>` in the defining scope
+ --> $DIR/generic_nondefining_use.rs:27:1
+ |
+LL | fn concrete_lifetime() -> OneLifetime<'static> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item does not constrain `OneConst::{opaque#0}`
+ --> $DIR/generic_nondefining_use.rs:35:4
+ |
+LL | fn concrete_const() -> OneConst<{ 123 }> {
+ | ^^^^^^^^^^^^^^
+ |
+ = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+ --> $DIR/generic_nondefining_use.rs:15:33
+ |
+LL | type OneConst<const X: usize> = impl Debug;
+ | ^^^^^^^^^^
+note: this use of `OneConst<123>` does not have unique universal generic arguments
+ --> $DIR/generic_nondefining_use.rs:38:5
+ |
+LL | 7u32
+ | ^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
index cf38c93..7250a9a 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
@@ -1,5 +1,9 @@
#![feature(type_alias_impl_trait)]
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
use std::fmt::Debug;
fn main() {}
@@ -14,18 +18,22 @@ fn main() {}
#[define_opaque(OneTy)]
fn concrete_ty() -> OneTy<u32> {
- //~^ ERROR: expected generic type parameter, found `u32`
+ //[current]~^ ERROR: expected generic type parameter, found `u32`
+ //[next]~^^ ERROR: item does not constrain `OneTy::{opaque#0}`
5u32
}
#[define_opaque(OneLifetime)]
fn concrete_lifetime() -> OneLifetime<'static> {
+ //[next]~^ ERROR: non-defining use of `OneLifetime<'_>` in the defining scope
6u32
- //~^ ERROR: expected generic lifetime parameter, found `'static`
+ //[current]~^ ERROR: expected generic lifetime parameter, found `'static`
+
}
#[define_opaque(OneConst)]
fn concrete_const() -> OneConst<{ 123 }> {
- //~^ ERROR: expected generic constant parameter, found `123`
+ //[current]~^ ERROR: expected generic constant parameter, found `123`
+ //[next]~^^ ERROR: item does not constrain `OneConst::{opaque#0}`
7u32
}
diff --git a/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs b/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs
index 987fad2..476babd 100644
--- a/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs
+++ b/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs
@@ -1,6 +1,6 @@
//@ check-pass
-use std::error::Error as StdError;
+use std::error::Error;
use std::pin::Pin;
use std::task::{Context, Poll};
@@ -51,7 +51,7 @@ impl<S> Stream for SseKeepAlive<S>
where
S: TryStream + Send + 'static,
S::Ok: ServerSentEvent,
- S::Error: StdError + Send + Sync + 'static,
+ S::Error: Error + Send + Sync + 'static,
{
type Item = Result<SseComment<&'static str>, ()>;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Option<Self::Item>> {
@@ -65,7 +65,7 @@ pub fn keep<S>(
where
S: TryStream + Send + 'static,
S::Ok: ServerSentEvent + Send,
- S::Error: StdError + Send + Sync + 'static,
+ S::Error: Error + Send + Sync + 'static,
{
SseKeepAlive { event_stream }
}
diff --git a/tests/ui/type-alias-impl-trait/normalize-args-before-defining-use-check.rs b/tests/ui/type-alias-impl-trait/normalize-args-before-defining-use-check.rs
new file mode 100644
index 0000000..2879b8f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/normalize-args-before-defining-use-check.rs
@@ -0,0 +1,33 @@
+#![feature(type_alias_impl_trait)]
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ [next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for trait-system-refactor-initiative#49.
+
+trait Mirror<'a> {
+ type Assoc;
+}
+impl<'a, T> Mirror<'a> for T {
+ type Assoc = T;
+}
+
+type HrAmbigAlias<T> = impl Sized;
+fn ret_tait<T>() -> for<'a> fn(HrAmbigAlias<<T as Mirror<'a>>::Assoc>) {
+ |_| ()
+}
+
+#[define_opaque(HrAmbigAlias)]
+fn define_hr_ambig_alias<T>() {
+ let _: fn(T) = ret_tait::<T>();
+}
+
+type InUserType<T> = impl Sized;
+#[define_opaque(InUserType)]
+fn in_user_type<T>() {
+ let x: InUserType<<T as Mirror<'static>>::Assoc> = ();
+}
+
+fn main() {}
diff --git a/tests/ui/type/issue-7607-1.stderr b/tests/ui/type/issue-7607-1.stderr
index db4c8f2..69b6d62 100644
--- a/tests/ui/type/issue-7607-1.stderr
+++ b/tests/ui/type/issue-7607-1.stderr
@@ -3,6 +3,7 @@
|
LL | impl Fo {
| ^^ help: a trait with a similar name exists: `Fn`
+ |
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
= note: similarly named trait `Fn` defined here
diff --git a/tests/ui/typeck/issue-83693.stderr b/tests/ui/typeck/issue-83693.stderr
index 34bca42..0359b8a 100644
--- a/tests/ui/typeck/issue-83693.stderr
+++ b/tests/ui/typeck/issue-83693.stderr
@@ -3,6 +3,7 @@
|
LL | impl F {
| ^ help: a trait with a similar name exists: `Fn`
+ |
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
= note: similarly named trait `Fn` defined here
diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr
index 69d6bd7..a854ecb 100644
--- a/tests/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr
@@ -12,6 +12,7 @@
|
LL | let _: <u8 as E>::N;
| ^ help: a trait with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named trait `Eq` defined here
@@ -42,6 +43,7 @@
|
LL | <u8 as E>::N;
| ^ help: a trait with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named trait `Eq` defined here
@@ -63,6 +65,7 @@
|
LL | let _: <u8 as E>::Y;
| ^ help: a trait with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named trait `Eq` defined here
@@ -72,6 +75,7 @@
|
LL | <u8 as E>::Y;
| ^ help: a trait with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named trait `Eq` defined here
@@ -90,6 +94,7 @@
|
LL | let _: <u8 as E>::N::NN;
| ^ help: a trait with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named trait `Eq` defined here
@@ -120,6 +125,7 @@
|
LL | <u8 as E>::N::NN;
| ^ help: a trait with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named trait `Eq` defined here
@@ -141,6 +147,7 @@
|
LL | let _: <u8 as E>::Y::NN;
| ^ help: a trait with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named trait `Eq` defined here
@@ -150,6 +157,7 @@
|
LL | <u8 as E>::Y::NN;
| ^ help: a trait with a similar name exists: `Eq`
+ |
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: similarly named trait `Eq` defined here
diff --git a/tests/ui/issues/issue-7344.rs b/tests/ui/unreachable-code/boolean-negation-in-unreachable-code-7344.rs
similarity index 81%
rename from tests/ui/issues/issue-7344.rs
rename to tests/ui/unreachable-code/boolean-negation-in-unreachable-code-7344.rs
index 406b246..8fd0918 100644
--- a/tests/ui/issues/issue-7344.rs
+++ b/tests/ui/unreachable-code/boolean-negation-in-unreachable-code-7344.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/7344
//@ run-pass
#![allow(unused_must_use)]
diff --git a/tests/ui/issues/auxiliary/issue-5844-aux.rs b/tests/ui/unsafe/auxiliary/aux-5844.rs
similarity index 100%
rename from tests/ui/issues/auxiliary/issue-5844-aux.rs
rename to tests/ui/unsafe/auxiliary/aux-5844.rs
diff --git a/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs b/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs
new file mode 100644
index 0000000..11863ce
--- /dev/null
+++ b/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs
@@ -0,0 +1,8 @@
+// https://github.com/rust-lang/rust/issues/5844
+//@aux-build:aux-5844.rs
+
+extern crate aux_5844;
+
+fn main() {
+ aux_5844::rand(); //~ ERROR: requires unsafe
+}
diff --git a/tests/ui/issues/issue-5844.stderr b/tests/ui/unsafe/extern-function-requires-unsafe-5844.stderr
similarity index 69%
rename from tests/ui/issues/issue-5844.stderr
rename to tests/ui/unsafe/extern-function-requires-unsafe-5844.stderr
index bae917f..44dee17 100644
--- a/tests/ui/issues/issue-5844.stderr
+++ b/tests/ui/unsafe/extern-function-requires-unsafe-5844.stderr
@@ -1,8 +1,8 @@
error[E0133]: call to unsafe function `rand` is unsafe and requires unsafe function or block
- --> $DIR/issue-5844.rs:6:5
+ --> $DIR/extern-function-requires-unsafe-5844.rs:7:5
|
-LL | issue_5844_aux::rand();
- | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+LL | aux_5844::rand();
+ | ^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
diff --git a/tests/ui/wasm/wasm-import-module.rs b/tests/ui/wasm/wasm-import-module.rs
index 2b3bca9..c38fcb1 100644
--- a/tests/ui/wasm/wasm-import-module.rs
+++ b/tests/ui/wasm/wasm-import-module.rs
@@ -1,12 +1,12 @@
#![feature(link_cfg)]
-#[link(name = "...", wasm_import_module)] //~ ERROR: must be of the form
+#[link(name = "...", wasm_import_module)] //~ ERROR: malformed `link` attribute input
extern "C" {}
-#[link(name = "...", wasm_import_module(x))] //~ ERROR: must be of the form
+#[link(name = "...", wasm_import_module(x))] //~ ERROR: malformed `link` attribute input
extern "C" {}
-#[link(name = "...", wasm_import_module())] //~ ERROR: must be of the form
+#[link(name = "...", wasm_import_module())] //~ ERROR: malformed `link` attribute input
extern "C" {}
#[link(wasm_import_module = "foo", name = "bar")] //~ ERROR: `wasm_import_module` is incompatible with other arguments
diff --git a/tests/ui/wasm/wasm-import-module.stderr b/tests/ui/wasm/wasm-import-module.stderr
index 84f4379..f5ea449 100644
--- a/tests/ui/wasm/wasm-import-module.stderr
+++ b/tests/ui/wasm/wasm-import-module.stderr
@@ -1,20 +1,77 @@
-error: wasm import module must be of the form `wasm_import_module = "string"`
- --> $DIR/wasm-import-module.rs:3:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/wasm-import-module.rs:3:1
|
LL | #[link(name = "...", wasm_import_module)]
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^------------------^^
+ | |
+ | expected this to be of the form `wasm_import_module = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: wasm import module must be of the form `wasm_import_module = "string"`
- --> $DIR/wasm-import-module.rs:6:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/wasm-import-module.rs:6:1
|
LL | #[link(name = "...", wasm_import_module(x))]
- | ^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^---------------------^^
+ | |
+ | expected this to be of the form `wasm_import_module = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", wasm_import_module(x))]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", wasm_import_module(x))]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", wasm_import_module(x))]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", wasm_import_module(x))]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
-error: wasm import module must be of the form `wasm_import_module = "string"`
- --> $DIR/wasm-import-module.rs:9:22
+error[E0539]: malformed `link` attribute input
+ --> $DIR/wasm-import-module.rs:9:1
|
LL | #[link(name = "...", wasm_import_module())]
- | ^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^--------------------^^
+ | |
+ | expected this to be of the form `wasm_import_module = "..."`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...")]
+ |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+ |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+ |
+ = and 1 other candidate
error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
--> $DIR/wasm-import-module.rs:12:8
@@ -36,3 +93,4 @@
error: aborting due to 6 previous errors
+For more information about this error, try `rustc --explain E0539`.