mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
Auto merge of #155519 - JonathanBrouwer:rollup-P17uwTS, r=JonathanBrouwer
Rollup of 12 pull requests Successful merges: - rust-lang/rust#155370 (Add regression test for dead code elimination with drop + panic) - rust-lang/rust#154823 (Replace the spdx-rs dependency with a minimal in-tree SPDX tag-value parser) - rust-lang/rust#155294 (Add test for coalescing of diagnostic attribute duplicates) - rust-lang/rust#155352 (triagebot.toml: Sync `assign.owners` with `autolabel."T-compiler"`) - rust-lang/rust#155431 (Add temporary scope to assert_matches) - rust-lang/rust#153873 (deprecate `std::char` constants and functions) - rust-lang/rust#154865 (libtest: use binary search for --exact test filtering) - rust-lang/rust#154979 (add #[must_use] macros for floats) - rust-lang/rust#155486 (c-variadic: add roundtrip test) - rust-lang/rust#155504 (Remove `AttributeLintKind` variants - part 2) - rust-lang/rust#155510 (Update Tidy python executable path) - rust-lang/rust#155514 (codegen-options docs: remove -Csoft-float)
This commit is contained in:
+41
-108
@@ -199,7 +199,7 @@ dependencies = [
|
|||||||
"rustc-hash 2.1.1",
|
"rustc-hash 2.1.1",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -396,7 +396,7 @@ checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -573,7 +573,6 @@ checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
|
||||||
"windows-link 0.2.1",
|
"windows-link 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -635,10 +634,10 @@ version = "4.5.49"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -768,7 +767,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"similar",
|
"similar",
|
||||||
"spdx-rs",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -804,7 +802,7 @@ dependencies = [
|
|||||||
"nom",
|
"nom",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1036,7 +1034,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"scratch",
|
"scratch",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1050,7 +1048,7 @@ dependencies = [
|
|||||||
"indexmap",
|
"indexmap",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1068,7 +1066,7 @@ dependencies = [
|
|||||||
"indexmap",
|
"indexmap",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1092,7 +1090,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim",
|
"strsim",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1103,7 +1101,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1124,7 +1122,7 @@ checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1145,7 +1143,7 @@ dependencies = [
|
|||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1155,7 +1153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_builder_core",
|
"derive_builder_core",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1167,7 +1165,7 @@ dependencies = [
|
|||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1242,7 +1240,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1663,12 +1661,6 @@ dependencies = [
|
|||||||
"foldhash 0.2.0",
|
"foldhash 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "heck"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -2069,7 +2061,7 @@ checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2356,7 +2348,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2501,7 +2493,7 @@ checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2875,7 +2867,7 @@ dependencies = [
|
|||||||
"pest_meta",
|
"pest_meta",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3085,7 +3077,7 @@ checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3276,7 +3268,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3369,7 +3361,7 @@ checksum = "8100bb34c0a1d0f907143db3149e6b4eea3c33b9ee8b189720168e818303986f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4085,7 +4077,7 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4231,7 +4223,7 @@ dependencies = [
|
|||||||
"fluent-syntax",
|
"fluent-syntax",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4812,7 +4804,7 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4912,7 +4904,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5029,7 +5021,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde_derive_internals",
|
"serde_derive_internals",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5115,7 +5107,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5126,7 +5118,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5259,35 +5251,6 @@ dependencies = [
|
|||||||
"color-eyre",
|
"color-eyre",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spdx-expression"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "53d7ac03c67c572d85049d6db815e20a4a19b41b3d5cca732ac582342021ad77"
|
|
||||||
dependencies = [
|
|
||||||
"nom",
|
|
||||||
"serde",
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spdx-rs"
|
|
||||||
version = "0.5.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "990870190ec8d8c64ba66e4a6746243d6e57d99353991e0e6092334833f429b1"
|
|
||||||
dependencies = [
|
|
||||||
"chrono",
|
|
||||||
"log",
|
|
||||||
"nom",
|
|
||||||
"serde",
|
|
||||||
"spdx-expression",
|
|
||||||
"strum",
|
|
||||||
"strum_macros",
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
"uuid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stable_deref_trait"
|
name = "stable_deref_trait"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@@ -5353,36 +5316,6 @@ version = "0.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum"
|
|
||||||
version = "0.24.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum_macros"
|
|
||||||
version = "0.24.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
|
||||||
dependencies = [
|
|
||||||
"heck 0.4.1",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rustversion",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "1.0.109"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.110"
|
version = "2.0.110"
|
||||||
@@ -5402,7 +5335,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5539,7 +5472,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5550,7 +5483,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5792,7 +5725,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5988,7 +5921,7 @@ checksum = "a1249a628de3ad34b821ecb1001355bca3940bcb2f88558f1a8bd82e977f75b5"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
"unic-langid-impl",
|
"unic-langid-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -6232,7 +6165,7 @@ dependencies = [
|
|||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -6489,7 +6422,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6500,7 +6433,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6796,7 +6729,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -6817,7 +6750,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6837,7 +6770,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -6872,7 +6805,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
use super::prelude::{ALL_TARGETS, AllowedTargets};
|
use super::prelude::{ALL_TARGETS, AllowedTargets};
|
||||||
use super::{AcceptMapping, AttributeParser};
|
use super::{AcceptMapping, AttributeParser};
|
||||||
use crate::context::{AcceptContext, FinalizeContext, Stage};
|
use crate::context::{AcceptContext, FinalizeContext, Stage};
|
||||||
|
use crate::errors::{DocAliasDuplicated, DocAutoCfgExpectsHideOrShow, IllFormedAttributeInput};
|
||||||
use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser};
|
use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser};
|
||||||
use crate::session_diagnostics::{
|
use crate::session_diagnostics::{
|
||||||
DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel,
|
DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel,
|
||||||
@@ -255,9 +256,9 @@ fn add_alias<S: Stage>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(first_definition) = self.attribute.aliases.get(&alias).copied() {
|
if let Some(first_definition) = self.attribute.aliases.get(&alias).copied() {
|
||||||
cx.emit_lint(
|
cx.emit_dyn_lint(
|
||||||
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
||||||
AttributeLintKind::DuplicateDocAlias { first_definition },
|
move |dcx, level| DocAliasDuplicated { first_definition }.into_diag(dcx, level),
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -343,9 +344,9 @@ fn parse_auto_cfg<S: Stage>(
|
|||||||
ArgParser::List(list) => {
|
ArgParser::List(list) => {
|
||||||
for meta in list.mixed() {
|
for meta in list.mixed() {
|
||||||
let MetaItemOrLitParser::MetaItemParser(item) = meta else {
|
let MetaItemOrLitParser::MetaItemParser(item) = meta else {
|
||||||
cx.emit_lint(
|
cx.emit_dyn_lint(
|
||||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||||
AttributeLintKind::DocAutoCfgExpectsHideOrShow,
|
|dcx, level| DocAutoCfgExpectsHideOrShow.into_diag(dcx, level),
|
||||||
meta.span(),
|
meta.span(),
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
@@ -354,9 +355,9 @@ fn parse_auto_cfg<S: Stage>(
|
|||||||
Some(sym::hide) => (HideOrShow::Hide, sym::hide),
|
Some(sym::hide) => (HideOrShow::Hide, sym::hide),
|
||||||
Some(sym::show) => (HideOrShow::Show, sym::show),
|
Some(sym::show) => (HideOrShow::Show, sym::show),
|
||||||
_ => {
|
_ => {
|
||||||
cx.emit_lint(
|
cx.emit_dyn_lint(
|
||||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||||
AttributeLintKind::DocAutoCfgExpectsHideOrShow,
|
|dcx, level| DocAutoCfgExpectsHideOrShow.into_diag(dcx, level),
|
||||||
item.span(),
|
item.span(),
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
@@ -666,12 +667,10 @@ fn accept_single_doc_attr<S: Stage>(
|
|||||||
ArgParser::NoArgs => {
|
ArgParser::NoArgs => {
|
||||||
let suggestions = cx.adcx().suggestions();
|
let suggestions = cx.adcx().suggestions();
|
||||||
let span = cx.attr_span;
|
let span = cx.attr_span;
|
||||||
cx.emit_lint(
|
cx.emit_dyn_lint(
|
||||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||||
AttributeLintKind::IllFormedAttributeInput {
|
move |dcx, level| {
|
||||||
suggestions,
|
IllFormedAttributeInput::new(&suggestions, None, None).into_diag(dcx, level)
|
||||||
docs: None,
|
|
||||||
help: None,
|
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -897,11 +897,18 @@ pub(crate) fn expected_specific_argument_strings(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
|
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
|
||||||
let attr_path = self.attr_path.clone().to_string();
|
let attr_path = self.attr_path.to_string();
|
||||||
let valid_without_list = self.template.word;
|
let valid_without_list = self.template.word;
|
||||||
self.emit_lint(
|
self.emit_dyn_lint(
|
||||||
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
||||||
AttributeLintKind::EmptyAttribute { first_span: span, attr_path, valid_without_list },
|
move |dcx, level| {
|
||||||
|
crate::errors::EmptyAttributeList {
|
||||||
|
attr_span: span,
|
||||||
|
attr_path: &attr_path,
|
||||||
|
valid_without_list,
|
||||||
|
}
|
||||||
|
.into_diag(dcx, level)
|
||||||
|
},
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -916,9 +923,12 @@ pub(crate) fn warn_ill_formed_attribute_input_with_help(
|
|||||||
) {
|
) {
|
||||||
let suggestions = self.suggestions();
|
let suggestions = self.suggestions();
|
||||||
let span = self.attr_span;
|
let span = self.attr_span;
|
||||||
self.emit_lint(
|
self.emit_dyn_lint(
|
||||||
lint,
|
lint,
|
||||||
AttributeLintKind::IllFormedAttributeInput { suggestions, docs: None, help },
|
move |dcx, level| {
|
||||||
|
crate::errors::IllFormedAttributeInput::new(&suggestions, None, help.as_deref())
|
||||||
|
.into_diag(dcx, level)
|
||||||
|
},
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use rustc_errors::MultiSpan;
|
use rustc_errors::{DiagArgValue, MultiSpan};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
@@ -66,3 +66,114 @@ pub(crate) struct UnsafeAttrOutsideUnsafeLint {
|
|||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub suggestion: Option<crate::session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion>,
|
pub suggestion: Option<crate::session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(
|
||||||
|
"{$num_suggestions ->
|
||||||
|
[1] attribute must be of the form {$suggestions}
|
||||||
|
*[other] valid forms for the attribute are {$suggestions}
|
||||||
|
}"
|
||||||
|
)]
|
||||||
|
pub(crate) struct IllFormedAttributeInput {
|
||||||
|
pub num_suggestions: usize,
|
||||||
|
pub suggestions: DiagArgValue,
|
||||||
|
#[note("for more information, visit <{$docs}>")]
|
||||||
|
pub has_docs: bool,
|
||||||
|
pub docs: &'static str,
|
||||||
|
#[subdiagnostic]
|
||||||
|
help: Option<IllFormedAttributeInputHelp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IllFormedAttributeInput {
|
||||||
|
pub(crate) fn new(
|
||||||
|
suggestions: &[String],
|
||||||
|
docs: Option<&'static str>,
|
||||||
|
help: Option<&str>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
num_suggestions: suggestions.len(),
|
||||||
|
suggestions: DiagArgValue::StrListSepByAnd(
|
||||||
|
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
|
||||||
|
),
|
||||||
|
has_docs: docs.is_some(),
|
||||||
|
docs: docs.unwrap_or(""),
|
||||||
|
help: help.map(|h| IllFormedAttributeInputHelp { lint: h.to_string() }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[help(
|
||||||
|
"if you meant to silence a warning, consider using #![allow({$lint})] or #![expect({$lint})]"
|
||||||
|
)]
|
||||||
|
struct IllFormedAttributeInputHelp {
|
||||||
|
pub lint: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag("unused attribute")]
|
||||||
|
#[note(
|
||||||
|
"{$valid_without_list ->
|
||||||
|
[true] using `{$attr_path}` with an empty list is equivalent to not using a list at all
|
||||||
|
*[other] using `{$attr_path}` with an empty list has no effect
|
||||||
|
}"
|
||||||
|
)]
|
||||||
|
pub(crate) struct EmptyAttributeList<'a> {
|
||||||
|
#[suggestion(
|
||||||
|
"{$valid_without_list ->
|
||||||
|
[true] remove these parentheses
|
||||||
|
*[other] remove this attribute
|
||||||
|
}",
|
||||||
|
code = "",
|
||||||
|
applicability = "machine-applicable"
|
||||||
|
)]
|
||||||
|
pub attr_span: Span,
|
||||||
|
pub attr_path: &'a str,
|
||||||
|
pub valid_without_list: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag("`#[{$name}]` attribute cannot be used on {$target}")]
|
||||||
|
#[warning(
|
||||||
|
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
||||||
|
)]
|
||||||
|
#[help("`#[{$name}]` can {$only}be applied to {$applied}")]
|
||||||
|
pub(crate) struct InvalidTargetLint {
|
||||||
|
pub name: String,
|
||||||
|
pub target: &'static str,
|
||||||
|
pub applied: DiagArgValue,
|
||||||
|
pub only: &'static str,
|
||||||
|
#[suggestion(
|
||||||
|
"remove the attribute",
|
||||||
|
code = "",
|
||||||
|
applicability = "machine-applicable",
|
||||||
|
style = "tool-only"
|
||||||
|
)]
|
||||||
|
pub attr_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(
|
||||||
|
"{$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
|
||||||
|
}"
|
||||||
|
)]
|
||||||
|
pub(crate) struct InvalidAttrStyle<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub is_used_as_inner: bool,
|
||||||
|
#[note("this attribute does not have an `!`, which means it is applied to this {$target}")]
|
||||||
|
pub target_span: Option<Span>,
|
||||||
|
pub target: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag("doc alias is duplicated")]
|
||||||
|
pub(crate) struct DocAliasDuplicated {
|
||||||
|
#[label("first defined here")]
|
||||||
|
pub first_definition: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag("only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`")]
|
||||||
|
pub(crate) struct DocAutoCfgExpectsHideOrShow;
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use rustc_ast::AttrStyle;
|
use rustc_ast::AttrStyle;
|
||||||
use rustc_errors::{DiagArgValue, MultiSpan, StashKey};
|
use rustc_errors::{DiagArgValue, Diagnostic, MultiSpan, StashKey};
|
||||||
use rustc_feature::Features;
|
use rustc_feature::Features;
|
||||||
use rustc_hir::attrs::AttributeKind;
|
use rustc_hir::attrs::AttributeKind;
|
||||||
use rustc_hir::lints::AttributeLintKind;
|
|
||||||
use rustc_hir::{AttrItem, Attribute, MethodKind, Target};
|
use rustc_hir::{AttrItem, Attribute, MethodKind, Target};
|
||||||
use rustc_span::{BytePos, Span, Symbol, sym};
|
use rustc_span::{BytePos, Span, Symbol, sym};
|
||||||
|
|
||||||
use crate::AttributeParser;
|
use crate::AttributeParser;
|
||||||
use crate::context::{AcceptContext, Stage};
|
use crate::context::{AcceptContext, Stage};
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
InvalidAttrAtCrateLevel, ItemFollowingInnerAttr, UnsupportedAttributesInWhere,
|
InvalidAttrAtCrateLevel, InvalidTargetLint, ItemFollowingInnerAttr,
|
||||||
|
UnsupportedAttributesInWhere,
|
||||||
};
|
};
|
||||||
use crate::session_diagnostics::InvalidTarget;
|
use crate::session_diagnostics::InvalidTarget;
|
||||||
use crate::target_checking::Policy::Allow;
|
use crate::target_checking::Policy::Allow;
|
||||||
@@ -142,14 +142,19 @@ pub(crate) fn check_target(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let attr_span = cx.attr_span;
|
let attr_span = cx.attr_span;
|
||||||
cx.emit_lint(
|
cx.emit_dyn_lint(
|
||||||
lint,
|
lint,
|
||||||
AttributeLintKind::InvalidTarget {
|
move |dcx, level| {
|
||||||
name: name.to_string(),
|
InvalidTargetLint {
|
||||||
target: target.plural_name(),
|
name: name.to_string(),
|
||||||
only: if only { "only " } else { "" },
|
target: target.plural_name(),
|
||||||
applied,
|
only: if only { "only " } else { "" },
|
||||||
attr_span,
|
applied: DiagArgValue::StrListSepByAnd(
|
||||||
|
applied.iter().map(|i| Cow::Owned(i.to_string())).collect(),
|
||||||
|
),
|
||||||
|
attr_span,
|
||||||
|
}
|
||||||
|
.into_diag(dcx, level)
|
||||||
},
|
},
|
||||||
attr_span,
|
attr_span,
|
||||||
);
|
);
|
||||||
@@ -176,15 +181,24 @@ pub(crate) fn check_crate_level(target: Target, cx: &mut AcceptContext<'_, 'sess
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let kind = AttributeLintKind::InvalidStyle {
|
let name = cx.attr_path.to_string();
|
||||||
name: cx.attr_path.to_string(),
|
let is_used_as_inner = cx.attr_style == AttrStyle::Inner;
|
||||||
is_used_as_inner: cx.attr_style == AttrStyle::Inner,
|
let target_span = cx.target_span;
|
||||||
target: target.name(),
|
|
||||||
target_span: cx.target_span,
|
|
||||||
};
|
|
||||||
let attr_span = cx.attr_span;
|
let attr_span = cx.attr_span;
|
||||||
|
|
||||||
cx.emit_lint(rustc_session::lint::builtin::UNUSED_ATTRIBUTES, kind, attr_span);
|
cx.emit_dyn_lint(
|
||||||
|
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
||||||
|
move |dcx, level| {
|
||||||
|
crate::errors::InvalidAttrStyle {
|
||||||
|
name: &name,
|
||||||
|
is_used_as_inner,
|
||||||
|
target_span: (!is_used_as_inner).then_some(target_span),
|
||||||
|
target: target.name(),
|
||||||
|
}
|
||||||
|
.into_diag(dcx, level)
|
||||||
|
},
|
||||||
|
attr_span,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Fix "Cannot determine resolution" error and remove built-in macros
|
// FIXME: Fix "Cannot determine resolution" error and remove built-in macros
|
||||||
|
|||||||
@@ -8,10 +8,9 @@
|
|||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety,
|
self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety,
|
||||||
};
|
};
|
||||||
use rustc_errors::{Applicability, PResult};
|
use rustc_errors::{Applicability, Diagnostic, PResult};
|
||||||
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, template};
|
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, template};
|
||||||
use rustc_hir::AttrPath;
|
use rustc_hir::AttrPath;
|
||||||
use rustc_hir::lints::AttributeLintKind;
|
|
||||||
use rustc_parse::parse_in;
|
use rustc_parse::parse_in;
|
||||||
use rustc_session::errors::report_lit_error;
|
use rustc_session::errors::report_lit_error;
|
||||||
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
|
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
|
||||||
@@ -210,14 +209,14 @@ pub fn emit_malformed_attribute(
|
|||||||
suggestions.clear();
|
suggestions.clear();
|
||||||
}
|
}
|
||||||
if should_warn(name) {
|
if should_warn(name) {
|
||||||
psess.buffer_lint(
|
let suggestions = suggestions.clone();
|
||||||
|
psess.dyn_buffer_lint(
|
||||||
ILL_FORMED_ATTRIBUTE_INPUT,
|
ILL_FORMED_ATTRIBUTE_INPUT,
|
||||||
span,
|
span,
|
||||||
ast::CRATE_NODE_ID,
|
ast::CRATE_NODE_ID,
|
||||||
AttributeLintKind::IllFormedAttributeInput {
|
move |dcx, level| {
|
||||||
suggestions: suggestions.clone(),
|
crate::errors::IllFormedAttributeInput::new(&suggestions, template.docs, None)
|
||||||
docs: template.docs,
|
.into_diag(dcx, level)
|
||||||
help: None,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -370,6 +370,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> Box<ast::Expr> {
|
|||||||
let ecx = &cx.ext_cx;
|
let ecx = &cx.ext_cx;
|
||||||
|
|
||||||
let mut tests = cx.test_cases.clone();
|
let mut tests = cx.test_cases.clone();
|
||||||
|
// Note that this sort is load-bearing: the libtest harness uses binary search to find tests by
|
||||||
|
// name.
|
||||||
tests.sort_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
|
tests.sort_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
|
||||||
|
|
||||||
ecx.expr_array_ref(
|
ecx.expr_array_ref(
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
use std::{assert_matches, iter, ptr};
|
use std::{assert_matches, iter, ptr};
|
||||||
|
|
||||||
use rustc_abi::{
|
use rustc_abi::{
|
||||||
Align, BackendRepr, Float, HasDataLayout, NumScalableVectors, Primitive, Size, WrappingRange,
|
Align, BackendRepr, Float, HasDataLayout, Integer, NumScalableVectors, Primitive, Size,
|
||||||
|
WrappingRange,
|
||||||
};
|
};
|
||||||
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
|
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
|
||||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||||
@@ -288,10 +289,17 @@ fn codegen_intrinsic_call(
|
|||||||
bug!("the va_arg intrinsic does not support non-scalar types")
|
bug!("the va_arg intrinsic does not support non-scalar types")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We reject types that would never be passed as varargs in C because
|
||||||
|
// they get promoted to a larger type, specifically integers smaller than
|
||||||
|
// c_int and float type smaller than c_double.
|
||||||
match scalar.primitive() {
|
match scalar.primitive() {
|
||||||
Primitive::Pointer(_) => {
|
Primitive::Pointer(_) => {
|
||||||
// Pointers are always OK.
|
// Pointers are always OK.
|
||||||
emit_va_arg(self, args[0], result.layout.ty)
|
}
|
||||||
|
Primitive::Int(Integer::I128, _) => {
|
||||||
|
// FIXME: maybe we should support these? At least on 32-bit powerpc
|
||||||
|
// the logic in LLVM does not handle i128 correctly though.
|
||||||
|
bug!("the va_arg intrinsic does not support `i128`/`u128`")
|
||||||
}
|
}
|
||||||
Primitive::Int(..) => {
|
Primitive::Int(..) => {
|
||||||
let int_width = self.cx().size_of(result.layout.ty).bits();
|
let int_width = self.cx().size_of(result.layout.ty).bits();
|
||||||
@@ -305,27 +313,26 @@ fn codegen_intrinsic_call(
|
|||||||
target_c_int_width
|
target_c_int_width
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
emit_va_arg(self, args[0], result.layout.ty)
|
|
||||||
}
|
}
|
||||||
Primitive::Float(Float::F16) => {
|
Primitive::Float(Float::F16) => {
|
||||||
bug!("the va_arg intrinsic does not support `f16`")
|
bug!("the va_arg intrinsic does not support `f16`")
|
||||||
}
|
}
|
||||||
Primitive::Float(Float::F32) => {
|
Primitive::Float(Float::F32) => {
|
||||||
if self.cx().sess().target.arch == Arch::Avr {
|
// c_double is actually f32 on avr.
|
||||||
// c_double is actually f32 on avr.
|
if self.cx().sess().target.arch != Arch::Avr {
|
||||||
emit_va_arg(self, args[0], result.layout.ty)
|
|
||||||
} else {
|
|
||||||
bug!("the va_arg intrinsic does not support `f32` on this target")
|
bug!("the va_arg intrinsic does not support `f32` on this target")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Primitive::Float(Float::F64) => {
|
Primitive::Float(Float::F64) => {
|
||||||
// 64-bit floats are always OK.
|
// 64-bit floats are always OK.
|
||||||
emit_va_arg(self, args[0], result.layout.ty)
|
|
||||||
}
|
}
|
||||||
Primitive::Float(Float::F128) => {
|
Primitive::Float(Float::F128) => {
|
||||||
|
// FIXME(f128) figure out whether we should support this.
|
||||||
bug!("the va_arg intrinsic does not support `f128`")
|
bug!("the va_arg intrinsic does not support `f128`")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit_va_arg(self, args[0], result.layout.ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::volatile_load | sym::unaligned_volatile_load => {
|
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use rustc_data_structures::sync::DynSend;
|
use rustc_data_structures::sync::DynSend;
|
||||||
use rustc_errors::{Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, Level};
|
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level};
|
||||||
use rustc_hir::lints::{AttributeLintKind, FormatWarning};
|
use rustc_hir::lints::{AttributeLintKind, FormatWarning};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
@@ -35,50 +34,6 @@ pub struct DecorateAttrLint<'a, 'sess, 'tcx> {
|
|||||||
impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> {
|
impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> {
|
||||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
||||||
match self.diagnostic {
|
match self.diagnostic {
|
||||||
AttributeLintKind::IllFormedAttributeInput { suggestions, docs, help } => {
|
|
||||||
lints::IllFormedAttributeInput {
|
|
||||||
num_suggestions: suggestions.len(),
|
|
||||||
suggestions: DiagArgValue::StrListSepByAnd(
|
|
||||||
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
|
|
||||||
),
|
|
||||||
has_docs: docs.is_some(),
|
|
||||||
docs: docs.unwrap_or(""),
|
|
||||||
help: help.clone().map(|h| lints::IllFormedAttributeInputHelp { lint: h }),
|
|
||||||
}
|
|
||||||
.into_diag(dcx, level)
|
|
||||||
}
|
|
||||||
AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => {
|
|
||||||
lints::EmptyAttributeList {
|
|
||||||
attr_span: *first_span,
|
|
||||||
attr_path: attr_path.clone(),
|
|
||||||
valid_without_list: *valid_without_list,
|
|
||||||
}
|
|
||||||
.into_diag(dcx, level)
|
|
||||||
}
|
|
||||||
AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => {
|
|
||||||
lints::InvalidTargetLint {
|
|
||||||
name: name.clone(),
|
|
||||||
target,
|
|
||||||
applied: DiagArgValue::StrListSepByAnd(
|
|
||||||
applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
|
|
||||||
),
|
|
||||||
only,
|
|
||||||
attr_span: *attr_span,
|
|
||||||
}
|
|
||||||
.into_diag(dcx, level)
|
|
||||||
}
|
|
||||||
&AttributeLintKind::InvalidStyle {
|
|
||||||
ref name,
|
|
||||||
is_used_as_inner,
|
|
||||||
target,
|
|
||||||
target_span,
|
|
||||||
} => lints::InvalidAttrStyle {
|
|
||||||
name: name.clone(),
|
|
||||||
is_used_as_inner,
|
|
||||||
target_span: (!is_used_as_inner).then_some(target_span),
|
|
||||||
target,
|
|
||||||
}
|
|
||||||
.into_diag(dcx, level),
|
|
||||||
&AttributeLintKind::UnexpectedCfgName(name, value) => {
|
&AttributeLintKind::UnexpectedCfgName(name, value) => {
|
||||||
check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
|
check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
|
||||||
.into_diag(dcx, level)
|
.into_diag(dcx, level)
|
||||||
@@ -87,13 +42,6 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
|||||||
check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value)
|
check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value)
|
||||||
.into_diag(dcx, level)
|
.into_diag(dcx, level)
|
||||||
}
|
}
|
||||||
&AttributeLintKind::DuplicateDocAlias { first_definition } => {
|
|
||||||
lints::DocAliasDuplicated { first_defn: first_definition }.into_diag(dcx, level)
|
|
||||||
}
|
|
||||||
|
|
||||||
&AttributeLintKind::DocAutoCfgExpectsHideOrShow => {
|
|
||||||
lints::DocAutoCfgExpectsHideOrShow.into_diag(dcx, level)
|
|
||||||
}
|
|
||||||
|
|
||||||
&AttributeLintKind::AmbiguousDeriveHelpers => {
|
&AttributeLintKind::AmbiguousDeriveHelpers => {
|
||||||
lints::AmbiguousDeriveHelpers.into_diag(dcx, level)
|
lints::AmbiguousDeriveHelpers.into_diag(dcx, level)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::formatting::DiagMessageAddArg;
|
use rustc_errors::formatting::DiagMessageAddArg;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
|
Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
|
||||||
EmissionGuarantee, Level, Subdiagnostic, SuggestionStyle, msg,
|
EmissionGuarantee, Level, Subdiagnostic, SuggestionStyle, msg,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@@ -3025,32 +3025,6 @@ pub(crate) enum CargoHelp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(jdonszelmann): duplicated in rustc_attr_parsing, should be moved there completely.
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(
|
|
||||||
"{$num_suggestions ->
|
|
||||||
[1] attribute must be of the form {$suggestions}
|
|
||||||
*[other] valid forms for the attribute are {$suggestions}
|
|
||||||
}"
|
|
||||||
)]
|
|
||||||
pub(crate) struct IllFormedAttributeInput {
|
|
||||||
pub num_suggestions: usize,
|
|
||||||
pub suggestions: DiagArgValue,
|
|
||||||
#[note("for more information, visit <{$docs}>")]
|
|
||||||
pub has_docs: bool,
|
|
||||||
pub docs: &'static str,
|
|
||||||
#[subdiagnostic]
|
|
||||||
pub help: Option<IllFormedAttributeInputHelp>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
|
||||||
#[help(
|
|
||||||
"if you meant to silence a warning, consider using #![allow({$lint})] or #![expect({$lint})]"
|
|
||||||
)]
|
|
||||||
pub(crate) struct IllFormedAttributeInputHelp {
|
|
||||||
pub lint: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag("creating a {$shared_label}reference to mutable static")]
|
#[diag("creating a {$shared_label}reference to mutable static")]
|
||||||
pub(crate) struct RefOfMutStatic<'a> {
|
pub(crate) struct RefOfMutStatic<'a> {
|
||||||
@@ -3308,63 +3282,6 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag("unused attribute")]
|
|
||||||
#[note(
|
|
||||||
"{$valid_without_list ->
|
|
||||||
[true] using `{$attr_path}` with an empty list is equivalent to not using a list at all
|
|
||||||
*[other] using `{$attr_path}` with an empty list has no effect
|
|
||||||
}"
|
|
||||||
)]
|
|
||||||
pub(crate) struct EmptyAttributeList {
|
|
||||||
#[suggestion(
|
|
||||||
"{$valid_without_list ->
|
|
||||||
[true] remove these parentheses
|
|
||||||
*[other] remove this attribute
|
|
||||||
}",
|
|
||||||
code = "",
|
|
||||||
applicability = "machine-applicable"
|
|
||||||
)]
|
|
||||||
pub attr_span: Span,
|
|
||||||
pub attr_path: String,
|
|
||||||
pub valid_without_list: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag("`#[{$name}]` attribute cannot be used on {$target}")]
|
|
||||||
#[warning(
|
|
||||||
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
|
||||||
)]
|
|
||||||
#[help("`#[{$name}]` can {$only}be applied to {$applied}")]
|
|
||||||
pub(crate) struct InvalidTargetLint {
|
|
||||||
pub name: String,
|
|
||||||
pub target: &'static str,
|
|
||||||
pub applied: DiagArgValue,
|
|
||||||
pub only: &'static str,
|
|
||||||
#[suggestion(
|
|
||||||
"remove the attribute",
|
|
||||||
code = "",
|
|
||||||
applicability = "machine-applicable",
|
|
||||||
style = "tool-only"
|
|
||||||
)]
|
|
||||||
pub attr_span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(
|
|
||||||
"{$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
|
|
||||||
}"
|
|
||||||
)]
|
|
||||||
pub(crate) struct InvalidAttrStyle {
|
|
||||||
pub name: String,
|
|
||||||
pub is_used_as_inner: bool,
|
|
||||||
#[note("this attribute does not have an `!`, which means it is applied to this {$target}")]
|
|
||||||
pub target_span: Option<Span>,
|
|
||||||
pub target: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag("malformed `doc` attribute input")]
|
#[diag("malformed `doc` attribute input")]
|
||||||
#[warning(
|
#[warning(
|
||||||
@@ -3386,17 +3303,6 @@ pub(crate) struct InvalidAttrStyle {
|
|||||||
)]
|
)]
|
||||||
pub(crate) struct ExpectedNameValue;
|
pub(crate) struct ExpectedNameValue;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag("doc alias is duplicated")]
|
|
||||||
pub(crate) struct DocAliasDuplicated {
|
|
||||||
#[label("first defined here")]
|
|
||||||
pub first_defn: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag("only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`")]
|
|
||||||
pub(crate) struct DocAutoCfgExpectsHideOrShow;
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag("there exists a built-in attribute with the same name")]
|
#[diag("there exists a built-in attribute with the same name")]
|
||||||
pub(crate) struct AmbiguousDeriveHelpers;
|
pub(crate) struct AmbiguousDeriveHelpers;
|
||||||
|
|||||||
@@ -654,98 +654,32 @@ pub enum DeprecatedSinceKind {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AttributeLintKind {
|
pub enum AttributeLintKind {
|
||||||
IllFormedAttributeInput {
|
|
||||||
suggestions: Vec<String>,
|
|
||||||
docs: Option<&'static str>,
|
|
||||||
help: Option<String>,
|
|
||||||
},
|
|
||||||
EmptyAttribute {
|
|
||||||
first_span: Span,
|
|
||||||
attr_path: String,
|
|
||||||
valid_without_list: bool,
|
|
||||||
},
|
|
||||||
InvalidTarget {
|
|
||||||
name: String,
|
|
||||||
target: &'static str,
|
|
||||||
applied: Vec<String>,
|
|
||||||
only: &'static str,
|
|
||||||
attr_span: Span,
|
|
||||||
},
|
|
||||||
InvalidStyle {
|
|
||||||
name: String,
|
|
||||||
is_used_as_inner: bool,
|
|
||||||
target: &'static str,
|
|
||||||
target_span: Span,
|
|
||||||
},
|
|
||||||
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
||||||
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
||||||
DuplicateDocAlias {
|
DocAutoCfgHideShowUnexpectedItem { attr_name: Symbol },
|
||||||
first_definition: Span,
|
DocAutoCfgHideShowExpectsList { attr_name: Symbol },
|
||||||
},
|
|
||||||
DocAutoCfgExpectsHideOrShow,
|
|
||||||
DocAutoCfgHideShowUnexpectedItem {
|
|
||||||
attr_name: Symbol,
|
|
||||||
},
|
|
||||||
DocAutoCfgHideShowExpectsList {
|
|
||||||
attr_name: Symbol,
|
|
||||||
},
|
|
||||||
DocInvalid,
|
DocInvalid,
|
||||||
AmbiguousDeriveHelpers,
|
AmbiguousDeriveHelpers,
|
||||||
DocUnknownInclude {
|
DocUnknownInclude { span: Span, inner: &'static str, value: Symbol },
|
||||||
span: Span,
|
DocUnknownSpotlight { span: Span },
|
||||||
inner: &'static str,
|
DocUnknownPasses { name: Symbol, span: Span },
|
||||||
value: Symbol,
|
DocUnknownPlugins { span: Span },
|
||||||
},
|
DocUnknownAny { name: Symbol },
|
||||||
DocUnknownSpotlight {
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
DocUnknownPasses {
|
|
||||||
name: Symbol,
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
DocUnknownPlugins {
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
DocUnknownAny {
|
|
||||||
name: Symbol,
|
|
||||||
},
|
|
||||||
DocAutoCfgWrongLiteral,
|
DocAutoCfgWrongLiteral,
|
||||||
DocTestTakesList,
|
DocTestTakesList,
|
||||||
DocTestUnknown {
|
DocTestUnknown { name: Symbol },
|
||||||
name: Symbol,
|
|
||||||
},
|
|
||||||
DocTestLiteral,
|
DocTestLiteral,
|
||||||
AttrCrateLevelOnly,
|
AttrCrateLevelOnly,
|
||||||
DoNotRecommendDoesNotExpectArgs,
|
DoNotRecommendDoesNotExpectArgs,
|
||||||
CrateTypeUnknown {
|
CrateTypeUnknown { span: Span, suggested: Option<Symbol> },
|
||||||
span: Span,
|
|
||||||
suggested: Option<Symbol>,
|
|
||||||
},
|
|
||||||
MalformedDoc,
|
MalformedDoc,
|
||||||
ExpectedNoArgs,
|
ExpectedNoArgs,
|
||||||
ExpectedNameValue,
|
ExpectedNameValue,
|
||||||
MalFormedDiagnosticAttribute {
|
MalFormedDiagnosticAttribute { attribute: &'static str, options: &'static str, span: Span },
|
||||||
attribute: &'static str,
|
MalformedDiagnosticFormat { warning: FormatWarning },
|
||||||
options: &'static str,
|
DiagnosticWrappedParserError { description: String, label: String, span: Span },
|
||||||
span: Span,
|
IgnoredDiagnosticOption { option_name: Symbol, first_span: Span, later_span: Span },
|
||||||
},
|
MissingOptionsForDiagnosticAttribute { attribute: &'static str, options: &'static str },
|
||||||
MalformedDiagnosticFormat {
|
|
||||||
warning: FormatWarning,
|
|
||||||
},
|
|
||||||
DiagnosticWrappedParserError {
|
|
||||||
description: String,
|
|
||||||
label: String,
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
IgnoredDiagnosticOption {
|
|
||||||
option_name: Symbol,
|
|
||||||
first_span: Span,
|
|
||||||
later_span: Span,
|
|
||||||
},
|
|
||||||
MissingOptionsForDiagnosticAttribute {
|
|
||||||
attribute: &'static str,
|
|
||||||
options: &'static str,
|
|
||||||
},
|
|
||||||
NonMetaItemDiagnosticAttribute,
|
NonMetaItemDiagnosticAttribute,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,31 +93,31 @@
|
|||||||
|
|
||||||
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`. Use [`char::MAX`] instead.
|
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`. Use [`char::MAX`] instead.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on `char`")]
|
||||||
pub const MAX: char = char::MAX;
|
pub const MAX: char = char::MAX;
|
||||||
|
|
||||||
/// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
|
|
||||||
/// UTF-8 encoding.
|
|
||||||
#[unstable(feature = "char_max_len", issue = "121714")]
|
|
||||||
pub const MAX_LEN_UTF8: usize = char::MAX_LEN_UTF8;
|
|
||||||
|
|
||||||
/// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
|
|
||||||
/// to UTF-16 encoding.
|
|
||||||
#[unstable(feature = "char_max_len", issue = "121714")]
|
|
||||||
pub const MAX_LEN_UTF16: usize = char::MAX_LEN_UTF16;
|
|
||||||
|
|
||||||
/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
|
/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
|
||||||
/// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead.
|
/// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead.
|
||||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||||
|
#[deprecated(
|
||||||
|
since = "TBD",
|
||||||
|
note = "replaced by the `REPLACEMENT_CHARACTER` associated constant on `char`"
|
||||||
|
)]
|
||||||
pub const REPLACEMENT_CHARACTER: char = char::REPLACEMENT_CHARACTER;
|
pub const REPLACEMENT_CHARACTER: char = char::REPLACEMENT_CHARACTER;
|
||||||
|
|
||||||
/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
|
/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
|
||||||
/// `char` and `str` methods are based on. Use [`char::UNICODE_VERSION`] instead.
|
/// `char` and `str` methods are based on. Use [`char::UNICODE_VERSION`] instead.
|
||||||
#[stable(feature = "unicode_version", since = "1.45.0")]
|
#[stable(feature = "unicode_version", since = "1.45.0")]
|
||||||
|
#[deprecated(
|
||||||
|
since = "TBD",
|
||||||
|
note = "replaced by the `UNICODE_VERSION` associated constant on `char`"
|
||||||
|
)]
|
||||||
pub const UNICODE_VERSION: (u8, u8, u8) = char::UNICODE_VERSION;
|
pub const UNICODE_VERSION: (u8, u8, u8) = char::UNICODE_VERSION;
|
||||||
|
|
||||||
/// Creates an iterator over the UTF-16 encoded code points in `iter`, returning
|
/// Creates an iterator over the UTF-16 encoded code points in `iter`, returning
|
||||||
/// unpaired surrogates as `Err`s. Use [`char::decode_utf16`] instead.
|
/// unpaired surrogates as `Err`s. Use [`char::decode_utf16`] instead.
|
||||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||||
|
#[deprecated(since = "TBD", note = "replaced by the `decode_utf16` method on `char`")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
|
pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
|
||||||
self::decode::decode_utf16(iter)
|
self::decode::decode_utf16(iter)
|
||||||
@@ -126,6 +126,7 @@ pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::Into
|
|||||||
/// Converts a `u32` to a `char`. Use [`char::from_u32`] instead.
|
/// Converts a `u32` to a `char`. Use [`char::from_u32`] instead.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
|
#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
|
||||||
|
#[deprecated(since = "TBD", note = "replaced by the `from_u32` method on `char`")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_u32(i: u32) -> Option<char> {
|
pub const fn from_u32(i: u32) -> Option<char> {
|
||||||
@@ -136,6 +137,7 @@ pub const fn from_u32(i: u32) -> Option<char> {
|
|||||||
/// instead.
|
/// instead.
|
||||||
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
|
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
|
||||||
#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
|
#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
|
||||||
|
#[deprecated(since = "TBD", note = "replaced by the `from_u32_unchecked` method on `char`")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn from_u32_unchecked(i: u32) -> char {
|
pub const unsafe fn from_u32_unchecked(i: u32) -> char {
|
||||||
@@ -146,6 +148,7 @@ pub const fn from_u32(i: u32) -> Option<char> {
|
|||||||
/// Converts a digit in the given radix to a `char`. Use [`char::from_digit`] instead.
|
/// Converts a digit in the given radix to a `char`. Use [`char::from_digit`] instead.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
|
#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
|
||||||
|
#[deprecated(since = "TBD", note = "replaced by the `from_digit` method on `char`")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
|
pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ macro_rules! assert_ne {
|
|||||||
#[allow_internal_unstable(panic_internals)]
|
#[allow_internal_unstable(panic_internals)]
|
||||||
#[rustc_macro_transparency = "semiopaque"]
|
#[rustc_macro_transparency = "semiopaque"]
|
||||||
pub macro assert_matches {
|
pub macro assert_matches {
|
||||||
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
|
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {{
|
||||||
match $left {
|
match $left {
|
||||||
$( $pattern )|+ $( if $guard )? => {}
|
$( $pattern )|+ $( if $guard )? => {}
|
||||||
ref left_val => {
|
ref left_val => {
|
||||||
@@ -179,8 +179,8 @@ macro_rules! assert_ne {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}},
|
||||||
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => {
|
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => {{
|
||||||
match $left {
|
match $left {
|
||||||
$( $pattern )|+ $( if $guard )? => {}
|
$( $pattern )|+ $( if $guard )? => {}
|
||||||
ref left_val => {
|
ref left_val => {
|
||||||
@@ -191,7 +191,7 @@ macro_rules! assert_ne {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Selects code at compile-time based on `cfg` predicates.
|
/// Selects code at compile-time based on `cfg` predicates.
|
||||||
|
|||||||
@@ -508,6 +508,7 @@ pub const fn is_normal(self) -> bool {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[must_use]
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
let bits = self.to_bits();
|
let bits = self.to_bits();
|
||||||
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {
|
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {
|
||||||
@@ -608,6 +609,7 @@ pub const fn is_sign_negative(self) -> bool {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[doc(alias = "nextUp")]
|
#[doc(alias = "nextUp")]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub const fn next_up(self) -> Self {
|
pub const fn next_up(self) -> Self {
|
||||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||||
// denormals to zero. This is in general unsound and unsupported, but here
|
// denormals to zero. This is in general unsound and unsupported, but here
|
||||||
@@ -662,6 +664,7 @@ pub const fn next_up(self) -> Self {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[doc(alias = "nextDown")]
|
#[doc(alias = "nextDown")]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub const fn next_down(self) -> Self {
|
pub const fn next_down(self) -> Self {
|
||||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||||
// denormals to zero. This is in general unsound and unsupported, but here
|
// denormals to zero. This is in general unsound and unsupported, but here
|
||||||
@@ -907,6 +910,8 @@ pub const fn minimum(self, other: f128) -> f128 {
|
|||||||
#[doc(alias = "average")]
|
#[doc(alias = "average")]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[must_use = "this returns the result of the operation, \
|
||||||
|
without modifying the original"]
|
||||||
pub const fn midpoint(self, other: f128) -> f128 {
|
pub const fn midpoint(self, other: f128) -> f128 {
|
||||||
const HI: f128 = f128::MAX / 2.;
|
const HI: f128 = f128::MAX / 2.;
|
||||||
|
|
||||||
|
|||||||
@@ -500,6 +500,7 @@ pub const fn is_normal(self) -> bool {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[must_use]
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
let b = self.to_bits();
|
let b = self.to_bits();
|
||||||
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
||||||
@@ -604,6 +605,7 @@ pub const fn is_sign_negative(self) -> bool {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[doc(alias = "nextUp")]
|
#[doc(alias = "nextUp")]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub const fn next_up(self) -> Self {
|
pub const fn next_up(self) -> Self {
|
||||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||||
// denormals to zero. This is in general unsound and unsupported, but here
|
// denormals to zero. This is in general unsound and unsupported, but here
|
||||||
@@ -658,6 +660,7 @@ pub const fn next_up(self) -> Self {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[doc(alias = "nextDown")]
|
#[doc(alias = "nextDown")]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub const fn next_down(self) -> Self {
|
pub const fn next_down(self) -> Self {
|
||||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||||
// denormals to zero. This is in general unsound and unsupported, but here
|
// denormals to zero. This is in general unsound and unsupported, but here
|
||||||
@@ -901,6 +904,8 @@ pub const fn minimum(self, other: f16) -> f16 {
|
|||||||
#[doc(alias = "average")]
|
#[doc(alias = "average")]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[must_use = "this returns the result of the operation, \
|
||||||
|
without modifying the original"]
|
||||||
pub const fn midpoint(self, other: f16) -> f16 {
|
pub const fn midpoint(self, other: f16) -> f16 {
|
||||||
const HI: f16 = f16::MAX / 2.;
|
const HI: f16 = f16::MAX / 2.;
|
||||||
|
|
||||||
|
|||||||
@@ -723,6 +723,7 @@ pub const fn is_normal(self) -> bool {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
|
||||||
|
#[must_use]
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
||||||
// around buggy codegen for x87 targets (see
|
// around buggy codegen for x87 targets (see
|
||||||
@@ -822,6 +823,7 @@ pub const fn is_sign_negative(self) -> bool {
|
|||||||
#[doc(alias = "nextUp")]
|
#[doc(alias = "nextUp")]
|
||||||
#[stable(feature = "float_next_up_down", since = "1.86.0")]
|
#[stable(feature = "float_next_up_down", since = "1.86.0")]
|
||||||
#[rustc_const_stable(feature = "float_next_up_down", since = "1.86.0")]
|
#[rustc_const_stable(feature = "float_next_up_down", since = "1.86.0")]
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub const fn next_up(self) -> Self {
|
pub const fn next_up(self) -> Self {
|
||||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||||
// denormals to zero. This is in general unsound and unsupported, but here
|
// denormals to zero. This is in general unsound and unsupported, but here
|
||||||
@@ -873,6 +875,7 @@ pub const fn next_up(self) -> Self {
|
|||||||
#[doc(alias = "nextDown")]
|
#[doc(alias = "nextDown")]
|
||||||
#[stable(feature = "float_next_up_down", since = "1.86.0")]
|
#[stable(feature = "float_next_up_down", since = "1.86.0")]
|
||||||
#[rustc_const_stable(feature = "float_next_up_down", since = "1.86.0")]
|
#[rustc_const_stable(feature = "float_next_up_down", since = "1.86.0")]
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub const fn next_down(self) -> Self {
|
pub const fn next_down(self) -> Self {
|
||||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||||
// denormals to zero. This is in general unsound and unsupported, but here
|
// denormals to zero. This is in general unsound and unsupported, but here
|
||||||
@@ -1089,6 +1092,8 @@ pub const fn minimum(self, other: f32) -> f32 {
|
|||||||
#[doc(alias = "average")]
|
#[doc(alias = "average")]
|
||||||
#[stable(feature = "num_midpoint", since = "1.85.0")]
|
#[stable(feature = "num_midpoint", since = "1.85.0")]
|
||||||
#[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
|
#[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
|
||||||
|
#[must_use = "this returns the result of the operation, \
|
||||||
|
without modifying the original"]
|
||||||
pub const fn midpoint(self, other: f32) -> f32 {
|
pub const fn midpoint(self, other: f32) -> f32 {
|
||||||
cfg_select! {
|
cfg_select! {
|
||||||
// Allow faster implementation that have known good 64-bit float
|
// Allow faster implementation that have known good 64-bit float
|
||||||
|
|||||||
@@ -722,6 +722,7 @@ pub const fn is_normal(self) -> bool {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
|
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
|
||||||
|
#[must_use]
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
||||||
// around buggy codegen for x87 targets (see
|
// around buggy codegen for x87 targets (see
|
||||||
@@ -839,6 +840,7 @@ pub fn is_negative(self) -> bool {
|
|||||||
#[doc(alias = "nextUp")]
|
#[doc(alias = "nextUp")]
|
||||||
#[stable(feature = "float_next_up_down", since = "1.86.0")]
|
#[stable(feature = "float_next_up_down", since = "1.86.0")]
|
||||||
#[rustc_const_stable(feature = "float_next_up_down", since = "1.86.0")]
|
#[rustc_const_stable(feature = "float_next_up_down", since = "1.86.0")]
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub const fn next_up(self) -> Self {
|
pub const fn next_up(self) -> Self {
|
||||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||||
// denormals to zero. This is in general unsound and unsupported, but here
|
// denormals to zero. This is in general unsound and unsupported, but here
|
||||||
@@ -890,6 +892,7 @@ pub const fn next_up(self) -> Self {
|
|||||||
#[doc(alias = "nextDown")]
|
#[doc(alias = "nextDown")]
|
||||||
#[stable(feature = "float_next_up_down", since = "1.86.0")]
|
#[stable(feature = "float_next_up_down", since = "1.86.0")]
|
||||||
#[rustc_const_stable(feature = "float_next_up_down", since = "1.86.0")]
|
#[rustc_const_stable(feature = "float_next_up_down", since = "1.86.0")]
|
||||||
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
pub const fn next_down(self) -> Self {
|
pub const fn next_down(self) -> Self {
|
||||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||||
// denormals to zero. This is in general unsound and unsupported, but here
|
// denormals to zero. This is in general unsound and unsupported, but here
|
||||||
@@ -1107,6 +1110,8 @@ pub const fn minimum(self, other: f64) -> f64 {
|
|||||||
#[doc(alias = "average")]
|
#[doc(alias = "average")]
|
||||||
#[stable(feature = "num_midpoint", since = "1.85.0")]
|
#[stable(feature = "num_midpoint", since = "1.85.0")]
|
||||||
#[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
|
#[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
|
||||||
|
#[must_use = "this returns the result of the operation, \
|
||||||
|
without modifying the original"]
|
||||||
pub const fn midpoint(self, other: f64) -> f64 {
|
pub const fn midpoint(self, other: f64) -> f64 {
|
||||||
const HI: f64 = f64::MAX / 2.;
|
const HI: f64 = f64::MAX / 2.;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#![feature(bstr)]
|
#![feature(bstr)]
|
||||||
#![feature(cfg_target_has_reliable_f16_f128)]
|
#![feature(cfg_target_has_reliable_f16_f128)]
|
||||||
#![feature(char_internals)]
|
#![feature(char_internals)]
|
||||||
#![feature(char_max_len)]
|
|
||||||
#![feature(clone_to_uninit)]
|
#![feature(clone_to_uninit)]
|
||||||
#![feature(cmp_minmax)]
|
#![feature(cmp_minmax)]
|
||||||
#![feature(const_array)]
|
#![feature(const_array)]
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#![allow(unused_must_use)]
|
#![allow(unused_must_use)]
|
||||||
|
|
||||||
|
use std::{assert_matches, debug_assert_matches};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
trait Trait {
|
trait Trait {
|
||||||
fn blah(&self);
|
fn blah(&self);
|
||||||
@@ -219,3 +221,27 @@ fn _matches_does_not_trigger_non_exhaustive_omitted_patterns_lint(o: core::sync:
|
|||||||
// Ordering is a #[non_exhaustive] enum from a separate crate
|
// Ordering is a #[non_exhaustive] enum from a separate crate
|
||||||
let _m = matches!(o, core::sync::atomic::Ordering::Relaxed);
|
let _m = matches!(o, core::sync::atomic::Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MutRefWithDrop<'a>(&'a mut u32);
|
||||||
|
|
||||||
|
// MutRefWithDrop needs to have a non-trivial drop to encounter potential lifetime issues if the
|
||||||
|
// macros don't introduce a temporary scope.
|
||||||
|
impl Drop for MutRefWithDrop<'_> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
*self.0 = u32::MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn temporary_scope_introduction() {
|
||||||
|
// Fails to compile if the macros don't introduce a temporary scope, since `&mut val` would
|
||||||
|
// create a second mutable borrow while `MutRefWithDrop` still holds a unique ref.
|
||||||
|
// See https://github.com/rust-lang/rust/issues/154406 for reference.
|
||||||
|
let mut val = 0;
|
||||||
|
|
||||||
|
(assert_matches!(*MutRefWithDrop(&mut val).0, 0), std::mem::take(&mut val));
|
||||||
|
(assert_matches!(*MutRefWithDrop(&mut val).0, 0, "msg"), std::mem::take(&mut val));
|
||||||
|
|
||||||
|
(debug_assert_matches!(*MutRefWithDrop(&mut val).0, 0), std::mem::take(&mut val));
|
||||||
|
(debug_assert_matches!(*MutRefWithDrop(&mut val).0, 0, "msg"), std::mem::take(&mut val));
|
||||||
|
}
|
||||||
|
|||||||
@@ -643,6 +643,7 @@ pub fn atan2(self, other: f128) -> f128 {
|
|||||||
#[doc(alias = "sincos")]
|
#[doc(alias = "sincos")]
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub fn sin_cos(self) -> (f128, f128) {
|
pub fn sin_cos(self) -> (f128, f128) {
|
||||||
(self.sin(), self.cos())
|
(self.sin(), self.cos())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -608,6 +608,7 @@ pub fn atan2(self, other: f16) -> f16 {
|
|||||||
#[doc(alias = "sincos")]
|
#[doc(alias = "sincos")]
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub fn sin_cos(self) -> (f16, f16) {
|
pub fn sin_cos(self) -> (f16, f16) {
|
||||||
(self.sin(), self.cos())
|
(self.sin(), self.cos())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -907,6 +907,7 @@ pub fn atan2(self, other: f32) -> f32 {
|
|||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub fn sin_cos(self) -> (f32, f32) {
|
pub fn sin_cos(self) -> (f32, f32) {
|
||||||
(self.sin(), self.cos())
|
(self.sin(), self.cos())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -907,6 +907,7 @@ pub fn atan2(self, other: f64) -> f64 {
|
|||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub fn sin_cos(self) -> (f64, f64) {
|
pub fn sin_cos(self) -> (f64, f64) {
|
||||||
(self.sin(), self.cos())
|
(self.sin(), self.cos())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
use super::options::{Options, OutputFormat};
|
use super::options::{Options, OutputFormat};
|
||||||
use super::test_result::TestResult;
|
use super::test_result::TestResult;
|
||||||
use super::time::{TestExecTime, TestSuiteExecTime};
|
use super::time::{TestExecTime, TestSuiteExecTime};
|
||||||
use super::types::{NamePadding, TestDesc, TestDescAndFn};
|
use super::types::{NamePadding, TestDesc, TestDescAndFn, TestList};
|
||||||
use super::{filter_tests, run_tests, term};
|
use super::{filter_tests, run_tests, term};
|
||||||
|
|
||||||
/// Generic wrapper over stdout.
|
/// Generic wrapper over stdout.
|
||||||
@@ -170,7 +170,7 @@ fn current_test_count(&self) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List the tests to console, and optionally to logfile. Filters are honored.
|
// List the tests to console, and optionally to logfile. Filters are honored.
|
||||||
pub(crate) fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> {
|
pub(crate) fn list_tests_console(opts: &TestOpts, tests: TestList) -> io::Result<()> {
|
||||||
let output = match term::stdout() {
|
let output = match term::stdout() {
|
||||||
None => OutputLocation::Raw(io::stdout().lock()),
|
None => OutputLocation::Raw(io::stdout().lock()),
|
||||||
Some(t) => OutputLocation::Pretty(t),
|
Some(t) => OutputLocation::Pretty(t),
|
||||||
@@ -186,7 +186,7 @@ pub(crate) fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) ->
|
|||||||
let mut st = ConsoleTestDiscoveryState::new(opts)?;
|
let mut st = ConsoleTestDiscoveryState::new(opts)?;
|
||||||
|
|
||||||
out.write_discovery_start()?;
|
out.write_discovery_start()?;
|
||||||
for test in filter_tests(opts, tests).into_iter() {
|
for test in filter_tests(opts, tests) {
|
||||||
use crate::TestFn::*;
|
use crate::TestFn::*;
|
||||||
|
|
||||||
let TestDescAndFn { desc, testfn } = test;
|
let TestDescAndFn { desc, testfn } = test;
|
||||||
@@ -307,8 +307,9 @@ pub(crate) fn get_formatter(opts: &TestOpts, max_name_len: usize) -> Box<dyn Out
|
|||||||
|
|
||||||
/// A simple console test runner.
|
/// A simple console test runner.
|
||||||
/// Runs provided tests reporting process and results to the stdout.
|
/// Runs provided tests reporting process and results to the stdout.
|
||||||
pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<bool> {
|
pub fn run_tests_console(opts: &TestOpts, tests: TestList) -> io::Result<bool> {
|
||||||
let max_name_len = tests
|
let max_name_len = tests
|
||||||
|
.tests
|
||||||
.iter()
|
.iter()
|
||||||
.max_by_key(|t| len_if_padded(t))
|
.max_by_key(|t| len_if_padded(t))
|
||||||
.map(|t| t.desc.name.as_slice().len())
|
.map(|t| t.desc.name.as_slice().len())
|
||||||
|
|||||||
+78
-17
@@ -49,7 +49,7 @@ pub mod test {
|
|||||||
pub use crate::time::{TestExecTime, TestTimeOptions};
|
pub use crate::time::{TestExecTime, TestTimeOptions};
|
||||||
pub use crate::types::{
|
pub use crate::types::{
|
||||||
DynTestFn, DynTestName, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc,
|
DynTestFn, DynTestName, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc,
|
||||||
TestDescAndFn, TestId, TestName, TestType,
|
TestDescAndFn, TestId, TestList, TestListOrder, TestName, TestType,
|
||||||
};
|
};
|
||||||
pub use crate::{assert_test_result, filter_tests, run_test, test_main, test_main_static};
|
pub use crate::{assert_test_result, filter_tests, run_test, test_main, test_main_static};
|
||||||
}
|
}
|
||||||
@@ -106,6 +106,16 @@ pub fn test_main_with_exit_callback<F: FnOnce()>(
|
|||||||
tests: Vec<TestDescAndFn>,
|
tests: Vec<TestDescAndFn>,
|
||||||
options: Option<Options>,
|
options: Option<Options>,
|
||||||
exit_callback: F,
|
exit_callback: F,
|
||||||
|
) {
|
||||||
|
let tests = TestList::new(tests, TestListOrder::Unsorted);
|
||||||
|
test_main_inner(args, tests, options, exit_callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main_inner<F: FnOnce()>(
|
||||||
|
args: &[String],
|
||||||
|
tests: TestList,
|
||||||
|
options: Option<Options>,
|
||||||
|
exit_callback: F,
|
||||||
) {
|
) {
|
||||||
let mut opts = match cli::parse_opts(args) {
|
let mut opts = match cli::parse_opts(args) {
|
||||||
Some(Ok(o)) => o,
|
Some(Ok(o)) => o,
|
||||||
@@ -180,7 +190,9 @@ pub fn test_main_with_exit_callback<F: FnOnce()>(
|
|||||||
pub fn test_main_static(tests: &[&TestDescAndFn]) {
|
pub fn test_main_static(tests: &[&TestDescAndFn]) {
|
||||||
let args = env::args().collect::<Vec<_>>();
|
let args = env::args().collect::<Vec<_>>();
|
||||||
let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect();
|
let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect();
|
||||||
test_main(&args, owned_tests, None)
|
// Tests are sorted by name at compile time by mk_tests_slice.
|
||||||
|
let tests = TestList::new(owned_tests, TestListOrder::Sorted);
|
||||||
|
test_main_inner(&args, tests, None, || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A variant optimized for invocation with a static test vector.
|
/// A variant optimized for invocation with a static test vector.
|
||||||
@@ -229,7 +241,9 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
|
|||||||
|
|
||||||
let args = env::args().collect::<Vec<_>>();
|
let args = env::args().collect::<Vec<_>>();
|
||||||
let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect();
|
let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect();
|
||||||
test_main(&args, owned_tests, Some(Options::new().panic_abort(true)))
|
// Tests are sorted by name at compile time by mk_tests_slice.
|
||||||
|
let tests = TestList::new(owned_tests, TestListOrder::Sorted);
|
||||||
|
test_main_inner(&args, tests, Some(Options::new().panic_abort(true)), || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clones static values for putting into a dynamic vector, which test_main()
|
/// Clones static values for putting into a dynamic vector, which test_main()
|
||||||
@@ -298,7 +312,7 @@ fn total_len(&self) -> usize {
|
|||||||
|
|
||||||
pub fn run_tests<F>(
|
pub fn run_tests<F>(
|
||||||
opts: &TestOpts,
|
opts: &TestOpts,
|
||||||
tests: Vec<TestDescAndFn>,
|
tests: TestList,
|
||||||
mut notify_about_test_event: F,
|
mut notify_about_test_event: F,
|
||||||
) -> io::Result<()>
|
) -> io::Result<()>
|
||||||
where
|
where
|
||||||
@@ -334,7 +348,7 @@ struct TimeoutEntry {
|
|||||||
timeout: Instant,
|
timeout: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
let tests_len = tests.len();
|
let tests_len = tests.tests.len();
|
||||||
|
|
||||||
let mut filtered = FilteredTests { tests: Vec::new(), benches: Vec::new(), next_id: 0 };
|
let mut filtered = FilteredTests { tests: Vec::new(), benches: Vec::new(), next_id: 0 };
|
||||||
|
|
||||||
@@ -512,25 +526,48 @@ fn calc_timeout(timeout_queue: &VecDeque<TimeoutEntry>) -> Option<Duration> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
|
pub fn filter_tests(opts: &TestOpts, tests: TestList) -> Vec<TestDescAndFn> {
|
||||||
|
let TestList { tests, order } = tests;
|
||||||
let mut filtered = tests;
|
let mut filtered = tests;
|
||||||
let matches_filter = |test: &TestDescAndFn, filter: &str| {
|
|
||||||
let test_name = test.desc.name.as_slice();
|
|
||||||
|
|
||||||
match opts.filter_exact {
|
// Remove tests that don't match the test filter.
|
||||||
true => test_name == filter,
|
|
||||||
false => test_name.contains(filter),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove tests that don't match the test filter
|
|
||||||
if !opts.filters.is_empty() {
|
if !opts.filters.is_empty() {
|
||||||
filtered.retain(|test| opts.filters.iter().any(|filter| matches_filter(test, filter)));
|
if opts.filter_exact && order == TestListOrder::Sorted {
|
||||||
|
// Let's say that `f` is the number of filters and `n` is the number
|
||||||
|
// of tests.
|
||||||
|
//
|
||||||
|
// The test array is sorted by name (guaranteed by the caller via
|
||||||
|
// TestListOrder::Sorted), so use binary search for O(f log n)
|
||||||
|
// exact-match lookups instead of an O(n) linear scan.
|
||||||
|
//
|
||||||
|
// This is important for Miri, where the interpreted execution makes
|
||||||
|
// the linear scan very expensive.
|
||||||
|
filtered = filter_exact_match(filtered, &opts.filters);
|
||||||
|
} else {
|
||||||
|
filtered.retain(|test| {
|
||||||
|
let test_name = test.desc.name.as_slice();
|
||||||
|
opts.filters.iter().any(|filter| {
|
||||||
|
if opts.filter_exact {
|
||||||
|
test_name == filter.as_str()
|
||||||
|
} else {
|
||||||
|
test_name.contains(filter.as_str())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip tests that match any of the skip filters
|
// Skip tests that match any of the skip filters
|
||||||
|
//
|
||||||
|
// After exact positive filtering above, the filtered set is small, so a
|
||||||
|
// linear scan is acceptable even under Miri.
|
||||||
if !opts.skip.is_empty() {
|
if !opts.skip.is_empty() {
|
||||||
filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf)));
|
filtered.retain(|test| {
|
||||||
|
let name = test.desc.name.as_slice();
|
||||||
|
!opts.skip.iter().any(|sf| {
|
||||||
|
if opts.filter_exact { name == sf.as_str() } else { name.contains(sf.as_str()) }
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Excludes #[should_panic] tests
|
// Excludes #[should_panic] tests
|
||||||
@@ -553,6 +590,30 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
|
|||||||
filtered
|
filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract tests whose names exactly match one of the given `filters`, using
|
||||||
|
/// binary search on the (assumed sorted) test list.
|
||||||
|
fn filter_exact_match(mut tests: Vec<TestDescAndFn>, filters: &[String]) -> Vec<TestDescAndFn> {
|
||||||
|
// Binary search for each filter in the sorted test list.
|
||||||
|
let mut indexes: Vec<usize> = filters
|
||||||
|
.iter()
|
||||||
|
.filter_map(|f| tests.binary_search_by(|t| t.desc.name.as_slice().cmp(f.as_str())).ok())
|
||||||
|
.collect();
|
||||||
|
indexes.sort_unstable();
|
||||||
|
indexes.dedup();
|
||||||
|
|
||||||
|
// Extract matching tests. Process indexes in descending order so that
|
||||||
|
// swap_remove (which replaces the removed element with the last) does not
|
||||||
|
// invalidate indexes we haven't visited yet.
|
||||||
|
let mut result = Vec::with_capacity(indexes.len());
|
||||||
|
for &idx in indexes.iter().rev() {
|
||||||
|
result.push(tests.swap_remove(idx));
|
||||||
|
}
|
||||||
|
// Reverse to restore the original sorted order, since we extracted the
|
||||||
|
// matching tests in descending index order.
|
||||||
|
result.reverse();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
|
pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
|
||||||
// convert benchmarks to tests, if we're not benchmarking them
|
// convert benchmarks to tests, if we're not benchmarking them
|
||||||
tests
|
tests
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ fn filter_for_ignored_option() {
|
|||||||
opts.run_tests = true;
|
opts.run_tests = true;
|
||||||
opts.run_ignored = RunIgnored::Only;
|
opts.run_ignored = RunIgnored::Only;
|
||||||
|
|
||||||
let tests = one_ignored_one_unignored_test();
|
let tests = TestList::new(one_ignored_one_unignored_test(), TestListOrder::Unsorted);
|
||||||
let filtered = filter_tests(&opts, tests);
|
let filtered = filter_tests(&opts, tests);
|
||||||
|
|
||||||
assert_eq!(filtered.len(), 1);
|
assert_eq!(filtered.len(), 1);
|
||||||
@@ -494,7 +494,7 @@ fn run_include_ignored_option() {
|
|||||||
opts.run_tests = true;
|
opts.run_tests = true;
|
||||||
opts.run_ignored = RunIgnored::Yes;
|
opts.run_ignored = RunIgnored::Yes;
|
||||||
|
|
||||||
let tests = one_ignored_one_unignored_test();
|
let tests = TestList::new(one_ignored_one_unignored_test(), TestListOrder::Unsorted);
|
||||||
let filtered = filter_tests(&opts, tests);
|
let filtered = filter_tests(&opts, tests);
|
||||||
|
|
||||||
assert_eq!(filtered.len(), 2);
|
assert_eq!(filtered.len(), 2);
|
||||||
@@ -527,7 +527,7 @@ fn exclude_should_panic_option() {
|
|||||||
testfn: DynTestFn(Box::new(move || Ok(()))),
|
testfn: DynTestFn(Box::new(move || Ok(()))),
|
||||||
});
|
});
|
||||||
|
|
||||||
let filtered = filter_tests(&opts, tests);
|
let filtered = filter_tests(&opts, TestList::new(tests, TestListOrder::Unsorted));
|
||||||
|
|
||||||
assert_eq!(filtered.len(), 2);
|
assert_eq!(filtered.len(), 2);
|
||||||
assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
|
assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
|
||||||
@@ -535,8 +535,8 @@ fn exclude_should_panic_option() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exact_filter_match() {
|
fn exact_filter_match() {
|
||||||
fn tests() -> Vec<TestDescAndFn> {
|
fn tests() -> TestList {
|
||||||
["base", "base::test", "base::test1", "base::test2"]
|
let tests = ["base", "base::test", "base::test1", "base::test2"]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|name| TestDescAndFn {
|
.map(|name| TestDescAndFn {
|
||||||
desc: TestDesc {
|
desc: TestDesc {
|
||||||
@@ -555,7 +555,8 @@ fn tests() -> Vec<TestDescAndFn> {
|
|||||||
},
|
},
|
||||||
testfn: DynTestFn(Box::new(move || Ok(()))),
|
testfn: DynTestFn(Box::new(move || Ok(()))),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect();
|
||||||
|
TestList::new(tests, TestListOrder::Sorted)
|
||||||
}
|
}
|
||||||
|
|
||||||
let substr =
|
let substr =
|
||||||
@@ -908,7 +909,8 @@ fn f(_: &mut Bencher) -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
run_tests(&TestOpts { run_tests: true, ..TestOpts::new() }, vec![desc], notify).unwrap();
|
let tests = TestList::new(vec![desc], TestListOrder::Unsorted);
|
||||||
|
run_tests(&TestOpts { run_tests: true, ..TestOpts::new() }, tests, notify).unwrap();
|
||||||
let result = rx.recv().unwrap().result;
|
let result = rx.recv().unwrap().result;
|
||||||
assert_eq!(result, TrFailed);
|
assert_eq!(result, TrFailed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,3 +284,30 @@ pub const fn new_doctest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether a [`TestList`]'s tests are known to be sorted by name.
|
||||||
|
///
|
||||||
|
/// When tests are sorted, `filter_tests` can use binary search for `--exact`
|
||||||
|
/// matches instead of a linear scan.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum TestListOrder {
|
||||||
|
/// Tests are sorted by name. This is guaranteed for tests generated by
|
||||||
|
/// `rustc --test` (see `mk_tests_slice` in
|
||||||
|
/// `compiler/rustc_builtin_macros/src/test_harness.rs`).
|
||||||
|
Sorted,
|
||||||
|
/// Test order is unknown; binary search must not be used.
|
||||||
|
Unsorted,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A list of tests, tagged with whether they are sorted by name.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TestList {
|
||||||
|
pub tests: Vec<TestDescAndFn>,
|
||||||
|
pub order: TestListOrder,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestList {
|
||||||
|
pub fn new(tests: Vec<TestDescAndFn>, order: TestListOrder) -> Self {
|
||||||
|
Self { tests, order }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -655,16 +655,6 @@ deleted once compilation finishes. It takes one of the following values:
|
|||||||
* `y`, `yes`, `on`, `true` or no value: save temporary files.
|
* `y`, `yes`, `on`, `true` or no value: save temporary files.
|
||||||
* `n`, `no`, `off` or `false`: delete temporary files (the default).
|
* `n`, `no`, `off` or `false`: delete temporary files (the default).
|
||||||
|
|
||||||
## soft-float
|
|
||||||
|
|
||||||
This option controls whether `rustc` generates code that emulates floating
|
|
||||||
point instructions in software. It takes one of the following values:
|
|
||||||
|
|
||||||
* `y`, `yes`, `on`, `true` or no value: use soft floats.
|
|
||||||
* `n`, `no`, `off` or `false`: use hardware floats (the default).
|
|
||||||
|
|
||||||
This flag only works on `*eabihf` targets and **is unsound and deprecated**.
|
|
||||||
|
|
||||||
## split-debuginfo
|
## split-debuginfo
|
||||||
|
|
||||||
This option controls the emission of "split debuginfo" for debug information
|
This option controls the emission of "split debuginfo" for debug information
|
||||||
|
|||||||
@@ -10,4 +10,3 @@ anyhow = "1.0.65"
|
|||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
serde_json = "1.0.85"
|
serde_json = "1.0.85"
|
||||||
similar = "2.7.0"
|
similar = "2.7.0"
|
||||||
spdx-rs = "0.5.1"
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
mod licenses;
|
mod licenses;
|
||||||
mod path_tree;
|
mod path_tree;
|
||||||
mod reuse;
|
mod reuse;
|
||||||
|
mod spdx;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
|||||||
@@ -15,18 +15,15 @@ pub(crate) fn collect(
|
|||||||
let raw = &obtain_spdx_document(reuse_exe)?;
|
let raw = &obtain_spdx_document(reuse_exe)?;
|
||||||
println!("finished gathering the license information from REUSE in {:.2?}", start.elapsed());
|
println!("finished gathering the license information from REUSE in {:.2?}", start.elapsed());
|
||||||
|
|
||||||
let document = spdx_rs::parsers::spdx_from_tag_value(&raw)?;
|
let files = crate::spdx::parse_tag_value(raw)?;
|
||||||
|
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
for file in document.file_information {
|
for file in files {
|
||||||
let concluded_license = file.concluded_license.expect("File should have licence info");
|
|
||||||
let copyright_text = file.copyright_text.expect("File should have copyright text");
|
|
||||||
let license = interner.intern(License {
|
let license = interner.intern(License {
|
||||||
spdx: concluded_license.to_string(),
|
spdx: file.concluded_license,
|
||||||
copyright: copyright_text.split('\n').map(|s| s.into()).collect(),
|
copyright: file.copyright_text.split('\n').map(|s| s.into()).collect(),
|
||||||
});
|
});
|
||||||
|
result.push((file.name.into(), license));
|
||||||
result.push((file.file_name.into(), license));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
use anyhow::Error;
|
||||||
|
|
||||||
|
/// A single file entry extracted from an SPDX tag-value document.
|
||||||
|
pub(crate) struct SpdxFileEntry {
|
||||||
|
pub(crate) name: String,
|
||||||
|
pub(crate) concluded_license: String,
|
||||||
|
pub(crate) copyright_text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses an SPDX tag-value document and extracts file information.
|
||||||
|
///
|
||||||
|
/// This is a minimal parser that only extracts the fields we need
|
||||||
|
/// (FileName, LicenseConcluded, FileCopyrightText) rather than the full model.
|
||||||
|
/// The format is specified by the SPDX specification:
|
||||||
|
/// each line is a `Tag: Value` pair,
|
||||||
|
/// and multi-line values are wrapped in `<text>…</text>`.
|
||||||
|
pub(crate) fn parse_tag_value(input: &str) -> Result<Vec<SpdxFileEntry>, Error> {
|
||||||
|
let mut files = Vec::new();
|
||||||
|
let mut current_name: Option<String> = None;
|
||||||
|
let mut current_license: Option<String> = None;
|
||||||
|
let mut current_copyright: Option<String> = None;
|
||||||
|
|
||||||
|
let mut lines = input.lines();
|
||||||
|
while let Some(line) = lines.next() {
|
||||||
|
let Some((tag, value)) = line.split_once(": ") else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let value = resolve_multiline_value(value, &mut lines)?;
|
||||||
|
|
||||||
|
match tag {
|
||||||
|
"FileName" => {
|
||||||
|
// A new file section begins. Flush the previous one if present.
|
||||||
|
if let Some(name) = current_name.take() {
|
||||||
|
files.push(build_file_entry(
|
||||||
|
name,
|
||||||
|
current_license.take(),
|
||||||
|
current_copyright.take(),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
current_name = Some(value);
|
||||||
|
current_license = None;
|
||||||
|
current_copyright = None;
|
||||||
|
}
|
||||||
|
"LicenseConcluded" => current_license = Some(value),
|
||||||
|
"FileCopyrightText" => current_copyright = Some(value),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the last file section.
|
||||||
|
if let Some(name) = current_name {
|
||||||
|
files.push(build_file_entry(name, current_license, current_copyright)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolves a tag value that might span multiple lines using `<text>…</text>`.
|
||||||
|
fn resolve_multiline_value<'a>(
|
||||||
|
value: &str,
|
||||||
|
further_lines: &mut impl Iterator<Item = &'a str>,
|
||||||
|
) -> Result<String, Error> {
|
||||||
|
let Some(start) = value.strip_prefix("<text>") else {
|
||||||
|
return Ok(value.to_string());
|
||||||
|
};
|
||||||
|
|
||||||
|
// The closing tag might be on the same line.
|
||||||
|
if let Some(content) = start.strip_suffix("</text>") {
|
||||||
|
return Ok(content.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut text = start.to_string();
|
||||||
|
for line in further_lines.by_ref() {
|
||||||
|
if let Some(rest) = line.strip_suffix("</text>") {
|
||||||
|
text.push('\n');
|
||||||
|
text.push_str(rest);
|
||||||
|
return Ok(text);
|
||||||
|
}
|
||||||
|
text.push('\n');
|
||||||
|
text.push_str(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
anyhow::bail!("unexpected end of input inside <text> block")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_file_entry(
|
||||||
|
name: String,
|
||||||
|
concluded_license: Option<String>,
|
||||||
|
copyright_text: Option<String>,
|
||||||
|
) -> Result<SpdxFileEntry, Error> {
|
||||||
|
Ok(SpdxFileEntry {
|
||||||
|
name,
|
||||||
|
concluded_license: concluded_license
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("file missing LicenseConcluded"))?,
|
||||||
|
copyright_text: copyright_text
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("file missing FileCopyrightText"))?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
// Clause 8.1 ("File name field") specifies that each file section begins with
|
||||||
|
// a `FileName` tag whose value is a relative path prefixed with "./".
|
||||||
|
// Clause 8.5 ("Concluded license") and 8.8 ("Copyright text") give the
|
||||||
|
// corresponding per-file fields.
|
||||||
|
// <https://spdx.github.io/spdx-spec/v2.3/file-information/>
|
||||||
|
#[test]
|
||||||
|
fn single_file_entry() {
|
||||||
|
let input = "\
|
||||||
|
FileName: ./package/foo.c
|
||||||
|
LicenseConcluded: LGPL-2.0-only
|
||||||
|
FileCopyrightText: Copyright 2008-2010 John Smith";
|
||||||
|
|
||||||
|
let files = parse_tag_value(input).unwrap();
|
||||||
|
assert_eq!(files.len(), 1);
|
||||||
|
assert_eq!(files[0].name, "./package/foo.c");
|
||||||
|
assert_eq!(files[0].concluded_license, "LGPL-2.0-only");
|
||||||
|
assert_eq!(files[0].copyright_text, "Copyright 2008-2010 John Smith");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clause 8.5 shows compound SPDX licence expressions as valid values for
|
||||||
|
// `LicenseConcluded`, e.g. "(LGPL-2.0-only OR LicenseRef-2)".
|
||||||
|
// <https://spdx.github.io/spdx-spec/v2.3/file-information/>
|
||||||
|
#[test]
|
||||||
|
fn compound_license_expression() {
|
||||||
|
let input = "\
|
||||||
|
FileName: ./src/lib.rs
|
||||||
|
LicenseConcluded: (LGPL-2.0-only OR LicenseRef-2)
|
||||||
|
FileCopyrightText: Copyright Example Company";
|
||||||
|
|
||||||
|
let files = parse_tag_value(input).unwrap();
|
||||||
|
assert_eq!(files.len(), 1);
|
||||||
|
assert_eq!(files[0].concluded_license, "(LGPL-2.0-only OR LicenseRef-2)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clause 8.8 shows the copyright text wrapped in a single-line
|
||||||
|
// <text>...</text> block: e.g.
|
||||||
|
// `FileCopyrightText: <text>Copyright 2008-2010 John Smith</text>`
|
||||||
|
// <https://spdx.github.io/spdx-spec/v2.3/file-information/>
|
||||||
|
#[test]
|
||||||
|
fn single_line_text_block() {
|
||||||
|
let input = "\
|
||||||
|
FileName: ./package/foo.c
|
||||||
|
LicenseConcluded: LGPL-2.0-only
|
||||||
|
FileCopyrightText: <text>Copyright 2008-2010 John Smith</text>";
|
||||||
|
|
||||||
|
let files = parse_tag_value(input).unwrap();
|
||||||
|
assert_eq!(files.len(), 1);
|
||||||
|
assert_eq!(files[0].copyright_text, "Copyright 2008-2010 John Smith");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clause 6.10 ("Creator comment") demonstrates a multi-line <text>...</text> block.
|
||||||
|
// <https://spdx.github.io/spdx-spec/v2.3/document-creation-information/>
|
||||||
|
#[test]
|
||||||
|
fn multi_line_text_block() {
|
||||||
|
let input = "\
|
||||||
|
FileName: ./package/foo.c
|
||||||
|
LicenseConcluded: MIT
|
||||||
|
FileCopyrightText: <text>Copyright 2008-2010 John Smith
|
||||||
|
Copyright 2019 Jane Doe</text>";
|
||||||
|
|
||||||
|
let files = parse_tag_value(input).unwrap();
|
||||||
|
assert_eq!(files.len(), 1);
|
||||||
|
assert_eq!(files[0].copyright_text, "Copyright 2008-2010 John Smith\nCopyright 2019 Jane Doe");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clause 5 ("Composition of an SPDX document") states that a document may
|
||||||
|
// contain zero or many File Information sections. Each `FileName` tag starts
|
||||||
|
// a new section, so consecutive file blocks must be parsed independently.
|
||||||
|
// <https://spdx.github.io/spdx-spec/v2.3/composition-of-an-SPDX-document/>
|
||||||
|
#[test]
|
||||||
|
fn multiple_file_entries() {
|
||||||
|
let input = "\
|
||||||
|
FileName: ./package/foo.c
|
||||||
|
LicenseConcluded: LGPL-2.0-only
|
||||||
|
FileCopyrightText: Copyright 2008-2010 John Smith
|
||||||
|
FileName: ./package/bar.c
|
||||||
|
LicenseConcluded: MIT
|
||||||
|
FileCopyrightText: Copyright Example Company";
|
||||||
|
|
||||||
|
let files = parse_tag_value(input).unwrap();
|
||||||
|
assert_eq!(files.len(), 2);
|
||||||
|
|
||||||
|
assert_eq!(files[0].name, "./package/foo.c");
|
||||||
|
assert_eq!(files[0].concluded_license, "LGPL-2.0-only");
|
||||||
|
assert_eq!(files[0].copyright_text, "Copyright 2008-2010 John Smith");
|
||||||
|
|
||||||
|
assert_eq!(files[1].name, "./package/bar.c");
|
||||||
|
assert_eq!(files[1].concluded_license, "MIT");
|
||||||
|
assert_eq!(files[1].copyright_text, "Copyright Example Company");
|
||||||
|
}
|
||||||
|
|
||||||
|
// A file section without a `LicenseConcluded` tag is malformed.
|
||||||
|
#[test]
|
||||||
|
fn missing_license_is_an_error() {
|
||||||
|
let input = "\
|
||||||
|
FileName: ./package/foo.c
|
||||||
|
FileCopyrightText: Copyright 2008-2010 John Smith";
|
||||||
|
|
||||||
|
assert!(parse_tag_value(input).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
// A file section without a `FileCopyrightText` tag is malformed.
|
||||||
|
#[test]
|
||||||
|
fn missing_copyright_is_an_error() {
|
||||||
|
let input = "\
|
||||||
|
FileName: ./package/foo.c
|
||||||
|
LicenseConcluded: MIT";
|
||||||
|
|
||||||
|
assert!(parse_tag_value(input).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
// A section with an unterminated <text> block (no closing </text>) is malformed.
|
||||||
|
#[test]
|
||||||
|
fn unterminated_text_block_is_an_error() {
|
||||||
|
let input = "\
|
||||||
|
FileName: ./package/foo.c
|
||||||
|
LicenseConcluded: MIT
|
||||||
|
FileCopyrightText: <text>Copyright 2008-2010 John Smith";
|
||||||
|
|
||||||
|
assert!(parse_tag_value(input).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
// A document with no `FileName` tags at all should produce an empty result.
|
||||||
|
#[test]
|
||||||
|
fn empty_document_returns_no_entries() {
|
||||||
|
let input = "\
|
||||||
|
SPDXVersion: SPDX-2.3
|
||||||
|
DataLicense: CC0-1.0";
|
||||||
|
|
||||||
|
let files = parse_tag_value(input).unwrap();
|
||||||
|
assert!(files.is_empty());
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
/// Path to find the python executable within a virtual environment
|
/// Path to find the python executable within a virtual environment
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const REL_PY_PATH: &[&str] = &["Scripts", "python3.exe"];
|
const REL_PY_PATH: &[&str] = &["Scripts", "python.exe"];
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
const REL_PY_PATH: &[&str] = &["bin", "python3"];
|
const REL_PY_PATH: &[&str] = &["bin", "python3"];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
//@ compile-flags: -Copt-level=3
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// Regression test for #114532.
|
||||||
|
// Dead code elimination used to fail when a Drop impl contained a panic
|
||||||
|
// and a potentially-panicking function was called after the value was created.
|
||||||
|
|
||||||
|
struct Foo(bool);
|
||||||
|
|
||||||
|
impl Drop for Foo {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
panic!("dead");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @foo(
|
||||||
|
// CHECK-NOT: panic
|
||||||
|
// CHECK-NOT: call void @{{.*}}panicking
|
||||||
|
// CHECK: call {{.*}} @unknown(
|
||||||
|
// CHECK-NEXT: ret void
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn foo() {
|
||||||
|
let _a = Foo(true);
|
||||||
|
unsafe {
|
||||||
|
unknown(9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "Rust" {
|
||||||
|
fn unknown(x: i32) -> bool;
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
//@ run-pass
|
||||||
|
//@ ignore-backends: gcc
|
||||||
|
#![feature(c_variadic, const_c_variadic, const_destruct, const_raw_ptr_comparison)]
|
||||||
|
|
||||||
|
use std::ffi::*;
|
||||||
|
|
||||||
|
// In rustc we implement `va_arg` for the callee reading from a VaList, but still rely on LLVM
|
||||||
|
// for exactly how to pass c-variadic arguments and for constructing the VaList. Here we test
|
||||||
|
// that the rustc implementation works with what LLVM gives us.
|
||||||
|
|
||||||
|
#[allow(improper_ctypes_definitions)]
|
||||||
|
const unsafe extern "C" fn variadic<T: VaArgSafe>(mut ap: ...) -> (T, T) {
|
||||||
|
let x = ap.arg::<T>();
|
||||||
|
// Intersperse a small type to test alignment logic. A `u32` (i.e. `c_uint`) is the smallest
|
||||||
|
// type that implements `VaArgSafe`: smaller types would automatically be promoted.
|
||||||
|
assert!(ap.arg::<u32>() == 0xAAAA_AAAA);
|
||||||
|
let y = ap.arg::<T>();
|
||||||
|
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! roundtrip {
|
||||||
|
($ty:ty, $a:expr, $b:expr) => {
|
||||||
|
const {
|
||||||
|
let a: $ty = $a;
|
||||||
|
let b: $ty = $b;
|
||||||
|
let (x, y) = variadic::<$ty>(a, 0xAAAA_AAAAu32, b);
|
||||||
|
assert!(a == x);
|
||||||
|
assert!(b == y);
|
||||||
|
}
|
||||||
|
|
||||||
|
let a: $ty = $a;
|
||||||
|
let b: $ty = $b;
|
||||||
|
assert_eq!(variadic::<$ty>(a, 0xAAAA_AAAAu32, b), (a, b))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! roundtrip_ptr {
|
||||||
|
($ty:ty, $a:expr, $b:expr) => {
|
||||||
|
const {
|
||||||
|
let a: $ty = $a;
|
||||||
|
let b: $ty = $b;
|
||||||
|
let (x, y) = variadic::<$ty>(a, 0xAAAA_AAAAu32, b);
|
||||||
|
assert!(a.guaranteed_eq(x).unwrap());
|
||||||
|
assert!(b.guaranteed_eq(y).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
let a: $ty = $a;
|
||||||
|
let b: $ty = $b;
|
||||||
|
assert_eq!(variadic::<$ty>(a, 0xAAAA_AAAAu32, b), (a, b))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
roundtrip!(i32, -1, -2);
|
||||||
|
roundtrip!(i64, -1, -2);
|
||||||
|
roundtrip!(isize, -1, -2);
|
||||||
|
roundtrip!(c_int, -1, -2);
|
||||||
|
roundtrip!(c_long, -1, -2);
|
||||||
|
roundtrip!(c_longlong, -1, -2);
|
||||||
|
|
||||||
|
roundtrip!(u32, 1, 2);
|
||||||
|
roundtrip!(u64, 1, 2);
|
||||||
|
roundtrip!(usize, 1, 2);
|
||||||
|
roundtrip!(c_uint, 1, 2);
|
||||||
|
roundtrip!(c_ulong, 1, 2);
|
||||||
|
roundtrip!(c_ulonglong, 1, 2);
|
||||||
|
|
||||||
|
roundtrip!(f64, 3.14, 6.28);
|
||||||
|
roundtrip!(c_double, 3.14, 6.28);
|
||||||
|
|
||||||
|
static mut A: u32 = 1u32;
|
||||||
|
static mut B: u32 = 2u32;
|
||||||
|
roundtrip_ptr!(*const u32, &raw const A, &raw const B);
|
||||||
|
roundtrip_ptr!(*mut u32, &raw mut A, &raw mut B);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
error[E0277]: this message
|
||||||
|
--> $DIR/duplicate_coalescing.rs:15:17
|
||||||
|
|
|
||||||
|
LL | takes_trait(());
|
||||||
|
| ----------- ^^ this label
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
= help: the trait `Trait` is not implemented for `()`
|
||||||
|
= note: a note
|
||||||
|
= note: another note
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/duplicate_coalescing.rs:10:1
|
||||||
|
|
|
||||||
|
LL | trait Trait {}
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
note: required by a bound in `takes_trait`
|
||||||
|
--> $DIR/duplicate_coalescing.rs:12:24
|
||||||
|
|
|
||||||
|
LL | fn takes_trait(_: impl Trait) {}
|
||||||
|
| ^^^^^ required by this bound in `takes_trait`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
error[E0277]: this message
|
||||||
|
--> $DIR/duplicate_coalescing.rs:15:17
|
||||||
|
|
|
||||||
|
LL | takes_trait(());
|
||||||
|
| ----------- ^^ this label
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
= help: the trait `Trait` is not implemented for `()`
|
||||||
|
= note: a note
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/duplicate_coalescing.rs:10:1
|
||||||
|
|
|
||||||
|
LL | trait Trait {}
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
note: required by a bound in `takes_trait`
|
||||||
|
--> $DIR/duplicate_coalescing.rs:12:24
|
||||||
|
|
|
||||||
|
LL | fn takes_trait(_: impl Trait) {}
|
||||||
|
| ^^^^^ required by this bound in `takes_trait`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
error[E0277]: this message
|
||||||
|
--> $DIR/duplicate_coalescing.rs:15:17
|
||||||
|
|
|
||||||
|
LL | takes_trait(());
|
||||||
|
| ----------- ^^ the trait `Trait` is not implemented for `()`
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
= note: a note
|
||||||
|
= note: another note
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/duplicate_coalescing.rs:10:1
|
||||||
|
|
|
||||||
|
LL | trait Trait {}
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
note: required by a bound in `takes_trait`
|
||||||
|
--> $DIR/duplicate_coalescing.rs:12:24
|
||||||
|
|
|
||||||
|
LL | fn takes_trait(_: impl Trait) {}
|
||||||
|
| ^^^^^ required by this bound in `takes_trait`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
//@ revisions: label note both
|
||||||
|
//@[both] compile-flags: --cfg label --cfg note
|
||||||
|
//@ dont-require-annotations: NOTE
|
||||||
|
|
||||||
|
//! Example and test of multiple diagnostic attributes coalescing together.
|
||||||
|
|
||||||
|
#[diagnostic::on_unimplemented(message = "this message", note = "a note")]
|
||||||
|
#[cfg_attr(label, diagnostic::on_unimplemented(label = "this label"))]
|
||||||
|
#[cfg_attr(note, diagnostic::on_unimplemented(note = "another note"))]
|
||||||
|
trait Trait {}
|
||||||
|
|
||||||
|
fn takes_trait(_: impl Trait) {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
takes_trait(());
|
||||||
|
//~^ERROR this message
|
||||||
|
//[label]~|NOTE this label
|
||||||
|
//[both]~|NOTE this label
|
||||||
|
//~|NOTE a note
|
||||||
|
//[note]~|NOTE another note
|
||||||
|
//[both]~|NOTE another note
|
||||||
|
}
|
||||||
@@ -1633,6 +1633,18 @@ dep-bumps = [
|
|||||||
"/src/llvm-project" = ["@cuviper"]
|
"/src/llvm-project" = ["@cuviper"]
|
||||||
"/src/rustdoc-json-types" = ["rustdoc"]
|
"/src/rustdoc-json-types" = ["rustdoc"]
|
||||||
"/src/stage0" = ["bootstrap"]
|
"/src/stage0" = ["bootstrap"]
|
||||||
|
"/tests/assembly-llvm" = ["compiler"]
|
||||||
|
"/tests/auxiliary" = ["compiler"]
|
||||||
|
"/tests/codegen-llvm" = ["compiler"]
|
||||||
|
"/tests/codegen-units" = ["compiler"]
|
||||||
|
"/tests/COMPILER_TESTS.md" = ["compiler"]
|
||||||
|
"/tests/coverage-run-rustdoc" = ["compiler"]
|
||||||
|
"/tests/coverage" = ["compiler"]
|
||||||
|
"/tests/crashes" = ["compiler"]
|
||||||
|
"/tests/debuginfo" = ["compiler"]
|
||||||
|
"/tests/incremental" = ["compiler"]
|
||||||
|
"/tests/mir-opt" = ["compiler"]
|
||||||
|
"/tests/pretty" = ["compiler"]
|
||||||
"/tests/run-make" = ["compiler"]
|
"/tests/run-make" = ["compiler"]
|
||||||
"/tests/run-make-cargo" = ["compiler"]
|
"/tests/run-make-cargo" = ["compiler"]
|
||||||
"/tests/rustdoc-html" = ["rustdoc"]
|
"/tests/rustdoc-html" = ["rustdoc"]
|
||||||
@@ -1642,6 +1654,7 @@ dep-bumps = [
|
|||||||
"/tests/rustdoc-json" = ["@aDotInTheVoid"]
|
"/tests/rustdoc-json" = ["@aDotInTheVoid"]
|
||||||
"/tests/rustdoc-ui" = ["rustdoc"]
|
"/tests/rustdoc-ui" = ["rustdoc"]
|
||||||
"/tests/ui" = ["compiler"]
|
"/tests/ui" = ["compiler"]
|
||||||
|
"/tests/ui-fulldeps" = ["compiler"]
|
||||||
"/src/tools/build-manifest" = ["bootstrap"]
|
"/src/tools/build-manifest" = ["bootstrap"]
|
||||||
"/src/tools/cargo" = ["@ehuss"]
|
"/src/tools/cargo" = ["@ehuss"]
|
||||||
"/src/tools/compiletest" = ["bootstrap", "@wesleywiser", "@oli-obk", "@jieyouxu"]
|
"/src/tools/compiletest" = ["bootstrap", "@wesleywiser", "@oli-obk", "@jieyouxu"]
|
||||||
|
|||||||
Reference in New Issue
Block a user