diff options
105 files changed, 1426 insertions, 563 deletions
diff --git a/Cargo.lock b/Cargo.lock index 9d1481ec768..241a37588b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,7 +266,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -601,9 +601,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.5" +version = "4.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4" +checksum = "fbca90c87c2a04da41e95d1856e8bcd22f159bdbfa147314d2ce5218057b0e58" dependencies = [ "clap", ] @@ -617,7 +617,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -644,7 +644,7 @@ dependencies = [ "regex", "rustc_tools_util", "serde", - "syn 2.0.66", + "syn 2.0.67", "tempfile", "termize", "tokio", @@ -755,7 +755,7 @@ dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -991,7 +991,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1002,7 +1002,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1028,7 +1028,7 @@ version = "0.1.81" dependencies = [ "itertools", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1069,7 +1069,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1079,7 +1079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1090,7 +1090,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1102,7 +1102,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1180,13 +1180,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1506,7 +1506,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1739,7 +1739,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1781,18 +1781,6 @@ dependencies = [ ] [[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] name = "icu_list" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1846,51 +1834,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" [[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] name = "icu_provider" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1928,7 +1871,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1939,14 +1882,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -2146,9 +2087,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" @@ -2521,9 +2462,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "compiler_builtins", @@ -2949,7 +2890,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -3141,9 +3082,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4045,7 +3986,7 @@ dependencies = [ "fluent-syntax", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "unic-langid", ] @@ -4179,7 +4120,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -4326,7 +4267,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "synstructure", ] @@ -4905,7 +4846,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "synstructure", ] @@ -5003,7 +4944,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5153,7 +5094,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5446,9 +5387,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" dependencies = [ "proc-macro2", "quote", @@ -5463,7 +5404,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5640,7 +5581,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5678,6 +5619,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ + "build_helper", "cargo_metadata 0.15.4", "fluent-syntax", "ignore", @@ -5854,7 +5796,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -6054,7 +5996,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b" dependencies = [ "proc-macro-hack", "quote", - "syn 2.0.66", + "syn 2.0.67", "unic-langid-impl", ] @@ -6075,6 +6017,12 @@ dependencies = [ ] [[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6175,9 +6123,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -6191,24 +6139,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] name = "utf8-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" [[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6292,7 +6228,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "wasm-bindgen-shared", ] @@ -6314,7 +6250,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6395,7 +6331,7 @@ dependencies = [ "rayon", "serde", "serde_json", - "syn 2.0.66", + "syn 2.0.67", "windows-metadata", ] @@ -6572,12 +6508,6 @@ dependencies = [ ] [[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] name = "writeable" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6647,7 +6577,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "synstructure", ] @@ -6668,7 +6598,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -6688,7 +6618,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "synstructure", ] @@ -6711,5 +6641,5 @@ checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index cc66cc87652..efe19566152 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -1,6 +1,8 @@ pub use BinOpToken::*; pub use LitKind::*; pub use Nonterminal::*; +pub use NtExprKind::*; +pub use NtPatKind::*; pub use TokenKind::*; use crate::ast; @@ -871,6 +873,27 @@ impl PartialEq<TokenKind> for Token { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)] +pub enum NtPatKind { + // Matches or-patterns. Was written using `pat` in edition 2021 or later. + PatWithOr, + // Doesn't match or-patterns. + // - `inferred`: was written using `pat` in edition 2015 or 2018. + // - `!inferred`: was written using `pat_param`. + PatParam { inferred: bool }, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)] +pub enum NtExprKind { + // Matches expressions using the post-edition 2024. Was written using + // `expr` in edition 2024 or later. + Expr, + // Matches expressions using the pre-edition 2024 rules. + // - `inferred`: was written using `expr` in edition 2021 or earlier. + // - `!inferred`: was written using `expr_2021`. + Expr2021 { inferred: bool }, +} + #[derive(Clone, Encodable, Decodable)] /// For interpolation during macro expansion. pub enum Nonterminal { @@ -892,19 +915,8 @@ pub enum NonterminalKind { Item, Block, Stmt, - PatParam { - /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the - /// edition of the span. This is used for diagnostics. - inferred: bool, - }, - PatWithOr, - Expr, - /// Matches an expression using the rules from edition 2021 and earlier. - Expr2021 { - /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the - /// edition of the span. This is used for diagnostics AND feature gating. - inferred: bool, - }, + Pat(NtPatKind), + Expr(NtExprKind), Ty, Ident, Lifetime, @@ -926,20 +938,22 @@ impl NonterminalKind { sym::item => NonterminalKind::Item, sym::block => NonterminalKind::Block, sym::stmt => NonterminalKind::Stmt, - sym::pat => match edition() { - Edition::Edition2015 | Edition::Edition2018 => { - NonterminalKind::PatParam { inferred: true } + sym::pat => { + if edition().at_least_rust_2021() { + NonterminalKind::Pat(PatWithOr) + } else { + NonterminalKind::Pat(PatParam { inferred: true }) } - Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr, - }, - sym::pat_param => NonterminalKind::PatParam { inferred: false }, - sym::expr => match edition() { - Edition::Edition2015 | Edition::Edition2018 | Edition::Edition2021 => { - NonterminalKind::Expr2021 { inferred: true } + } + sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }), + sym::expr => { + if edition().at_least_rust_2024() { + NonterminalKind::Expr(Expr) + } else { + NonterminalKind::Expr(Expr2021 { inferred: true }) } - Edition::Edition2024 => NonterminalKind::Expr, - }, - sym::expr_2021 => NonterminalKind::Expr2021 { inferred: false }, + } + sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }), sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, @@ -951,15 +965,16 @@ impl NonterminalKind { _ => return None, }) } + fn symbol(self) -> Symbol { match self { NonterminalKind::Item => sym::item, NonterminalKind::Block => sym::block, NonterminalKind::Stmt => sym::stmt, - NonterminalKind::PatParam { inferred: false } => sym::pat_param, - NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, - NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: true } => sym::expr, - NonterminalKind::Expr2021 { inferred: false } => sym::expr_2021, + NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat, + NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param, + NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr, + NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, NonterminalKind::Lifetime => sym::lifetime, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 79717c969d7..941bb78c0dd 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -899,7 +899,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - validate_attr::check_attr(&self.session.psess, attr); + validate_attr::check_attr(&self.features, &self.session.psess, attr); } fn visit_ty(&mut self, ty: &'a Ty) { diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 3e6d0311b27..0bae1bd07a2 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -126,7 +126,7 @@ impl<'tcx> BorrowSet<'tcx> { ) -> Self { let mut visitor = GatherBorrows { tcx, - body: body, + body, location_map: Default::default(), activation_map: Default::default(), local_map: Default::default(), diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index c1f75328272..8a2936c2657 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -213,7 +213,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { via(msg_old), ); - if msg_new == "" { + if msg_new.is_empty() { // If `msg_new` is empty, then this isn't a borrow of a union field. err.span_label(span, format!("{kind_new} borrow occurs here")); err.span_label(old_span, format!("{kind_old} borrow occurs here")); diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index ec7d4582a60..f2b5ddcd782 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -43,9 +43,9 @@ impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> { } fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) { - state.borrows.clone_from(&self.borrows.entry_set_for_block(block)); - state.uninits.clone_from(&self.uninits.entry_set_for_block(block)); - state.ever_inits.clone_from(&self.ever_inits.entry_set_for_block(block)); + state.borrows.clone_from(self.borrows.entry_set_for_block(block)); + state.uninits.clone_from(self.uninits.entry_set_for_block(block)); + state.ever_inits.clone_from(self.ever_inits.entry_set_for_block(block)); } fn reconstruct_before_statement_effect( diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 67c11ff4a5b..c214c52880a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -895,7 +895,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { for alias_ty in alias_tys { if alias_ty.span.desugaring_kind().is_some() { // Skip `async` desugaring `impl Future`. - () } if let TyKind::TraitObject(_, lt, _) = alias_ty.kind { if lt.ident.name == kw::Empty { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 77fb9fb4315..25a0d40218b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -519,7 +519,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } // Otherwise, let's descend into the referent types. - search_stack.push((*referent_ty, &referent_hir_ty.ty)); + search_stack.push((*referent_ty, referent_hir_ty.ty)); } // Match up something like `Foo<'1>` @@ -558,7 +558,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } (ty::RawPtr(mut_ty, _), hir::TyKind::Ptr(mut_hir_ty)) => { - search_stack.push((*mut_ty, &mut_hir_ty.ty)); + search_stack.push((*mut_ty, mut_hir_ty.ty)); } _ => { @@ -652,7 +652,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?; let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region( self.infcx.tcx, - &self.upvars, + self.upvars, upvar_index, ); let region_name = self.synthesize_region_name(); @@ -717,7 +717,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .output; span = output.span(); if let hir::FnRetTy::Return(ret) = output { - hir_ty = Some(self.get_future_inner_return_ty(*ret)); + hir_ty = Some(self.get_future_inner_return_ty(ret)); } " of async function" } @@ -958,7 +958,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { { let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region( self.infcx.tcx, - &self.upvars, + self.upvars, upvar_index, ); let region_name = self.synthesize_region_name(); diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 5d7ce548469..923cf7e9405 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -114,7 +114,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( move_data, elements, upvars, - polonius_input, ); // Create the region inference context, taking ownership of the diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 9984f76e6d4..c590104978c 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -43,8 +43,8 @@ pub(crate) fn emit_facts<'tcx>( emit_universal_region_facts( all_facts, borrow_set, - &universal_regions, - &universal_region_relations, + universal_regions, + universal_region_relations, ); emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set); emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set); diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index bf1c1b1433e..c56eaaff076 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -344,7 +344,7 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() { let reg_var = ty::RegionVid::from_usize(reg_var_idx); - let origin = var_to_origin.get(®_var).unwrap_or_else(|| &RegionCtxt::Unknown); + let origin = var_to_origin.get(®_var).unwrap_or(&RegionCtxt::Unknown); components[scc_idx.as_usize()].insert((reg_var, *origin)); } @@ -2216,7 +2216,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // #114907 where this happens via liveness and dropck outlives results. // Therefore, we return a default value in case that happens, which should at worst emit a // suboptimal error, instead of the ICE. - self.universe_causes.get(&universe).cloned().unwrap_or_else(|| UniverseInfo::other()) + self.universe_causes.get(&universe).cloned().unwrap_or_else(UniverseInfo::other) } /// Tries to find the terminator of the loop in which the region 'r' resides. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 51c3648d730..67e5c8352df 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -418,9 +418,7 @@ fn check_opaque_type_parameter_valid<'tcx>( let opaque_param = opaque_generics.param_at(i, tcx); let kind = opaque_param.kind.descr(); - if let Err(guar) = opaque_env.param_is_error(i) { - return Err(guar); - } + opaque_env.param_is_error(i)?; return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam { ty: arg, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 8b863efad6c..b777e01f7a6 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -12,9 +12,7 @@ use rustc_mir_dataflow::ResultsCursor; use std::rc::Rc; use crate::{ - constraints::OutlivesConstraintSet, - facts::{AllFacts, AllFactsExt}, - region_infer::values::LivenessValues, + constraints::OutlivesConstraintSet, region_infer::values::LivenessValues, universal_regions::UniversalRegions, }; @@ -38,7 +36,6 @@ pub(super) fn generate<'mir, 'tcx>( elements: &Rc<DenseLocationMap>, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, - use_polonius: bool, ) { debug!("liveness::generate"); @@ -49,11 +46,8 @@ pub(super) fn generate<'mir, 'tcx>( ); let (relevant_live_locals, boring_locals) = compute_relevant_live_locals(typeck.tcx(), &free_regions, body); - let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx()); - if facts_enabled { - polonius::populate_access_facts(typeck, body, move_data); - }; + polonius::populate_access_facts(typeck, body, move_data); trace::trace( typeck, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index d8f03a07a63..a009e28a0dd 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -87,10 +87,10 @@ pub(super) fn populate_access_facts<'a, 'tcx>( body: &Body<'tcx>, move_data: &MoveData<'tcx>, ) { - debug!("populate_access_facts()"); - let location_table = typeck.borrowck_context.location_table; - if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { + debug!("populate_access_facts()"); + let location_table = typeck.borrowck_context.location_table; + let mut extractor = UseFactsExtractor { var_defined_at: &mut facts.var_defined_at, var_used_at: &mut facts.var_used_at, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 50843c602cc..359c4ea0eb1 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -217,35 +217,52 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { /// Add facts for all locals with free regions, since regions may outlive /// the function body only at certain nodes in the CFG. fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) -> Option<()> { - let drop_used = self - .cx - .typeck - .borrowck_context - .all_facts - .as_ref() - .map(|facts| facts.var_dropped_at.clone())?; + // This collect is more necessary than immediately apparent + // because these facts go into `add_drop_live_facts_for()`, + // which also writes to `all_facts`, and so this is genuinely + // a simulatneous overlapping mutable borrow. + // FIXME for future hackers: investigate whether this is + // actually necessary; these facts come from Polonius + // and probably maybe plausibly does not need to go back in. + // It may be necessary to just pick out the parts of + // `add_drop_live_facts_for()` that make sense. + let facts_to_add: Vec<_> = { + let drop_used = &self.cx.typeck.borrowck_context.all_facts.as_ref()?.var_dropped_at; + + let relevant_live_locals: FxIndexSet<_> = + relevant_live_locals.iter().copied().collect(); + + drop_used + .iter() + .filter_map(|(local, location_index)| { + let local_ty = self.cx.body.local_decls[*local].ty; + if relevant_live_locals.contains(local) || !local_ty.has_free_regions() { + return None; + } - let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect(); - - let locations = IntervalSet::new(self.cx.elements.num_points()); - - for (local, location_index) in drop_used { - if !relevant_live_locals.contains(&local) { - let local_ty = self.cx.body.local_decls[local].ty; - if local_ty.has_free_regions() { let location = match self .cx .typeck .borrowck_context .location_table - .to_location(location_index) + .to_location(*location_index) { RichLocation::Start(l) => l, RichLocation::Mid(l) => l, }; - self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations); - } - } + + Some((*local, local_ty, location)) + }) + .collect() + }; + + // FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end, ...), but I don't know which one. Please help me rename it to something descriptive! + // Also, if this IntervalSet is used in many places, it maybe should have a newtype'd + // name with a description of what it means for future mortals passing by. + let locations = IntervalSet::new(self.cx.elements.num_points()); + + for (local, local_ty, location) in facts_to_add { + self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations); } Some(()) } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index c7c1b2af6a7..81bde14a82f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -133,7 +133,6 @@ pub(crate) fn type_check<'mir, 'tcx>( move_data: &MoveData<'tcx>, elements: &Rc<DenseLocationMap>, upvars: &[&ty::CapturedPlace<'tcx>], - use_polonius: bool, ) -> MirTypeckResults<'tcx> { let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body); let mut constraints = MirTypeckRegionConstraints { @@ -189,7 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>( checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output); checker.check_signature_annotation(body); - liveness::generate(&mut checker, body, elements, flow_inits, move_data, use_polonius); + liveness::generate(&mut checker, body, elements, flow_inits, move_data); translate_outlives_facts(&mut checker); let opaque_type_values = infcx.take_opaque_types(); diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 1476fe285ef..cd269810741 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -89,6 +89,8 @@ const_eval_exact_div_has_remainder = const_eval_extern_static = cannot access extern static ({$did}) +const_eval_extern_type_field = `extern type` field does not have a known offset + const_eval_fn_ptr_call = function pointers need an RFC before allowed to be called in {const_eval_const_context}s const_eval_for_loop_into_iter_non_const = diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index c60df06bb0e..d8efaa66415 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -386,33 +386,8 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error), ); let res = ecx.load_mir(cid.instance.def, cid.promoted); - res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)).map_err(|error| { - let (error, backtrace) = error.into_parts(); - backtrace.print_backtrace(); - - let (kind, instance) = if ecx.tcx.is_static(cid.instance.def_id()) { - ("static", String::new()) - } else { - // If the current item has generics, we'd like to enrich the message with the - // instance and its args: to show the actual compile-time values, in addition to - // the expression, leading to the const eval error. - let instance = &cid.instance; - if !instance.args.is_empty() { - let instance = with_no_trimmed_paths!(instance.to_string()); - ("const_with_path", instance) - } else { - ("const", String::new()) - } - }; - - super::report( - *ecx.tcx, - error, - DUMMY_SP, - || super::get_span_and_frames(ecx.tcx, ecx.stack()), - |span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames }, - ) - }) + res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)) + .map_err(|error| report_eval_error(&ecx, cid, error)) } #[inline(always)] @@ -438,24 +413,61 @@ fn const_validate_mplace<'tcx>( ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode) // Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted // error about the validation failure. - .map_err(|error| report_validation_error(&ecx, error, alloc_id))?; + .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?; inner = true; } Ok(()) } -#[inline(always)] +#[inline(never)] +fn report_eval_error<'tcx>( + ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>, + cid: GlobalId<'tcx>, + error: InterpErrorInfo<'tcx>, +) -> ErrorHandled { + let (error, backtrace) = error.into_parts(); + backtrace.print_backtrace(); + + let (kind, instance) = if ecx.tcx.is_static(cid.instance.def_id()) { + ("static", String::new()) + } else { + // If the current item has generics, we'd like to enrich the message with the + // instance and its args: to show the actual compile-time values, in addition to + // the expression, leading to the const eval error. + let instance = &cid.instance; + if !instance.args.is_empty() { + let instance = with_no_trimmed_paths!(instance.to_string()); + ("const_with_path", instance) + } else { + ("const", String::new()) + } + }; + + super::report( + *ecx.tcx, + error, + DUMMY_SP, + || super::get_span_and_frames(ecx.tcx, ecx.stack()), + |span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames }, + ) +} + +#[inline(never)] fn report_validation_error<'tcx>( ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>, + cid: GlobalId<'tcx>, error: InterpErrorInfo<'tcx>, alloc_id: AllocId, ) -> ErrorHandled { + if !matches!(error.kind(), InterpError::UndefinedBehavior(_)) { + // Some other error happened during validation, e.g. an unsupported operation. + return report_eval_error(ecx, cid, error); + } + let (error, backtrace) = error.into_parts(); backtrace.print_backtrace(); - let ub_note = matches!(error, InterpError::UndefinedBehavior(_)).then(|| {}); - let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id); let (size, align, _) = ecx.get_alloc_info(alloc_id); let raw_bytes = errors::RawBytesNote { size: size.bytes(), align: align.bytes(), bytes }; @@ -465,6 +477,6 @@ fn report_validation_error<'tcx>( error, DUMMY_SP, || crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()), - move |span, frames| errors::ValidationFailure { span, ub_note, frames, raw_bytes }, + move |span, frames| errors::ValidationFailure { span, ub_note: (), frames, raw_bytes }, ) } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 5fa48a59794..292d6ba9d08 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -425,7 +425,7 @@ pub struct ValidationFailure { #[primary_span] pub span: Span, #[note(const_eval_validation_failure_note)] - pub ub_note: Option<()>, + pub ub_note: (), #[subdiagnostic] pub frames: Vec<FrameNote>, #[subdiagnostic] @@ -825,6 +825,7 @@ impl ReportErrorExt for UnsupportedOpInfo { use crate::fluent_generated::*; match self { UnsupportedOpInfo::Unsupported(s) => s.clone().into(), + UnsupportedOpInfo::ExternTypeField => const_eval_extern_type_field, UnsupportedOpInfo::UnsizedLocal => const_eval_unsized_local, UnsupportedOpInfo::OverwritePartialPointer(_) => const_eval_partial_pointer_overwrite, UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy, @@ -845,7 +846,10 @@ impl ReportErrorExt for UnsupportedOpInfo { // `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to // be further processed by validity checking which then turns it into something nice to // print. So it's not worth the effort of having diagnostics that can print the `info`. - UnsizedLocal | Unsupported(_) | ReadPointerAsInt(_) => {} + UnsizedLocal + | UnsupportedOpInfo::ExternTypeField + | Unsupported(_) + | ReadPointerAsInt(_) => {} OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => { diag.arg("ptr", ptr); } diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index efa01b54342..cfa814c810a 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -21,7 +21,7 @@ use rustc_target::abi::{self, VariantIdx}; use tracing::{debug, instrument}; use super::{ - throw_ub, throw_unsup_format, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, + throw_ub, throw_unsup, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Provenance, Scalar, }; @@ -186,8 +186,8 @@ where (base_meta, offset) } None => { - // We don't know the alignment of this field, so we cannot adjust. - throw_unsup_format!("`extern type` does not have a known offset") + // We cannot know the alignment of this field, so we cannot adjust. + throw_unsup!(ExternTypeField) } } } else { diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index ca8b9884933..add48e1b186 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -5,6 +5,7 @@ //! to be const-safe. use std::fmt::Write; +use std::hash::Hash; use std::num::NonZero; use either::{Left, Right}; @@ -17,7 +18,8 @@ use rustc_hir as hir; use rustc_middle::bug; use rustc_middle::mir::interpret::{ ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, - ValidationErrorInfo, ValidationErrorKind, ValidationErrorKind::*, + UnsupportedOpInfo, ValidationErrorInfo, + ValidationErrorKind::{self, *}, }; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; @@ -26,8 +28,6 @@ use rustc_target::abi::{ Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, }; -use std::hash::Hash; - use super::{ err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, AllocKind, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, @@ -1028,7 +1028,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Err(err) if matches!( err.kind(), - err_ub!(ValidationError { .. }) | InterpError::InvalidProgram(_) + err_ub!(ValidationError { .. }) + | InterpError::InvalidProgram(_) + | InterpError::Unsupported(UnsupportedOpInfo::ExternTypeField) ) => { Err(err) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 6113580491e..cc0b110d2bc 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -61,6 +61,9 @@ expand_feature_removed = expand_glob_delegation_outside_impls = glob delegation is only supported in impls +expand_glob_delegation_traitless_qpath = + qualified path without a trait in glob delegation + expand_helper_attribute_name_invalid = `{$name}` cannot be a name of derive helper attribute diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index c883121fb40..0be7403f25b 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -449,6 +449,13 @@ pub(crate) struct GlobDelegationOutsideImpls { pub span: Span, } +#[derive(Diagnostic)] +#[diag(expand_glob_delegation_traitless_qpath)] +pub(crate) struct GlobDelegationTraitlessQpath { + #[primary_span] + pub span: Span, +} + // This used to be the `proc_macro_back_compat` lint (#83125). It was later // turned into a hard error. #[derive(Diagnostic)] diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 716bfc8c26b..26fc77c7f33 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1,8 +1,9 @@ use crate::base::*; use crate::config::StripUnconfigured; use crate::errors::{ - EmptyDelegationMac, GlobDelegationOutsideImpls, IncompleteParse, RecursionLimitReached, - RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind, + EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse, + RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, + WrongFragmentKind, }; use crate::mbe::diagnostics::annotate_err_with_kind; use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod}; @@ -1882,7 +1883,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let mut span: Option<Span> = None; while let Some(attr) = attrs.next() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); - validate_attr::check_attr(&self.cx.sess.psess, attr); + validate_attr::check_attr(features, &self.cx.sess.psess, attr); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; span = Some(current_span); @@ -1989,6 +1990,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } None if let Some((deleg, item)) = node.delegation() => { let Some(suffixes) = &deleg.suffixes else { + let traitless_qself = + matches!(&deleg.qself, Some(qself) if qself.position == 0); let item = match node.to_annotatable() { Annotatable::ImplItem(item) => item, ann @ (Annotatable::Item(_) @@ -2000,6 +2003,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } _ => unreachable!(), }; + if traitless_qself { + let span = item.span; + self.cx.dcx().emit_err(GlobDelegationTraitlessQpath { span }); + return Default::default(); + } return self.collect_glob_delegation(item, Node::KIND).make_ast::<Node>(); }; diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 0050ff10539..e43ba7c3a5a 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -10,7 +10,9 @@ use crate::mbe::transcribe::transcribe; use ast::token::IdentIsRaw; use rustc_ast as ast; -use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind, TokenKind::*}; +use rustc_ast::token::{ + self, Delimiter, NonterminalKind, NtPatKind::*, Token, TokenKind, TokenKind::*, +}; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; @@ -1145,14 +1147,17 @@ fn check_matcher_core<'tt>( // Macros defined in the current crate have a real node id, // whereas macros from an external crate have a dummy id. if def.id != DUMMY_NODE_ID - && matches!(kind, NonterminalKind::PatParam { inferred: true }) - && matches!(next_token, TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or)) + && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true })) + && matches!( + next_token, + TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or) + ) { // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param. let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( span, name, - Some(NonterminalKind::PatParam { inferred: false }), + Some(NonterminalKind::Pat(PatParam { inferred: false })), )); sess.psess.buffer_lint( RUST_2021_INCOMPATIBLE_OR_PATTERNS, @@ -1185,14 +1190,14 @@ fn check_matcher_core<'tt>( ); err.span_label(sp, format!("not allowed after `{kind}` fragments")); - if kind == NonterminalKind::PatWithOr + if kind == NonterminalKind::Pat(PatWithOr) && sess.psess.edition.at_least_rust_2021() && next_token.is_token(&BinOp(token::BinOpToken::Or)) { let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( span, name, - Some(NonterminalKind::PatParam { inferred: false }), + Some(NonterminalKind::Pat(PatParam { inferred: false })), )); err.span_suggestion( span, @@ -1292,9 +1297,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { // maintain IsInFollow::Yes } - NonterminalKind::Stmt - | NonterminalKind::Expr - | NonterminalKind::Expr2021 { inferred: _ } => { + NonterminalKind::Stmt | NonterminalKind::Expr(_) => { const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; match tok { TokenTree::Token(token) => match token.kind { @@ -1304,7 +1307,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - NonterminalKind::PatParam { .. } => { + NonterminalKind::Pat(PatParam { .. }) => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { @@ -1317,7 +1320,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - NonterminalKind::PatWithOr => { + NonterminalKind::Pat(PatWithOr) => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index fdf187438d3..9c480f17b42 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -2,7 +2,7 @@ use crate::errors; use crate::mbe::macro_parser::count_metavar_decls; use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree}; -use rustc_ast::token::{self, Delimiter, IdentIsRaw, Token}; +use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, NtExprKind::*, Token}; use rustc_ast::{tokenstream, NodeId}; use rustc_ast_pretty::pprust; use rustc_feature::Features; @@ -85,36 +85,31 @@ pub(super) fn parse( span.edition() } }; - let kind = - token::NonterminalKind::from_symbol(fragment.name, edition) - .unwrap_or_else(|| { - let help = match fragment.name { - sym::expr_2021 => { - format!( - "fragment specifier `expr_2021` \ - requires Rust 2021 or later\n\ - {VALID_FRAGMENT_NAMES_MSG}" - ) - } - _ if edition().at_least_rust_2021() - && features - .expr_fragment_specifier_2024 => - { - VALID_FRAGMENT_NAMES_MSG_2021.into() - } - _ => VALID_FRAGMENT_NAMES_MSG.into(), - }; - sess.dcx().emit_err( - errors::InvalidFragmentSpecifier { - span, - fragment, - help, - }, - ); - token::NonterminalKind::Ident + let kind = NonterminalKind::from_symbol(fragment.name, edition) + .unwrap_or_else(|| { + let help = match fragment.name { + sym::expr_2021 => { + format!( + "fragment specifier `expr_2021` \ + requires Rust 2021 or later\n\ + {VALID_FRAGMENT_NAMES_MSG}" + ) + } + _ if edition().at_least_rust_2021() + && features.expr_fragment_specifier_2024 => + { + VALID_FRAGMENT_NAMES_MSG_2021.into() + } + _ => VALID_FRAGMENT_NAMES_MSG.into(), + }; + sess.dcx().emit_err(errors::InvalidFragmentSpecifier { + span, + fragment, + help, }); - if kind - == (token::NonterminalKind::Expr2021 { inferred: false }) + NonterminalKind::Ident + }); + if kind == NonterminalKind::Expr(Expr2021 { inferred: false }) && !features.expr_fragment_specifier_2024 { rustc_session::parse::feature_err( diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 9e2756f07ed..5e83e0d27e1 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1145,10 +1145,6 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool { }) } -pub fn is_unsafe_attr(name: Symbol) -> bool { - BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.safety == AttributeSafety::Unsafe) -} - pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> = LazyLock::new(|| { let mut map = FxHashMap::default(); diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index fb3b7c0a127..bf429364318 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -125,7 +125,7 @@ pub use accepted::ACCEPTED_FEATURES; pub use builtin_attrs::AttributeDuplicates; pub use builtin_attrs::{ deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name, - is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, + is_valid_for_get_attr, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, }; pub use removed::REMOVED_FEATURES; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index fbd67657e3b..f66c9604cbe 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -629,7 +629,7 @@ declare_features! ( /// Allows unsafe on extern declarations and safety qualifiers over internal items. (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)), /// Allows unsized fn parameters. - (unstable, unsized_fn_params, "1.49.0", Some(48055)), + (internal, unsized_fn_params, "1.49.0", Some(48055)), /// Allows unsized rvalues at arguments and parameters. (incomplete, unsized_locals, "1.30.0", Some(48055)), /// Allows unsized tuple coercion. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 9dd82868adc..b3ebc0621cb 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -26,10 +26,8 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{ - self, suggest_constraining_type_params, Article, Binder, IsSuggestable, Ty, TypeVisitableExt, - Upcast, -}; +use rustc_middle::ty::{self, suggest_constraining_type_params, Article, Binder}; +use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Upcast}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; @@ -1111,12 +1109,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)), ) { - err.multipart_suggestion( + // When the expr is in a match arm's body, we shouldn't add semicolon ';' at the end. + // For example: + // fn mismatch_types() -> i32 { + // match 1 { + // x => dbg!(x), + // } + // todo!() + // } + // -------------^^^^^^^- + // Don't add semicolon `;` at the end of `dbg!(x)` expr + fn is_in_arm<'tcx>(expr: &'tcx hir::Expr<'tcx>, tcx: TyCtxt<'tcx>) -> bool { + for (_, node) in tcx.hir().parent_iter(expr.hir_id) { + match node { + hir::Node::Block(block) => { + if let Some(ret) = block.expr + && ret.hir_id == expr.hir_id + { + continue; + } + } + hir::Node::Arm(arm) => { + if let hir::ExprKind::Block(block, _) = arm.body.kind + && let Some(ret) = block.expr + && ret.hir_id == expr.hir_id + { + return true; + } + } + hir::Node::Expr(e) if let hir::ExprKind::Block(block, _) = e.kind => { + if let Some(ret) = block.expr + && ret.hir_id == expr.hir_id + { + continue; + } + } + _ => { + return false; + } + } + } + + false + } + let mut suggs = vec![(span.shrink_to_lo(), "return ".to_string())]; + if !is_in_arm(expr, self.tcx) { + suggs.push((span.shrink_to_hi(), ";".to_string())); + } + err.multipart_suggestion_verbose( "you might have meant to return this value", - vec![ - (span.shrink_to_lo(), "return ".to_string()), - (span.shrink_to_hi(), ";".to_string()), - ], + suggs, Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index fdedf2c2e6d..eac5083ffbf 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -825,6 +825,10 @@ lint_unnameable_test_items = cannot test inner items lint_unnecessary_qualification = unnecessary qualification .suggestion = remove the unnecessary path segments +lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe + .label = usage of unsafe attribute +lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` + lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´ lint_untranslatable_diag = diagnostics should be created using translatable messages diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 290bb5173db..adb2a3275c0 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -319,6 +319,16 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnusedQualifications { removal_span } => { lints::UnusedQualifications { removal_span }.decorate_lint(diag); } + BuiltinLintDiag::UnsafeAttrOutsideUnsafe { + attribute_name_span, + sugg_spans: (left, right), + } => { + lints::UnsafeAttrOutsideUnsafe { + span: attribute_name_span, + suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }, + } + .decorate_lint(diag); + } BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index b26d04d0618..6df3a11deb0 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2890,3 +2890,24 @@ pub struct RedundantImportVisibility { pub import_vis: String, pub max_vis: String, } + +#[derive(LintDiagnostic)] +#[diag(lint_unsafe_attr_outside_unsafe)] +pub struct UnsafeAttrOutsideUnsafe { + #[label] + pub span: Span, + #[subdiagnostic] + pub suggestion: UnsafeAttrOutsideUnsafeSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + lint_unsafe_attr_outside_unsafe_suggestion, + applicability = "machine-applicable" +)] +pub struct UnsafeAttrOutsideUnsafeSuggestion { + #[suggestion_part(code = "unsafe(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 1913b9d6a1c..265779c9374 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -115,6 +115,7 @@ declare_lint_pass! { UNNAMEABLE_TYPES, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, + UNSAFE_ATTR_OUTSIDE_UNSAFE, UNSAFE_OP_IN_UNSAFE_FN, UNSTABLE_NAME_COLLISIONS, UNSTABLE_SYNTAX_PRE_EXPANSION, @@ -4902,3 +4903,45 @@ declare_lint! { reference: "issue #123743 <https://github.com/rust-lang/rust/issues/123743>", }; } + +declare_lint! { + /// The `unsafe_attr_outside_unsafe` lint detects a missing unsafe keyword + /// on attributes considered unsafe. + /// + /// ### Example + /// + /// ```rust + /// #![feature(unsafe_attributes)] + /// #![warn(unsafe_attr_outside_unsafe)] + /// + /// #[no_mangle] + /// extern "C" fn foo() {} + /// + /// fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Some attributes (e.g. `no_mangle`, `export_name`, `link_section` -- see + /// [issue #82499] for a more complete list) are considered "unsafe" attributes. + /// An unsafe attribute must only be used inside unsafe(...). + /// + /// This lint can automatically wrap the attributes in `unsafe(...)` , but this + /// obviously cannot verify that the preconditions of the `unsafe` + /// attributes are fulfilled, so that is still up to the user. + /// + /// The lint is currently "allow" by default, but that might change in the + /// future. + /// + /// [editions]: https://doc.rust-lang.org/edition-guide/ + /// [issue #82499]: https://github.com/rust-lang/rust/issues/82499 + pub UNSAFE_ATTR_OUTSIDE_UNSAFE, + Allow, + "detects unsafe attributes outside of unsafe", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024), + reference: "issue #123757 <https://github.com/rust-lang/rust/issues/123757>", + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index b3838f915f6..f33aadfbbc8 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -691,6 +691,10 @@ pub enum BuiltinLintDiag { /// The span of the unnecessarily-qualified path to remove. removal_span: Span, }, + UnsafeAttrOutsideUnsafe { + attribute_name_span: Span, + sugg_spans: (Span, Span), + }, AssociatedConstElidedLifetime { elided: bool, span: Span, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 23680f14397..6a8498abaf9 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -520,6 +520,8 @@ pub enum UnsupportedOpInfo { Unsupported(String), /// Unsized local variables. UnsizedLocal, + /// Extern type field with an indeterminate offset. + ExternTypeField, // // The variants below are only reachable from CTFE/const prop, miri will never emit them. // diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index efb9526eabc..f08efe60d96 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -366,6 +366,10 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item} .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style +parse_invalid_attr_unsafe = `{$name}` is not an unsafe attribute + .suggestion = remove the `unsafe(...)` + .note = extraneous unsafe is not allowed in attributes + parse_invalid_block_macro_segment = cannot use a `block` macro fragment here .label = the `block` fragment is within this context .suggestion = wrap this in another block @@ -866,6 +870,11 @@ parse_unmatched_angle_brackets = {$num_extra_brackets -> *[other] remove extra angle brackets } +parse_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe + .label = usage of unsafe attribute +parse_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` + + parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped .label = {parse_unskipped_whitespace} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 46e15734853..8d49887f164 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2997,3 +2997,34 @@ pub(crate) struct DotDotRangeAttribute { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(parse_invalid_attr_unsafe)] +#[note] +pub struct InvalidAttrUnsafe { + #[primary_span] + pub span: Span, + pub name: Path, +} + +#[derive(Diagnostic)] +#[diag(parse_unsafe_attr_outside_unsafe)] +pub struct UnsafeAttrOutsideUnsafe { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub suggestion: UnsafeAttrOutsideUnsafeSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + parse_unsafe_attr_outside_unsafe_suggestion, + applicability = "machine-applicable" +)] +pub struct UnsafeAttrOutsideUnsafeSuggestion { + #[suggestion_part(code = "unsafe(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 59f6eff07b3..4a78b427832 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,5 +1,7 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token}; +use rustc_ast::token::{ + self, Delimiter, Nonterminal::*, NonterminalKind, NtExprKind::*, NtPatKind::*, Token, +}; use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; @@ -36,14 +38,14 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr2021 { inferred: _ } => { + NonterminalKind::Expr(Expr2021 { .. }) => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) // This exception is here for backwards compatibility. && !token.is_keyword(kw::Const) } - NonterminalKind::Expr => { + NonterminalKind::Expr(Expr) => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) @@ -74,7 +76,7 @@ impl<'a> Parser<'a> { token::Interpolated(nt) => may_be_ident(nt), _ => false, }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => match &token.kind { + NonterminalKind::Pat(pat_kind) => match &token.kind { // box, ref, mut, and other identifiers (can stricten) token::Ident(..) | token::NtIdent(..) | token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern @@ -89,7 +91,7 @@ impl<'a> Parser<'a> { token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern - token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr), + token::BinOp(token::Or) => matches!(pat_kind, PatWithOr), token::Interpolated(nt) => may_be_ident(nt), _ => false, }, @@ -135,31 +137,25 @@ impl<'a> Parser<'a> { .create_err(UnexpectedNonterminal::Statement(self.token.span))); } }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { - NtPat(self.collect_tokens_no_attrs(|this| match kind { - NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None), - NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt( + NonterminalKind::Pat(pat_kind) => { + NtPat(self.collect_tokens_no_attrs(|this| match pat_kind { + PatParam { .. } => this.parse_pat_no_top_alt(None, None), + PatWithOr => this.parse_pat_allow_top_alt( None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe, ), - _ => unreachable!(), })?) } - - NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: _ } => { - NtExpr(self.parse_expr_force_collect()?) - } + NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { // The `:literal` matcher does not support attributes NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) } - NonterminalKind::Ty => { NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?) } - // this could be handled like a token, since it is one NonterminalKind::Ident => { return if let Some((ident, is_raw)) = get_macro_ident(&self.token) { diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 4ca52146039..bcb1131cc19 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -5,21 +5,73 @@ use crate::{errors, parse_in}; use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::MetaItemKind; -use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem}; +use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety}; use rustc_errors::{Applicability, FatalError, PResult}; -use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; +use rustc_feature::{ + AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP, +}; 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, UNSAFE_ATTR_OUTSIDE_UNSAFE}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::ParseSess; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{sym, BytePos, Span, Symbol}; -pub fn check_attr(psess: &ParseSess, attr: &Attribute) { +pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) { if attr.is_doc_comment() { return; } let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); + let attr_item = attr.get_normal_item(); + + let is_unsafe_attr = attr_info.is_some_and(|attr| attr.safety == AttributeSafety::Unsafe); + + if features.unsafe_attributes { + if is_unsafe_attr { + if let ast::Safety::Default = attr_item.unsafety { + let path_span = attr_item.path.span; + + // If the `attr_item`'s span is not from a macro, then just suggest + // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the + // `unsafe(`, `)` right after and right before the opening and closing + // square bracket respectively. + let diag_span = if attr_item.span().can_be_used_for_suggestions() { + attr_item.span() + } else { + attr.span + .with_lo(attr.span.lo() + BytePos(2)) + .with_hi(attr.span.hi() - BytePos(1)) + }; + + if attr.span.at_least_rust_2024() { + psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe { + span: path_span, + suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { + left: diag_span.shrink_to_lo(), + right: diag_span.shrink_to_hi(), + }, + }); + } else { + psess.buffer_lint( + UNSAFE_ATTR_OUTSIDE_UNSAFE, + path_span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::UnsafeAttrOutsideUnsafe { + attribute_name_span: path_span, + sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), + }, + ); + } + } + } else { + if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { + psess.dcx().emit_err(errors::InvalidAttrUnsafe { + span: unsafe_span, + name: attr_item.path.clone(), + }); + } + } + } // Check input tokens for built-in and key-value attributes. match attr_info { @@ -32,7 +84,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { } } } - _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => { + _ if let AttrArgs::Eq(..) = attr_item.args => { // All key-value attributes are restricted to meta-item syntax. match parse_meta(psess, attr) { Ok(_) => {} diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 84c71c4bed2..9a830b0f49b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -384,10 +384,6 @@ passes_invalid_attr_at_crate_level = passes_invalid_attr_at_crate_level_item = the inner attribute doesn't annotate this {$kind} -passes_invalid_attr_unsafe = `{$name}` is not an unsafe attribute - .suggestion = remove the `unsafe(...)` - .note = extraneous unsafe is not allowed in attributes - passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a0b3470df6d..2ed5bba85c6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -10,9 +10,7 @@ use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, IntoDiagArg, MultiSpan}; use rustc_errors::{DiagCtxtHandle, StashKey}; -use rustc_feature::{ - is_unsafe_attr, AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP, -}; +use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir::def_id::LocalModDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir}; @@ -116,8 +114,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let mut seen = FxHashMap::default(); let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { - self.check_unsafe_attr(attr); - match attr.path().as_slice() { [sym::diagnostic, sym::do_not_recommend] => { self.check_do_not_recommend(attr.span, hir_id, target) @@ -312,21 +308,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { true } - /// Checks if `unsafe()` is applied to an invalid attribute. - fn check_unsafe_attr(&self, attr: &Attribute) { - if !attr.is_doc_comment() { - let attr_item = attr.get_normal_item(); - if let ast::Safety::Unsafe(unsafe_span) = attr_item.unsafety { - if !is_unsafe_attr(attr.name_or_empty()) { - self.dcx().emit_err(errors::InvalidAttrUnsafe { - span: unsafe_span, - name: attr_item.path.clone(), - }); - } - } - } - } - /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition fn check_diagnostic_on_unimplemented( &self, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index d27b94ebd22..f0596568092 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -4,7 +4,7 @@ use std::{ }; use crate::fluent_generated as fluent; -use rustc_ast::{ast, Label}; +use rustc_ast::Label; use rustc_errors::{ codes::*, Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic, @@ -863,15 +863,6 @@ pub struct InvalidAttrAtCrateLevel { pub item: Option<ItemFollowingInnerAttr>, } -#[derive(Diagnostic)] -#[diag(passes_invalid_attr_unsafe)] -#[note] -pub struct InvalidAttrUnsafe { - #[primary_span] - pub span: Span, - pub name: ast::Path, -} - #[derive(Clone, Copy)] pub struct ItemFollowingInnerAttr { pub span: Span, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 87794d11cea..8763e7aec43 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -140,9 +140,10 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { } } } - // We implicitly add `rustfmt`, `clippy`, `diagnostic` to known tools, - // but it's not an error to register them explicitly. - let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri]; + // We implicitly add `rustfmt`, `clippy`, `diagnostic`, `miri` and `rust_analyzer` to known + // tools, but it's not an error to register them explicitly. + let predefined_tools = + [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri, sym::rust_analyzer]; registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span)); registered_tools } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8d8f4927e99..ab0538ff282 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1559,6 +1559,7 @@ symbols! { rust_2018_preview, rust_2021, rust_2024, + rust_analyzer, rust_begin_unwind, rust_cold_cc, rust_eh_catch_typeinfo, diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 9d79faadd61..70fcaab1847 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -148,22 +148,22 @@ def_regs! { r11: reg = ["r11", "fp"] % frame_pointer_r11, r12: reg = ["r12", "ip"] % not_thumb1, r14: reg = ["r14", "lr"] % not_thumb1, - s0: sreg, sreg_low16 = ["s0"], - s1: sreg, sreg_low16 = ["s1"], - s2: sreg, sreg_low16 = ["s2"], - s3: sreg, sreg_low16 = ["s3"], - s4: sreg, sreg_low16 = ["s4"], - s5: sreg, sreg_low16 = ["s5"], - s6: sreg, sreg_low16 = ["s6"], - s7: sreg, sreg_low16 = ["s7"], - s8: sreg, sreg_low16 = ["s8"], - s9: sreg, sreg_low16 = ["s9"], - s10: sreg, sreg_low16 = ["s10"], - s11: sreg, sreg_low16 = ["s11"], - s12: sreg, sreg_low16 = ["s12"], - s13: sreg, sreg_low16 = ["s13"], - s14: sreg, sreg_low16 = ["s14"], - s15: sreg, sreg_low16 = ["s15"], + s0: sreg_low16, sreg = ["s0"], + s1: sreg_low16, sreg = ["s1"], + s2: sreg_low16, sreg = ["s2"], + s3: sreg_low16, sreg = ["s3"], + s4: sreg_low16, sreg = ["s4"], + s5: sreg_low16, sreg = ["s5"], + s6: sreg_low16, sreg = ["s6"], + s7: sreg_low16, sreg = ["s7"], + s8: sreg_low16, sreg = ["s8"], + s9: sreg_low16, sreg = ["s9"], + s10: sreg_low16, sreg = ["s10"], + s11: sreg_low16, sreg = ["s11"], + s12: sreg_low16, sreg = ["s12"], + s13: sreg_low16, sreg = ["s13"], + s14: sreg_low16, sreg = ["s14"], + s15: sreg_low16, sreg = ["s15"], s16: sreg = ["s16"], s17: sreg = ["s17"], s18: sreg = ["s18"], @@ -180,22 +180,22 @@ def_regs! { s29: sreg = ["s29"], s30: sreg = ["s30"], s31: sreg = ["s31"], - d0: dreg, dreg_low16, dreg_low8 = ["d0"], - d1: dreg, dreg_low16, dreg_low8 = ["d1"], - d2: dreg, dreg_low16, dreg_low8 = ["d2"], - d3: dreg, dreg_low16, dreg_low8 = ["d3"], - d4: dreg, dreg_low16, dreg_low8 = ["d4"], - d5: dreg, dreg_low16, dreg_low8 = ["d5"], - d6: dreg, dreg_low16, dreg_low8 = ["d6"], - d7: dreg, dreg_low16, dreg_low8 = ["d7"], - d8: dreg, dreg_low16 = ["d8"], - d9: dreg, dreg_low16 = ["d9"], - d10: dreg, dreg_low16 = ["d10"], - d11: dreg, dreg_low16 = ["d11"], - d12: dreg, dreg_low16 = ["d12"], - d13: dreg, dreg_low16 = ["d13"], - d14: dreg, dreg_low16 = ["d14"], - d15: dreg, dreg_low16 = ["d15"], + d0: dreg_low8, dreg_low16, dreg = ["d0"], + d1: dreg_low8, dreg_low16, dreg = ["d1"], + d2: dreg_low8, dreg_low16, dreg = ["d2"], + d3: dreg_low8, dreg_low16, dreg = ["d3"], + d4: dreg_low8, dreg_low16, dreg = ["d4"], + d5: dreg_low8, dreg_low16, dreg = ["d5"], + d6: dreg_low8, dreg_low16, dreg = ["d6"], + d7: dreg_low8, dreg_low16, dreg = ["d7"], + d8: dreg_low16, dreg = ["d8"], + d9: dreg_low16, dreg = ["d9"], + d10: dreg_low16, dreg = ["d10"], + d11: dreg_low16, dreg = ["d11"], + d12: dreg_low16, dreg = ["d12"], + d13: dreg_low16, dreg = ["d13"], + d14: dreg_low16, dreg = ["d14"], + d15: dreg_low16, dreg = ["d15"], d16: dreg = ["d16"], d17: dreg = ["d17"], d18: dreg = ["d18"], @@ -212,14 +212,14 @@ def_regs! { d29: dreg = ["d29"], d30: dreg = ["d30"], d31: dreg = ["d31"], - q0: qreg, qreg_low8, qreg_low4 = ["q0"], - q1: qreg, qreg_low8, qreg_low4 = ["q1"], - q2: qreg, qreg_low8, qreg_low4 = ["q2"], - q3: qreg, qreg_low8, qreg_low4 = ["q3"], - q4: qreg, qreg_low8 = ["q4"], - q5: qreg, qreg_low8 = ["q5"], - q6: qreg, qreg_low8 = ["q6"], - q7: qreg, qreg_low8 = ["q7"], + q0: qreg_low4, qreg_low8, qreg = ["q0"], + q1: qreg_low4, qreg_low8, qreg = ["q1"], + q2: qreg_low4, qreg_low8, qreg = ["q2"], + q3: qreg_low4, qreg_low8, qreg = ["q3"], + q4: qreg_low8, qreg = ["q4"], + q5: qreg_low8, qreg = ["q5"], + q6: qreg_low8, qreg = ["q6"], + q7: qreg_low8, qreg = ["q7"], q8: qreg = ["q8"], q9: qreg = ["q9"], q10: qreg = ["q10"], diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index c709ea2a15d..1d19c985f23 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -443,8 +443,8 @@ impl AtomicBool { /// /// # Safety /// - /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can - /// be bigger than `align_of::<bool>()`). + /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that this is always true, since + /// `align_of::<AtomicBool>() == 1`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, @@ -2091,10 +2091,10 @@ impl<T> From<*mut T> for AtomicPtr<T> { } #[allow(unused_macros)] // This macro ends up being unused on some architectures. -macro_rules! if_not_8_bit { - (u8, $($tt:tt)*) => { "" }; - (i8, $($tt:tt)*) => { "" }; - ($_:ident, $($tt:tt)*) => { $($tt)* }; +macro_rules! if_8_bit { + (u8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) }; + (i8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) }; + ($_:ident, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($no)*)?) }; } #[cfg(target_has_atomic_load_store)] @@ -2116,18 +2116,24 @@ macro_rules! atomic_int { $int_type:ident $atomic_type:ident) => { /// An integer type which can be safely shared between threads. /// - /// This type has the same size and bit validity as the underlying - /// integer type, [` + /// This type has the same + #[doc = if_8_bit!( + $int_type, + yes = ["size, alignment, and bit validity"], + no = ["size and bit validity"], + )] + /// as the underlying integer type, [` #[doc = $s_int_type] /// `]. - #[doc = if_not_8_bit! { + #[doc = if_8_bit! { $int_type, - concat!( + no = [ "However, the alignment of this type is always equal to its ", "size, even on targets where [`", $s_int_type, "`] has a ", "lesser alignment." - ) + ], }] + /// /// For more about the differences between atomic types and /// non-atomic types as well as information about the portability of /// this type, please see the [module-level documentation]. @@ -2220,9 +2226,19 @@ macro_rules! atomic_int { /// /// # Safety /// - #[doc = concat!(" * `ptr` must be aligned to \ - `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this \ - can be bigger than `align_of::<", stringify!($int_type), ">()`).")] + /// * `ptr` must be aligned to + #[doc = concat!(" `align_of::<", stringify!($atomic_type), ">()`")] + #[doc = if_8_bit!{ + $int_type, + yes = [ + " (note that this is always true, since `align_of::<", + stringify!($atomic_type), ">() == 1`)." + ], + no = [ + " (note that on some platforms this can be bigger than `align_of::<", + stringify!($int_type), ">()`)." + ], + }] /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, @@ -2261,12 +2277,12 @@ macro_rules! atomic_int { #[doc = concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.")] /// - #[doc = if_not_8_bit! { + #[doc = if_8_bit! { $int_type, - concat!( + no = [ "**Note:** This function is only available on targets where `", stringify!($int_type), "` has an alignment of ", $align, " bytes." - ) + ], }] /// /// # Examples diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 5c4ccd32850..92c76ec4303 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -20,14 +20,14 @@ use crate::sys::time::SystemTime; use crate::sys::{cvt, cvt_r}; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))] +#[cfg(all(target_os = "linux", target_env = "gnu"))] use crate::sys::weak::syscall; #[cfg(target_os = "android")] use crate::sys::weak::weak; use libc::{c_int, mode_t}; -#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))] +#[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::c_char; #[cfg(any( all(target_os = "linux", not(target_env = "musl")), @@ -1891,8 +1891,6 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { #[cfg(target_vendor = "apple")] pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { - use crate::sync::atomic::{AtomicBool, Ordering}; - const COPYFILE_ALL: libc::copyfile_flags_t = libc::COPYFILE_METADATA | libc::COPYFILE_DATA; struct FreeOnDrop(libc::copyfile_state_t); @@ -1907,39 +1905,21 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { } } - // MacOS prior to 10.12 don't support `fclonefileat` - // We store the availability in a global to avoid unnecessary syscalls - static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true); - syscall! { - // Mirrors `libc::fclonefileat` - fn fclonefileat( - srcfd: libc::c_int, - dst_dirfd: libc::c_int, - dst: *const c_char, - flags: libc::c_int - ) -> libc::c_int - } - let (reader, reader_metadata) = open_from(from)?; - // Opportunistically attempt to create a copy-on-write clone of `from` - // using `fclonefileat`. - if HAS_FCLONEFILEAT.load(Ordering::Relaxed) { - let clonefile_result = run_path_with_cstr(to, &|to| { - cvt(unsafe { fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) }) - }); - match clonefile_result { - Ok(_) => return Ok(reader_metadata.len()), - Err(err) => match err.raw_os_error() { - // `fclonefileat` will fail on non-APFS volumes, if the - // destination already exists, or if the source and destination - // are on different devices. In all these cases `fcopyfile` - // should succeed. - Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (), - Some(libc::ENOSYS) => HAS_FCLONEFILEAT.store(false, Ordering::Relaxed), - _ => return Err(err), - }, - } + let clonefile_result = run_path_with_cstr(to, &|to| { + cvt(unsafe { libc::fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) }) + }); + match clonefile_result { + Ok(_) => return Ok(reader_metadata.len()), + Err(e) => match e.raw_os_error() { + // `fclonefileat` will fail on non-APFS volumes, if the + // destination already exists, or if the source and destination + // are on different devices. In all these cases `fcopyfile` + // should succeed. + Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (), + _ => return Err(e), + }, } // Fall back to using `fcopyfile` if `fclonefileat` does not succeed. diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 2e71ceceb58..40e2d1403ef 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -738,17 +738,17 @@ pub fn home_dir() -> Option<PathBuf> { n => n as usize, }; let mut buf = Vec::with_capacity(amt); - let mut passwd: libc::passwd = mem::zeroed(); + let mut p = mem::MaybeUninit::<libc::passwd>::uninit(); let mut result = ptr::null_mut(); match libc::getpwuid_r( libc::getuid(), - &mut passwd, + p.as_mut_ptr(), buf.as_mut_ptr(), buf.capacity(), &mut result, ) { 0 if !result.is_null() => { - let ptr = passwd.pw_dir as *const _; + let ptr = (*result).pw_dir as *const _; let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); Some(OsStringExt::from_vec(bytes)) } diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index e4dbd3a13fe..258a0347451 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/125141 +Last change is for: https://github.com/rust-lang/rust/pull/126298 diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index cc5b0073213..5b18cb3f7e1 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1290,15 +1290,21 @@ fn needs_codegen_config(run: &RunConfig<'_>) -> bool { pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_"; fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool { - if path.path.to_str().unwrap().contains(CODEGEN_BACKEND_PREFIX) { + let path = path.path.to_str().unwrap(); + + let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) }; + let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install; + + if path.contains(CODEGEN_BACKEND_PREFIX) { let mut needs_codegen_backend_config = true; for backend in run.builder.config.codegen_backends(run.target) { - if path.path.to_str().unwrap().ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) - { + if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) { needs_codegen_backend_config = false; } } - if needs_codegen_backend_config { + if (is_explicitly_called(&PathBuf::from(path)) || should_enforce) + && needs_codegen_backend_config + { run.builder.info( "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \ HELP: add backend to codegen-backends in config.toml.", diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 4fb64595504..2dc7cd7de6a 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1018,7 +1018,7 @@ impl Step for PlainSourceTarball { // perhaps it should be removed in favor of making `dist` perform the `vendor` step? // Ensure we have all submodules from src and other directories checked out. - for submodule in builder.get_all_submodules() { + for submodule in build_helper::util::parse_gitmodules(&builder.src) { builder.update_submodule(Path::new(submodule)); } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index f90403d2ec4..8b379d3be5c 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -217,6 +217,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool { ("arm-unknown-linux-gnueabihf", false), ("armv7-unknown-linux-gnueabihf", false), ("loongarch64-unknown-linux-gnu", false), + ("loongarch64-unknown-linux-musl", false), ("mips-unknown-linux-gnu", false), ("mips64-unknown-linux-gnuabi64", false), ("mips64el-unknown-linux-gnuabi64", false), diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 8a2bc3b9d48..efc09c41bf4 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1048,8 +1048,6 @@ impl Step for Tidy { /// Once tidy passes, this step also runs `fmt --check` if tests are being run /// for the `dev` or `nightly` channels. fn run(self, builder: &Builder<'_>) { - builder.build.update_submodule(Path::new("src/tools/rustc-perf")); - let mut cmd = builder.tool_cmd(Tool::Tidy); cmd.arg(&builder.src); cmd.arg(&builder.initial_cargo); diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 2e9c04624c7..14ccbfe0267 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -4,13 +4,11 @@ use std::collections::BTreeSet; use std::env; use std::ffi::{OsStr, OsString}; use std::fmt::{Debug, Write}; -use std::fs::{self, File}; +use std::fs; use std::hash::Hash; -use std::io::{BufRead, BufReader}; use std::ops::Deref; use std::path::{Path, PathBuf}; use std::process::Command; -use std::sync::OnceLock; use std::time::{Duration, Instant}; use crate::core::build_steps::tool::{self, SourceType}; @@ -594,7 +592,7 @@ impl<'a> ShouldRun<'a> { /// /// [`path`]: ShouldRun::path pub fn paths(mut self, paths: &[&str]) -> Self { - let submodules_paths = self.builder.get_all_submodules(); + let submodules_paths = build_helper::util::parse_gitmodules(&self.builder.src); self.paths.insert(PathSet::Set( paths @@ -2243,28 +2241,6 @@ impl<'a> Builder<'a> { out } - /// Return paths of all submodules. - pub fn get_all_submodules(&self) -> &[String] { - static SUBMODULES_PATHS: OnceLock<Vec<String>> = OnceLock::new(); - - let init_submodules_paths = |src: &PathBuf| { - let file = File::open(src.join(".gitmodules")).unwrap(); - - let mut submodules_paths = vec![]; - for line in BufReader::new(file).lines().map_while(Result::ok) { - let line = line.trim(); - if line.starts_with("path") { - let actual_path = line.split(' ').last().expect("Couldn't get value of path"); - submodules_paths.push(actual_path.to_owned()); - } - } - - submodules_paths - }; - - SUBMODULES_PATHS.get_or_init(|| init_submodules_paths(&self.src)) - } - /// Ensure that a given step is built *only if it's supposed to be built by default*, returning /// its output. This will cache the step, so it's safe (and good!) to call this as often as /// needed to ensure that all dependencies are build. diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 4b6dc45b436..59b29eedb79 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -135,7 +135,7 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result< if config.dry_run() { return Ok(()); } - let _ = fs::remove_dir(link); + let _ = fs::remove_dir_all(link); return symlink_dir_inner(original, link); #[cfg(not(windows))] diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 824c904e17f..985e3b37422 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -271,6 +271,22 @@ For targets: `loongarch64-unknown-linux-gnu` - C compiler > gcc version = 13.2.0 - C compiler > C++ = ENABLE -- to cross compile LLVM +### `loongarch64-linux-musl.defconfig` + +For targets: `loongarch64-unknown-linux-musl` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Path and misc options > Use a mirror = ENABLE +- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc +- Target options > Target Architecture = loongarch +- Target options > Bitness = 64-bit +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 5.19.16 +- Binary utilities > Version of binutils = 2.41 +- C-library > musl version = 1.2.5 +- C compiler > gcc version = 13.2.0 +- C compiler > C++ = ENABLE -- to cross compile LLVM + ### `mips-linux-gnu.defconfig` For targets: `mips-unknown-linux-gnu` diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile new file mode 100644 index 00000000000..560adf971ba --- /dev/null +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile @@ -0,0 +1,35 @@ +FROM ubuntu:22.04 + +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/crosstool-ng-git.sh /scripts/ +RUN sh /scripts/crosstool-ng-git.sh + +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh +WORKDIR /tmp + +COPY scripts/crosstool-ng-build.sh /scripts/ +COPY host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig /tmp/crosstool.defconfig +RUN /scripts/crosstool-ng-build.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV PATH=$PATH:/x-tools/loongarch64-unknown-linux-musl/bin + +ENV CC_loongarch64_unknown_linux_musl=loongarch64-unknown-linux-musl-gcc \ + AR_loongarch64_unknown_linux_musl=loongarch64-unknown-linux-musl-ar \ + CXX_loongarch64_unknown_linux_musl=loongarch64-unknown-linux-musl-g++ + +ENV HOSTS=loongarch64-unknown-linux-musl + +ENV RUST_CONFIGURE_ARGS \ + --enable-extended \ + --enable-lld \ + --disable-docs \ + --set target.loongarch64-unknown-linux-musl.crt-static=false \ + --musl-root-loongarch64=/x-tools/loongarch64-unknown-linux-musl/loongarch64-unknown-linux-musl/sysroot/usr + +ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig new file mode 100644 index 00000000000..3ab676ed971 --- /dev/null +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig @@ -0,0 +1,15 @@ +CT_CONFIG_VERSION="4" +CT_EXPERIMENTAL=y +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_USE_MIRROR=y +CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" +CT_ARCH_LOONGARCH=y +# CT_DEMULTILIB is not set +CT_ARCH_USE_MMU=y +CT_ARCH_ARCH="loongarch64" +CT_KERNEL_LINUX=y +CT_LINUX_V_5_19=y +CT_LIBC_MUSL=y +CT_CC_GCC_ENABLE_DEFAULT_PIE=y +CT_CC_LANG_CXX=y +CT_GETTEXT_NEEDED=y diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh new file mode 100644 index 00000000000..2a10e262df8 --- /dev/null +++ b/src/ci/docker/scripts/crosstool-ng-git.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -ex + +URL=https://github.com/crosstool-ng/crosstool-ng +REV=c64500d94be92ed1bcdfdef911048a14e216a5e1 + +mkdir crosstool-ng +cd crosstool-ng +git init +git fetch --depth=1 ${URL} ${REV} +git reset --hard FETCH_HEAD +./bootstrap +./configure --prefix=/usr/local +make -j$(nproc) +make install +cd .. +rm -rf crosstool-ng diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 4366a92fbcd..e3903c3dd5a 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -144,6 +144,9 @@ auto: - image: dist-loongarch64-linux <<: *job-linux-4c + - image: dist-loongarch64-musl + <<: *job-linux-4c + - image: dist-ohos <<: *job-linux-4c diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 537c88cd22b..71dc8c4ca0f 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -93,6 +93,7 @@ target | notes `arm-unknown-linux-gnueabihf` | Armv6 Linux, hardfloat (kernel 3.2, glibc 2.17) `armv7-unknown-linux-gnueabihf` | Armv7-A Linux, hardfloat (kernel 3.2, glibc 2.17) [`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36) +[`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, musl 1.2.5) `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17) `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17) @@ -118,7 +119,7 @@ The `std` column in the table below has the following meanings: * ✓ indicates the full standard library is available. * \* indicates the target only supports [`no_std`] development. -* ? indicates the standard library support is unknown or a work-in-progress. +* ? indicates the standard library support is a work-in-progress. [`no_std`]: https://rust-embedded.github.io/book/intro/no-std.html @@ -305,7 +306,6 @@ target | std | host | notes `i686-uwp-windows-msvc` | ✓ | | [^x86_32-floats-return-ABI] [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI] `i686-wrs-vxworks` | ? | | [^x86_32-floats-return-ABI] -[`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | ? | | LoongArch64 Linux (LP64D ABI) with musl 1.2.3 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) `mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl 1.2.3 diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh index c9e1a2733fd..6f86c7ab8a4 100755 --- a/src/etc/pre-push.sh +++ b/src/etc/pre-push.sh @@ -7,8 +7,6 @@ set -Euo pipefail -# https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570 -unset GIT_DIR ROOT_DIR="$(git rev-parse --show-toplevel)" echo "Running pre-push script $ROOT_DIR/x test tidy" diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md index 9d30c554186..2ea1bffb35f 100644 --- a/src/tools/build-manifest/README.md +++ b/src/tools/build-manifest/README.md @@ -4,7 +4,7 @@ This tool generates the manifests uploaded to static.rust-lang.org and used by r You can see a full list of all manifests at <https://static.rust-lang.org/manifests.txt>. This listing is updated by <https://github.com/rust-lang/generate-manifest-list> every 7 days. -This gets called by `promote-release` <https://github.com/rust-lang/promote-release> via `x.py dist hash-and-sign`. +This gets called by `promote-release` <https://github.com/rust-lang/promote-release>. `promote-release` downloads a pre-built binary of `build-manifest` which is generated in the dist-x86_64-linux builder and uploaded to s3. ## Adding a new component diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index a709aab7ce2..a2e7907b532 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -25,6 +25,7 @@ static HOSTS: &[&str] = &[ "i686-pc-windows-msvc", "i686-unknown-linux-gnu", "loongarch64-unknown-linux-gnu", + "loongarch64-unknown-linux-musl", "mips-unknown-linux-gnu", "mips64-unknown-linux-gnuabi64", "mips64el-unknown-linux-gnuabi64", @@ -106,6 +107,7 @@ static TARGETS: &[&str] = &[ "i686-unknown-redox", "i686-unknown-uefi", "loongarch64-unknown-linux-gnu", + "loongarch64-unknown-linux-musl", "loongarch64-unknown-none", "loongarch64-unknown-none-softfloat", "m68k-unknown-linux-gnu", diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs index 5801a8648f2..72c05c4c48a 100644 --- a/src/tools/build_helper/src/util.rs +++ b/src/tools/build_helper/src/util.rs @@ -1,4 +1,8 @@ +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::Path; use std::process::Command; +use std::sync::OnceLock; /// Invokes `build_helper::util::detail_exit` with `cfg!(test)` /// @@ -45,3 +49,27 @@ pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> { Ok(()) } } + +/// Returns the submodule paths from the `.gitmodules` file in the given directory. +pub fn parse_gitmodules(target_dir: &Path) -> &[String] { + static SUBMODULES_PATHS: OnceLock<Vec<String>> = OnceLock::new(); + let gitmodules = target_dir.join(".gitmodules"); + assert!(gitmodules.exists(), "'{}' file is missing.", gitmodules.display()); + + let init_submodules_paths = || { + let file = File::open(gitmodules).unwrap(); + + let mut submodules_paths = vec![]; + for line in BufReader::new(file).lines().map_while(Result::ok) { + let line = line.trim(); + if line.starts_with("path") { + let actual_path = line.split(' ').last().expect("Couldn't get value of path"); + submodules_paths.push(actual_path.to_owned()); + } + } + + submodules_paths + }; + + SUBMODULES_PATHS.get_or_init(|| init_submodules_paths()) +} diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 82d80fcc19c..31ae0deb7ec 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -877,6 +877,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-shadow-call-stack", "needs-sanitizer-support", "needs-sanitizer-thread", + "needs-symlink", "needs-threads", "needs-unwind", "needs-wasmtime", diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index b96832db67b..5b2665f7d0b 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -144,6 +144,11 @@ pub(super) fn handle_needs( condition: config.runner.as_ref().is_some_and(|r| r.contains("wasmtime")), ignore_reason: "ignored when wasmtime runner is not available", }, + Need { + name: "needs-symlink", + condition: cache.symlinks, + ignore_reason: "ignored if symlinks are unavailable", + }, ]; let (name, comment) = match ln.split_once([':', ' ']) { @@ -209,6 +214,7 @@ pub(super) struct CachedNeedsConditions { xray: bool, rust_lld: bool, dlltool: bool, + symlinks: bool, } impl CachedNeedsConditions { @@ -253,6 +259,7 @@ impl CachedNeedsConditions { .exists(), dlltool: find_dlltool(&config), + symlinks: has_symlinks(), } } } @@ -279,3 +286,22 @@ fn find_dlltool(config: &Config) -> bool { }; dlltool_found } + +#[cfg(windows)] +fn has_symlinks() -> bool { + if std::env::var_os("CI").is_some() { + return true; + } + let link = std::env::temp_dir().join("RUST_COMPILETEST_SYMLINK_CHECK"); + if std::os::windows::fs::symlink_file("DOES NOT EXIST", &link).is_ok() { + std::fs::remove_file(&link).unwrap(); + true + } else { + false + } +} + +#[cfg(not(windows))] +fn has_symlinks() -> bool { + true +} diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 12fb76f3972..1b70a1a1cf0 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -311,7 +311,9 @@ pub fn report_error<'tcx>( ResourceExhaustion(_) => "resource exhaustion", Unsupported( // We list only the ones that can actually happen. - UnsupportedOpInfo::Unsupported(_) | UnsupportedOpInfo::UnsizedLocal, + UnsupportedOpInfo::Unsupported(_) + | UnsupportedOpInfo::UnsizedLocal + | UnsupportedOpInfo::ExternTypeField, ) => "unsupported operation", InvalidProgram( // We list only the ones that can actually happen. diff --git a/src/tools/miri/tests/fail/extern-type-field-offset.stderr b/src/tools/miri/tests/fail/extern-type-field-offset.stderr index e0d6e9ebf1d..3ed5732b4eb 100644 --- a/src/tools/miri/tests/fail/extern-type-field-offset.stderr +++ b/src/tools/miri/tests/fail/extern-type-field-offset.stderr @@ -1,8 +1,8 @@ -error: unsupported operation: `extern type` does not have a known offset +error: unsupported operation: `extern type` field does not have a known offset --> $DIR/extern-type-field-offset.rs:LL:CC | LL | let _field = &x.a; - | ^^^^ `extern type` does not have a known offset + | ^^^^ `extern type` field does not have a known offset | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support = note: BACKTRACE: diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index c8ea104e9d6..eb11604b277 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1994,7 +1994,6 @@ fn rewrite_static( static_parts: &StaticParts<'_>, offset: Indent, ) -> Option<String> { - println!("rewriting static"); let colon = colon_spaces(context.config); let mut prefix = format!( "{}{}{}{} {}{}{}", diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs index c44f3788d97..a1de71a35be 100644 --- a/src/tools/rustfmt/src/overflow.rs +++ b/src/tools/rustfmt/src/overflow.rs @@ -83,6 +83,7 @@ pub(crate) enum OverflowableItem<'a> { TuplePatField(&'a TuplePatField<'a>), Ty(&'a ast::Ty), Pat(&'a ast::Pat), + PreciseCapturingArg(&'a ast::PreciseCapturingArg), } impl<'a> Rewrite for OverflowableItem<'a> { @@ -123,6 +124,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::TuplePatField(pat) => f(*pat), OverflowableItem::Ty(ty) => f(*ty), OverflowableItem::Pat(pat) => f(*pat), + OverflowableItem::PreciseCapturingArg(arg) => f(*arg), } } @@ -137,6 +139,9 @@ impl<'a> OverflowableItem<'a> { matches!(meta_item.kind, ast::MetaItemKind::Word) } }, + // FIXME: Why don't we consider `SegmentParam` to be simple? + // FIXME: If we also fix `SegmentParam`, then we should apply the same + // heuristic to `PreciseCapturingArg`. _ => false, } } @@ -244,7 +249,15 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types { } } -impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty, Pat); +impl_into_overflowable_item_for_ast_node!( + Expr, + GenericParam, + NestedMetaItem, + FieldDef, + Ty, + Pat, + PreciseCapturingArg +); impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]); pub(crate) fn into_overflowable_list<'a, T>( diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index 89169e10715..60c827fd03b 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -1,4 +1,4 @@ -use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind}; +use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ast, ptr}; use rustc_parse::parser::{ForceCollect, Parser, Recovery}; @@ -48,7 +48,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> { parse_macro_arg!( Expr, - NonterminalKind::Expr, + NonterminalKind::Expr(Expr), |parser: &mut Parser<'b>| parser.parse_expr(), |x: ptr::P<ast::Expr>| Some(x) ); @@ -60,7 +60,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> { ); parse_macro_arg!( Pat, - NonterminalKind::PatParam { inferred: false }, + NonterminalKind::Pat(PatParam { inferred: false }), |parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None), |x: ptr::P<ast::Pat>| Some(x) ); diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 28911f8af1d..1ee691b4ade 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -203,3 +203,12 @@ impl Spanned for ast::NestedMetaItem { self.span() } } + +impl Spanned for ast::PreciseCapturingArg { + fn span(&self) -> Span { + match self { + ast::PreciseCapturingArg::Lifetime(lt) => lt.ident.span, + ast::PreciseCapturingArg::Arg(path, _) => path.span, + } + } +} diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index c12f271bc5d..c0bf9482b11 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -177,6 +177,17 @@ impl<'a> Rewrite for SegmentParam<'a> { } } +impl Rewrite for ast::PreciseCapturingArg { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { + match self { + ast::PreciseCapturingArg::Lifetime(lt) => lt.rewrite(context, shape), + ast::PreciseCapturingArg::Arg(p, _) => { + rewrite_path(context, PathContext::Type, &None, p, shape) + } + } + } +} + impl Rewrite for ast::AssocItemConstraint { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { use ast::AssocItemConstraintKind::{Bound, Equality}; @@ -564,9 +575,10 @@ impl Rewrite for ast::GenericBound { .map(|s| format!("{constness}{asyncness}{polarity}{s}")) .map(|s| if has_paren { format!("({})", s) } else { s }) } + ast::GenericBound::Use(ref args, span) => { + overflow::rewrite_with_angle_brackets(context, "use", args.iter(), shape, span) + } ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape), - // FIXME(precise_capturing): Should implement formatting before stabilization. - ast::GenericBound::Use(..) => None, } } } @@ -933,9 +945,7 @@ fn rewrite_bare_fn( fn is_generic_bounds_in_order(generic_bounds: &[ast::GenericBound]) -> bool { let is_trait = |b: &ast::GenericBound| match b { ast::GenericBound::Outlives(..) => false, - ast::GenericBound::Trait(..) => true, - // FIXME(precise_capturing): This ordering fn should be reworked. - ast::GenericBound::Use(..) => false, + ast::GenericBound::Trait(..) | ast::GenericBound::Use(..) => true, }; let is_lifetime = |b: &ast::GenericBound| !is_trait(b); let last_trait_index = generic_bounds.iter().rposition(is_trait); @@ -969,9 +979,8 @@ fn join_bounds_inner( let generic_bounds_in_order = is_generic_bounds_in_order(items); let is_bound_extendable = |s: &str, b: &ast::GenericBound| match b { ast::GenericBound::Outlives(..) => true, - ast::GenericBound::Trait(..) => last_line_extendable(s), - // FIXME(precise_capturing): This ordering fn should be reworked. - ast::GenericBound::Use(..) => true, + // We treat `use<>` like a trait bound here. + ast::GenericBound::Trait(..) | ast::GenericBound::Use(..) => last_line_extendable(s), }; // Whether a GenericBound item is a PathSegment segment that includes internal array @@ -993,6 +1002,7 @@ fn join_bounds_inner( } } } + ast::GenericBound::Use(args, _) => args.len() > 1, _ => false, }; diff --git a/src/tools/rustfmt/tests/source/precise-capturing.rs b/src/tools/rustfmt/tests/source/precise-capturing.rs new file mode 100644 index 00000000000..b61cceeffe8 --- /dev/null +++ b/src/tools/rustfmt/tests/source/precise-capturing.rs @@ -0,0 +1,9 @@ +fn hello() -> impl +use<'a> + Sized {} + +fn all_three() -> impl Sized + use<'a> + 'a; + +fn pathological() -> impl use<'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, +'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, +'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, +'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a> + Sized {} diff --git a/src/tools/rustfmt/tests/target/precise-capturing.rs b/src/tools/rustfmt/tests/target/precise-capturing.rs new file mode 100644 index 00000000000..d21374f44c1 --- /dev/null +++ b/src/tools/rustfmt/tests/target/precise-capturing.rs @@ -0,0 +1,55 @@ +fn hello() -> impl use<'a> + Sized {} + +fn all_three() -> impl Sized + use<'a> + 'a; + +fn pathological() -> impl use< + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, + 'a, +> + Sized { +} diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index f39438bd9ac..0b05d5add52 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" autobins = false [dependencies] +build_helper = { path = "../build_helper" } cargo_metadata = "0.15" regex = "1" miropt-test-tools = { path = "../miropt-test-tools" } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 7337c9843c7..aa119819aaa 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -1,7 +1,9 @@ //! Checks the licenses of third-party dependencies. +use build_helper::ci::CiEnv; use cargo_metadata::{Metadata, Package, PackageId}; use std::collections::HashSet; +use std::fs::read_dir; use std::path::Path; /// These are licenses that are allowed for all crates, including the runtime, @@ -514,7 +516,19 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { let mut checked_runtime_licenses = false; + let submodules = build_helper::util::parse_gitmodules(root); for &(workspace, exceptions, permitted_deps) in WORKSPACES { + // Skip if it's a submodule, not in a CI environment, and not initialized. + // + // This prevents enforcing developers to fetch submodules for tidy. + if submodules.contains(&workspace.into()) + && !CiEnv::is_ci() + // If the directory is empty, we can consider it as an uninitialized submodule. + && read_dir(root.join(workspace)).unwrap().next().is_none() + { + continue; + } + if !root.join(workspace).join("Cargo.lock").exists() { tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock"); continue; diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index 2118de5f204..8bb80f11711 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -1,6 +1,7 @@ //! Check for external package sources. Allow only vendorable packages. -use std::fs; +use build_helper::ci::CiEnv; +use std::fs::{self, read_dir}; use std::path::Path; /// List of allowed sources for packages. @@ -13,7 +14,19 @@ const ALLOWED_SOURCES: &[&str] = &[ /// Checks for external package sources. `root` is the path to the directory that contains the /// workspace `Cargo.toml`. pub fn check(root: &Path, bad: &mut bool) { + let submodules = build_helper::util::parse_gitmodules(root); for &(workspace, _, _) in crate::deps::WORKSPACES { + // Skip if it's a submodule, not in a CI environment, and not initialized. + // + // This prevents enforcing developers to fetch submodules for tidy. + if submodules.contains(&workspace.into()) + && !CiEnv::is_ci() + // If the directory is empty, we can consider it as an uninitialized submodule. + && read_dir(root.join(workspace)).unwrap().next().is_none() + { + continue; + } + // FIXME check other workspaces too // `Cargo.lock` of rust. let path = root.join(workspace).join("Cargo.lock"); diff --git a/tests/run-make/symlinked-extern/rmake.rs b/tests/run-make/symlinked-extern/rmake.rs index 98f69aefbe6..9ed5b76edcb 100644 --- a/tests/run-make/symlinked-extern/rmake.rs +++ b/tests/run-make/symlinked-extern/rmake.rs @@ -9,6 +9,7 @@ // can result in successful compilation. //@ ignore-cross-compile +//@ needs-symlink use run_make_support::{create_symlink, cwd, fs_wrapper, rustc}; diff --git a/tests/run-make/symlinked-libraries/rmake.rs b/tests/run-make/symlinked-libraries/rmake.rs index 3f02f19ccd5..1d1dce5b5cf 100644 --- a/tests/run-make/symlinked-libraries/rmake.rs +++ b/tests/run-make/symlinked-libraries/rmake.rs @@ -6,6 +6,7 @@ // See https://github.com/rust-lang/rust/issues/12459 //@ ignore-cross-compile +//@ needs-symlink use run_make_support::{create_symlink, dynamic_lib_name, fs_wrapper, rustc}; diff --git a/tests/run-make/symlinked-rlib/rmake.rs b/tests/run-make/symlinked-rlib/rmake.rs index 3759ca25928..65ebb191428 100644 --- a/tests/run-make/symlinked-rlib/rmake.rs +++ b/tests/run-make/symlinked-rlib/rmake.rs @@ -6,6 +6,7 @@ // See https://github.com/rust-lang/rust/pull/32828 //@ ignore-cross-compile +//@ needs-symlink use run_make_support::{create_symlink, cwd, rustc}; diff --git a/tests/ui/asm/arm-low-dreg.rs b/tests/ui/asm/arm-low-dreg.rs new file mode 100644 index 00000000000..e9ff0117e2d --- /dev/null +++ b/tests/ui/asm/arm-low-dreg.rs @@ -0,0 +1,33 @@ +//@ build-pass +//@ compile-flags: --target=armv7-unknown-linux-gnueabihf +//@ needs-llvm-components: arm +#![feature(no_core, rustc_attrs, decl_macro, lang_items)] +#![crate_type = "rlib"] +#![no_std] +#![no_core] + +// We accidentally classified "d0"..="d15" as dregs, even though they are in dreg_low16, +// and thus didn't compile them on platforms with only 16 dregs. +// Highlighted in https://github.com/rust-lang/rust/issues/126797 + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +impl Copy for f64 {} + +#[rustc_builtin_macro] +pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} + + +fn f(x: f64) -> f64 { + let out: f64; + unsafe { + asm!("vmov.f64 d1, d0", out("d1") out, in("d0") x); + } + out +} diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr index 1c07a5bf8ba..ea82bac6df0 100644 --- a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr @@ -9,12 +9,6 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(r#unsafe(no_mangle))] | ++ -error: cannot find attribute `r#unsafe` in this scope - --> $DIR/double-unsafe-attributes.rs:3:10 - | -LL | #[unsafe(unsafe(no_mangle))] - | ^^^^^^ - error: `r#unsafe` is not an unsafe attribute --> $DIR/double-unsafe-attributes.rs:3:3 | @@ -23,5 +17,11 @@ LL | #[unsafe(unsafe(no_mangle))] | = note: extraneous unsafe is not allowed in attributes +error: cannot find attribute `r#unsafe` in this scope + --> $DIR/double-unsafe-attributes.rs:3:10 + | +LL | #[unsafe(unsafe(no_mangle))] + | ^^^^^^ + error: aborting due to 3 previous errors diff --git a/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr b/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr index 99f37fedd3d..54d45ee8ffb 100644 --- a/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr +++ b/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-91827-extern-types-field-offset.rs:38:17 | LL | let field = &x.a; - | ^^^^ `extern type` does not have a known offset + | ^^^^ `extern type` field does not have a known offset error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs b/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs new file mode 100644 index 00000000000..3502409d576 --- /dev/null +++ b/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs @@ -0,0 +1,15 @@ +#![feature(extern_types)] + +extern { + type Opaque; +} + +struct ThinDst { + x: u8, + tail: Opaque, +} + +const C1: &ThinDst = unsafe { std::mem::transmute(b"d".as_ptr()) }; +//~^ERROR: evaluation of constant value failed + +fn main() {} diff --git a/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr b/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr new file mode 100644 index 00000000000..1ec36abc2ec --- /dev/null +++ b/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/validation-ice-extern-type-field.rs:12:1 + | +LL | const C1: &ThinDst = unsafe { std::mem::transmute(b"d".as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^ `extern type` field does not have a known offset + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/delegation/glob-traitless-qpath.rs b/tests/ui/delegation/glob-traitless-qpath.rs new file mode 100644 index 00000000000..abf4b3180ed --- /dev/null +++ b/tests/ui/delegation/glob-traitless-qpath.rs @@ -0,0 +1,11 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +struct S; + +impl S { + reuse <u8>::*; //~ ERROR qualified path without a trait in glob delegation + reuse <()>::*; //~ ERROR qualified path without a trait in glob delegation +} + +fn main() {} diff --git a/tests/ui/delegation/glob-traitless-qpath.stderr b/tests/ui/delegation/glob-traitless-qpath.stderr new file mode 100644 index 00000000000..e3257de347a --- /dev/null +++ b/tests/ui/delegation/glob-traitless-qpath.stderr @@ -0,0 +1,14 @@ +error: qualified path without a trait in glob delegation + --> $DIR/glob-traitless-qpath.rs:7:5 + | +LL | reuse <u8>::*; + | ^^^^^^^^^^^^^^ + +error: qualified path without a trait in glob delegation + --> $DIR/glob-traitless-qpath.rs:8:5 + | +LL | reuse <()>::*; + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed b/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed new file mode 100644 index 00000000000..30fd0028f19 --- /dev/null +++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed @@ -0,0 +1,34 @@ +//@ run-rustfix +#![allow(unreachable_code, dead_code)] + +fn main() { + fn mismatch_types1() -> i32 { + match 1 { + x => return dbg!(x), //~ ERROR mismatched types + } + todo!() + } + + fn mismatch_types2() -> i32 { + match 2 { + x => { + return dbg!(x) //~ ERROR mismatched types + } + } + todo!() + } + + fn mismatch_types3() -> i32 { + match 1 { + _ => return dbg!(1) //~ ERROR mismatched types + } + todo!() + } + + fn mismatch_types4() -> i32 { + match 1 { + _ => {return dbg!(1)} //~ ERROR mismatched types + } + todo!() + } +} diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.rs b/tests/ui/mismatched_types/mismatched-types-issue-126222.rs new file mode 100644 index 00000000000..59178702489 --- /dev/null +++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.rs @@ -0,0 +1,34 @@ +//@ run-rustfix +#![allow(unreachable_code, dead_code)] + +fn main() { + fn mismatch_types1() -> i32 { + match 1 { + x => dbg!(x), //~ ERROR mismatched types + } + todo!() + } + + fn mismatch_types2() -> i32 { + match 2 { + x => { + dbg!(x) //~ ERROR mismatched types + } + } + todo!() + } + + fn mismatch_types3() -> i32 { + match 1 { + _ => dbg!(1) //~ ERROR mismatched types + } + todo!() + } + + fn mismatch_types4() -> i32 { + match 1 { + _ => {dbg!(1)} //~ ERROR mismatched types + } + todo!() + } +} diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr b/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr new file mode 100644 index 00000000000..2a8f9867abb --- /dev/null +++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr @@ -0,0 +1,51 @@ +error[E0308]: mismatched types + --> $DIR/mismatched-types-issue-126222.rs:7:18 + | +LL | x => dbg!(x), + | ^^^^^^^ expected `()`, found integer + | + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to return this value + | +LL | x => return dbg!(x), + | ++++++ + +error[E0308]: mismatched types + --> $DIR/mismatched-types-issue-126222.rs:15:17 + | +LL | dbg!(x) + | ^^^^^^^ expected `()`, found integer + | + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to return this value + | +LL | return dbg!(x) + | ++++++ + +error[E0308]: mismatched types + --> $DIR/mismatched-types-issue-126222.rs:23:18 + | +LL | _ => dbg!(1) + | ^^^^^^^ expected `()`, found integer + | + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to return this value + | +LL | _ => return dbg!(1) + | ++++++ + +error[E0308]: mismatched types + --> $DIR/mismatched-types-issue-126222.rs:30:19 + | +LL | _ => {dbg!(1)} + | ^^^^^^^ expected `()`, found integer + | + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to return this value + | +LL | _ => {return dbg!(1)} + | ++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs new file mode 100644 index 00000000000..c6f9115cde7 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs @@ -0,0 +1,9 @@ +#![deny(rust_2024_compatibility)] +#![feature(unsafe_attributes)] + +#[no_mangle] +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +extern "C" fn foo() {} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr new file mode 100644 index 00000000000..f0689d9883c --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr @@ -0,0 +1,21 @@ +error: unsafe attribute used without unsafe + --> $DIR/in_2024_compatibility.rs:4:3 + | +LL | #[no_mangle] + | ^^^^^^^^^ usage of unsafe attribute + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757> +note: the lint level is defined here + --> $DIR/in_2024_compatibility.rs:1:9 + | +LL | #![deny(rust_2024_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(unsafe_attr_outside_unsafe)]` implied by `#[deny(rust_2024_compatibility)]` +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe(no_mangle)] + | +++++++ + + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs new file mode 100644 index 00000000000..279ced2525a --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs @@ -0,0 +1,12 @@ +//@ revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 +//@[edition2024] compile-flags: -Zunstable-options +//@ check-pass + +#![feature(unsafe_attributes)] + +#[unsafe(no_mangle)] +extern "C" fn foo() {} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed new file mode 100644 index 00000000000..6ebdff0334c --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed @@ -0,0 +1,61 @@ +//@ run-rustfix +#![feature(unsafe_attributes)] +#![deny(unsafe_attr_outside_unsafe)] + +macro_rules! tt { + ($e:tt) => { + #$e + extern fn foo() {} + } +} + +macro_rules! ident { + ($e:ident) => { + #[unsafe($e)] + //~^ ERROR: unsafe attribute used without unsafe + //~| WARN this is accepted in the current edition + extern fn bar() {} + } +} + +macro_rules! ident2 { + ($e:ident, $l:literal) => { + #[unsafe($e = $l)] + //~^ ERROR: unsafe attribute used without unsafe + //~| WARN this is accepted in the current edition + extern fn bars() {} + } +} + +macro_rules! meta { + ($m:meta) => { + #[$m] + extern fn baz() {} + } +} + +macro_rules! meta2 { + ($m:meta) => { + #[$m] + extern fn baw() {} + } +} + +tt!([unsafe(no_mangle)]); +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +ident!(no_mangle); +meta!(unsafe(no_mangle)); +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +meta2!(unsafe(export_name = "baw")); +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +ident2!(export_name, "bars"); + +#[unsafe(no_mangle)] +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +extern "C" fn one() {} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs new file mode 100644 index 00000000000..c78ff45ea4c --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs @@ -0,0 +1,61 @@ +//@ run-rustfix +#![feature(unsafe_attributes)] +#![deny(unsafe_attr_outside_unsafe)] + +macro_rules! tt { + ($e:tt) => { + #$e + extern fn foo() {} + } +} + +macro_rules! ident { + ($e:ident) => { + #[$e] + //~^ ERROR: unsafe attribute used without unsafe + //~| WARN this is accepted in the current edition + extern fn bar() {} + } +} + +macro_rules! ident2 { + ($e:ident, $l:literal) => { + #[$e = $l] + //~^ ERROR: unsafe attribute used without unsafe + //~| WARN this is accepted in the current edition + extern fn bars() {} + } +} + +macro_rules! meta { + ($m:meta) => { + #[$m] + extern fn baz() {} + } +} + +macro_rules! meta2 { + ($m:meta) => { + #[$m] + extern fn baw() {} + } +} + +tt!([no_mangle]); +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +ident!(no_mangle); +meta!(no_mangle); +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +meta2!(export_name = "baw"); +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +ident2!(export_name, "bars"); + +#[no_mangle] +//~^ ERROR: unsafe attribute used without unsafe +//~| WARN this is accepted in the current edition +extern "C" fn one() {} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr new file mode 100644 index 00000000000..c95984f58ec --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr @@ -0,0 +1,93 @@ +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-fix.rs:44:6 + | +LL | tt!([no_mangle]); + | ^^^^^^^^^ usage of unsafe attribute + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757> +note: the lint level is defined here + --> $DIR/unsafe-attributes-fix.rs:3:9 + | +LL | #![deny(unsafe_attr_outside_unsafe)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: wrap the attribute in `unsafe(...)` + | +LL | tt!([unsafe(no_mangle)]); + | +++++++ + + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-fix.rs:14:11 + | +LL | #[$e] + | ^^ usage of unsafe attribute +... +LL | ident!(no_mangle); + | ----------------- in this macro invocation + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757> + = note: this error originates in the macro `ident` (in Nightly builds, run with -Z macro-backtrace for more info) +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe($e)] + | +++++++ + + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-fix.rs:48:7 + | +LL | meta!(no_mangle); + | ^^^^^^^^^ usage of unsafe attribute + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757> +help: wrap the attribute in `unsafe(...)` + | +LL | meta!(unsafe(no_mangle)); + | +++++++ + + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-fix.rs:51:8 + | +LL | meta2!(export_name = "baw"); + | ^^^^^^^^^^^ usage of unsafe attribute + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757> +help: wrap the attribute in `unsafe(...)` + | +LL | meta2!(unsafe(export_name = "baw")); + | +++++++ + + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-fix.rs:23:11 + | +LL | #[$e = $l] + | ^^ usage of unsafe attribute +... +LL | ident2!(export_name, "bars"); + | ---------------------------- in this macro invocation + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757> + = note: this error originates in the macro `ident2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe($e = $l)] + | +++++++ + + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-fix.rs:56:3 + | +LL | #[no_mangle] + | ^^^^^^^^^ usage of unsafe attribute + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757> +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe(no_mangle)] + | +++++++ + + +error: aborting due to 6 previous errors + diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr new file mode 100644 index 00000000000..35475d66716 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr @@ -0,0 +1,13 @@ +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes.rs:9:3 + | +LL | #[no_mangle] + | ^^^^^^^^^ usage of unsafe attribute + | +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe(no_mangle)] + | +++++++ + + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs new file mode 100644 index 00000000000..3a6af9dfb2b --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs @@ -0,0 +1,12 @@ +//@ revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2021] check-pass +//@[edition2024] edition:2024 +//@[edition2024] compile-flags: -Zunstable-options + +#![feature(unsafe_attributes)] + +#[no_mangle] //[edition2024]~ ERROR: unsafe attribute used without unsafe +extern "C" fn foo() {} + +fn main() {} diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr index 3f8011d961a..6bbd81ae3e1 100644 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr @@ -9,15 +9,11 @@ LL | const _: *const Foo = 0 as _; | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0080]: it is undefined behavior to use this value +error[E0080]: evaluation of constant value failed --> $DIR/stack-overflow-trait-infer-98842.rs:15:1 | LL | const _: *const Foo = 0 as _; | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation - | - = note: the raw bytes of the constant (size: 4, align: 4) { - 00 00 00 00 │ .... - } error: aborting due to 2 previous errors diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr index 04e2c4483bf..6bbd81ae3e1 100644 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr @@ -9,15 +9,11 @@ LL | const _: *const Foo = 0 as _; | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0080]: it is undefined behavior to use this value +error[E0080]: evaluation of constant value failed --> $DIR/stack-overflow-trait-infer-98842.rs:15:1 | LL | const _: *const Foo = 0 as _; | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation - | - = note: the raw bytes of the constant (size: 8, align: 8) { - 00 00 00 00 00 00 00 00 │ ........ - } error: aborting due to 2 previous errors diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.rs b/tests/ui/sized/stack-overflow-trait-infer-98842.rs index 54d50346cc8..be4807b2e4a 100644 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.rs +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.rs @@ -13,6 +13,6 @@ struct Foo(<&'static Foo as ::core::ops::Deref>::Target); // and it will infinitely recurse somewhere trying to figure out the // size of this pointer (is my guess): const _: *const Foo = 0 as _; -//~^ ERROR it is undefined behavior to use this value +//~^ ERROR evaluation of constant value failed pub fn main() {} diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr deleted file mode 100644 index 8ddddeb5bf2..00000000000 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0391]: cycle detected when computing layout of `Foo` - | - = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`... - = note: ...which again requires computing layout of `Foo`, completing the cycle -note: cycle used when const-evaluating + checking `_` - --> $DIR/stack-overflow-trait-infer-98842.rs:13:1 - | -LL | const _: *const Foo = 0 as _; - | ^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0080]: it is undefined behavior to use this value - --> $DIR/stack-overflow-trait-infer-98842.rs:13:1 - | -LL | const _: *const Foo = 0 as _; - | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation - | - = note: the raw bytes of the constant (size: 8, align: 8) { - 00 00 00 00 00 00 00 00 │ ........ - } - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0080, E0391. -For more information about an error, try `rustc --explain E0080`. |
