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",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -396,7 +396,7 @@ checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -573,7 +573,6 @@ checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
@@ -635,10 +634,10 @@ version = "4.5.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -768,7 +767,6 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"similar",
|
||||
"spdx-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -804,7 +802,7 @@ dependencies = [
|
||||
"nom",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1036,7 +1034,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1050,7 +1048,7 @@ dependencies = [
|
||||
"indexmap",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1068,7 +1066,7 @@ dependencies = [
|
||||
"indexmap",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1092,7 +1090,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1103,7 +1101,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1124,7 +1122,7 @@ checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1145,7 +1143,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1155,7 +1153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1167,7 +1165,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1242,7 +1240,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1663,12 +1661,6 @@ dependencies = [
|
||||
"foldhash 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
@@ -2069,7 +2061,7 @@ checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2356,7 +2348,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2501,7 +2493,7 @@ checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2875,7 +2867,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3085,7 +3077,7 @@ checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3276,7 +3268,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3369,7 +3361,7 @@ checksum = "8100bb34c0a1d0f907143db3149e6b4eea3c33b9ee8b189720168e818303986f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4085,7 +4077,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4231,7 +4223,7 @@ dependencies = [
|
||||
"fluent-syntax",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -4812,7 +4804,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -4912,7 +4904,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5029,7 +5021,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5115,7 +5107,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5126,7 +5118,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5259,35 +5251,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
@@ -5353,36 +5316,6 @@ version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "syn"
|
||||
version = "2.0.110"
|
||||
@@ -5402,7 +5335,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5539,7 +5472,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5550,7 +5483,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5792,7 +5725,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5988,7 +5921,7 @@ checksum = "a1249a628de3ad34b821ecb1001355bca3940bcb2f88558f1a8bd82e977f75b5"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
"unic-langid-impl",
|
||||
]
|
||||
|
||||
@@ -6232,7 +6165,7 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -6489,7 +6422,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6500,7 +6433,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6796,7 +6729,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -6817,7 +6750,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6837,7 +6770,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -6872,7 +6805,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
use super::prelude::{ALL_TARGETS, AllowedTargets};
|
||||
use super::{AcceptMapping, AttributeParser};
|
||||
use crate::context::{AcceptContext, FinalizeContext, Stage};
|
||||
use crate::errors::{DocAliasDuplicated, DocAutoCfgExpectsHideOrShow, IllFormedAttributeInput};
|
||||
use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser};
|
||||
use crate::session_diagnostics::{
|
||||
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() {
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
||||
AttributeLintKind::DuplicateDocAlias { first_definition },
|
||||
move |dcx, level| DocAliasDuplicated { first_definition }.into_diag(dcx, level),
|
||||
span,
|
||||
);
|
||||
}
|
||||
@@ -343,9 +344,9 @@ fn parse_auto_cfg<S: Stage>(
|
||||
ArgParser::List(list) => {
|
||||
for meta in list.mixed() {
|
||||
let MetaItemOrLitParser::MetaItemParser(item) = meta else {
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::DocAutoCfgExpectsHideOrShow,
|
||||
|dcx, level| DocAutoCfgExpectsHideOrShow.into_diag(dcx, level),
|
||||
meta.span(),
|
||||
);
|
||||
continue;
|
||||
@@ -354,9 +355,9 @@ fn parse_auto_cfg<S: Stage>(
|
||||
Some(sym::hide) => (HideOrShow::Hide, sym::hide),
|
||||
Some(sym::show) => (HideOrShow::Show, sym::show),
|
||||
_ => {
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::DocAutoCfgExpectsHideOrShow,
|
||||
|dcx, level| DocAutoCfgExpectsHideOrShow.into_diag(dcx, level),
|
||||
item.span(),
|
||||
);
|
||||
continue;
|
||||
@@ -666,12 +667,10 @@ fn accept_single_doc_attr<S: Stage>(
|
||||
ArgParser::NoArgs => {
|
||||
let suggestions = cx.adcx().suggestions();
|
||||
let span = cx.attr_span;
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::IllFormedAttributeInput {
|
||||
suggestions,
|
||||
docs: None,
|
||||
help: None,
|
||||
move |dcx, level| {
|
||||
IllFormedAttributeInput::new(&suggestions, None, None).into_diag(dcx, level)
|
||||
},
|
||||
span,
|
||||
);
|
||||
|
||||
@@ -897,11 +897,18 @@ pub(crate) fn expected_specific_argument_strings(
|
||||
}
|
||||
|
||||
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;
|
||||
self.emit_lint(
|
||||
self.emit_dyn_lint(
|
||||
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,
|
||||
);
|
||||
}
|
||||
@@ -916,9 +923,12 @@ pub(crate) fn warn_ill_formed_attribute_input_with_help(
|
||||
) {
|
||||
let suggestions = self.suggestions();
|
||||
let span = self.attr_span;
|
||||
self.emit_lint(
|
||||
self.emit_dyn_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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_errors::{DiagArgValue, MultiSpan};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
@@ -66,3 +66,114 @@ pub(crate) struct UnsafeAttrOutsideUnsafeLint {
|
||||
#[subdiagnostic]
|
||||
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 rustc_ast::AttrStyle;
|
||||
use rustc_errors::{DiagArgValue, MultiSpan, StashKey};
|
||||
use rustc_errors::{DiagArgValue, Diagnostic, MultiSpan, StashKey};
|
||||
use rustc_feature::Features;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{AttrItem, Attribute, MethodKind, Target};
|
||||
use rustc_span::{BytePos, Span, Symbol, sym};
|
||||
|
||||
use crate::AttributeParser;
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::errors::{
|
||||
InvalidAttrAtCrateLevel, ItemFollowingInnerAttr, UnsupportedAttributesInWhere,
|
||||
InvalidAttrAtCrateLevel, InvalidTargetLint, ItemFollowingInnerAttr,
|
||||
UnsupportedAttributesInWhere,
|
||||
};
|
||||
use crate::session_diagnostics::InvalidTarget;
|
||||
use crate::target_checking::Policy::Allow;
|
||||
@@ -142,14 +142,19 @@ pub(crate) fn check_target(
|
||||
};
|
||||
|
||||
let attr_span = cx.attr_span;
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
lint,
|
||||
AttributeLintKind::InvalidTarget {
|
||||
move |dcx, level| {
|
||||
InvalidTargetLint {
|
||||
name: name.to_string(),
|
||||
target: target.plural_name(),
|
||||
only: if only { "only " } else { "" },
|
||||
applied,
|
||||
applied: DiagArgValue::StrListSepByAnd(
|
||||
applied.iter().map(|i| Cow::Owned(i.to_string())).collect(),
|
||||
),
|
||||
attr_span,
|
||||
}
|
||||
.into_diag(dcx, level)
|
||||
},
|
||||
attr_span,
|
||||
);
|
||||
@@ -176,15 +181,24 @@ pub(crate) fn check_crate_level(target: Target, cx: &mut AcceptContext<'_, 'sess
|
||||
return;
|
||||
}
|
||||
|
||||
let kind = AttributeLintKind::InvalidStyle {
|
||||
name: cx.attr_path.to_string(),
|
||||
is_used_as_inner: cx.attr_style == AttrStyle::Inner,
|
||||
target: target.name(),
|
||||
target_span: cx.target_span,
|
||||
};
|
||||
let name = cx.attr_path.to_string();
|
||||
let is_used_as_inner = cx.attr_style == AttrStyle::Inner;
|
||||
let target_span = cx.target_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
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
use rustc_ast::{
|
||||
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_hir::AttrPath;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_parse::parse_in;
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
|
||||
@@ -210,14 +209,14 @@ pub fn emit_malformed_attribute(
|
||||
suggestions.clear();
|
||||
}
|
||||
if should_warn(name) {
|
||||
psess.buffer_lint(
|
||||
let suggestions = suggestions.clone();
|
||||
psess.dyn_buffer_lint(
|
||||
ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
span,
|
||||
ast::CRATE_NODE_ID,
|
||||
AttributeLintKind::IllFormedAttributeInput {
|
||||
suggestions: suggestions.clone(),
|
||||
docs: template.docs,
|
||||
help: None,
|
||||
move |dcx, level| {
|
||||
crate::errors::IllFormedAttributeInput::new(&suggestions, template.docs, None)
|
||||
.into_diag(dcx, level)
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -370,6 +370,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> Box<ast::Expr> {
|
||||
let ecx = &cx.ext_cx;
|
||||
|
||||
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()));
|
||||
|
||||
ecx.expr_array_ref(
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
use std::{assert_matches, iter, ptr};
|
||||
|
||||
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::common::{IntPredicate, TypeKind};
|
||||
@@ -288,10 +289,17 @@ fn codegen_intrinsic_call(
|
||||
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() {
|
||||
Primitive::Pointer(_) => {
|
||||
// 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(..) => {
|
||||
let int_width = self.cx().size_of(result.layout.ty).bits();
|
||||
@@ -305,27 +313,26 @@ fn codegen_intrinsic_call(
|
||||
target_c_int_width
|
||||
);
|
||||
}
|
||||
emit_va_arg(self, args[0], result.layout.ty)
|
||||
}
|
||||
Primitive::Float(Float::F16) => {
|
||||
bug!("the va_arg intrinsic does not support `f16`")
|
||||
}
|
||||
Primitive::Float(Float::F32) => {
|
||||
if self.cx().sess().target.arch == Arch::Avr {
|
||||
// c_double is actually f32 on avr.
|
||||
emit_va_arg(self, args[0], result.layout.ty)
|
||||
} else {
|
||||
if self.cx().sess().target.arch != Arch::Avr {
|
||||
bug!("the va_arg intrinsic does not support `f32` on this target")
|
||||
}
|
||||
}
|
||||
Primitive::Float(Float::F64) => {
|
||||
// 64-bit floats are always OK.
|
||||
emit_va_arg(self, args[0], result.layout.ty)
|
||||
}
|
||||
Primitive::Float(Float::F128) => {
|
||||
// FIXME(f128) figure out whether we should support this.
|
||||
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 => {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use std::any::Any;
|
||||
use std::borrow::Cow;
|
||||
|
||||
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_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
@@ -35,50 +34,6 @@ pub struct DecorateAttrLint<'a, 'sess, 'tcx> {
|
||||
impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> {
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
||||
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) => {
|
||||
check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value)
|
||||
.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)
|
||||
.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 => {
|
||||
lints::AmbiguousDeriveHelpers.into_diag(dcx, level)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::formatting::DiagMessageAddArg;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
|
||||
Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
|
||||
EmissionGuarantee, Level, Subdiagnostic, SuggestionStyle, msg,
|
||||
};
|
||||
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)]
|
||||
#[diag("creating a {$shared_label}reference to mutable static")]
|
||||
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)]
|
||||
#[diag("malformed `doc` attribute input")]
|
||||
#[warning(
|
||||
@@ -3386,17 +3303,6 @@ pub(crate) struct InvalidAttrStyle {
|
||||
)]
|
||||
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)]
|
||||
#[diag("there exists a built-in attribute with the same name")]
|
||||
pub(crate) struct AmbiguousDeriveHelpers;
|
||||
|
||||
@@ -654,98 +654,32 @@ pub enum DeprecatedSinceKind {
|
||||
|
||||
#[derive(Debug)]
|
||||
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)>),
|
||||
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
||||
DuplicateDocAlias {
|
||||
first_definition: Span,
|
||||
},
|
||||
DocAutoCfgExpectsHideOrShow,
|
||||
DocAutoCfgHideShowUnexpectedItem {
|
||||
attr_name: Symbol,
|
||||
},
|
||||
DocAutoCfgHideShowExpectsList {
|
||||
attr_name: Symbol,
|
||||
},
|
||||
DocAutoCfgHideShowUnexpectedItem { attr_name: Symbol },
|
||||
DocAutoCfgHideShowExpectsList { attr_name: Symbol },
|
||||
DocInvalid,
|
||||
AmbiguousDeriveHelpers,
|
||||
DocUnknownInclude {
|
||||
span: Span,
|
||||
inner: &'static str,
|
||||
value: Symbol,
|
||||
},
|
||||
DocUnknownSpotlight {
|
||||
span: Span,
|
||||
},
|
||||
DocUnknownPasses {
|
||||
name: Symbol,
|
||||
span: Span,
|
||||
},
|
||||
DocUnknownPlugins {
|
||||
span: Span,
|
||||
},
|
||||
DocUnknownAny {
|
||||
name: Symbol,
|
||||
},
|
||||
DocUnknownInclude { span: Span, inner: &'static str, value: Symbol },
|
||||
DocUnknownSpotlight { span: Span },
|
||||
DocUnknownPasses { name: Symbol, span: Span },
|
||||
DocUnknownPlugins { span: Span },
|
||||
DocUnknownAny { name: Symbol },
|
||||
DocAutoCfgWrongLiteral,
|
||||
DocTestTakesList,
|
||||
DocTestUnknown {
|
||||
name: Symbol,
|
||||
},
|
||||
DocTestUnknown { name: Symbol },
|
||||
DocTestLiteral,
|
||||
AttrCrateLevelOnly,
|
||||
DoNotRecommendDoesNotExpectArgs,
|
||||
CrateTypeUnknown {
|
||||
span: Span,
|
||||
suggested: Option<Symbol>,
|
||||
},
|
||||
CrateTypeUnknown { span: Span, suggested: Option<Symbol> },
|
||||
MalformedDoc,
|
||||
ExpectedNoArgs,
|
||||
ExpectedNameValue,
|
||||
MalFormedDiagnosticAttribute {
|
||||
attribute: &'static str,
|
||||
options: &'static str,
|
||||
span: Span,
|
||||
},
|
||||
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,
|
||||
},
|
||||
MalFormedDiagnosticAttribute { attribute: &'static str, options: &'static str, span: Span },
|
||||
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,
|
||||
}
|
||||
|
||||
|
||||
@@ -93,31 +93,31 @@
|
||||
|
||||
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`. Use [`char::MAX`] instead.
|
||||
#[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;
|
||||
|
||||
/// 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
|
||||
/// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead.
|
||||
#[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;
|
||||
|
||||
/// 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.
|
||||
#[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;
|
||||
|
||||
/// Creates an iterator over the UTF-16 encoded code points in `iter`, returning
|
||||
/// unpaired surrogates as `Err`s. Use [`char::decode_utf16`] instead.
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
#[deprecated(since = "TBD", note = "replaced by the `decode_utf16` method on `char`")]
|
||||
#[inline]
|
||||
pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
|
||||
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.
|
||||
#[stable(feature = "rust1", since = "1.0.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]
|
||||
#[inline]
|
||||
pub const fn from_u32(i: u32) -> Option<char> {
|
||||
@@ -136,6 +137,7 @@ pub const fn from_u32(i: u32) -> Option<char> {
|
||||
/// instead.
|
||||
#[stable(feature = "char_from_unchecked", since = "1.5.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]
|
||||
#[inline]
|
||||
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.
|
||||
#[stable(feature = "rust1", since = "1.0.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]
|
||||
#[inline]
|
||||
pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
|
||||
|
||||
@@ -168,7 +168,7 @@ macro_rules! assert_ne {
|
||||
#[allow_internal_unstable(panic_internals)]
|
||||
#[rustc_macro_transparency = "semiopaque"]
|
||||
pub macro assert_matches {
|
||||
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
|
||||
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {{
|
||||
match $left {
|
||||
$( $pattern )|+ $( if $guard )? => {}
|
||||
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 {
|
||||
$( $pattern )|+ $( if $guard )? => {}
|
||||
ref left_val => {
|
||||
@@ -191,7 +191,7 @@ macro_rules! assert_ne {
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
/// Selects code at compile-time based on `cfg` predicates.
|
||||
|
||||
@@ -508,6 +508,7 @@ pub const fn is_normal(self) -> bool {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[must_use]
|
||||
pub const fn classify(self) -> FpCategory {
|
||||
let bits = self.to_bits();
|
||||
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {
|
||||
@@ -608,6 +609,7 @@ pub const fn is_sign_negative(self) -> bool {
|
||||
#[inline]
|
||||
#[doc(alias = "nextUp")]
|
||||
#[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 {
|
||||
// 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
|
||||
@@ -662,6 +664,7 @@ pub const fn next_up(self) -> Self {
|
||||
#[inline]
|
||||
#[doc(alias = "nextDown")]
|
||||
#[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 {
|
||||
// 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
|
||||
@@ -907,6 +910,8 @@ pub const fn minimum(self, other: f128) -> f128 {
|
||||
#[doc(alias = "average")]
|
||||
#[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 {
|
||||
const HI: f128 = f128::MAX / 2.;
|
||||
|
||||
|
||||
@@ -500,6 +500,7 @@ pub const fn is_normal(self) -> bool {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
#[must_use]
|
||||
pub const fn classify(self) -> FpCategory {
|
||||
let b = self.to_bits();
|
||||
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
||||
@@ -604,6 +605,7 @@ pub const fn is_sign_negative(self) -> bool {
|
||||
#[inline]
|
||||
#[doc(alias = "nextUp")]
|
||||
#[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 {
|
||||
// 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
|
||||
@@ -658,6 +660,7 @@ pub const fn next_up(self) -> Self {
|
||||
#[inline]
|
||||
#[doc(alias = "nextDown")]
|
||||
#[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 {
|
||||
// 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
|
||||
@@ -901,6 +904,8 @@ pub const fn minimum(self, other: f16) -> f16 {
|
||||
#[doc(alias = "average")]
|
||||
#[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 {
|
||||
const HI: f16 = f16::MAX / 2.;
|
||||
|
||||
|
||||
@@ -723,6 +723,7 @@ pub const fn is_normal(self) -> bool {
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
|
||||
#[must_use]
|
||||
pub const fn classify(self) -> FpCategory {
|
||||
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
||||
// around buggy codegen for x87 targets (see
|
||||
@@ -822,6 +823,7 @@ pub const fn is_sign_negative(self) -> bool {
|
||||
#[doc(alias = "nextUp")]
|
||||
#[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 {
|
||||
// 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
|
||||
@@ -873,6 +875,7 @@ pub const fn next_up(self) -> Self {
|
||||
#[doc(alias = "nextDown")]
|
||||
#[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 {
|
||||
// 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
|
||||
@@ -1089,6 +1092,8 @@ pub const fn minimum(self, other: f32) -> f32 {
|
||||
#[doc(alias = "average")]
|
||||
#[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 {
|
||||
cfg_select! {
|
||||
// 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")]
|
||||
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
|
||||
#[must_use]
|
||||
pub const fn classify(self) -> FpCategory {
|
||||
// We used to have complicated logic here that avoids the simple bit-based tests to work
|
||||
// around buggy codegen for x87 targets (see
|
||||
@@ -839,6 +840,7 @@ pub fn is_negative(self) -> bool {
|
||||
#[doc(alias = "nextUp")]
|
||||
#[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 {
|
||||
// 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
|
||||
@@ -890,6 +892,7 @@ pub const fn next_up(self) -> Self {
|
||||
#[doc(alias = "nextDown")]
|
||||
#[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 {
|
||||
// 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
|
||||
@@ -1107,6 +1110,8 @@ pub const fn minimum(self, other: f64) -> f64 {
|
||||
#[doc(alias = "average")]
|
||||
#[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 {
|
||||
const HI: f64 = f64::MAX / 2.;
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#![feature(bstr)]
|
||||
#![feature(cfg_target_has_reliable_f16_f128)]
|
||||
#![feature(char_internals)]
|
||||
#![feature(char_max_len)]
|
||||
#![feature(clone_to_uninit)]
|
||||
#![feature(cmp_minmax)]
|
||||
#![feature(const_array)]
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#![allow(unused_must_use)]
|
||||
|
||||
use std::{assert_matches, debug_assert_matches};
|
||||
|
||||
#[allow(dead_code)]
|
||||
trait Trait {
|
||||
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
|
||||
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")]
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[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) {
|
||||
(self.sin(), self.cos())
|
||||
}
|
||||
|
||||
@@ -608,6 +608,7 @@ pub fn atan2(self, other: f16) -> f16 {
|
||||
#[doc(alias = "sincos")]
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[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) {
|
||||
(self.sin(), self.cos())
|
||||
}
|
||||
|
||||
@@ -907,6 +907,7 @@ pub fn atan2(self, other: f32) -> f32 {
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn sin_cos(self) -> (f32, f32) {
|
||||
(self.sin(), self.cos())
|
||||
}
|
||||
|
||||
@@ -907,6 +907,7 @@ pub fn atan2(self, other: f64) -> f64 {
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn sin_cos(self) -> (f64, f64) {
|
||||
(self.sin(), self.cos())
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
use super::options::{Options, OutputFormat};
|
||||
use super::test_result::TestResult;
|
||||
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};
|
||||
|
||||
/// 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.
|
||||
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() {
|
||||
None => OutputLocation::Raw(io::stdout().lock()),
|
||||
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)?;
|
||||
|
||||
out.write_discovery_start()?;
|
||||
for test in filter_tests(opts, tests).into_iter() {
|
||||
for test in filter_tests(opts, tests) {
|
||||
use crate::TestFn::*;
|
||||
|
||||
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.
|
||||
/// 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
|
||||
.tests
|
||||
.iter()
|
||||
.max_by_key(|t| len_if_padded(t))
|
||||
.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::types::{
|
||||
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};
|
||||
}
|
||||
@@ -106,6 +106,16 @@ pub fn test_main_with_exit_callback<F: FnOnce()>(
|
||||
tests: Vec<TestDescAndFn>,
|
||||
options: Option<Options>,
|
||||
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) {
|
||||
Some(Ok(o)) => o,
|
||||
@@ -180,7 +190,9 @@ pub fn test_main_with_exit_callback<F: FnOnce()>(
|
||||
pub fn test_main_static(tests: &[&TestDescAndFn]) {
|
||||
let args = env::args().collect::<Vec<_>>();
|
||||
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.
|
||||
@@ -229,7 +241,9 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
|
||||
|
||||
let args = env::args().collect::<Vec<_>>();
|
||||
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()
|
||||
@@ -298,7 +312,7 @@ fn total_len(&self) -> usize {
|
||||
|
||||
pub fn run_tests<F>(
|
||||
opts: &TestOpts,
|
||||
tests: Vec<TestDescAndFn>,
|
||||
tests: TestList,
|
||||
mut notify_about_test_event: F,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
@@ -334,7 +348,7 @@ struct TimeoutEntry {
|
||||
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 };
|
||||
|
||||
@@ -512,25 +526,48 @@ fn calc_timeout(timeout_queue: &VecDeque<TimeoutEntry>) -> Option<Duration> {
|
||||
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 matches_filter = |test: &TestDescAndFn, filter: &str| {
|
||||
let test_name = test.desc.name.as_slice();
|
||||
|
||||
match opts.filter_exact {
|
||||
true => test_name == filter,
|
||||
false => test_name.contains(filter),
|
||||
}
|
||||
};
|
||||
|
||||
// Remove tests that don't match the test filter
|
||||
// Remove tests that don't match the test filter.
|
||||
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
|
||||
//
|
||||
// After exact positive filtering above, the filtered set is small, so a
|
||||
// linear scan is acceptable even under Miri.
|
||||
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
|
||||
@@ -553,6 +590,30 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
|
||||
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> {
|
||||
// convert benchmarks to tests, if we're not benchmarking them
|
||||
tests
|
||||
|
||||
@@ -477,7 +477,7 @@ fn filter_for_ignored_option() {
|
||||
opts.run_tests = true;
|
||||
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);
|
||||
|
||||
assert_eq!(filtered.len(), 1);
|
||||
@@ -494,7 +494,7 @@ fn run_include_ignored_option() {
|
||||
opts.run_tests = true;
|
||||
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);
|
||||
|
||||
assert_eq!(filtered.len(), 2);
|
||||
@@ -527,7 +527,7 @@ fn exclude_should_panic_option() {
|
||||
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!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
|
||||
@@ -535,8 +535,8 @@ fn exclude_should_panic_option() {
|
||||
|
||||
#[test]
|
||||
fn exact_filter_match() {
|
||||
fn tests() -> Vec<TestDescAndFn> {
|
||||
["base", "base::test", "base::test1", "base::test2"]
|
||||
fn tests() -> TestList {
|
||||
let tests = ["base", "base::test", "base::test1", "base::test2"]
|
||||
.into_iter()
|
||||
.map(|name| TestDescAndFn {
|
||||
desc: TestDesc {
|
||||
@@ -555,7 +555,8 @@ fn tests() -> Vec<TestDescAndFn> {
|
||||
},
|
||||
testfn: DynTestFn(Box::new(move || Ok(()))),
|
||||
})
|
||||
.collect()
|
||||
.collect();
|
||||
TestList::new(tests, TestListOrder::Sorted)
|
||||
}
|
||||
|
||||
let substr =
|
||||
@@ -908,7 +909,8 @@ fn f(_: &mut Bencher) -> Result<(), String> {
|
||||
}
|
||||
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;
|
||||
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.
|
||||
* `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
|
||||
|
||||
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_json = "1.0.85"
|
||||
similar = "2.7.0"
|
||||
spdx-rs = "0.5.1"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
mod licenses;
|
||||
mod path_tree;
|
||||
mod reuse;
|
||||
mod spdx;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
@@ -15,18 +15,15 @@ pub(crate) fn collect(
|
||||
let raw = &obtain_spdx_document(reuse_exe)?;
|
||||
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();
|
||||
for file in document.file_information {
|
||||
let concluded_license = file.concluded_license.expect("File should have licence info");
|
||||
let copyright_text = file.copyright_text.expect("File should have copyright text");
|
||||
for file in files {
|
||||
let license = interner.intern(License {
|
||||
spdx: concluded_license.to_string(),
|
||||
copyright: copyright_text.split('\n').map(|s| s.into()).collect(),
|
||||
spdx: file.concluded_license,
|
||||
copyright: file.copyright_text.split('\n').map(|s| s.into()).collect(),
|
||||
});
|
||||
|
||||
result.push((file.file_name.into(), license));
|
||||
result.push((file.name.into(), license));
|
||||
}
|
||||
|
||||
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
|
||||
#[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"))]
|
||||
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/rustdoc-json-types" = ["rustdoc"]
|
||||
"/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-cargo" = ["compiler"]
|
||||
"/tests/rustdoc-html" = ["rustdoc"]
|
||||
@@ -1642,6 +1654,7 @@ dep-bumps = [
|
||||
"/tests/rustdoc-json" = ["@aDotInTheVoid"]
|
||||
"/tests/rustdoc-ui" = ["rustdoc"]
|
||||
"/tests/ui" = ["compiler"]
|
||||
"/tests/ui-fulldeps" = ["compiler"]
|
||||
"/src/tools/build-manifest" = ["bootstrap"]
|
||||
"/src/tools/cargo" = ["@ehuss"]
|
||||
"/src/tools/compiletest" = ["bootstrap", "@wesleywiser", "@oli-obk", "@jieyouxu"]
|
||||
|
||||
Reference in New Issue
Block a user