diff options
| author | Oli Scherer <github35764891676564198441@oli-obk.de> | 2025-08-30 07:07:41 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-30 07:07:41 +0000 |
| commit | c8d20ceb1be87bc35035328aa1925cb3d95ad10b (patch) | |
| tree | f3ccfe3fdc0af4ed3cda4e0352ba5743c1c10536 | |
| parent | b00c449ef7330353c85e4b1bb4cd30cf5a10f919 (diff) | |
| parent | d269d234e033e2b52722ea78767fe10898184993 (diff) | |
| download | rust-c8d20ceb1be87bc35035328aa1925cb3d95ad10b.tar.gz rust-c8d20ceb1be87bc35035328aa1925cb3d95ad10b.zip | |
Merge pull request #4548 from rust-lang/rustup-2025-08-30
Automatic Rustup
494 files changed, 5833 insertions, 4250 deletions
diff --git a/.mailmap b/.mailmap index 2b75f5a145f..6e3eed1226e 100644 --- a/.mailmap +++ b/.mailmap @@ -255,6 +255,7 @@ Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume1.gomez@gmail.com> ggomez <ggomez@ggo.ifr.lan> Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <ggomez@ggo.ifr.lan> Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume.gomez@huawei.com> +gnzlbg <gonzalobg88@gmail.com> <gnzlbg@users.noreply.github.com> hamidreza kalbasi <hamidrezakalbasi@protonmail.com> Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com> Heather <heather@cynede.net> <Cynede@Gentoo.org> diff --git a/Cargo.lock b/Cargo.lock index af7c24abd13..8b9c243879c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1674,76 +1674,59 @@ checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", "potential_utf", - "yoke 0.8.0", + "yoke", "zerofrom", - "zerovec 0.11.4", + "zerovec", ] [[package]] name = "icu_list" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfeda1d7775b6548edd4e8b7562304a559a91ed56ab56e18961a053f367c365" -dependencies = [ - "displaydoc", - "icu_list_data", - "icu_locid_transform", - "icu_provider 1.5.0", - "regex-automata 0.2.0", - "writeable 0.5.5", -] - -[[package]] -name = "icu_list_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52b1a7fbdbf3958f1be8354cb59ac73f165b7b7082d447ff2090355c9a069120" - -[[package]] -name = "icu_locale_core" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "e26f94ec776bb8b28cedc7dcf91033b822c5cb4c1783cf7a3f796fc168aa0c8b" dependencies = [ "displaydoc", - "litemap 0.8.0", - "tinystr 0.8.1", - "writeable 0.6.1", - "zerovec 0.11.4", + "icu_provider", + "regex-automata 0.4.9", + "serde", + "writeable", + "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd" dependencies = [ "displaydoc", - "litemap 0.7.5", - "tinystr 0.7.6", - "writeable 0.5.5", - "zerovec 0.10.4", + "icu_collections", + "icu_locale_core", + "icu_locale_data", + "icu_provider", + "potential_utf", + "tinystr", + "zerovec", ] [[package]] -name = "icu_locid_transform" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider 1.5.0", - "tinystr 0.7.6", - "zerovec 0.10.4", + "litemap", + "tinystr", + "writeable", + "zerovec", ] [[package]] -name = "icu_locid_transform_data" -version = "1.5.1" +name = "icu_locale_data" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" +checksum = "4fdef0c124749d06a743c69e938350816554eb63ac979166590e2b4ee4252765" [[package]] name = "icu_normalizer" @@ -1755,9 +1738,9 @@ dependencies = [ "icu_collections", "icu_normalizer_data", "icu_properties", - "icu_provider 2.0.0", + "icu_provider", "smallvec", - "zerovec 0.11.4", + "zerovec", ] [[package]] @@ -1776,10 +1759,10 @@ dependencies = [ "icu_collections", "icu_locale_core", "icu_properties_data", - "icu_provider 2.0.0", + "icu_provider", "potential_utf", "zerotrie", - "zerovec 0.11.4", + "zerovec", ] [[package]] @@ -1790,23 +1773,6 @@ checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr 0.7.6", - "writeable 0.5.5", - "yoke 0.7.5", - "zerofrom", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_provider" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" @@ -1814,36 +1780,12 @@ dependencies = [ "displaydoc", "icu_locale_core", "stable_deref_trait", - "tinystr 0.8.1", - "writeable 0.6.1", - "yoke 0.8.0", + "tinystr", + "writeable", + "yoke", "zerofrom", "zerotrie", - "zerovec 0.11.4", -] - -[[package]] -name = "icu_provider_adapters" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6324dfd08348a8e0374a447ebd334044d766b1839bb8d5ccf2482a99a77c0bc" -dependencies = [ - "icu_locid", - "icu_locid_transform", - "icu_provider 1.5.0", - "tinystr 0.7.6", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "zerovec", ] [[package]] @@ -2245,12 +2187,6 @@ checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" - -[[package]] -name = "litemap" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" @@ -2959,7 +2895,8 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" dependencies = [ - "zerovec 0.11.4", + "serde", + "zerovec", ] [[package]] @@ -3207,15 +3144,6 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9368763f5a9b804326f3af749e16f9abf378d227bcdee7634b13d8f17793782" -dependencies = [ - "memchr", -] - -[[package]] -name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" @@ -3480,6 +3408,7 @@ dependencies = [ "rustc_parse", "rustc_session", "rustc_span", + "rustc_target", "thin-vec", ] @@ -3488,10 +3417,9 @@ name = "rustc_baked_icu_data" version = "0.0.0" dependencies = [ "icu_list", - "icu_locid", - "icu_locid_transform", - "icu_provider 1.5.0", - "zerovec 0.10.4", + "icu_locale", + "icu_provider", + "zerovec", ] [[package]] @@ -3764,8 +3692,7 @@ dependencies = [ "fluent-bundle", "fluent-syntax", "icu_list", - "icu_locid", - "icu_provider_adapters", + "icu_locale", "intl-memoizer", "rustc_ast", "rustc_ast_pretty", @@ -5499,22 +5426,12 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec 0.10.4", -] - -[[package]] -name = "tinystr" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", - "zerovec 0.11.4", + "zerovec", ] [[package]] @@ -5779,7 +5696,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658" dependencies = [ - "tinystr 0.8.1", + "tinystr", ] [[package]] @@ -5789,7 +5706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5957eb82e346d7add14182a3315a7e298f04e1ba4baac36f7f0dbfedba5fc25" dependencies = [ "proc-macro-hack", - "tinystr 0.8.1", + "tinystr", "unic-langid-impl", "unic-langid-macros-impl", ] @@ -6685,12 +6602,6 @@ dependencies = [ [[package]] name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "writeable" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" @@ -6729,42 +6640,18 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive 0.7.5", - "zerofrom", -] - -[[package]] -name = "yoke" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", - "yoke-derive 0.8.0", + "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", - "synstructure", -] - -[[package]] -name = "yoke-derive" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" @@ -6823,41 +6710,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" dependencies = [ "displaydoc", - "yoke 0.8.0", + "yoke", "zerofrom", ] [[package]] name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke 0.7.5", - "zerofrom", - "zerovec-derive 0.10.3", -] - -[[package]] -name = "zerovec" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ - "yoke 0.8.0", + "yoke", "zerofrom", - "zerovec-derive 0.11.1", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "zerovec-derive", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 67c7a9d67ed..2c5044f6a35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,33 @@ exclude = [ "obj", ] +[workspace.dependencies] +# tidy-alphabetical-start +bitflags = "2.9.3" +derive-where = "1.6.0" +either = "1.15.0" +indexmap = "2.10.0" +itertools = "0.12.1" +# FIXME: Remove this pin once this rustix issue is resolved +# https://github.com/bytecodealliance/rustix/issues/1496 +libc = "=0.2.174" +measureme = "12.0.3" +memchr = "2.7.5" +odht = { version = "0.3.1", features = ["nightly"] } +polonius-engine = "0.13.0" +proc-macro2 = "1.0.101" +quote = "1.0.40" +rustc-demangle = "0.1.26" +rustc-hash = "2.1.1" +rustc-literal-escaper = "0.0.5" +rustc_apfloat = "0.2.3" +scoped-tls = "1.0.1" +serde_json = "1.0.142" +tempfile = "3.20.0" +thin-vec = "0.2.14" +tracing = "0.1.37" +# tidy-alphabetical-end + [profile.release.package.rustc_thread_pool] # The rustc fork of Rayon has deadlock detection code which intermittently # causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227) diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml index 83d96d8d04d..3de6d186b8a 100644 --- a/compiler/rustc_abi/Cargo.toml +++ b/compiler/rustc_abi/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" +bitflags.workspace = true rand = { version = "0.9.0", default-features = false, optional = true } rand_xoshiro = { version = "0.7.0", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } @@ -15,7 +15,7 @@ rustc_index = { path = "../rustc_index", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index c2405553756..5004d0c8022 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -594,23 +594,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> { discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool), discriminants: impl Iterator<Item = (VariantIdx, i128)>, ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> { - // Until we've decided whether to use the tagged or - // niche filling LayoutData, we don't want to intern the - // variant layouts, so we can't store them in the - // overall LayoutData. Store the overall LayoutData - // and the variant LayoutDatas here until then. - struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> { - layout: LayoutData<FieldIdx, VariantIdx>, - variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>, - } - let dl = self.cx.data_layout(); // bail if the enum has an incoherent repr that cannot be computed if repr.packed() { return Err(LayoutCalculatorError::ReprConflict); } - let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> { + let calculate_niche_filling_layout = || -> Option<LayoutData<FieldIdx, VariantIdx>> { if repr.inhibit_enum_layout_opt() { return None; } @@ -746,7 +736,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> { niche_start, }, tag_field: FieldIdx::new(0), - variants: IndexVec::new(), + variants: variant_layouts, }, fields: FieldsShape::Arbitrary { offsets: [niche_offset].into(), @@ -762,7 +752,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> { randomization_seed: combined_seed, }; - Some(TmpLayout { layout, variants: variant_layouts }) + Some(layout) }; let niche_filling_layout = calculate_niche_filling_layout(); @@ -1093,7 +1083,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> { tag, tag_encoding: TagEncoding::Direct, tag_field: FieldIdx::new(0), - variants: IndexVec::new(), + variants: layout_variants, }, fields: FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), @@ -1109,18 +1099,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> { randomization_seed: combined_seed, }; - let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants }; - - let mut best_layout = match (tagged_layout, niche_filling_layout) { + let best_layout = match (tagged_layout, niche_filling_layout) { (tl, Some(nl)) => { // Pick the smaller layout; otherwise, // pick the layout with the larger niche; otherwise, // pick tagged as it has simpler codegen. use cmp::Ordering::*; - let niche_size = |tmp_l: &TmpLayout<FieldIdx, VariantIdx>| { - tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl)) + let niche_size = |l: &LayoutData<FieldIdx, VariantIdx>| { + l.largest_niche.map_or(0, |n| n.available(dl)) }; - match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) { + match (tl.size.cmp(&nl.size), niche_size(&tl).cmp(&niche_size(&nl))) { (Greater, _) => nl, (Equal, Less) => nl, _ => tl, @@ -1129,16 +1117,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> { (tl, None) => tl, }; - // Now we can intern the variant layouts and store them in the enum layout. - best_layout.layout.variants = match best_layout.layout.variants { - Variants::Multiple { tag, tag_encoding, tag_field, .. } => { - Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants } - } - Variants::Single { .. } | Variants::Empty => { - panic!("encountered a single-variant or empty enum during multi-variant layout") - } - }; - Ok(best_layout.layout) + Ok(best_layout) } fn univariant_biased< diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 155e14a3796..7f948a65220 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" -memchr = "2.7.4" -rustc-literal-escaper = "0.0.5" +bitflags.workspace = true +memchr.workspace = true +rustc-literal-escaper.workspace = true rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } @@ -15,6 +15,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index f4f35a4d2ee..a5d8fbfac61 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -3,15 +3,6 @@ //! `TokenStream`s represent syntactic objects before they are converted into ASTs. //! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s, //! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens. -//! -//! ## Ownership -//! -//! `TokenStream`s are persistent data structures constructed as ropes with reference -//! counted-children. In general, this means that calling an operation on a `TokenStream` -//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to -//! the original. This essentially coerces `TokenStream`s into "views" of their subparts, -//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking -//! ownership of the original. use std::borrow::Cow; use std::ops::Range; @@ -99,17 +90,6 @@ impl TokenTree { } } -impl<CTX> HashStable<CTX> for TokenStream -where - CTX: crate::HashStableContext, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - for sub_tt in self.iter() { - sub_tt.hash_stable(hcx, hasher); - } - } -} - /// A lazy version of [`AttrTokenStream`], which defers creation of an actual /// `AttrTokenStream` until it is needed. #[derive(Clone)] @@ -556,10 +536,6 @@ pub struct AttrsTarget { pub tokens: LazyAttrTokenStream, } -/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. -#[derive(Clone, Debug, Default, Encodable, Decodable)] -pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>); - /// Indicates whether a token can join with the following token to form a /// compound token. Used for conversions to `proc_macro::Spacing`. Also used to /// guide pretty-printing, which is where the `JointHidden` value (which isn't @@ -620,58 +596,9 @@ pub enum Spacing { JointHidden, } -impl TokenStream { - /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` - /// separating the two arguments with a comma for diagnostic suggestions. - pub fn add_comma(&self) -> Option<(TokenStream, Span)> { - // Used to suggest if a user writes `foo!(a b);` - let mut suggestion = None; - let mut iter = self.0.iter().enumerate().peekable(); - while let Some((pos, ts)) = iter.next() { - if let Some((_, next)) = iter.peek() { - let sp = match (&ts, &next) { - (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue, - ( - TokenTree::Token(token_left, Spacing::Alone), - TokenTree::Token(token_right, _), - ) if (token_left.is_non_reserved_ident() || token_left.is_lit()) - && (token_right.is_non_reserved_ident() || token_right.is_lit()) => - { - token_left.span - } - (TokenTree::Delimited(sp, ..), _) => sp.entire(), - _ => continue, - }; - let sp = sp.shrink_to_hi(); - let comma = TokenTree::token_alone(token::Comma, sp); - suggestion = Some((pos, comma, sp)); - } - } - if let Some((pos, comma, sp)) = suggestion { - let mut new_stream = Vec::with_capacity(self.0.len() + 1); - let parts = self.0.split_at(pos + 1); - new_stream.extend_from_slice(parts.0); - new_stream.push(comma); - new_stream.extend_from_slice(parts.1); - return Some((TokenStream::new(new_stream), sp)); - } - None - } -} - -impl FromIterator<TokenTree> for TokenStream { - fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self { - TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>()) - } -} - -impl Eq for TokenStream {} - -impl PartialEq<TokenStream> for TokenStream { - fn eq(&self, other: &TokenStream) -> bool { - self.iter().eq(other.iter()) - } -} +/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. +#[derive(Clone, Debug, Default, Encodable, Decodable)] +pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>); impl TokenStream { pub fn new(tts: Vec<TokenTree>) -> TokenStream { @@ -847,6 +774,68 @@ impl TokenStream { } } } + + /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` + /// separating the two arguments with a comma for diagnostic suggestions. + pub fn add_comma(&self) -> Option<(TokenStream, Span)> { + // Used to suggest if a user writes `foo!(a b);` + let mut suggestion = None; + let mut iter = self.0.iter().enumerate().peekable(); + while let Some((pos, ts)) = iter.next() { + if let Some((_, next)) = iter.peek() { + let sp = match (&ts, &next) { + (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue, + ( + TokenTree::Token(token_left, Spacing::Alone), + TokenTree::Token(token_right, _), + ) if (token_left.is_non_reserved_ident() || token_left.is_lit()) + && (token_right.is_non_reserved_ident() || token_right.is_lit()) => + { + token_left.span + } + (TokenTree::Delimited(sp, ..), _) => sp.entire(), + _ => continue, + }; + let sp = sp.shrink_to_hi(); + let comma = TokenTree::token_alone(token::Comma, sp); + suggestion = Some((pos, comma, sp)); + } + } + if let Some((pos, comma, sp)) = suggestion { + let mut new_stream = Vec::with_capacity(self.0.len() + 1); + let parts = self.0.split_at(pos + 1); + new_stream.extend_from_slice(parts.0); + new_stream.push(comma); + new_stream.extend_from_slice(parts.1); + return Some((TokenStream::new(new_stream), sp)); + } + None + } +} + +impl PartialEq<TokenStream> for TokenStream { + fn eq(&self, other: &TokenStream) -> bool { + self.iter().eq(other.iter()) + } +} + +impl Eq for TokenStream {} + +impl FromIterator<TokenTree> for TokenStream { + fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self { + TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>()) + } +} + +impl<CTX> HashStable<CTX> for TokenStream +where + CTX: crate::HashStableContext, +{ + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + for sub_tt in self.iter() { + sub_tt.hash_stable(hcx, hasher); + } + } } #[derive(Clone)] diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 6ac258155fe..317742a3bb8 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -24,6 +24,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 3e04f8b11ec..6d2bcbed22b 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools = "0.12" +itertools.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } @@ -18,5 +18,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -thin-vec = "0.2.12" +thin-vec.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index e763c9d69fc..9ab5b0b3547 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -188,6 +188,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { notable_trait => doc_notable_trait } "meant for internal use only" { + attribute => rustdoc_internals keyword => rustdoc_internals fake_variadic => rustdoc_internals search_unbox => rustdoc_internals diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index b704040be96..0c7e55305b4 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools = "0.12" +itertools.workspace = true rustc_ast = { path = "../rustc_ast" } rustc_lexer = { path = "../rustc_lexer" } rustc_span = { path = "../rustc_span" } @@ -13,5 +13,5 @@ rustc_span = { path = "../rustc_span" } [dev-dependencies] # tidy-alphabetical-start -thin-vec = "0.2.12" +thin-vec.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index fd8f7ffb2ed..8bfde43fd33 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -17,5 +17,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -thin-vec = "0.2.12" +rustc_target = { path = "../rustc_target" } +thin-vec.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 8f24b51f1d9..b8a748563d5 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -195,3 +195,55 @@ attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"` attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +attr_parsing_as_needed_compatibility = + linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds + +attr_parsing_bundle_needs_static = + linking modifier `bundle` is only compatible with `static` linking kind + +attr_parsing_empty_link_name = + link name must not be empty + .label = empty link name + +attr_parsing_import_name_type_raw = + import name type can only be used with link kind `raw-dylib` + +attr_parsing_import_name_type_x86 = + import name type is only supported on x86 + +attr_parsing_incompatible_wasm_link = + `wasm_import_module` is incompatible with other arguments in `#[link]` attributes + +attr_parsing_invalid_link_modifier = + invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed + +attr_parsing_link_arg_unstable = + link kind `link-arg` is unstable + +attr_parsing_link_cfg_unstable = + link cfg is unstable + +attr_parsing_link_framework_apple = + link kind `framework` is only supported on Apple targets + +attr_parsing_link_requires_name = + `#[link]` attribute requires a `name = "string"` argument + .label = missing `name` argument + +attr_parsing_multiple_modifiers = + multiple `{$modifier}` modifiers in a single `modifiers` argument + +attr_parsing_multiple_renamings = + multiple renamings were specified for library `{$lib_name}` +attr_parsing_raw_dylib_no_nul = + link name must not contain NUL characters if link kind is `raw-dylib` + +attr_parsing_raw_dylib_elf_unstable = + link kind `raw-dylib` is unstable on ELF platforms + +attr_parsing_raw_dylib_only_windows = + link kind `raw-dylib` is only supported on Windows targets + +attr_parsing_whole_archive_needs_static = + linking modifier `whole-archive` is only compatible with `static` linking kind diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 695ee666476..70855611079 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -36,7 +36,7 @@ pub fn parse_cfg_attr<'c, S: Stage>( parse_cfg_entry(cx, single) } -fn parse_cfg_entry<S: Stage>( +pub(crate) fn parse_cfg_entry<S: Stage>( cx: &mut AcceptContext<'_, '_, S>, item: &MetaItemOrLitParser<'_>, ) -> Option<CfgEntry> { diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 5e4551ccd79..d4942e56f42 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,9 +1,21 @@ +use rustc_feature::Features; use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; -use rustc_hir::attrs::Linkage; +use rustc_hir::attrs::*; +use rustc_session::Session; +use rustc_session::parse::feature_err; +use rustc_span::kw; +use rustc_target::spec::BinaryFormat; use super::prelude::*; use super::util::parse_single_integer; -use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection}; +use crate::attributes::cfg::parse_cfg_entry; +use crate::fluent_generated; +use crate::session_diagnostics::{ + AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86, + IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange, + LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows, + WholeArchiveNeedsStatic, +}; pub(crate) struct LinkNameParser; @@ -34,6 +46,409 @@ impl<S: Stage> SingleAttributeParser<S> for LinkNameParser { } } +pub(crate) struct LinkParser; + +impl<S: Stage> CombineAttributeParser<S> for LinkParser { + type Item = LinkEntry; + const PATH: &[Symbol] = &[sym::link]; + const CONVERT: ConvertFn<Self::Item> = AttributeKind::Link; + const TEMPLATE: AttributeTemplate = template!(List: &[ + r#"name = "...""#, + r#"name = "...", kind = "dylib|static|...""#, + r#"name = "...", wasm_import_module = "...""#, + r#"name = "...", import_name_type = "decorated|noprefix|undecorated""#, + r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#, + ], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute"); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` + + fn extend<'c>( + cx: &'c mut AcceptContext<'_, '_, S>, + args: &'c ArgParser<'_>, + ) -> impl IntoIterator<Item = Self::Item> + 'c { + let mut result = None; + let Some(items) = args.list() else { + cx.expected_list(cx.attr_span); + return result; + }; + + let sess = cx.sess(); + let features = cx.features(); + + let mut name = None; + let mut kind = None; + let mut modifiers = None; + let mut cfg = None; + let mut wasm_import_module = None; + let mut import_name_type = None; + for item in items.mixed() { + let Some(item) = item.meta_item() else { + cx.unexpected_literal(item.span()); + continue; + }; + + let cont = match item.path().word().map(|ident| ident.name) { + Some(sym::name) => Self::parse_link_name(item, &mut name, cx), + Some(sym::kind) => Self::parse_link_kind(item, &mut kind, cx, sess, features), + Some(sym::modifiers) => Self::parse_link_modifiers(item, &mut modifiers, cx), + Some(sym::cfg) => Self::parse_link_cfg(item, &mut cfg, cx, sess, features), + Some(sym::wasm_import_module) => { + Self::parse_link_wasm_import_module(item, &mut wasm_import_module, cx) + } + Some(sym::import_name_type) => { + Self::parse_link_import_name_type(item, &mut import_name_type, cx) + } + _ => { + cx.expected_specific_argument_strings( + item.span(), + &[ + sym::name, + sym::kind, + sym::modifiers, + sym::cfg, + sym::wasm_import_module, + sym::import_name_type, + ], + ); + true + } + }; + if !cont { + return result; + } + } + + // Do this outside the above loop so we don't depend on modifiers coming after kinds + let mut verbatim = None; + if let Some((modifiers, span)) = modifiers { + for modifier in modifiers.as_str().split(',') { + let (modifier, value): (Symbol, bool) = match modifier.strip_prefix(&['+', '-']) { + Some(m) => (Symbol::intern(m), modifier.starts_with('+')), + None => { + cx.emit_err(InvalidLinkModifier { span }); + continue; + } + }; + + macro report_unstable_modifier($feature: ident) { + if !features.$feature() { + // FIXME: make this translatable + #[expect(rustc::untranslatable_diagnostic)] + feature_err( + sess, + sym::$feature, + span, + format!("linking modifier `{modifier}` is unstable"), + ) + .emit(); + } + } + let assign_modifier = |dst: &mut Option<bool>| { + if dst.is_some() { + cx.emit_err(MultipleModifiers { span, modifier }); + } else { + *dst = Some(value); + } + }; + match (modifier, &mut kind) { + (sym::bundle, Some(NativeLibKind::Static { bundle, .. })) => { + assign_modifier(bundle) + } + (sym::bundle, _) => { + cx.emit_err(BundleNeedsStatic { span }); + } + + (sym::verbatim, _) => assign_modifier(&mut verbatim), + + ( + sym::whole_dash_archive, + Some(NativeLibKind::Static { whole_archive, .. }), + ) => assign_modifier(whole_archive), + (sym::whole_dash_archive, _) => { + cx.emit_err(WholeArchiveNeedsStatic { span }); + } + + (sym::as_dash_needed, Some(NativeLibKind::Dylib { as_needed })) + | (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed })) => { + report_unstable_modifier!(native_link_modifiers_as_needed); + assign_modifier(as_needed) + } + (sym::as_dash_needed, _) => { + cx.emit_err(AsNeededCompatibility { span }); + } + + _ => { + cx.expected_specific_argument_strings( + span, + &[ + sym::bundle, + sym::verbatim, + sym::whole_dash_archive, + sym::as_dash_needed, + ], + ); + } + } + } + } + + if let Some((_, span)) = wasm_import_module { + if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { + cx.emit_err(IncompatibleWasmLink { span }); + } + } + + if wasm_import_module.is_some() { + (name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule)); + } + let Some((name, name_span)) = name else { + cx.emit_err(LinkRequiresName { span: cx.attr_span }); + return result; + }; + + // Do this outside of the loop so that `import_name_type` can be specified before `kind`. + if let Some((_, span)) = import_name_type { + if kind != Some(NativeLibKind::RawDylib) { + cx.emit_err(ImportNameTypeRaw { span }); + } + } + + if let Some(NativeLibKind::RawDylib) = kind + && name.as_str().contains('\0') + { + cx.emit_err(RawDylibNoNul { span: name_span }); + } + + result = Some(LinkEntry { + span: cx.attr_span, + kind: kind.unwrap_or(NativeLibKind::Unspecified), + name, + cfg, + verbatim, + import_name_type, + }); + result + } +} + +impl LinkParser { + fn parse_link_name<S: Stage>( + item: &MetaItemParser<'_>, + name: &mut Option<(Symbol, Span)>, + cx: &mut AcceptContext<'_, '_, S>, + ) -> bool { + if name.is_some() { + cx.duplicate_key(item.span(), sym::name); + return true; + } + let Some(nv) = item.args().name_value() else { + cx.expected_name_value(item.span(), Some(sym::name)); + return false; + }; + let Some(link_name) = nv.value_as_str() else { + cx.expected_name_value(item.span(), Some(sym::name)); + return false; + }; + + if link_name.is_empty() { + cx.emit_err(EmptyLinkName { span: nv.value_span }); + } + *name = Some((link_name, nv.value_span)); + true + } + + fn parse_link_kind<S: Stage>( + item: &MetaItemParser<'_>, + kind: &mut Option<NativeLibKind>, + cx: &mut AcceptContext<'_, '_, S>, + sess: &Session, + features: &Features, + ) -> bool { + if kind.is_some() { + cx.duplicate_key(item.span(), sym::kind); + return true; + } + let Some(nv) = item.args().name_value() else { + cx.expected_name_value(item.span(), Some(sym::kind)); + return true; + }; + let Some(link_kind) = nv.value_as_str() else { + cx.expected_name_value(item.span(), Some(sym::kind)); + return true; + }; + + let link_kind = match link_kind { + kw::Static => NativeLibKind::Static { bundle: None, whole_archive: None }, + sym::dylib => NativeLibKind::Dylib { as_needed: None }, + sym::framework => { + if !sess.target.is_like_darwin { + cx.emit_err(LinkFrameworkApple { span: nv.value_span }); + } + NativeLibKind::Framework { as_needed: None } + } + sym::raw_dash_dylib => { + if sess.target.is_like_windows { + // raw-dylib is stable and working on Windows + } else if sess.target.binary_format == BinaryFormat::Elf && features.raw_dylib_elf() + { + // raw-dylib is unstable on ELF, but the user opted in + } else if sess.target.binary_format == BinaryFormat::Elf && sess.is_nightly_build() + { + feature_err( + sess, + sym::raw_dylib_elf, + nv.value_span, + fluent_generated::attr_parsing_raw_dylib_elf_unstable, + ) + .emit(); + } else { + cx.emit_err(RawDylibOnlyWindows { span: nv.value_span }); + } + + NativeLibKind::RawDylib + } + sym::link_dash_arg => { + if !features.link_arg_attribute() { + feature_err( + sess, + sym::link_arg_attribute, + nv.value_span, + fluent_generated::attr_parsing_link_arg_unstable, + ) + .emit(); + } + NativeLibKind::LinkArg + } + _kind => { + cx.expected_specific_argument_strings( + nv.value_span, + &[ + kw::Static, + sym::dylib, + sym::framework, + sym::raw_dash_dylib, + sym::link_dash_arg, + ], + ); + return true; + } + }; + *kind = Some(link_kind); + true + } + + fn parse_link_modifiers<S: Stage>( + item: &MetaItemParser<'_>, + modifiers: &mut Option<(Symbol, Span)>, + cx: &mut AcceptContext<'_, '_, S>, + ) -> bool { + if modifiers.is_some() { + cx.duplicate_key(item.span(), sym::modifiers); + return true; + } + let Some(nv) = item.args().name_value() else { + cx.expected_name_value(item.span(), Some(sym::modifiers)); + return true; + }; + let Some(link_modifiers) = nv.value_as_str() else { + cx.expected_name_value(item.span(), Some(sym::modifiers)); + return true; + }; + *modifiers = Some((link_modifiers, nv.value_span)); + true + } + + fn parse_link_cfg<S: Stage>( + item: &MetaItemParser<'_>, + cfg: &mut Option<CfgEntry>, + cx: &mut AcceptContext<'_, '_, S>, + sess: &Session, + features: &Features, + ) -> bool { + if cfg.is_some() { + cx.duplicate_key(item.span(), sym::cfg); + return true; + } + let Some(link_cfg) = item.args().list() else { + cx.expected_list(item.span()); + return true; + }; + let Some(link_cfg) = link_cfg.single() else { + cx.expected_single_argument(item.span()); + return true; + }; + if !features.link_cfg() { + feature_err( + sess, + sym::link_cfg, + item.span(), + fluent_generated::attr_parsing_link_cfg_unstable, + ) + .emit(); + } + *cfg = parse_cfg_entry(cx, link_cfg); + true + } + + fn parse_link_wasm_import_module<S: Stage>( + item: &MetaItemParser<'_>, + wasm_import_module: &mut Option<(Symbol, Span)>, + cx: &mut AcceptContext<'_, '_, S>, + ) -> bool { + if wasm_import_module.is_some() { + cx.duplicate_key(item.span(), sym::wasm_import_module); + return true; + } + let Some(nv) = item.args().name_value() else { + cx.expected_name_value(item.span(), Some(sym::wasm_import_module)); + return true; + }; + let Some(link_wasm_import_module) = nv.value_as_str() else { + cx.expected_name_value(item.span(), Some(sym::wasm_import_module)); + return true; + }; + *wasm_import_module = Some((link_wasm_import_module, item.span())); + true + } + + fn parse_link_import_name_type<S: Stage>( + item: &MetaItemParser<'_>, + import_name_type: &mut Option<(PeImportNameType, Span)>, + cx: &mut AcceptContext<'_, '_, S>, + ) -> bool { + if import_name_type.is_some() { + cx.duplicate_key(item.span(), sym::import_name_type); + return true; + } + let Some(nv) = item.args().name_value() else { + cx.expected_name_value(item.span(), Some(sym::import_name_type)); + return true; + }; + let Some(link_import_name_type) = nv.value_as_str() else { + cx.expected_name_value(item.span(), Some(sym::import_name_type)); + return true; + }; + if cx.sess().target.arch != "x86" { + cx.emit_err(ImportNameTypeX86 { span: item.span() }); + return true; + } + + let link_import_name_type = match link_import_name_type { + sym::decorated => PeImportNameType::Decorated, + sym::noprefix => PeImportNameType::NoPrefix, + sym::undecorated => PeImportNameType::Undecorated, + _ => { + cx.expected_specific_argument_strings( + item.span(), + &[sym::decorated, sym::noprefix, sym::undecorated], + ); + return true; + } + }; + *import_name_type = Some((link_import_name_type, item.span())); + true + } +} + pub(crate) struct LinkSectionParser; impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser { diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs index 2bcdee55c75..6aef7e7a67b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs @@ -1,20 +1,30 @@ -// parsing // templates +#[doc(hidden)] pub(super) use rustc_feature::{AttributeTemplate, template}; // data structures +#[doc(hidden)] pub(super) use rustc_hir::attrs::AttributeKind; +#[doc(hidden)] pub(super) use rustc_hir::lints::AttributeLintKind; +#[doc(hidden)] pub(super) use rustc_hir::{MethodKind, Target}; +#[doc(hidden)] pub(super) use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; +#[doc(hidden)] pub(super) use thin_vec::ThinVec; +#[doc(hidden)] pub(super) use crate::attributes::{ AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, }; // contexts +#[doc(hidden)] pub(super) use crate::context::{AcceptContext, FinalizeContext, Stage}; +#[doc(hidden)] pub(super) use crate::parser::*; // target checking +#[doc(hidden)] pub(super) use crate::target_checking::Policy::{Allow, Error, Warn}; +#[doc(hidden)] pub(super) use crate::target_checking::{ALL_TARGETS, AllowedTargets}; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index b16ef7edd64..7f5b810f244 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -30,7 +30,7 @@ use crate::attributes::dummy::DummyParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; use crate::attributes::link_attrs::{ ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser, - LinkSectionParser, LinkageParser, StdInternalSymbolParser, + LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser, }; use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, @@ -162,6 +162,7 @@ attribute_parsers!( Combine<AllowConstFnUnstableParser>, Combine<AllowInternalUnstableParser>, Combine<ForceTargetFeatureParser>, + Combine<LinkParser>, Combine<ReprParser>, Combine<TargetFeatureParser>, Combine<UnstableFeatureBoundParser>, diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index a3558850ef3..0fe3c209421 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -273,14 +273,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { (accept.accept_fn)(&mut cx, args); if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) { Self::check_type(accept.attribute_type, target, &mut cx); - self.check_target( - path.get_attribute_path(), - attr.span, - &accept.allowed_targets, - target, - target_id, - &mut emit_lint, - ); + Self::check_target(&accept.allowed_targets, target, &mut cx); } } } else { diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 4dd908cdc40..f51cc8c4e8b 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -79,6 +79,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![doc(rust_logo)] +#![feature(decl_macro)] #![feature(rustdoc_internals)] #![recursion_limit = "256"] // tidy-alphabetical-end diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 6d3cf684296..4f903594225 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -10,11 +10,11 @@ use rustc_ast::token::{self, Delimiter, MetaVarKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path}; use rustc_ast_pretty::pprust; -use rustc_errors::PResult; +use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; use rustc_parse::exp; use rustc_parse::parser::{Parser, PathStyle, token_descr}; -use rustc_session::errors::report_lit_error; +use rustc_session::errors::{create_lit_error, report_lit_error}; use rustc_session::parse::ParseSess; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym}; use thin_vec::ThinVec; @@ -379,22 +379,23 @@ struct MetaItemListParserContext<'a, 'sess> { impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'sess, MetaItemLit> { - let uninterpolated_span = self.parser.token_uninterpolated_span(); - let Some(token_lit) = self.parser.eat_token_lit() else { - return self.parser.handle_missing_lit(Parser::mk_meta_item_lit_char); - }; + let Some(token_lit) = self.parser.eat_token_lit() else { return Err(self.expected_lit()) }; + self.unsuffixed_meta_item_from_lit(token_lit) + } + fn unsuffixed_meta_item_from_lit( + &mut self, + token_lit: token::Lit, + ) -> PResult<'sess, MetaItemLit> { let lit = match MetaItemLit::from_token_lit(token_lit, self.parser.prev_token.span) { Ok(lit) => lit, Err(err) => { - let guar = - report_lit_error(&self.parser.psess, err, token_lit, uninterpolated_span); - // Pack possible quotes and prefixes from the original literal into - // the error literal's symbol so they can be pretty-printed faithfully. - let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None); - let symbol = Symbol::intern(&suffixless_lit.to_string()); - let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix); - MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap() + return Err(create_lit_error( + &self.parser.psess, + err, + token_lit, + self.parser.prev_token_uninterpolated_span(), + )); } }; @@ -448,16 +449,28 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { } fn parse_meta_item_inner(&mut self) -> PResult<'sess, MetaItemOrLitParser<'static>> { - match self.parse_unsuffixed_meta_item_lit() { - Ok(lit) => return Ok(MetaItemOrLitParser::Lit(lit)), - Err(err) => err.cancel(), // we provide a better error below - } - - match self.parse_attr_item() { - Ok(mi) => return Ok(MetaItemOrLitParser::MetaItemParser(mi)), - Err(err) => err.cancel(), // we provide a better error below + if let Some(token_lit) = self.parser.eat_token_lit() { + // If a literal token is parsed, we commit to parsing a MetaItemLit for better errors + Ok(MetaItemOrLitParser::Lit(self.unsuffixed_meta_item_from_lit(token_lit)?)) + } else { + let prev_pros = self.parser.approx_token_stream_pos(); + match self.parse_attr_item() { + Ok(item) => Ok(MetaItemOrLitParser::MetaItemParser(item)), + Err(err) => { + // If `parse_attr_item` made any progress, it likely has a more precise error we should prefer + // If it didn't make progress we use the `expected_lit` from below + if self.parser.approx_token_stream_pos() != prev_pros { + Err(err) + } else { + err.cancel(); + Err(self.expected_lit()) + } + } + } } + } + fn expected_lit(&mut self) -> Diag<'sess> { let mut err = InvalidMetaItem { span: self.parser.token.span, descr: token_descr(&self.parser.token), @@ -492,7 +505,7 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { self.parser.bump(); } - Err(self.parser.dcx().create_err(err)) + self.parser.dcx().create_err(err) } fn parse( diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index a639b55e81f..a9dee23bf6a 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -836,3 +836,97 @@ pub(crate) struct InvalidAttrStyle { pub target_span: Option<Span>, pub target: Target, } + +#[derive(Diagnostic)] +#[diag(attr_parsing_empty_link_name, code = E0454)] +pub(crate) struct EmptyLinkName { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_link_framework_apple, code = E0455)] +pub(crate) struct LinkFrameworkApple { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_incompatible_wasm_link)] +pub(crate) struct IncompatibleWasmLink { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_link_requires_name, code = E0459)] +pub(crate) struct LinkRequiresName { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_raw_dylib_no_nul)] +pub(crate) struct RawDylibNoNul { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_raw_dylib_only_windows, code = E0455)] +pub(crate) struct RawDylibOnlyWindows { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_invalid_link_modifier)] +pub(crate) struct InvalidLinkModifier { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_multiple_modifiers)] +pub(crate) struct MultipleModifiers { + #[primary_span] + pub span: Span, + pub modifier: Symbol, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_import_name_type_x86)] +pub(crate) struct ImportNameTypeX86 { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_bundle_needs_static)] +pub(crate) struct BundleNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_whole_archive_needs_static)] +pub(crate) struct WholeArchiveNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_as_needed_compatibility)] +pub(crate) struct AsNeededCompatibility { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_import_name_type_raw)] +pub(crate) struct ImportNameTypeRaw { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 6f4dd76fa81..edc496b460c 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -3,9 +3,8 @@ use std::borrow::Cow; use rustc_ast::AttrStyle; use rustc_errors::DiagArgValue; use rustc_feature::{AttributeType, Features}; -use rustc_hir::lints::{AttributeLint, AttributeLintKind}; -use rustc_hir::{AttrPath, MethodKind, Target}; -use rustc_span::Span; +use rustc_hir::lints::AttributeLintKind; +use rustc_hir::{MethodKind, Target}; use crate::AttributeParser; use crate::context::{AcceptContext, Stage}; @@ -71,38 +70,34 @@ pub(crate) enum Policy { impl<'sess, S: Stage> AttributeParser<'sess, S> { pub(crate) fn check_target( - &self, - attr_name: AttrPath, - attr_span: Span, allowed_targets: &AllowedTargets, target: Target, - target_id: S::Id, - mut emit_lint: impl FnMut(AttributeLint<S::Id>), + cx: &mut AcceptContext<'_, 'sess, S>, ) { match allowed_targets.is_allowed(target) { AllowedResult::Allowed => {} AllowedResult::Warn => { let allowed_targets = allowed_targets.allowed_targets(); - let (applied, only) = - allowed_targets_applied(allowed_targets, target, self.features); - emit_lint(AttributeLint { - id: target_id, - span: attr_span, - kind: AttributeLintKind::InvalidTarget { - name: attr_name, + let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features); + let name = cx.attr_path.clone(); + let attr_span = cx.attr_span; + cx.emit_lint( + AttributeLintKind::InvalidTarget { + name, target, only: if only { "only " } else { "" }, applied, }, - }); + attr_span, + ); } AllowedResult::Error => { let allowed_targets = allowed_targets.allowed_targets(); - let (applied, only) = - allowed_targets_applied(allowed_targets, target, self.features); - self.dcx().emit_err(InvalidTarget { - span: attr_span, - name: attr_name, + let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features); + let name = cx.attr_path.clone(); + cx.dcx().emit_err(InvalidTarget { + span: cx.attr_span.clone(), + name, target: target.plural_name(), only: if only { "only " } else { "" }, applied: DiagArgValue::StrListSepByAnd( diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml index cb0e145386b..2f1ab7df379 100644 --- a/compiler/rustc_baked_icu_data/Cargo.toml +++ b/compiler/rustc_baked_icu_data/Cargo.toml @@ -5,9 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -icu_list = "1.2" -icu_locid = "1.2" -icu_locid_transform = "1.3.2" -icu_provider = { version = "1.2", features = ["sync"] } -zerovec = "0.10.0" +icu_list = { version = "2.0", default-features = false } +icu_locale = { version = "2.0", default-features = false, features = ["compiled_data"] } +icu_provider = { version = "2.0", features = ["baked", "sync"] } +zerovec = "0.11.0" # tidy-alphabetical-end diff --git a/compiler/rustc_baked_icu_data/src/data/any.rs b/compiler/rustc_baked_icu_data/src/data/any.rs deleted file mode 100644 index 23028876676..00000000000 --- a/compiler/rustc_baked_icu_data/src/data/any.rs +++ /dev/null @@ -1,2 +0,0 @@ -// @generated -impl_any_provider!(BakedDataProvider); diff --git a/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data b/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data new file mode 100644 index 00000000000..1d60e0085fc --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data @@ -0,0 +1,71 @@ +// @generated +/// Implement `DataProvider<ListAndV1>` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +/// +/// Using this implementation will embed the following data in the binary's data segment: +/// * 179B for the lookup data structure (33 data identifiers) +/// * 4183B[^1] for the actual data (11 unique structs) +/// +/// [^1]: these numbers can be smaller in practice due to linker deduplication +/// +/// This macro requires the following crates: +/// * `icu_list` +/// * `icu_locale/compiled_data` +/// * `icu_provider` +/// * `icu_provider/baked` +/// * `zerovec` +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_list_and_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.82"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.82"] + impl $provider { + const DATA_LIST_AND_V1: icu_provider::baked::zerotrie::Data<icu_list::provider::ListAndV1> = { + const TRIE: icu_provider::baked::zerotrie::ZeroTrieSimpleAscii<&'static [u8]> = icu_provider::baked::zerotrie::ZeroTrieSimpleAscii { store: b"\xC8efijprtz\x18#.9DOZ\xC2ns\n\x1E\xC3NSW\x01\x02\x80\x85\x8A\x1E\xC3NSW\x01\x02\x81\x81\x81r\x1E\xC3NSW\x01\x02\x80\x86\x86t\x1E\xC3NSW\x01\x02\x82\x82\x82a\x1E\xC3NSW\x01\x02\x83\x83\x83t\x1E\xC3NSW\x01\x02\x80\x82\x82u\x1E\xC3NSW\x01\x02\x80\x87\x87r\x1E\xC3NSW\x01\x02\x80\x88\x88h\xC2\x1E-\t\xC3NSW\x01\x02\x83\x89\x89Han\xC2st\n\x1E\xC3NSW\x01\x02\x83\x89\x89\x1E\xC3NSW\x01\x02\x84\x89\x89" }; + const VALUES: &'static [<icu_list::provider::ListAndV1 as icu_provider::baked::zerotrie::DynamicDataMarker>::DataStruct] = &[icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" y ") }, 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x02\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\x01\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x06\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF`\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\x12\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x02\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x80\x01\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\x05\x05\x05\x06\x06\x0C\x0C\r\r\0\0\0\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\x02\0\x1B\0\0\0\0\0\x12\0\0\0\x12\0\0\x03\x06\x06\r\r\0\0\0\0\0h\0\0\0h\0\0\0\0\0\0\x0E\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\x01\n\0\0\x01\x19\0\0\0\x12\0\0\x02\x0F\x11\0\0\0\0\0D\0\0\0\0\0\0\x02\x11\x11\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x0F\x11\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x0F\x10\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x10\x11\0\0\0\0\0\xDD\0\0\0\0\0\0\x02\x0F\x11\0\0\0\0\0\xDD\0\0\0\0\0\0\x02\x0F\x0F\0\0\0\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\x03\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\x01\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x06\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0`\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\x12\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" e ") }, 3u8) }) }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" e ") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE5\x92\x8C") }, 3u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), special_case: None }) }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", & ") }, 4u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" & ") }, 3u8), special_case: None }) }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" et ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" \xD0\xB8 ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" ve ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE5\x92\x8C") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", and ") }, 6u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" and ") }, 5u8), special_case: None }) }]; + unsafe { icu_provider::baked::zerotrie::Data::from_trie_and_values_unchecked(TRIE, VALUES) } + }; + } + #[clippy::msrv = "1.82"] + impl icu_provider::DataProvider<icu_list::provider::ListAndV1> for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_list::provider::ListAndV1>, icu_provider::DataError> { + let mut metadata = icu_provider::DataResponseMetadata::default(); + let payload = if let Some(payload) = icu_provider::baked::DataStore::get(&Self::DATA_LIST_AND_V1, req.id, req.metadata.attributes_prefix_match) { + payload + } else { + const FALLBACKER: icu_locale::fallback::LocaleFallbackerWithConfig<'static> = icu_locale::fallback::LocaleFallbacker::new().for_config(<icu_list::provider::ListAndV1 as icu_provider::DataMarker>::INFO.fallback_config); + let mut fallback_iterator = FALLBACKER.fallback_for(req.id.locale.clone()); + loop { + if let Some(payload) = icu_provider::baked::DataStore::get(&Self::DATA_LIST_AND_V1, icu_provider::DataIdentifierBorrowed::for_marker_attributes_and_locale(req.id.marker_attributes, fallback_iterator.get()), req.metadata.attributes_prefix_match) { + metadata.locale = Some(fallback_iterator.take()); + break payload; + } + if fallback_iterator.get().is_unknown() { + return Err(icu_provider::DataErrorKind::IdentifierNotFound.with_req(<icu_list::provider::ListAndV1 as icu_provider::DataMarker>::INFO, req)); + } + fallback_iterator.step(); + } + }; + Ok(icu_provider::DataResponse { payload, metadata }) + } + } + }; + ($ provider : ty , ITER) => { + __impl_list_and_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider<icu_list::provider::ListAndV1> for $provider { + fn iter_ids(&self) -> Result<std::collections::BTreeSet<icu_provider::DataIdentifierCow<'static>>, icu_provider::DataError> { + Ok(icu_provider::baked::DataStore::iter(&Self::DATA_LIST_AND_V1).collect()) + } + } + }; + ($ provider : ty , DRY) => {}; + ($ provider : ty , DRY , ITER) => { + __impl_list_and_v1!($provider, ITER); + }; +} +#[doc(inline)] +pub use __impl_list_and_v1 as impl_list_and_v1; diff --git a/compiler/rustc_baked_icu_data/src/data/macros.rs b/compiler/rustc_baked_icu_data/src/data/macros.rs deleted file mode 100644 index bee309f9b81..00000000000 --- a/compiler/rustc_baked_icu_data/src/data/macros.rs +++ /dev/null @@ -1,46 +0,0 @@ -// @generated -/// Marks a type as a data provider. You can then use macros like -/// `impl_core_helloworld_v1` to add implementations. -/// -/// ```ignore -/// struct MyProvider; -/// const _: () = { -/// include!("path/to/generated/macros.rs"); -/// make_provider!(MyProvider); -/// impl_core_helloworld_v1!(MyProvider); -/// } -/// ``` -#[doc(hidden)] -#[macro_export] -macro_rules! __make_provider { - ($ name : ty) => { - #[clippy::msrv = "1.66"] - impl $name { - #[doc(hidden)] - #[allow(dead_code)] - pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); - } - }; -} -#[doc(inline)] -pub use __make_provider as make_provider; -#[macro_use] -#[path = "macros/fallback_likelysubtags_v1.data.rs"] -mod fallback_likelysubtags_v1; -#[doc(inline)] -pub use __impl_fallback_likelysubtags_v1 as impl_fallback_likelysubtags_v1; -#[macro_use] -#[path = "macros/fallback_parents_v1.data.rs"] -mod fallback_parents_v1; -#[doc(inline)] -pub use __impl_fallback_parents_v1 as impl_fallback_parents_v1; -#[macro_use] -#[path = "macros/fallback_supplement_co_v1.data.rs"] -mod fallback_supplement_co_v1; -#[doc(inline)] -pub use __impl_fallback_supplement_co_v1 as impl_fallback_supplement_co_v1; -#[macro_use] -#[path = "macros/list_and_v1.data.rs"] -mod list_and_v1; -#[doc(inline)] -pub use __impl_list_and_v1 as impl_list_and_v1; diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs deleted file mode 100644 index 1adb58743f7..00000000000 --- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs +++ /dev/null @@ -1,40 +0,0 @@ -// @generated -/// Implement `DataProvider<LocaleFallbackLikelySubtagsV1Marker>` on the given struct using the data -/// hardcoded in this file. This allows the struct to be used with -/// `icu`'s `_unstable` constructors. -#[doc(hidden)] -#[macro_export] -macro_rules! __impl_fallback_likelysubtags_v1 { - ($ provider : ty) => { - #[clippy::msrv = "1.66"] - const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; - #[clippy::msrv = "1.66"] - impl $provider { - #[doc(hidden)] - pub const SINGLETON_FALLBACK_LIKELYSUBTAGS_V1: &'static <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1 { - l2s: unsafe { - #[allow(unused_unsafe)] - zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") }) - }, - lr2s: unsafe { - #[allow(unused_unsafe)] - zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") }) - }, - l2r: unsafe { - #[allow(unused_unsafe)] - zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") }) - }, - ls2r: unsafe { - #[allow(unused_unsafe)] - zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0") }) - }, - }; - } - #[clippy::msrv = "1.66"] - impl icu_provider::DataProvider<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider { - fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>, icu_provider::DataError> { - if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_LIKELYSUBTAGS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) } - } - } - }; -} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs deleted file mode 100644 index 6f8d6590b08..00000000000 --- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs +++ /dev/null @@ -1,28 +0,0 @@ -// @generated -/// Implement `DataProvider<LocaleFallbackParentsV1Marker>` on the given struct using the data -/// hardcoded in this file. This allows the struct to be used with -/// `icu`'s `_unstable` constructors. -#[doc(hidden)] -#[macro_export] -macro_rules! __impl_fallback_parents_v1 { - ($ provider : ty) => { - #[clippy::msrv = "1.66"] - const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; - #[clippy::msrv = "1.66"] - impl $provider { - #[doc(hidden)] - pub const SINGLETON_FALLBACK_PARENTS_V1: &'static <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackParentsV1 { - parents: unsafe { - #[allow(unused_unsafe)] - zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") }) - }, - }; - } - #[clippy::msrv = "1.66"] - impl icu_provider::DataProvider<icu_locid_transform::provider::LocaleFallbackParentsV1Marker> for $provider { - fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>, icu_provider::DataError> { - if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_PARENTS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) } - } - } - }; -} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs deleted file mode 100644 index 02eec37ee09..00000000000 --- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs +++ /dev/null @@ -1,32 +0,0 @@ -// @generated -/// Implement `DataProvider<CollationFallbackSupplementV1Marker>` on the given struct using the data -/// hardcoded in this file. This allows the struct to be used with -/// `icu`'s `_unstable` constructors. -#[doc(hidden)] -#[macro_export] -macro_rules! __impl_fallback_supplement_co_v1 { - ($ provider : ty) => { - #[clippy::msrv = "1.66"] - const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; - #[clippy::msrv = "1.66"] - impl $provider { - #[doc(hidden)] - pub const SINGLETON_FALLBACK_SUPPLEMENT_CO_V1: &'static <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackSupplementV1 { - parents: unsafe { - #[allow(unused_unsafe)] - zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") }) - }, - unicode_extension_defaults: unsafe { - #[allow(unused_unsafe)] - zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"co") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") }) - }, - }; - } - #[clippy::msrv = "1.66"] - impl icu_provider::DataProvider<icu_locid_transform::provider::CollationFallbackSupplementV1Marker> for $provider { - fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>, icu_provider::DataError> { - if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_SUPPLEMENT_CO_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) } - } - } - }; -} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs deleted file mode 100644 index 186f706cdb2..00000000000 --- a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs +++ /dev/null @@ -1,35 +0,0 @@ -// @generated -/// Implement `DataProvider<AndListV1Marker>` on the given struct using the data -/// hardcoded in this file. This allows the struct to be used with -/// `icu`'s `_unstable` constructors. -#[doc(hidden)] -#[macro_export] -macro_rules! __impl_list_and_v1 { - ($ provider : ty) => { - #[clippy::msrv = "1.66"] - const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; - #[clippy::msrv = "1.66"] - impl icu_provider::DataProvider<icu_list::provider::AndListV1Marker> for $provider { - fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_list::provider::AndListV1Marker>, icu_provider::DataError> { - static EN_001: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); - static EN_IN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); - static IT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }]); - static PT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); - static FR: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); - static TR: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); - static ES: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }]); - static RU: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); - static UND: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); - static EN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", & ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" & ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); - static HI_LATN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }]); - static JA: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]); - static ZH_HK: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }]); - static ZH: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]); - static ZH_HANT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }]); - static VALUES: [&<icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable; 215usize] = [&EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_IN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &HI_LATN, &IT, &IT, &IT, &IT, &JA, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &RU, &RU, &RU, &RU, &RU, &RU, &TR, &TR, &UND, &ZH, &ZH_HK, &ZH, &ZH, &ZH, &ZH_HANT, &ZH_HK, &ZH]; - static KEYS: [&str; 215usize] = ["en", "en-001", "en-150", "en-AE", "en-AG", "en-AI", "en-AS", "en-AT", "en-AU", "en-BB", "en-BE", "en-BI", "en-BM", "en-BS", "en-BW", "en-BZ", "en-CA", "en-CC", "en-CH", "en-CK", "en-CM", "en-CX", "en-CY", "en-DE", "en-DG", "en-DK", "en-DM", "en-ER", "en-FI", "en-FJ", "en-FK", "en-FM", "en-GB", "en-GD", "en-GG", "en-GH", "en-GI", "en-GM", "en-GU", "en-GY", "en-HK", "en-IE", "en-IL", "en-IM", "en-IN", "en-IO", "en-JE", "en-JM", "en-KE", "en-KI", "en-KN", "en-KY", "en-LC", "en-LR", "en-LS", "en-MG", "en-MH", "en-MO", "en-MP", "en-MS", "en-MT", "en-MU", "en-MV", "en-MW", "en-MY", "en-NA", "en-NF", "en-NG", "en-NL", "en-NR", "en-NU", "en-NZ", "en-PG", "en-PH", "en-PK", "en-PN", "en-PR", "en-PW", "en-RW", "en-SB", "en-SC", "en-SD", "en-SE", "en-SG", "en-SH", "en-SI", "en-SL", "en-SS", "en-SX", "en-SZ", "en-TC", "en-TK", "en-TO", "en-TT", "en-TV", "en-TZ", "en-UG", "en-UM", "en-VC", "en-VG", "en-VI", "en-VU", "en-WS", "en-ZA", "en-ZM", "en-ZW", "es", "es-419", "es-AR", "es-BO", "es-BR", "es-BZ", "es-CL", "es-CO", "es-CR", "es-CU", "es-DO", "es-EA", "es-EC", "es-GQ", "es-GT", "es-HN", "es-IC", "es-MX", "es-NI", "es-PA", "es-PE", "es-PH", "es-PR", "es-PY", "es-SV", "es-US", "es-UY", "es-VE", "fr", "fr-BE", "fr-BF", "fr-BI", "fr-BJ", "fr-BL", "fr-CA", "fr-CD", "fr-CF", "fr-CG", "fr-CH", "fr-CI", "fr-CM", "fr-DJ", "fr-DZ", "fr-GA", "fr-GF", "fr-GN", "fr-GP", "fr-GQ", "fr-HT", "fr-KM", "fr-LU", "fr-MA", "fr-MC", "fr-MF", "fr-MG", "fr-ML", "fr-MQ", "fr-MR", "fr-MU", "fr-NC", "fr-NE", "fr-PF", "fr-PM", "fr-RE", "fr-RW", "fr-SC", "fr-SN", "fr-SY", "fr-TD", "fr-TG", "fr-TN", "fr-VU", "fr-WF", "fr-YT", "hi-Latn", "it", "it-CH", "it-SM", "it-VA", "ja", "pt", "pt-AO", "pt-CH", "pt-CV", "pt-GQ", "pt-GW", "pt-LU", "pt-MO", "pt-MZ", "pt-PT", "pt-ST", "pt-TL", "ru", "ru-BY", "ru-KG", "ru-KZ", "ru-MD", "ru-UA", "tr", "tr-CY", "und", "zh", "zh-HK", "zh-Hans", "zh-Hans-HK", "zh-Hans-MO", "zh-Hant", "zh-MO", "zh-SG"]; - if let Ok(payload) = KEYS.binary_search_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).map(|i| *unsafe { VALUES.get_unchecked(i) }) { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(payload)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::MissingLocale.with_req(<icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) } - } - } - }; -} diff --git a/compiler/rustc_baked_icu_data/src/data/mod.rs b/compiler/rustc_baked_icu_data/src/data/mod.rs index 465689f0cb8..3146188a8e7 100644 --- a/compiler/rustc_baked_icu_data/src/data/mod.rs +++ b/compiler/rustc_baked_icu_data/src/data/mod.rs @@ -1,31 +1,40 @@ // @generated -include!("macros.rs"); -macro_rules! impl_data_provider { - ($ provider : ty) => { - make_provider!($provider); - impl_fallback_likelysubtags_v1!($provider); - impl_fallback_parents_v1!($provider); - impl_fallback_supplement_co_v1!($provider); - impl_list_and_v1!($provider); +include!("list_and_v1.rs.data"); +/// Marks a type as a data provider. You can then use macros like +/// `impl_core_helloworld_v1` to add implementations. +/// +/// ```ignore +/// struct MyProvider; +/// const _: () = { +/// include!("path/to/generated/macros.rs"); +/// make_provider!(MyProvider); +/// impl_core_helloworld_v1!(MyProvider); +/// } +/// ``` +#[doc(hidden)] +#[macro_export] +macro_rules! __make_provider { + ($ name : ty) => { + #[clippy::msrv = "1.82"] + impl $name { + #[allow(dead_code)] + pub(crate) const MUST_USE_MAKE_PROVIDER_MACRO: () = (); + } + icu_provider::marker::impl_data_provider_never_marker!($name); }; } +#[doc(inline)] +pub use __make_provider as make_provider; +/// This macro requires the following crates: +/// * `icu_list` +/// * `icu_locale/compiled_data` +/// * `icu_provider` +/// * `icu_provider/baked` +/// * `zerovec` #[allow(unused_macros)] -macro_rules! impl_any_provider { +macro_rules! impl_data_provider { ($ provider : ty) => { - #[clippy::msrv = "1.66"] - impl icu_provider::AnyProvider for $provider { - fn load_any(&self, key: icu_provider::DataKey, req: icu_provider::DataRequest) -> Result<icu_provider::AnyResponse, icu_provider::DataError> { - match key.hashed() { - h if h == <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), - h if h == <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), - h if h == <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), - h if h == <icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_list::provider::AndListV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), - _ => Err(icu_provider::DataErrorKind::MissingDataKey.with_req(key, req)), - } - } - } + make_provider!($provider); + impl_list_and_v1!($provider); }; } -#[clippy::msrv = "1.66"] -pub struct BakedDataProvider; -impl_data_provider!(BakedDataProvider); diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs index f3f6522f575..ea4c8242c62 100644 --- a/compiler/rustc_baked_icu_data/src/lib.rs +++ b/compiler/rustc_baked_icu_data/src/lib.rs @@ -14,10 +14,9 @@ //! To regenerate the data, run this command: //! //! ```text -//! icu4x-datagen -W --pretty --fingerprint --use-separate-crates \ -//! --format mod -l en es fr it ja pt ru tr zh zh-Hans zh-Hant \ -//! -k list/and@1 fallback/likelysubtags@1 fallback/parents@1 fallback/supplement/co@1 \ -//! --cldr-tag latest --icuexport-tag latest -o src/data +//! icu4x-datagen -W --pretty --use-separate-crates \ +//! --format baked --locales @en @es @fr @it @ja @pt @ru @tr @zh @zh-Hans @zh-Hant \ +//! -m ListAndV1 -o src/data //! ``` // tidy-alphabetical-start @@ -29,26 +28,26 @@ // #![warn(unreachable_pub)] // don't use because this crate is mostly generated code // tidy-alphabetical-end -mod data { - include!("data/mod.rs"); - include!("data/any.rs"); -} +pub struct BakedDataProvider; -pub use data::BakedDataProvider; +include!("data/mod.rs"); +const _: () = { + impl_data_provider!(BakedDataProvider); +}; pub const fn baked_data_provider() -> BakedDataProvider { - data::BakedDataProvider + BakedDataProvider } pub mod supported_locales { - pub const EN: icu_locid::Locale = icu_locid::locale!("en"); - pub const ES: icu_locid::Locale = icu_locid::locale!("es"); - pub const FR: icu_locid::Locale = icu_locid::locale!("fr"); - pub const IT: icu_locid::Locale = icu_locid::locale!("it"); - pub const JA: icu_locid::Locale = icu_locid::locale!("ja"); - pub const PT: icu_locid::Locale = icu_locid::locale!("pt"); - pub const RU: icu_locid::Locale = icu_locid::locale!("ru"); - pub const TR: icu_locid::Locale = icu_locid::locale!("tr"); - pub const ZH_HANS: icu_locid::Locale = icu_locid::locale!("zh-Hans"); - pub const ZH_HANT: icu_locid::Locale = icu_locid::locale!("zh-Hant"); + pub const EN: icu_locale::Locale = icu_locale::locale!("en"); + pub const ES: icu_locale::Locale = icu_locale::locale!("es"); + pub const FR: icu_locale::Locale = icu_locale::locale!("fr"); + pub const IT: icu_locale::Locale = icu_locale::locale!("it"); + pub const JA: icu_locale::Locale = icu_locale::locale!("ja"); + pub const PT: icu_locale::Locale = icu_locale::locale!("pt"); + pub const RU: icu_locale::Locale = icu_locale::locale!("ru"); + pub const TR: icu_locale::Locale = icu_locale::locale!("tr"); + pub const ZH_HANS: icu_locale::Locale = icu_locale::locale!("zh-Hans"); + pub const ZH_HANT: icu_locale::Locale = icu_locale::locale!("zh-Hant"); } diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 9e7d55180a2..5f9dc41766b 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -either = "1.5.0" -itertools = "0.12" -polonius-engine = "0.13.0" +either.workspace = true +itertools.workspace = true +polonius-engine.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -25,5 +25,5 @@ rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_traits = { path = "../rustc_traits" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index fdca6b56540..fda96dde826 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -565,7 +565,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let (blame_constraint, path) = self.regioncx.best_blame_constraint( borrow_region, NllRegionVariableOrigin::FreeRegion, - |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region), + outlived_region, ); let BlameConstraint { category, from_closure, cause, .. } = blame_constraint; diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs index f77f759035b..99913626418 100644 --- a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs +++ b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs @@ -243,10 +243,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> { let opaque_region_vid = self.regioncx.to_region_vid(opaque_region); // Find a path between the borrow region and our opaque capture. - if let Some((path, _)) = - self.regioncx.find_constraint_path_between_regions(self.borrow_region, |r| { - r == opaque_region_vid - }) + if let Some(path) = self + .regioncx + .constraint_path_between_regions(self.borrow_region, opaque_region_vid) { for constraint in path { // If we find a call in this path, then check if it defines the opaque. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index c7d2267e5f7..bec4c934502 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -61,7 +61,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal - | ConstraintCategory::IllegalUniverse => "", + | ConstraintCategory::OutlivesUnnameablePlaceholder(..) => "", } } } @@ -369,11 +369,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let error_vid = self.regioncx.region_from_element(longer_fr, &error_element); // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let (_, cause) = self.regioncx.find_outlives_blame_span( - longer_fr, - NllRegionVariableOrigin::Placeholder(placeholder), - error_vid, - ); + let cause = self + .regioncx + .best_blame_constraint( + longer_fr, + NllRegionVariableOrigin::Placeholder(placeholder), + error_vid, + ) + .0 + .cause; let universe = placeholder.universe; let universe_info = self.regioncx.universe_info(universe); @@ -429,9 +433,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) { debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let (blame_constraint, path) = self.regioncx.best_blame_constraint(fr, fr_origin, |r| { - self.regioncx.provides_universal_region(r, fr, outlived_fr) - }); + let (blame_constraint, path) = + self.regioncx.best_blame_constraint(fr, fr_origin, outlived_fr); let BlameConstraint { category, cause, variance_info, .. } = blame_constraint; debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info); diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index 4661906fbeb..94379cdebf7 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -1,7 +1,6 @@ //! Logic for lowering higher-kinded outlives constraints //! (with placeholders and universes) and turn them into regular //! outlives constraints. - use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph::scc; @@ -10,7 +9,7 @@ use rustc_index::IndexVec; use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{RegionVid, UniverseIndex}; -use tracing::debug; +use tracing::{debug, trace}; use crate::constraints::{ConstraintSccIndex, OutlivesConstraintSet}; use crate::consumers::OutlivesConstraint; @@ -62,18 +61,71 @@ impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> { type SccIdx = ConstraintSccIndex; } +#[derive(Copy, Debug, Clone, PartialEq, Eq)] +enum PlaceholderReachability { + /// This SCC reaches no placeholders. + NoPlaceholders, + /// This SCC reaches at least one placeholder. + Placeholders { + /// The largest-universed placeholder we can reach + max_universe: (UniverseIndex, RegionVid), + + /// The placeholder with the smallest ID + min_placeholder: RegionVid, + + /// The placeholder with the largest ID + max_placeholder: RegionVid, + }, +} + +impl PlaceholderReachability { + /// Merge the reachable placeholders of two graph components. + fn merge(self, other: PlaceholderReachability) -> PlaceholderReachability { + use PlaceholderReachability::*; + match (self, other) { + (NoPlaceholders, NoPlaceholders) => NoPlaceholders, + (NoPlaceholders, p @ Placeholders { .. }) + | (p @ Placeholders { .. }, NoPlaceholders) => p, + ( + Placeholders { + min_placeholder: min_pl, + max_placeholder: max_pl, + max_universe: max_u, + }, + Placeholders { min_placeholder, max_placeholder, max_universe }, + ) => Placeholders { + min_placeholder: min_pl.min(min_placeholder), + max_placeholder: max_pl.max(max_placeholder), + max_universe: max_u.max(max_universe), + }, + } + } + + fn max_universe(&self) -> Option<(UniverseIndex, RegionVid)> { + match self { + Self::NoPlaceholders => None, + Self::Placeholders { max_universe, .. } => Some(*max_universe), + } + } + + /// If we have reached placeholders, determine if they can + /// be named from this universe. + fn can_be_named_by(&self, from: UniverseIndex) -> bool { + self.max_universe() + .is_none_or(|(max_placeholder_universe, _)| from.can_name(max_placeholder_universe)) + } +} + /// An annotation for region graph SCCs that tracks /// the values of its elements. This annotates a single SCC. #[derive(Copy, Debug, Clone)] pub(crate) struct RegionTracker { - /// The largest universe of a placeholder reached from this SCC. - /// This includes placeholders within this SCC. - max_placeholder_universe_reached: UniverseIndex, + reachable_placeholders: PlaceholderReachability, /// The largest universe nameable from this SCC. /// It is the smallest nameable universes of all - /// existential regions reachable from it. - max_nameable_universe: UniverseIndex, + /// existential regions reachable from it. Small Rvids are preferred. + max_nameable_universe: (UniverseIndex, RegionVid), /// The representative Region Variable Id for this SCC. pub(crate) representative: Representative, @@ -81,65 +133,73 @@ pub(crate) struct RegionTracker { impl RegionTracker { pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self { - let placeholder_universe = + let reachable_placeholders = if matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_)) { - definition.universe + PlaceholderReachability::Placeholders { + max_universe: (definition.universe, rvid), + min_placeholder: rvid, + max_placeholder: rvid, + } } else { - UniverseIndex::ROOT + PlaceholderReachability::NoPlaceholders }; Self { - max_placeholder_universe_reached: placeholder_universe, - max_nameable_universe: definition.universe, + reachable_placeholders, + max_nameable_universe: (definition.universe, rvid), representative: Representative::new(rvid, definition), } } /// The largest universe this SCC can name. It's the smallest - /// largest nameable uninverse of any reachable region. + /// largest nameable universe of any reachable region, or + /// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)` pub(crate) fn max_nameable_universe(self) -> UniverseIndex { - self.max_nameable_universe + self.max_nameable_universe.0 } pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex { - self.max_placeholder_universe_reached - } - - fn merge_min_max_seen(&mut self, other: &Self) { - self.max_placeholder_universe_reached = std::cmp::max( - self.max_placeholder_universe_reached, - other.max_placeholder_universe_reached, - ); - - self.max_nameable_universe = - std::cmp::min(self.max_nameable_universe, other.max_nameable_universe); - } - - /// Returns `true` if during the annotated SCC reaches a placeholder - /// with a universe larger than the smallest nameable universe of any - /// reachable existential region. - pub(crate) fn has_incompatible_universes(&self) -> bool { - self.max_nameable_universe().cannot_name(self.max_placeholder_universe_reached) + if let Some((universe, _)) = self.reachable_placeholders.max_universe() { + universe + } else { + UniverseIndex::ROOT + } } /// Determine if the tracked universes of the two SCCs are compatible. pub(crate) fn universe_compatible_with(&self, other: Self) -> bool { + // HACK: We first check whether we can name the highest existential universe + // of `other`. This only exists to avoid errors in case that scc already + // depends on a placeholder it cannot name itself. self.max_nameable_universe().can_name(other.max_nameable_universe()) - || self.max_nameable_universe().can_name(other.max_placeholder_universe_reached) + || other.reachable_placeholders.can_be_named_by(self.max_nameable_universe()) + } + + /// If this SCC reaches a placeholder it can't name, return it. + fn unnameable_placeholder(&self) -> Option<(UniverseIndex, RegionVid)> { + self.reachable_placeholders.max_universe().filter(|&(placeholder_universe, _)| { + !self.max_nameable_universe().can_name(placeholder_universe) + }) } } impl scc::Annotation for RegionTracker { - fn merge_scc(mut self, other: Self) -> Self { - self.representative = self.representative.merge_scc(other.representative); - self.merge_min_max_seen(&other); - self + fn merge_scc(self, other: Self) -> Self { + trace!("{:?} << {:?}", self.representative, other.representative); + + Self { + representative: self.representative.min(other.representative), + max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe), + reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders), + } } - fn merge_reached(mut self, other: Self) -> Self { - // No update to in-component values, only add seen values. - self.merge_min_max_seen(&other); - self + fn merge_reached(self, other: Self) -> Self { + Self { + max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe), + reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders), + representative: self.representative, + } } } @@ -310,28 +370,52 @@ fn rewrite_placeholder_outlives<'tcx>( let annotation = annotations[scc]; - // If this SCC participates in a universe violation, - // e.g. if it reaches a region with a universe smaller than - // the largest region reached, add a requirement that it must - // outlive `'static`. - if annotation.has_incompatible_universes() { - // Optimisation opportunity: this will add more constraints than - // needed for correctness, since an SCC upstream of another with - // a universe violation will "infect" its downstream SCCs to also - // outlive static. - let scc_representative_outlives_static = OutlivesConstraint { - sup: annotation.representative.rvid(), - sub: fr_static, - category: ConstraintCategory::IllegalUniverse, - locations: Locations::All(rustc_span::DUMMY_SP), - span: rustc_span::DUMMY_SP, - variance_info: VarianceDiagInfo::None, - from_closure: false, - }; - outlives_constraints.push(scc_representative_outlives_static); - added_constraints = true; - debug!("Added {:?}: 'static!", annotation.representative.rvid()); - } + let Some((max_u, max_u_rvid)) = annotation.unnameable_placeholder() else { + continue; + }; + + debug!( + "Placeholder universe {max_u:?} is too large for its SCC, represented by {:?}", + annotation.representative + ); + + // We only add one `r: 'static` constraint per SCC, where `r` is the SCC representative. + // That constraint is annotated with some placeholder `unnameable` where + // `unnameable` is unnameable from `r` and there is a path in the constraint graph + // between them. + // + // There is one exception; if some other region in this SCC can't name `'r`, then + // we pick the region with the smallest universe in the SCC, so that a path can + // always start in `'r` to find a motivation that isn't cyclic. + let blame_to = if annotation.representative.rvid() == max_u_rvid { + // Assertion: the region that lowered our universe is an existential one and we are a placeholder! + + // The SCC's representative is not nameable from some region + // that ends up in the SCC. + let small_universed_rvid = annotation.max_nameable_universe.1; + debug!( + "{small_universed_rvid:?} lowered our universe to {:?}", + annotation.max_nameable_universe() + ); + small_universed_rvid + } else { + // `max_u_rvid` is not nameable by the SCC's representative. + max_u_rvid + }; + + // FIXME: if we can extract a useful blame span here, future error + // reporting and constraint search can be simplified. + + added_constraints = true; + outlives_constraints.push(OutlivesConstraint { + sup: annotation.representative.rvid(), + sub: fr_static, + category: ConstraintCategory::OutlivesUnnameablePlaceholder(blame_to), + locations: Locations::All(rustc_span::DUMMY_SP), + span: rustc_span::DUMMY_SP, + variance_info: VarianceDiagInfo::None, + from_closure: false, + }); } added_constraints } diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index b2f67c43125..526e1850c2e 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -12,9 +12,13 @@ use rustc_middle::ty::UniverseIndex; use super::*; fn render_outlives_constraint(constraint: &OutlivesConstraint<'_>) -> String { - match constraint.locations { - Locations::All(_) => "All(...)".to_string(), - Locations::Single(loc) => format!("{loc:?}"), + if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = constraint.category { + format!("{unnameable:?} unnameable") + } else { + match constraint.locations { + Locations::All(_) => "All(...)".to_string(), + Locations::Single(loc) => format!("{loc:?}"), + } } } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 3d95eb4663a..9990f4cb3f2 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_data_structures::graph::scc::{self, Sccs}; +use rustc_data_structures::graph::scc::Sccs; use rustc_errors::Diag; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_index::IndexVec; @@ -74,18 +74,6 @@ impl Representative { } } -impl scc::Annotation for Representative { - fn merge_scc(self, other: Self) -> Self { - // Just pick the smallest one. Note that we order by tag first! - std::cmp::min(self, other) - } - - // For reachability, we do nothing since the representative doesn't change. - fn merge_reached(self, _other: Self) -> Self { - self - } -} - pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>; pub struct RegionInferenceContext<'tcx> { @@ -1285,11 +1273,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { { debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus); - let blame_span_category = self.find_outlives_blame_span( - longer_fr, - NllRegionVariableOrigin::FreeRegion, - shorter_fr, - ); + let blame_constraint = self + .best_blame_constraint(longer_fr, NllRegionVariableOrigin::FreeRegion, shorter_fr) + .0; // Grow `shorter_fr` until we find some non-local regions. (We // always will.) We'll call them `shorter_fr+` -- they're ever @@ -1302,8 +1288,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { propagated_outlives_requirements.push(ClosureOutlivesRequirement { subject: ClosureOutlivesSubject::Region(fr_minus), outlived_free_region: fr, - blame_span: blame_span_category.1.span, - category: blame_span_category.0, + blame_span: blame_constraint.cause.span, + category: blame_constraint.category, }); } return RegionRelationCheckResult::Propagated; @@ -1342,66 +1328,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - /// We have a constraint `fr1: fr2` that is not satisfied, where - /// `fr2` represents some universal region. Here, `r` is some - /// region where we know that `fr1: r` and this function has the - /// job of determining whether `r` is "to blame" for the fact that - /// `fr1: fr2` is required. - /// - /// This is true under two conditions: - /// - /// - `r == fr2` - /// - `fr2` is `'static` and `r` is some placeholder in a universe - /// that cannot be named by `fr1`; in that case, we will require - /// that `fr1: 'static` because it is the only way to `fr1: r` to - /// be satisfied. (See `add_incompatible_universe`.) - pub(crate) fn provides_universal_region( + pub(crate) fn constraint_path_between_regions( &self, - r: RegionVid, - fr1: RegionVid, - fr2: RegionVid, - ) -> bool { - debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2); - let result = { - r == fr2 || { - fr2 == self.universal_regions().fr_static && self.cannot_name_placeholder(fr1, r) - } - }; - debug!("provides_universal_region: result = {:?}", result); - result - } - - /// If `r2` represents a placeholder region, then this returns - /// `true` if `r1` cannot name that placeholder in its - /// value; otherwise, returns `false`. - pub(crate) fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool { - match self.definitions[r2].origin { - NllRegionVariableOrigin::Placeholder(placeholder) => { - let r1_universe = self.definitions[r1].universe; - debug!( - "cannot_name_value_of: universe1={r1_universe:?} placeholder={:?}", - placeholder - ); - r1_universe.cannot_name(placeholder.universe) - } - - NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { .. } => { - false - } + from_region: RegionVid, + to_region: RegionVid, + ) -> Option<Vec<OutlivesConstraint<'tcx>>> { + if from_region == to_region { + bug!("Tried to find a path between {from_region:?} and itself!"); } - } - - /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`. - pub(crate) fn find_outlives_blame_span( - &self, - fr1: RegionVid, - fr1_origin: NllRegionVariableOrigin, - fr2: RegionVid, - ) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) { - let BlameConstraint { category, cause, .. } = self - .best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2)) - .0; - (category, cause) + self.constraint_path_to(from_region, |to| to == to_region, true).map(|o| o.0) } /// Walks the graph of constraints (where `'a: 'b` is considered @@ -1410,15 +1345,30 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// /// Returns: a series of constraints as well as the region `R` /// that passed the target test. + /// If `include_static_outlives_all` is `true`, then the synthetic + /// outlives constraints `'static -> a` for every region `a` are + /// considered in the search, otherwise they are ignored. #[instrument(skip(self, target_test), ret)] - pub(crate) fn find_constraint_path_between_regions( + pub(crate) fn constraint_path_to( &self, from_region: RegionVid, target_test: impl Fn(RegionVid) -> bool, + include_placeholder_static: bool, ) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> { - self.find_constraint_path_between_regions_inner(true, from_region, &target_test).or_else( - || self.find_constraint_path_between_regions_inner(false, from_region, &target_test), + self.find_constraint_path_between_regions_inner( + true, + from_region, + &target_test, + include_placeholder_static, ) + .or_else(|| { + self.find_constraint_path_between_regions_inner( + false, + from_region, + &target_test, + include_placeholder_static, + ) + }) } /// The constraints we get from equating the hidden type of each use of an opaque @@ -1438,6 +1388,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ignore_opaque_type_constraints: bool, from_region: RegionVid, target_test: impl Fn(RegionVid) -> bool, + include_placeholder_static: bool, ) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> { let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions); context[from_region] = Trace::StartRegion; @@ -1452,7 +1403,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { while let Some(r) = deque.pop_front() { debug!( - "find_constraint_path_between_regions: from_region={:?} r={:?} value={}", + "constraint_path_to: from_region={:?} r={:?} value={}", from_region, r, self.region_value_str(r), @@ -1525,8 +1476,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { // This loop can be hot. for constraint in edges { match constraint.category { - ConstraintCategory::IllegalUniverse => { - debug!("Ignoring illegal universe constraint: {constraint:?}"); + ConstraintCategory::OutlivesUnnameablePlaceholder(_) + if !include_placeholder_static => + { + debug!("Ignoring illegal placeholder constraint: {constraint:?}"); continue; } ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => { @@ -1535,6 +1488,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } _ => {} } + debug_assert_eq!(constraint.sup, r); handle_trace(constraint.sub, Trace::FromGraph(constraint)); } @@ -1549,33 +1503,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid { trace!(scc = ?self.constraint_sccs.scc(fr1)); trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1))); - self.find_constraint_path_between_regions(fr1, |r| { - // First look for some `r` such that `fr1: r` and `r` is live at `location` + self.constraint_path_to(fr1, |r| { trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r)); self.liveness_constraints.is_live_at(r, location) - }) - .or_else(|| { - // If we fail to find that, we may find some `r` such that - // `fr1: r` and `r` is a placeholder from some universe - // `fr1` cannot name. This would force `fr1` to be - // `'static`. - self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(fr1, r)) - }) - .or_else(|| { - // If we fail to find THAT, it may be that `fr1` is a - // placeholder that cannot "fit" into its SCC. In that - // case, there should be some `r` where `fr1: r` and `fr1` is a - // placeholder that `r` cannot name. We can blame that - // edge. - // - // Remember that if `R1: R2`, then the universe of R1 - // must be able to name the universe of R2, because R2 will - // be at least `'empty(Universe(R2))`, and `R1` must be at - // larger than that. - self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(r, fr1)) - }) - .map(|(_path, r)| r) - .unwrap() + }, true).unwrap().1 } /// Get the region outlived by `longer_fr` and live at `element`. @@ -1619,22 +1550,38 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// creating a constraint path that forces `R` to outlive /// `from_region`, and then finding the best choices within that /// path to blame. - #[instrument(level = "debug", skip(self, target_test))] + #[instrument(level = "debug", skip(self))] pub(crate) fn best_blame_constraint( &self, from_region: RegionVid, from_region_origin: NllRegionVariableOrigin, - target_test: impl Fn(RegionVid) -> bool, + to_region: RegionVid, ) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) { - // Find all paths - let (path, target_region) = self - .find_constraint_path_between_regions(from_region, target_test) - .or_else(|| { - self.find_constraint_path_between_regions(from_region, |r| { - self.cannot_name_placeholder(from_region, r) - }) - }) - .unwrap(); + assert!(from_region != to_region, "Trying to blame a region for itself!"); + + let path = self.constraint_path_between_regions(from_region, to_region).unwrap(); + + // If we are passing through a constraint added because we reached an unnameable placeholder `'unnameable`, + // redirect search towards `'unnameable`. + let due_to_placeholder_outlives = path.iter().find_map(|c| { + if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = c.category { + Some(unnameable) + } else { + None + } + }); + + // Edge case: it's possible that `'from_region` is an unnameable placeholder. + let path = if let Some(unnameable) = due_to_placeholder_outlives + && unnameable != from_region + { + // We ignore the extra edges due to unnameable placeholders to get + // an explanation that was present in the original constraint graph. + self.constraint_path_to(from_region, |r| r == unnameable, false).unwrap().0 + } else { + path + }; + debug!( "path={:#?}", path.iter() @@ -1742,7 +1689,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ConstraintCategory::Cast { unsize_to: Some(unsize_ty), is_implicit_coercion: true, - } if target_region == self.universal_regions().fr_static + } if to_region == self.universal_regions().fr_static // Mirror the note's condition, to minimize how often this diverts blame. && let ty::Adt(_, args) = unsize_ty.kind() && args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait())) @@ -1780,7 +1727,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // specific, and are not used for relations that would make sense to blame. ConstraintCategory::BoringNoLocation => 6, // Do not blame internal constraints. - ConstraintCategory::IllegalUniverse => 7, + ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 7, ConstraintCategory::Internal => 8, }; @@ -1817,6 +1764,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { path[best_choice] }; + assert!( + !matches!( + best_constraint.category, + ConstraintCategory::OutlivesUnnameablePlaceholder(_) + ), + "Illegal placeholder constraint blamed; should have redirected to other region relation" + ); + let blame_constraint = BlameConstraint { category: best_constraint.category, from_closure: best_constraint.from_closure, diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index e56b9e641a1..9ca44d67150 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -30,6 +30,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index 3e5a26c0556..cf563a53973 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -416,7 +416,7 @@ pub(crate) mod printf { // Yes, this *is* the parameter. Some(('$', end2)) => { state = Flags; - parameter = Some(at.slice_between(end).unwrap().parse().unwrap()); + parameter = at.slice_between(end).unwrap().parse().ok(); move_to!(end2); } // Wait, no, actually, it's the width. diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 2d11628250c..b04310f3d54 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -8,15 +8,15 @@ test = false [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" +bitflags.workspace = true # To avoid duplicate dependencies, this should match the version of gimli used # by `rustc_codegen_ssa` via its `thorin-dwp` dependency. gimli = "0.31" -itertools = "0.12" -libc = "0.2" -measureme = "12.0.1" +itertools.workspace = true +libc.workspace = true +measureme.workspace = true object = { version = "0.37.0", default-features = false, features = ["std", "read"] } -rustc-demangle = "0.1.21" +rustc-demangle.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } @@ -38,9 +38,9 @@ rustc_span = { path = "../rustc_span" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } serde = { version = "1", features = ["derive"] } -serde_json = "1" +serde_json.workspace = true smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 399f8b6e762..ac7583f5666 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -44,7 +44,7 @@ const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] = const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 6] = [ (ArgAttribute::NoAlias, llvm::AttributeKind::NoAlias), - (ArgAttribute::NoCapture, llvm::AttributeKind::NoCapture), + (ArgAttribute::CapturesAddress, llvm::AttributeKind::CapturesAddress), (ArgAttribute::NonNull, llvm::AttributeKind::NonNull), (ArgAttribute::ReadOnly, llvm::AttributeKind::ReadOnly), (ArgAttribute::NoUndef, llvm::AttributeKind::NoUndef), @@ -84,8 +84,10 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&' } for (attr, llattr) in OPTIMIZATION_ATTRIBUTES { if regular.contains(attr) { - // captures(address, read_provenance) is only available since LLVM 21. - if attr == ArgAttribute::CapturesReadOnly && llvm_util::get_version() < (21, 0, 0) { + // captures(...) is only available since LLVM 21. + if (attr == ArgAttribute::CapturesReadOnly || attr == ArgAttribute::CapturesAddress) + && llvm_util::get_version() < (21, 0, 0) + { continue; } attrs.push(llattr.create_attr(cx.llcx)); diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index d85f432702c..fc38c4f3e51 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -15,6 +15,7 @@ use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; use rustc_errors::DiagCtxtHandle; +use rustc_hir::attrs::SanitizerSet; use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; use rustc_session::config::{self, Lto}; @@ -42,6 +43,37 @@ fn prepare_lto( .map(|symbol| CString::new(symbol.to_owned()).unwrap()) .collect::<Vec<CString>>(); + if cgcx.regular_module_config.instrument_coverage + || cgcx.regular_module_config.pgo_gen.enabled() + { + // These are weak symbols that point to the profile version and the + // profile name, which need to be treated as exported so LTO doesn't nix + // them. + const PROFILER_WEAK_SYMBOLS: [&CStr; 2] = + [c"__llvm_profile_raw_version", c"__llvm_profile_filename"]; + + symbols_below_threshold.extend(PROFILER_WEAK_SYMBOLS.iter().map(|&sym| sym.to_owned())); + } + + if cgcx.regular_module_config.sanitizer.contains(SanitizerSet::MEMORY) { + let mut msan_weak_symbols = Vec::new(); + + // Similar to profiling, preserve weak msan symbol during LTO. + if cgcx.regular_module_config.sanitizer_recover.contains(SanitizerSet::MEMORY) { + msan_weak_symbols.push(c"__msan_keep_going"); + } + + if cgcx.regular_module_config.sanitizer_memory_track_origins != 0 { + msan_weak_symbols.push(c"__msan_track_origins"); + } + + symbols_below_threshold.extend(msan_weak_symbols.into_iter().map(|sym| sym.to_owned())); + } + + // Preserve LLVM-injected, ASAN-related symbols. + // See also https://github.com/rust-lang/rust/issues/113404. + symbols_below_threshold.push(c"___asan_globals_registered".to_owned()); + // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to // __llvm_profile_runtime, therefore we won't know until link time if this symbol // should have default visibility. diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 0e9dbfba658..caa3369f413 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -19,7 +19,9 @@ use rustc_middle::ty::{ self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility, }; use rustc_session::config::{self, DebugInfo, Lto}; -use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Symbol, hygiene}; +use rustc_span::{ + DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span, Symbol, hygiene, +}; use rustc_symbol_mangling::typeid_for_trait_ref; use rustc_target::spec::DebuginfoKind; use smallvec::smallvec; @@ -423,6 +425,14 @@ fn build_slice_type_di_node<'ll, 'tcx>( /// This function will look up the debuginfo node in the TypeMap. If it can't find it, it /// will create the node by dispatching to the corresponding `build_*_di_node()` function. pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { + spanned_type_di_node(cx, t, DUMMY_SP) +} + +pub(crate) fn spanned_type_di_node<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, + span: Span, +) -> &'ll DIType { let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t); if let Some(existing_di_node) = debug_context(cx).type_map.di_node_for_unique_id(unique_type_id) @@ -460,7 +470,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> ty::Adt(def, ..) => match def.adt_kind() { AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id), AdtKind::Union => build_union_type_di_node(cx, unique_type_id), - AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id), + AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span), }, ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 7c701926d2c..caff3586079 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -10,7 +10,7 @@ use rustc_middle::bug; use rustc_middle::mir::CoroutineLayout; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef}; -use rustc_span::Symbol; +use rustc_span::{Span, Symbol}; use super::type_map::{DINodeCreationResult, UniqueTypeId}; use super::{SmallVec, size_and_align_of}; @@ -30,13 +30,14 @@ mod native; pub(super) fn build_enum_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId<'tcx>, + span: Span, ) -> DINodeCreationResult<'ll> { let enum_type = unique_type_id.expect_ty(); let &ty::Adt(enum_adt_def, _) = enum_type.kind() else { bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type) }; - let enum_type_and_layout = cx.layout_of(enum_type); + let enum_type_and_layout = cx.spanned_layout_of(enum_type, span); if wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout) { return build_c_style_enum_di_node(cx, enum_adt_def, enum_type_and_layout); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 2c3a84499ac..79334f7f9fe 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -28,7 +28,9 @@ use rustc_target::spec::DebuginfoKind; use smallvec::SmallVec; use tracing::debug; -use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, type_di_node}; +use self::metadata::{ + UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, spanned_type_di_node, type_di_node, +}; use self::namespace::mangled_name_of_instance; use self::utils::{DIB, create_DIArray, is_node_local_to_unit}; use crate::builder::Builder; @@ -626,7 +628,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file); - let type_metadata = type_di_node(self, variable_type); + let type_metadata = spanned_type_di_node(self, variable_type, span); let (argument_index, dwarf_tag) = match variable_kind { ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 7c79cba2273..ba590851dbd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -263,7 +263,7 @@ pub(crate) enum AttributeKind { MinSize = 4, Naked = 5, NoAlias = 6, - NoCapture = 7, + CapturesAddress = 7, NoInline = 8, NonNull = 9, NoRedZone = 10, diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 6a8971de746..57e1fee2c0a 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -6,12 +6,12 @@ edition = "2024" [dependencies] # tidy-alphabetical-start ar_archive_writer = "0.4.2" -bitflags = "2.4.1" +bitflags.workspace = true bstr = "1.11.3" # `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version # per crate", so if you change this, you need to also change it in `rustc_llvm`. cc = "=1.2.16" -itertools = "0.12" +itertools.workspace = true pathdiff = "0.2.0" regex = "1.4" rustc_abi = { path = "../rustc_abi" } @@ -37,18 +37,18 @@ rustc_span = { path = "../rustc_span" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -serde_json = "1.0.59" +serde_json.workspace = true smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tempfile = "3.2" -thin-vec = "0.2.12" +tempfile.workspace = true +thin-vec.workspace = true thorin-dwp = "0.9" -tracing = "0.1" +tracing.workspace = true wasm-encoder = "0.219" # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] # tidy-alphabetical-start -libc = "0.2.50" +libc.workspace = true # tidy-alphabetical-end [dependencies.object] diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c3777f64e9e..19c919c0e4e 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -14,11 +14,13 @@ use itertools::Itertools; use regex::Regex; use rustc_arena::TypedArena; use rustc_ast::CRATE_NODE_ID; +use rustc_attr_parsing::{ShouldEmit, eval_config_entry}; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize}; +use rustc_hir::attrs::NativeLibKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_macros::LintDiagnostic; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; @@ -38,7 +40,6 @@ use rustc_session::config::{ use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; -use rustc_session::utils::NativeLibKind; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. use rustc_session::{Session, filesearch}; @@ -3019,7 +3020,9 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) { fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { match lib.cfg { - Some(ref cfg) => rustc_attr_parsing::cfg_matches(cfg, sess, CRATE_NODE_ID, None), + Some(ref cfg) => { + eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool() + } None => true, } } diff --git a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs index 509168b2cd2..9f42991d4c0 100644 --- a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs +++ b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs @@ -7,9 +7,9 @@ use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::stable_hasher::StableHasher; use rustc_hashes::Hash128; +use rustc_hir::attrs::NativeLibKind; use rustc_session::Session; use rustc_session::cstore::DllImport; -use rustc_session::utils::NativeLibKind; use rustc_span::Symbol; use crate::back::archive::ImportLibraryItem; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 13419bcb22c..d8a1480e911 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolNam use rustc_middle::util::Providers; use rustc_session::config::{CrateType, OomStrategy}; use rustc_symbol_mangling::mangle_internal_symbol; -use rustc_target::spec::{SanitizerSet, TlsModel}; +use rustc_target::spec::TlsModel; use tracing::debug; use crate::base::allocator_kind_for_codegen; @@ -242,53 +242,6 @@ fn exported_non_generic_symbols_provider_local<'tcx>( } } - if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { - // These are weak symbols that point to the profile version and the - // profile name, which need to be treated as exported so LTO doesn't nix - // them. - const PROFILER_WEAK_SYMBOLS: [&str; 2] = - ["__llvm_profile_raw_version", "__llvm_profile_filename"]; - - symbols.extend(PROFILER_WEAK_SYMBOLS.iter().map(|sym| { - let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym)); - ( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::C, - kind: SymbolExportKind::Data, - used: false, - rustc_std_internal_symbol: false, - }, - ) - })); - } - - if tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) { - let mut msan_weak_symbols = Vec::new(); - - // Similar to profiling, preserve weak msan symbol during LTO. - if tcx.sess.opts.unstable_opts.sanitizer_recover.contains(SanitizerSet::MEMORY) { - msan_weak_symbols.push("__msan_keep_going"); - } - - if tcx.sess.opts.unstable_opts.sanitizer_memory_track_origins != 0 { - msan_weak_symbols.push("__msan_track_origins"); - } - - symbols.extend(msan_weak_symbols.into_iter().map(|sym| { - let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym)); - ( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::C, - kind: SymbolExportKind::Data, - used: false, - rustc_std_internal_symbol: false, - }, - ) - })); - } - // Sort so we get a stable incr. comp. hash. symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx)); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 9f22859ba81..92582dcc399 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -138,23 +138,12 @@ impl ModuleConfig { let emit_obj = if !should_emit_obj { EmitObj::None - } else if sess.target.obj_is_bitcode - || (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins) - { + } else if sess.target.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() { // This case is selected if the target uses objects as bitcode, or // if linker plugin LTO is enabled. In the linker plugin LTO case // the assumption is that the final link-step will read the bitcode // and convert it to object code. This may be done by either the // native linker or rustc itself. - // - // Note, however, that the linker-plugin-lto requested here is - // explicitly ignored for `#![no_builtins]` crates. These crates are - // specifically ignored by rustc's LTO passes and wouldn't work if - // loaded into the linker. These crates define symbols that LLVM - // lowers intrinsics to, and these symbol dependencies aren't known - // until after codegen. As a result any crate marked - // `#![no_builtins]` is assumed to not participate in LTO and - // instead goes on to generate object code. EmitObj::Bitcode } else if need_bitcode_in_object(tcx) { EmitObj::ObjectCode(BitcodeSection::Full) @@ -1957,10 +1946,13 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> { pub struct OngoingCodegen<B: ExtraBackendMethods> { pub backend: B, pub crate_info: CrateInfo, - pub codegen_worker_receive: Receiver<CguMessage>, - pub shared_emitter_main: SharedEmitterMain, pub output_filenames: Arc<OutputFilenames>, + // Field order below is intended to terminate the coordinator thread before two fields below + // drop and prematurely close channels used by coordinator thread. See `Coordinator`'s + // `Drop` implementation for more info. pub coordinator: Coordinator<B>, + pub codegen_worker_receive: Receiver<CguMessage>, + pub shared_emitter_main: SharedEmitterMain, } impl<B: ExtraBackendMethods> OngoingCodegen<B> { diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index a6fd6c763ed..08e2f355953 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -1,10 +1,11 @@ #![allow(non_camel_case_types)] use rustc_hir::LangItem; +use rustc_hir::attrs::PeImportNameType; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_middle::{bug, mir, span_bug}; -use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType}; +use rustc_session::cstore::{DllCallingConvention, DllImport}; use rustc_span::Span; use rustc_target::spec::Target; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 23ed387a3ff..fe0500a5d4c 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -25,10 +25,10 @@ use std::io; use std::path::{Path, PathBuf}; use std::sync::Arc; -use rustc_ast as ast; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordMap; use rustc_hir::CRATE_HIR_ID; +use rustc_hir::attrs::{CfgEntry, NativeLibKind}; use rustc_hir::def_id::CrateNum; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_metadata::EncodedMetadata; @@ -45,7 +45,6 @@ use rustc_session::Session; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; use rustc_session::lint::builtin::LINKER_MESSAGES; -use rustc_session::utils::NativeLibKind; use rustc_span::Symbol; pub mod assert_module_sources; @@ -187,7 +186,7 @@ pub struct NativeLib { pub kind: NativeLibKind, pub name: Symbol, pub filename: Option<Symbol>, - pub cfg: Option<ast::MetaItemInner>, + pub cfg: Option<CfgEntry>, pub verbatim: bool, pub dll_imports: Vec<cstore::DllImport>, } diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index 51dcee8d882..acf19b0f2fc 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -either = "1" +either.workspace = true rustc_abi = { path = "../rustc_abi" } -rustc_apfloat = "0.2.0" +rustc_apfloat.workspace = true rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -22,5 +22,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 17204883fb0..852fc11350b 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -6,14 +6,15 @@ edition = "2024" [dependencies] # tidy-alphabetical-start arrayvec = { version = "0.7", default-features = false } -bitflags = "2.4.1" -either = "1.0" +bitflags.workspace = true +either.workspace = true elsa = "1.11.0" ena = "0.14.3" -indexmap = "2.4.0" +indexmap.workspace = true jobserver_crate = { version = "0.1.28", package = "jobserver" } -measureme = "12.0.1" -rustc-hash = "2.0.0" +measureme.workspace = true +parking_lot = "0.12" +rustc-hash.workspace = true rustc-stable-hash = { version = "0.1.0", features = ["nightly"] } rustc_arena = { path = "../rustc_arena" } rustc_graphviz = { path = "../rustc_graphviz" } @@ -24,9 +25,9 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_thread_pool = { path = "../rustc_thread_pool" } smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] } stacker = "0.1.17" -tempfile = "3.2" -thin-vec = "0.2.12" -tracing = "0.1" +tempfile.workspace = true +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end [dependencies.hashbrown] @@ -34,9 +35,6 @@ version = "0.15.2" default-features = false features = ["nightly"] # for may_dangle -[dependencies.parking_lot] -version = "0.12" - [target.'cfg(windows)'.dependencies.windows] version = "0.61.0" features = [ @@ -49,7 +47,7 @@ features = [ [target.'cfg(unix)'.dependencies] # tidy-alphabetical-start -libc = "0.2" +libc.workspace = true # tidy-alphabetical-end [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index ae1dbd2cf51..196c8aa3547 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -49,14 +49,14 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } -serde_json = "1.0.59" +serde_json.workspace = true shlex = "1.0" -tracing = { version = "0.1.35" } +tracing.workspace = true # tidy-alphabetical-end [target.'cfg(all(unix, any(target_env = "gnu", target_os = "macos")))'.dependencies] # tidy-alphabetical-start -libc = "0.2" +libc.workspace = true # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] diff --git a/compiler/rustc_error_codes/src/error_codes/E0458.md b/compiler/rustc_error_codes/src/error_codes/E0458.md index 1b280cba44f..651bc378879 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0458.md +++ b/compiler/rustc_error_codes/src/error_codes/E0458.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + An unknown "kind" was specified for a link attribute. Erroneous code example: -```compile_fail,E0458 +```ignore (no longer emitted) #[link(kind = "wonderful_unicorn")] extern "C" {} // error: unknown kind: `wonderful_unicorn` ``` diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index 552ad672752..7d2dc20e136 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -7,9 +7,8 @@ edition = "2024" # tidy-alphabetical-start fluent-bundle = "0.16" fluent-syntax = "0.12" -icu_list = "1.2" -icu_locid = "1.2" -icu_provider_adapters = "1.2" +icu_list = { version = "2.0", default-features = false, features = ["alloc"] } +icu_locale = { version = "2.0", default-features = false } intl-memoizer = "0.5.1" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } @@ -18,6 +17,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } -tracing = "0.1" +tracing.workspace = true unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index d8bacbe762b..7b7843f6cf3 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -15,7 +15,6 @@ use fluent_bundle::FluentResource; pub use fluent_bundle::types::FluentType; pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue}; use fluent_syntax::parser::ParserError; -use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker}; use intl_memoizer::concurrent::IntlLangMemoizer; use rustc_data_structures::sync::{DynSend, IntoDynSyncSend}; use rustc_macros::{Decodable, Encodable}; @@ -515,8 +514,8 @@ impl From<Vec<Span>> for MultiSpan { } } -fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locid::Locale> { - icu_locid::Locale::try_from_bytes(lang.to_string().as_bytes()).ok() +fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locale::Locale> { + icu_locale::Locale::try_from_str(&lang.to_string()).ok() } pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> { @@ -568,21 +567,15 @@ pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValu where Self: Sized, { - let baked_data_provider = rustc_baked_icu_data::baked_data_provider(); - let locale_fallbacker = - LocaleFallbacker::try_new_with_any_provider(&baked_data_provider) - .expect("Failed to create fallback provider"); - let data_provider = - LocaleFallbackProvider::new_with_fallbacker(baked_data_provider, locale_fallbacker); let locale = icu_locale_from_unic_langid(lang) .unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN); - let list_formatter = - icu_list::ListFormatter::try_new_and_with_length_with_any_provider( - &data_provider, - &locale.into(), - icu_list::ListLength::Wide, - ) - .expect("Failed to create list formatter"); + let list_formatter = icu_list::ListFormatter::try_new_and_unstable( + &rustc_baked_icu_data::BakedDataProvider, + locale.into(), + icu_list::options::ListFormatterOptions::default() + .with_length(icu_list::options::ListLength::Wide), + ) + .expect("Failed to create list formatter"); Ok(MemoizableListFormatter(list_formatter)) } diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 7912b8e6098..67a17ce88fa 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -21,10 +21,10 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } serde = { version = "1.0.125", features = ["derive"] } -serde_json = "1.0.59" +serde_json.workspace = true termcolor = "1.2.0" termize = "0.2" -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 749bba5de12..b94370e8e9b 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1462,7 +1462,7 @@ impl HumanEmitter { max_line_num_len: usize, is_secondary: bool, is_cont: bool, - ) -> io::Result<()> { + ) -> io::Result<CodeWindowStatus> { let mut buffer = StyledBuffer::new(); if !msp.has_primary_spans() && !msp.has_span_labels() && is_secondary && !self.short_message @@ -1575,12 +1575,14 @@ impl HumanEmitter { } let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp); trace!("{annotated_files:#?}"); + let mut code_window_status = CodeWindowStatus::Open; // Make sure our primary file comes first let primary_span = msp.primary_span().unwrap_or_default(); let (Some(sm), false) = (self.sm.as_ref(), primary_span.is_dummy()) else { // If we don't have span information, emit and exit - return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message); + return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message) + .map(|_| code_window_status); }; let primary_lo = sm.lookup_char_pos(primary_span.lo()); if let Ok(pos) = @@ -1589,6 +1591,9 @@ impl HumanEmitter { annotated_files.swap(0, pos); } + // An end column separator should be emitted when a file with with a + // source, is followed by one without a source + let mut col_sep_before_no_show_source = false; let annotated_files_len = annotated_files.len(); // Print out the annotate source lines that correspond with the error for (file_idx, annotated_file) in annotated_files.into_iter().enumerate() { @@ -1599,6 +1604,26 @@ impl HumanEmitter { &annotated_file.file, ) { if !self.short_message { + // Add an end column separator when a file without a source + // comes after one with a source + // ╭▸ $DIR/deriving-meta-unknown-trait.rs:1:10 + // │ + // LL │ #[derive(Eqr)] + // │ ━━━ + // ╰╴ (<- It prints *this* line) + // ╭▸ $SRC_DIR/core/src/cmp.rs:356:0 + // │ + // ╰╴note: similarly named derive macro `Eq` defined here + if col_sep_before_no_show_source { + let buffer_msg_line_offset = buffer.num_lines(); + self.draw_col_separator_end( + &mut buffer, + buffer_msg_line_offset, + max_line_num_len + 1, + ); + } + col_sep_before_no_show_source = false; + // We'll just print an unannotated message. for (annotation_id, line) in annotated_file.lines.iter().enumerate() { let mut annotations = line.annotations.clone(); @@ -1639,29 +1664,42 @@ impl HumanEmitter { } line_idx += 1; } - for (label, is_primary) in labels.into_iter() { + if is_cont + && file_idx == annotated_files_len - 1 + && annotation_id == annotated_file.lines.len() - 1 + && !labels.is_empty() + { + code_window_status = CodeWindowStatus::Closed; + } + let labels_len = labels.len(); + for (label_idx, (label, is_primary)) in labels.into_iter().enumerate() { let style = if is_primary { Style::LabelPrimary } else { Style::LabelSecondary }; - let pipe = self.col_separator(); - buffer.prepend(line_idx, &format!(" {pipe}"), Style::LineNumber); - for _ in 0..max_line_num_len { - buffer.prepend(line_idx, " ", Style::NoStyle); - } + self.draw_col_separator_no_space( + &mut buffer, + line_idx, + max_line_num_len + 1, + ); line_idx += 1; - let chr = self.note_separator(); - buffer.append(line_idx, &format!(" {chr} note: "), style); - for _ in 0..max_line_num_len { - buffer.prepend(line_idx, " ", Style::NoStyle); - } + self.draw_note_separator( + &mut buffer, + line_idx, + max_line_num_len + 1, + label_idx != labels_len - 1, + ); + buffer.append(line_idx, "note", Style::MainHeaderMsg); + buffer.append(line_idx, ": ", Style::NoStyle); buffer.append(line_idx, label, style); line_idx += 1; } } } continue; + } else { + col_sep_before_no_show_source = true; } // print out the span location and spacer before we print the annotated source @@ -1976,7 +2014,7 @@ impl HumanEmitter { // final step: take our styled buffer, render it, then output it emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; - Ok(()) + Ok(code_window_status) } fn column_width(&self, code_offset: usize) -> usize { @@ -2491,7 +2529,7 @@ impl HumanEmitter { !children.is_empty() || suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden), ) { - Ok(()) => { + Ok(code_window_status) => { if !children.is_empty() || suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden) { @@ -2502,7 +2540,7 @@ impl HumanEmitter { { // We'll continue the vertical bar to point into the next note. self.draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1); - } else { + } else if matches!(code_window_status, CodeWindowStatus::Open) { // We'll close the vertical bar to visually end the code window. self.draw_col_separator_end(&mut buffer, 0, max_line_num_len + 1); } @@ -2829,10 +2867,11 @@ impl HumanEmitter { } } - fn note_separator(&self) -> char { + fn note_separator(&self, is_cont: bool) -> &'static str { match self.theme { - OutputTheme::Ascii => '=', - OutputTheme::Unicode => '╰', + OutputTheme::Ascii => "= ", + OutputTheme::Unicode if is_cont => "├ ", + OutputTheme::Unicode => "╰ ", } } @@ -2945,11 +2984,7 @@ impl HumanEmitter { col: usize, is_cont: bool, ) { - let chr = match self.theme { - OutputTheme::Ascii => "= ", - OutputTheme::Unicode if is_cont => "├ ", - OutputTheme::Unicode => "╰ ", - }; + let chr = self.note_separator(is_cont); buffer.puts(line, col, chr, Style::LineNumber); } @@ -3050,6 +3085,12 @@ enum DisplaySuggestion { Add, } +#[derive(Clone, Copy, Debug)] +enum CodeWindowStatus { + Closed, + Open, +} + impl FileWithAnnotatedLines { /// Preprocess all the annotations so that they are grouped by file and by line number /// This helps us quickly iterate over the whole message (including secondary file spans) diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index f897833d85c..9bb7143af51 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -29,6 +29,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml index a4746ac455c..b58f2375852 100644 --- a/compiler/rustc_feature/Cargo.toml +++ b/compiler/rustc_feature/Cargo.toml @@ -9,5 +9,5 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_span = { path = "../rustc_span" } serde = { version = "1.0.125", features = ["derive"] } -serde_json = "1.0.59" +serde_json.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml index d7ef4280aef..60afd9aca87 100644 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -11,8 +11,8 @@ proc-macro = true annotate-snippets = "0.11" fluent-bundle = "0.16" fluent-syntax = "0.12" -proc-macro2 = "1" -quote = "1" +proc-macro2.workspace = true +quote.workspace = true syn = { version = "2", features = ["full"] } unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml index 90a6acade8b..37970e81fea 100644 --- a/compiler/rustc_fs_util/Cargo.toml +++ b/compiler/rustc_fs_util/Cargo.toml @@ -5,5 +5,5 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -tempfile = "3.7.1" +tempfile.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index 1008a3e787d..e74fcfe7455 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -5,8 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.9.1" -odht = { version = "0.3.1", features = ["nightly"] } +bitflags.workspace = true +odht.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } @@ -21,6 +21,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 09da5772d23..dd5565d6f90 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -248,6 +248,120 @@ impl IntoDiagArg for MirPhase { } } +/// Different ways that the PE Format can decorate a symbol name. +/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type> +#[derive( + Copy, + Clone, + Debug, + Encodable, + Decodable, + HashStable_Generic, + PartialEq, + Eq, + PrintAttribute +)] +pub enum PeImportNameType { + /// IMPORT_ORDINAL + /// Uses the ordinal (i.e., a number) rather than the name. + Ordinal(u16), + /// Same as IMPORT_NAME + /// Name is decorated with all prefixes and suffixes. + Decorated, + /// Same as IMPORT_NAME_NOPREFIX + /// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept. + NoPrefix, + /// Same as IMPORT_NAME_UNDECORATE + /// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all + /// trailing characters) are skipped. + Undecorated, +} + +#[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Encodable, + Decodable, + PrintAttribute +)] +#[derive(HashStable_Generic)] +pub enum NativeLibKind { + /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC) + Static { + /// Whether to bundle objects from static library into produced rlib + bundle: Option<bool>, + /// Whether to link static library without throwing any object files away + whole_archive: Option<bool>, + }, + /// Dynamic library (e.g. `libfoo.so` on Linux) + /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC). + Dylib { + /// Whether the dynamic library will be linked only if it satisfies some undefined symbols + as_needed: Option<bool>, + }, + /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library. + /// On Linux, it refers to a generated shared library stub. + RawDylib, + /// A macOS-specific kind of dynamic libraries. + Framework { + /// Whether the framework will be linked only if it satisfies some undefined symbols + as_needed: Option<bool>, + }, + /// Argument which is passed to linker, relative order with libraries and other arguments + /// is preserved + LinkArg, + + /// Module imported from WebAssembly + WasmImportModule, + + /// The library kind wasn't specified, `Dylib` is currently used as a default. + Unspecified, +} + +impl NativeLibKind { + pub fn has_modifiers(&self) -> bool { + match self { + NativeLibKind::Static { bundle, whole_archive } => { + bundle.is_some() || whole_archive.is_some() + } + NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => { + as_needed.is_some() + } + NativeLibKind::RawDylib + | NativeLibKind::Unspecified + | NativeLibKind::LinkArg + | NativeLibKind::WasmImportModule => false, + } + } + + pub fn is_statically_included(&self) -> bool { + matches!(self, NativeLibKind::Static { .. }) + } + + pub fn is_dllimport(&self) -> bool { + matches!( + self, + NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified + ) + } +} + +#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)] +pub struct LinkEntry { + pub span: Span, + pub kind: NativeLibKind, + pub name: Symbol, + pub cfg: Option<CfgEntry>, + pub verbatim: Option<bool>, + pub import_name_type: Option<(PeImportNameType, Span)>, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -418,6 +532,9 @@ pub enum AttributeKind { /// Represents `#[inline]` and `#[rustc_force_inline]`. Inline(InlineAttr, Span), + /// Represents `#[link]`. + Link(ThinVec<LinkEntry>, Span), + /// Represents `#[link_name]`. LinkName { name: Symbol, span: Span }, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index e5329c104bb..3810bb6d003 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -50,6 +50,7 @@ impl AttributeKind { Fundamental { .. } => Yes, Ignore { .. } => No, Inline(..) => No, + Link(..) => No, LinkName { .. } => Yes, // Needed for rustdoc LinkOrdinal { .. } => No, LinkSection { .. } => Yes, // Needed for rustdoc diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index e5017794d8f..bb86beb2251 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -9,7 +9,7 @@ doctest = false [dependencies] # tidy-alphabetical-start -itertools = "0.12" +itertools.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } @@ -29,5 +29,5 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index c88c534e135..e27e68d3662 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -202,14 +202,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { Some((normalized_ty, ocx.into_pending_obligations())) } - /// Returns the final type we ended up with, which may be an inference - /// variable (we will resolve it first, if we want). - pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> { - if resolve { - self.infcx.resolve_vars_if_possible(self.state.cur_ty) - } else { - self.state.cur_ty - } + /// Returns the final type we ended up with, which may be an unresolved + /// inference variable. + pub fn final_ty(&self) -> Ty<'tcx> { + self.state.cur_ty } pub fn step_count(&self) -> usize { diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index f00125c3e09..5af0c6134ca 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools = "0.12" +itertools.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } @@ -25,5 +25,5 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 7af26623ce7..4fe77278706 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut obligations = PredicateObligations::new(); let targets = - steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false))); + steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty())); let steps: Vec<_> = steps .iter() .map(|&(source, kind)| { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 4200afb74e6..c6a4d78dcc8 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef); } - match autoderef.final_ty(false).kind() { + match autoderef.final_ty().kind() { ty::FnDef(def_id, _) => { let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi; self.check_call_abi(abi, call_expr.span); @@ -200,8 +200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs: &'tcx [hir::Expr<'tcx>], autoderef: &Autoderef<'a, 'tcx>, ) -> Option<CallStep<'tcx>> { - let adjusted_ty = - self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty()); // If the callee is a function pointer or a closure, then we're all set. match *adjusted_ty.kind() { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 940f0e3708d..a652e08905a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2918,7 +2918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Emits an error if we deref an infer variable, like calling `.field` on a base type // of `&_`. We can also use this to suppress unnecessary "missing field" errors that // will follow ambiguity errors. - let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty()); if let ty::Error(_) = final_ty.kind() { return final_ty; } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index bb4748b0565..ab584eb7c90 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -629,7 +629,7 @@ pub(crate) fn method_autoderef_steps<'tcx>( .collect(); (steps, autoderef_via_deref.reached_recursion_limit()) }; - let final_ty = autoderef_via_deref.final_ty(true); + let final_ty = autoderef_via_deref.final_ty(); let opt_bad_ty = match final_ty.kind() { ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy { reached_raw_pointer, diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index fedc75abe49..1125e984080 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -109,8 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { index_ty: Ty<'tcx>, index_expr: &hir::Expr<'_>, ) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { - let adjusted_ty = - self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty()); debug!( "try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \ index_ty={:?})", diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index db0a5841887..8d7f2eb8414 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -19,6 +19,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_index_macros/Cargo.toml b/compiler/rustc_index_macros/Cargo.toml index 34f3109a526..8593bde2615 100644 --- a/compiler/rustc_index_macros/Cargo.toml +++ b/compiler/rustc_index_macros/Cargo.toml @@ -8,8 +8,8 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -proc-macro2 = "1" -quote = "1" +proc-macro2.workspace = true +quote.workspace = true syn = { version = "2.0.9", features = ["full", "extra-traits"] } # tidy-alphabetical-end diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 08c03614884..6d97fa6af1f 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -18,6 +18,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 473ac5e0cea..40152e78f8a 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -46,7 +46,7 @@ rustc_thread_pool = { path = "../rustc_thread_pool" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_traits = { path = "../rustc_traits" } rustc_ty_utils = { path = "../rustc_ty_utils" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [dev-dependencies] diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 4425877308a..7730bddc0f1 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -8,6 +8,7 @@ use rustc_abi::Align; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::emitter::HumanReadableErrorType; use rustc_errors::{ColorConfig, registry}; +use rustc_hir::attrs::NativeLibKind; use rustc_session::config::{ AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, @@ -20,7 +21,7 @@ use rustc_session::config::{ }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; -use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; +use rustc_session::utils::{CanonicalizedPath, NativeLib}; use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, getopts}; use rustc_span::edition::{DEFAULT_EDITION, Edition}; use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 448a50faf45..e0019fb1821 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -14,13 +14,9 @@ Rust lexer used by rustc. No stability guarantees are provided. # Note that this crate purposefully does not depend on other rustc crates [dependencies] -memchr = "2.7.4" +memchr.workspace = true +unicode-properties = { version = "0.1.0", default-features = false, features = ["emoji"] } unicode-xid = "0.2.0" -[dependencies.unicode-properties] -version = "0.1.0" -default-features = false -features = ["emoji"] - [dev-dependencies] expect-test = "1.4.0" diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 7718f16984d..7900e4b9ab2 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -24,6 +24,6 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" +tracing.workspace = true unicode-security = "0.1.0" # tidy-alphabetical-end diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 426500dda4a..56d65ed08f9 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1554,7 +1554,7 @@ impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> { #[help(lint_help_exposed_provenance)] pub(crate) struct IntegerToPtrTransmutes<'tcx> { #[subdiagnostic] - pub suggestion: IntegerToPtrTransmutesSuggestion<'tcx>, + pub suggestion: Option<IntegerToPtrTransmutesSuggestion<'tcx>>, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs index 239c8649041..98510eea73b 100644 --- a/compiler/rustc_lint/src/transmute.rs +++ b/compiler/rustc_lint/src/transmute.rs @@ -169,19 +169,25 @@ fn check_int_to_ptr_transmute<'tcx>( expr.hir_id, expr.span, IntegerToPtrTransmutes { - suggestion: if dst.is_ref() { - IntegerToPtrTransmutesSuggestion::ToRef { - dst: *inner_ty, - suffix, - ref_mutbl: mutbl.prefix_str(), - start_call: expr.span.shrink_to_lo().until(arg.span), - } + suggestion: if layout_inner_ty.is_sized() { + Some(if dst.is_ref() { + IntegerToPtrTransmutesSuggestion::ToRef { + dst: *inner_ty, + suffix, + ref_mutbl: mutbl.prefix_str(), + start_call: expr.span.shrink_to_lo().until(arg.span), + } + } else { + IntegerToPtrTransmutesSuggestion::ToPtr { + dst: *inner_ty, + suffix, + start_call: expr.span.shrink_to_lo().until(arg.span), + } + }) } else { - IntegerToPtrTransmutesSuggestion::ToPtr { - dst: *inner_ty, - suffix, - start_call: expr.span.shrink_to_lo().until(arg.span), - } + // We can't suggest using `with_exposed_provenance` for unsized type + // so don't suggest anything. + None }, }, ); diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index cd352ce3d0f..e74de453be2 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -libc = "0.2.73" +libc.workspace = true # tidy-alphabetical-end [build-dependencies] diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 8c34052770e..dd492325814 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1226,12 +1226,6 @@ extern "C" void LLVMRustPrintPasses() { extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, size_t Len) { auto PreserveFunctions = [=](const GlobalValue &GV) { - // Preserve LLVM-injected, ASAN-related symbols. - // See also https://github.com/rust-lang/rust/issues/113404. - if (GV.getName() == "___asan_globals_registered") { - return true; - } - // Preserve symbols exported from Rust modules. for (size_t I = 0; I < Len; I++) { if (GV.getName() == Symbols[I]) { diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index cce40da354d..361a5f76551 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -242,7 +242,7 @@ enum class LLVMRustAttributeKind { MinSize = 4, Naked = 5, NoAlias = 6, - NoCapture = 7, + CapturesAddress = 7, NoInline = 8, NonNull = 9, NoRedZone = 10, @@ -297,12 +297,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { return Attribute::Naked; case LLVMRustAttributeKind::NoAlias: return Attribute::NoAlias; - case LLVMRustAttributeKind::NoCapture: -#if LLVM_VERSION_GE(21, 0) - report_fatal_error("NoCapture doesn't exist in LLVM 21"); -#else - return Attribute::NoCapture; -#endif case LLVMRustAttributeKind::NoCfCheck: return Attribute::NoCfCheck; case LLVMRustAttributeKind::NoInline: @@ -377,6 +371,7 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { #else report_fatal_error("DeadOnReturn attribute requires LLVM 21 or later"); #endif + case LLVMRustAttributeKind::CapturesAddress: case LLVMRustAttributeKind::CapturesReadOnly: report_fatal_error("Should be handled separately"); } @@ -429,9 +424,9 @@ extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) { extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) { #if LLVM_VERSION_GE(21, 0) - // LLVM 21 replaced the NoCapture attribute with Captures(none). - if (RustAttr == LLVMRustAttributeKind::NoCapture) { - return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none())); + if (RustAttr == LLVMRustAttributeKind::CapturesAddress) { + return wrap(Attribute::getWithCaptureInfo( + *unwrap(C), CaptureInfo(CaptureComponents::Address))); } if (RustAttr == LLVMRustAttributeKind::CapturesReadOnly) { return wrap(Attribute::getWithCaptureInfo( diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index c673d51a1d4..e9d7b4723f8 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -5,10 +5,10 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -tracing = "0.1.28" tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } tracing-tree = "0.3.1" +tracing.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index f9d3b758359..5add2691b88 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -8,8 +8,8 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -proc-macro2 = "1" -quote = "1" +proc-macro2.workspace = true +quote.workspace = true syn = { version = "2.0.9", features = ["full"] } synstructure = "0.13.0" # tidy-alphabetical-end diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 1b40d9f684e..a8f3dd18353 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" +bitflags.workspace = true libloading = "0.8.0" -odht = { version = "0.3.1", features = ["nightly"] } +odht.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } @@ -30,11 +30,11 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -tempfile = "3.7.1" -tracing = "0.1" +tempfile.workspace = true +tracing.workspace = true # tidy-alphabetical-end [target.'cfg(target_os = "aix")'.dependencies] # tidy-alphabetical-start -libc = "0.2" +libc.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 4d3e879a098..e104be2c466 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -1,6 +1,3 @@ -metadata_as_needed_compatibility = - linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds - metadata_async_drop_types_in_dependency = found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}` .help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used @@ -11,9 +8,6 @@ metadata_bad_panic_strategy = metadata_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty -metadata_bundle_needs_static = - linking modifier `bundle` is only compatible with `static` linking kind - metadata_cannot_find_crate = can't find crate for `{$crate_name}`{$add_info} @@ -60,10 +54,6 @@ metadata_crate_not_panic_runtime = metadata_dl_error = {$path}{$err} -metadata_empty_link_name = - link name must not be empty - .label = empty link name - metadata_empty_renaming_target = an empty renaming target was specified for library `{$lib_name}` @@ -108,15 +98,6 @@ metadata_full_metadata_not_found = metadata_global_alloc_required = no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait -metadata_import_name_type_form = - import name type must be of the form `import_name_type = "string"` - -metadata_import_name_type_raw = - import name type can only be used with link kind `raw-dylib` - -metadata_import_name_type_x86 = - import name type is only supported on x86 - metadata_incompatible_panic_in_drop_strategy = the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` @@ -143,15 +124,10 @@ metadata_incompatible_target_modifiers_r_missed = mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}` .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely -metadata_incompatible_wasm_link = - `wasm_import_module` is incompatible with other arguments in `#[link]` attributes metadata_install_missing_components = maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview` -metadata_invalid_link_modifier = - invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed - metadata_invalid_meta_files = found invalid metadata files for crate `{$crate_name}`{$add_info} @@ -164,67 +140,18 @@ metadata_lib_framework_apple = metadata_lib_required = crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form -metadata_link_arg_unstable = - link kind `link-arg` is unstable - -metadata_link_cfg_form = - link cfg must be of the form `cfg(/* predicate */)` - -metadata_link_cfg_single_predicate = - link cfg must have a single predicate argument - -metadata_link_cfg_unstable = - link cfg is unstable - -metadata_link_framework_apple = - link kind `framework` is only supported on Apple targets - -metadata_link_kind_form = - link kind must be of the form `kind = "string"` - -metadata_link_modifiers_form = - link modifiers must be of the form `modifiers = "string"` - -metadata_link_name_form = - link name must be of the form `name = "string"` - metadata_link_ordinal_raw_dylib = `#[link_ordinal]` is only supported if link kind is `raw-dylib` -metadata_link_requires_name = - `#[link]` attribute requires a `name = "string"` argument - .label = missing `name` argument - metadata_missing_native_library = could not find native static library `{$libname}`, perhaps an -L flag is missing? metadata_multiple_candidates = multiple candidates for `{$flavor}` dependency `{$crate_name}` found -metadata_multiple_cfgs = - multiple `cfg` arguments in a single `#[link]` attribute - -metadata_multiple_import_name_type = - multiple `import_name_type` arguments in a single `#[link]` attribute - -metadata_multiple_kinds_in_link = - multiple `kind` arguments in a single `#[link]` attribute - -metadata_multiple_link_modifiers = - multiple `modifiers` arguments in a single `#[link]` attribute - -metadata_multiple_modifiers = - multiple `{$modifier}` modifiers in a single `modifiers` argument - -metadata_multiple_names_in_link = - multiple `name` arguments in a single `#[link]` attribute - metadata_multiple_renamings = multiple renamings were specified for library `{$lib_name}` -metadata_multiple_wasm_import = - multiple `wasm_import_module` arguments in a single `#[link]` attribute - metadata_newer_crate_version = found possibly newer version of crate `{$crate_name}`{$add_info} .note = perhaps that crate needs to be recompiled? @@ -263,15 +190,6 @@ metadata_prev_alloc_error_handler = metadata_prev_global_alloc = previous global allocator defined here -metadata_raw_dylib_elf_unstable = - link kind `raw-dylib` is unstable on ELF platforms - -metadata_raw_dylib_no_nul = - link name must not contain NUL characters if link kind is `raw-dylib` - -metadata_raw_dylib_only_windows = - link kind `raw-dylib` is only supported on Windows targets - metadata_raw_dylib_unsupported_abi = ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture @@ -307,19 +225,6 @@ metadata_target_not_installed = metadata_two_panic_runtimes = cannot link together two panic runtimes: {$prev_name} and {$cur_name} -metadata_unexpected_link_arg = - unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type - -metadata_unknown_import_name_type = - unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated - -metadata_unknown_link_kind = - unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib, link-arg - .label = unknown link kind - -metadata_unknown_link_modifier = - unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed - metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}` metadata_wasm_c_abi = diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 0332dba1077..e5a4fd48353 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -84,187 +84,6 @@ pub struct IncompatiblePanicInDropStrategy { } #[derive(Diagnostic)] -#[diag(metadata_multiple_names_in_link)] -pub struct MultipleNamesInLink { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_multiple_kinds_in_link)] -pub struct MultipleKindsInLink { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_link_name_form)] -pub struct LinkNameForm { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_link_kind_form)] -pub struct LinkKindForm { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_link_modifiers_form)] -pub struct LinkModifiersForm { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_link_cfg_form)] -pub struct LinkCfgForm { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_wasm_import_form)] -pub struct WasmImportForm { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_empty_link_name, code = E0454)] -pub struct EmptyLinkName { - #[primary_span] - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_link_framework_apple, code = E0455)] -pub struct LinkFrameworkApple { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_raw_dylib_only_windows, code = E0455)] -pub struct RawDylibOnlyWindows { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_unknown_link_kind, code = E0458)] -pub struct UnknownLinkKind<'a> { - #[primary_span] - #[label] - pub span: Span, - pub kind: &'a str, -} - -#[derive(Diagnostic)] -#[diag(metadata_multiple_link_modifiers)] -pub struct MultipleLinkModifiers { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_multiple_cfgs)] -pub struct MultipleCfgs { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_link_cfg_single_predicate)] -pub struct LinkCfgSinglePredicate { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_multiple_wasm_import)] -pub struct MultipleWasmImport { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_unexpected_link_arg)] -pub struct UnexpectedLinkArg { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_invalid_link_modifier)] -pub struct InvalidLinkModifier { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_multiple_modifiers)] -pub struct MultipleModifiers<'a> { - #[primary_span] - pub span: Span, - pub modifier: &'a str, -} - -#[derive(Diagnostic)] -#[diag(metadata_bundle_needs_static)] -pub struct BundleNeedsStatic { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_whole_archive_needs_static)] -pub struct WholeArchiveNeedsStatic { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_as_needed_compatibility)] -pub struct AsNeededCompatibility { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_unknown_link_modifier)] -pub struct UnknownLinkModifier<'a> { - #[primary_span] - pub span: Span, - pub modifier: &'a str, -} - -#[derive(Diagnostic)] -#[diag(metadata_incompatible_wasm_link)] -pub struct IncompatibleWasmLink { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_link_requires_name, code = E0459)] -pub struct LinkRequiresName { - #[primary_span] - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_raw_dylib_no_nul)] -pub struct RawDylibNoNul { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(metadata_link_ordinal_raw_dylib)] pub struct LinkOrdinalRawDylib { #[primary_span] @@ -707,42 +526,6 @@ pub struct LibFilenameForm<'a> { } #[derive(Diagnostic)] -#[diag(metadata_multiple_import_name_type)] -pub struct MultipleImportNameType { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_import_name_type_form)] -pub struct ImportNameTypeForm { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_import_name_type_x86)] -pub struct ImportNameTypeX86 { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(metadata_unknown_import_name_type)] -pub struct UnknownImportNameType<'a> { - #[primary_span] - pub span: Span, - pub import_name_type: &'a str, -} - -#[derive(Diagnostic)] -#[diag(metadata_import_name_type_raw)] -pub struct ImportNameTypeRaw { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(metadata_wasm_c_abi)] pub(crate) struct WasmCAbi { #[primary_span] diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 63f1b51df1c..82738c68c59 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -3,25 +3,21 @@ use std::path::{Path, PathBuf}; use rustc_abi::ExternAbi; use rustc_ast::CRATE_NODE_ID; -use rustc_attr_parsing as attr; +use rustc_attr_parsing::{ShouldEmit, eval_config_entry}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::attrs::{AttributeKind, NativeLibKind, PeImportNameType}; use rustc_hir::find_attr; use rustc_middle::query::LocalCrate; use rustc_middle::ty::{self, List, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::config::CrateType; -use rustc_session::cstore::{ - DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType, -}; -use rustc_session::parse::feature_err; +use rustc_session::cstore::{DllCallingConvention, DllImport, ForeignModule, NativeLib}; use rustc_session::search_paths::PathKind; -use rustc_session::utils::NativeLibKind; +use rustc_span::Symbol; use rustc_span::def_id::{DefId, LOCAL_CRATE}; -use rustc_span::{Symbol, sym}; use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents}; -use crate::{errors, fluent_generated}; +use crate::errors; /// The fallback directories are passed to linker, but not used when rustc does the search, /// because in the latter case the set of fallback directories cannot always be determined @@ -192,7 +188,9 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib> pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { match lib.cfg { - Some(ref cfg) => attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None), + Some(ref cfg) => { + eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool() + } None => true, } } @@ -213,289 +211,23 @@ impl<'tcx> Collector<'tcx> { return; } - // Process all of the #[link(..)]-style arguments - let features = self.tcx.features(); - - for m in self.tcx.get_attrs(def_id, sym::link) { - let Some(items) = m.meta_item_list() else { - continue; - }; - - let mut name = None; - let mut kind = None; - let mut modifiers = None; - let mut cfg = None; - let mut wasm_import_module = None; - let mut import_name_type = None; - for item in items.iter() { - match item.name() { - Some(sym::name) => { - if name.is_some() { - sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() }); - continue; - } - let Some(link_name) = item.value_str() else { - sess.dcx().emit_err(errors::LinkNameForm { span: item.span() }); - continue; - }; - let span = item.name_value_literal_span().unwrap(); - if link_name.is_empty() { - sess.dcx().emit_err(errors::EmptyLinkName { span }); - } - name = Some((link_name, span)); - } - Some(sym::kind) => { - if kind.is_some() { - sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() }); - continue; - } - let Some(link_kind) = item.value_str() else { - sess.dcx().emit_err(errors::LinkKindForm { span: item.span() }); - continue; - }; - - let span = item.name_value_literal_span().unwrap(); - let link_kind = match link_kind.as_str() { - "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, - "dylib" => NativeLibKind::Dylib { as_needed: None }, - "framework" => { - if !sess.target.is_like_darwin { - sess.dcx().emit_err(errors::LinkFrameworkApple { span }); - } - NativeLibKind::Framework { as_needed: None } - } - "raw-dylib" => { - if sess.target.is_like_windows { - // raw-dylib is stable and working on Windows - } else if sess.target.binary_format == BinaryFormat::Elf - && features.raw_dylib_elf() - { - // raw-dylib is unstable on ELF, but the user opted in - } else if sess.target.binary_format == BinaryFormat::Elf - && sess.is_nightly_build() - { - feature_err( - sess, - sym::raw_dylib_elf, - span, - fluent_generated::metadata_raw_dylib_elf_unstable, - ) - .emit(); - } else { - sess.dcx().emit_err(errors::RawDylibOnlyWindows { span }); - } - - NativeLibKind::RawDylib - } - "link-arg" => { - if !features.link_arg_attribute() { - feature_err( - sess, - sym::link_arg_attribute, - span, - fluent_generated::metadata_link_arg_unstable, - ) - .emit(); - } - NativeLibKind::LinkArg - } - kind => { - sess.dcx().emit_err(errors::UnknownLinkKind { span, kind }); - continue; - } - }; - kind = Some(link_kind); - } - Some(sym::modifiers) => { - if modifiers.is_some() { - sess.dcx() - .emit_err(errors::MultipleLinkModifiers { span: item.span() }); - continue; - } - let Some(link_modifiers) = item.value_str() else { - sess.dcx().emit_err(errors::LinkModifiersForm { span: item.span() }); - continue; - }; - modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap())); - } - Some(sym::cfg) => { - if cfg.is_some() { - sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() }); - continue; - } - let Some(link_cfg) = item.meta_item_list() else { - sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() }); - continue; - }; - let [link_cfg] = link_cfg else { - sess.dcx() - .emit_err(errors::LinkCfgSinglePredicate { span: item.span() }); - continue; - }; - let Some(link_cfg) = link_cfg.meta_item_or_bool() else { - sess.dcx() - .emit_err(errors::LinkCfgSinglePredicate { span: item.span() }); - continue; - }; - if !features.link_cfg() { - feature_err( - sess, - sym::link_cfg, - item.span(), - fluent_generated::metadata_link_cfg_unstable, - ) - .emit(); - } - cfg = Some(link_cfg.clone()); - } - Some(sym::wasm_import_module) => { - if wasm_import_module.is_some() { - sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() }); - continue; - } - let Some(link_wasm_import_module) = item.value_str() else { - sess.dcx().emit_err(errors::WasmImportForm { span: item.span() }); - continue; - }; - wasm_import_module = Some((link_wasm_import_module, item.span())); - } - Some(sym::import_name_type) => { - if import_name_type.is_some() { - sess.dcx() - .emit_err(errors::MultipleImportNameType { span: item.span() }); - continue; - } - let Some(link_import_name_type) = item.value_str() else { - sess.dcx().emit_err(errors::ImportNameTypeForm { span: item.span() }); - continue; - }; - if self.tcx.sess.target.arch != "x86" { - sess.dcx().emit_err(errors::ImportNameTypeX86 { span: item.span() }); - continue; - } - - let link_import_name_type = match link_import_name_type.as_str() { - "decorated" => PeImportNameType::Decorated, - "noprefix" => PeImportNameType::NoPrefix, - "undecorated" => PeImportNameType::Undecorated, - import_name_type => { - sess.dcx().emit_err(errors::UnknownImportNameType { - span: item.span(), - import_name_type, - }); - continue; - } - }; - import_name_type = Some((link_import_name_type, item.span())); - } - _ => { - sess.dcx().emit_err(errors::UnexpectedLinkArg { span: item.span() }); - } - } - } - - // Do this outside the above loop so we don't depend on modifiers coming after kinds - let mut verbatim = None; - if let Some((modifiers, span)) = modifiers { - for modifier in modifiers.as_str().split(',') { - let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { - Some(m) => (m, modifier.starts_with('+')), - None => { - sess.dcx().emit_err(errors::InvalidLinkModifier { span }); - continue; - } - }; - - macro report_unstable_modifier($feature: ident) { - if !features.$feature() { - // FIXME: make this translatable - #[expect(rustc::untranslatable_diagnostic)] - feature_err( - sess, - sym::$feature, - span, - format!("linking modifier `{modifier}` is unstable"), - ) - .emit(); - } - } - let assign_modifier = |dst: &mut Option<bool>| { - if dst.is_some() { - sess.dcx().emit_err(errors::MultipleModifiers { span, modifier }); - } else { - *dst = Some(value); - } - }; - match (modifier, &mut kind) { - ("bundle", Some(NativeLibKind::Static { bundle, .. })) => { - assign_modifier(bundle) - } - ("bundle", _) => { - sess.dcx().emit_err(errors::BundleNeedsStatic { span }); - } - - ("verbatim", _) => assign_modifier(&mut verbatim), - - ("whole-archive", Some(NativeLibKind::Static { whole_archive, .. })) => { - assign_modifier(whole_archive) - } - ("whole-archive", _) => { - sess.dcx().emit_err(errors::WholeArchiveNeedsStatic { span }); - } - - ("as-needed", Some(NativeLibKind::Dylib { as_needed })) - | ("as-needed", Some(NativeLibKind::Framework { as_needed })) => { - report_unstable_modifier!(native_link_modifiers_as_needed); - assign_modifier(as_needed) - } - ("as-needed", _) => { - sess.dcx().emit_err(errors::AsNeededCompatibility { span }); - } - - _ => { - sess.dcx().emit_err(errors::UnknownLinkModifier { span, modifier }); - } - } - } - } - - if let Some((_, span)) = wasm_import_module { - if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { - sess.dcx().emit_err(errors::IncompatibleWasmLink { span }); - } - } - - if wasm_import_module.is_some() { - (name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule)); - } - let Some((name, name_span)) = name else { - sess.dcx().emit_err(errors::LinkRequiresName { span: m.span() }); - continue; - }; - - // Do this outside of the loop so that `import_name_type` can be specified before `kind`. - if let Some((_, span)) = import_name_type { - if kind != Some(NativeLibKind::RawDylib) { - sess.dcx().emit_err(errors::ImportNameTypeRaw { span }); - } - } - - let dll_imports = match kind { - Some(NativeLibKind::RawDylib) => { - if name.as_str().contains('\0') { - sess.dcx().emit_err(errors::RawDylibNoNul { span: name_span }); - } - foreign_items - .iter() - .map(|&child_item| { - self.build_dll_import( - abi, - import_name_type.map(|(import_name_type, _)| import_name_type), - child_item, - ) - }) - .collect() - } + for attr in + find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::Link(links, _) => links) + .iter() + .map(|v| v.iter()) + .flatten() + { + let dll_imports = match attr.kind { + NativeLibKind::RawDylib => foreign_items + .iter() + .map(|&child_item| { + self.build_dll_import( + abi, + attr.import_name_type.map(|(import_name_type, _)| import_name_type), + child_item, + ) + }) + .collect(), _ => { for &child_item in foreign_items { if let Some(span) = find_attr!(self.tcx.get_all_attrs(child_item), AttributeKind::LinkOrdinal {span, ..} => *span) @@ -508,15 +240,20 @@ impl<'tcx> Collector<'tcx> { } }; - let kind = kind.unwrap_or(NativeLibKind::Unspecified); - let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx); + let filename = find_bundled_library( + attr.name, + attr.verbatim, + attr.kind, + attr.cfg.is_some(), + self.tcx, + ); self.libs.push(NativeLib { - name, + name: attr.name, filename, - kind, - cfg, + kind: attr.kind, + cfg: attr.cfg.clone(), foreign_module: Some(def_id.to_def_id()), - verbatim, + verbatim: attr.verbatim, dll_imports, }); } diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index fbcce16cedc..f0832405567 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -5,12 +5,12 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" -either = "1.5.0" +bitflags.workspace = true +either.workspace = true gsgdt = "0.1.2" -polonius-engine = "0.13.0" +polonius-engine.workspace = true rustc_abi = { path = "../rustc_abi" } -rustc_apfloat = "0.2.0" +rustc_apfloat.workspace = true rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } @@ -34,8 +34,8 @@ rustc_target = { path = "../rustc_target" } rustc_thread_pool = { path = "../rustc_thread_pool" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index cf0549fa668..5023b2740ef 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -29,6 +29,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::direct_use_of_rustc_type_ir)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(allocator_api)] @@ -51,7 +52,6 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(ptr_alignment_type)] -#![feature(round_char_boundary)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(sized_hierarchy)] diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index a8a95c699d8..466b9c7a3c2 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -149,8 +149,15 @@ pub enum ConstraintCategory<'tcx> { /// A constraint that doesn't correspond to anything the user sees. Internal, - /// An internal constraint derived from an illegal universe relation. - IllegalUniverse, + /// An internal constraint added when a region outlives a placeholder + /// it cannot name and therefore has to outlive `'static`. The argument + /// is the unnameable placeholder and the constraint is always between + /// an SCC representative and `'static`. + OutlivesUnnameablePlaceholder( + #[type_foldable(identity)] + #[type_visitable(ignore)] + ty::RegionVid, + ), } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index f756f0a19ee..440cb0bdbf3 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools = "0.12" +itertools.workspace = true rustc_abi = { path = "../rustc_abi" } -rustc_apfloat = "0.2.0" +rustc_apfloat.workspace = true rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -23,5 +23,5 @@ rustc_pattern_analysis = { path = "../rustc_pattern_analysis" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 9621f9f20bd..11713bb77f1 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -polonius-engine = "0.13.0" +polonius-engine.workspace = true regex = "1" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } @@ -18,5 +18,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 08c43a4648c..99ef67e2625 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -5,8 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -either = "1" -itertools = "0.12" +either.workspace = true +itertools.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } @@ -26,5 +26,5 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 09a55f0b5f8..78266d3c6d8 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -16,6 +16,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } serde = "1" -serde_json = "1" -tracing = "0.1" +serde_json.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index 05bcabad02f..43db90c08f3 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -5,13 +5,13 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -derive-where = "1.2.7" +derive-where.workspace = true rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_index = { path = "../rustc_index", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } rustc_type_ir = { path = "../rustc_type_ir", default-features = false } rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index 6d738a10371..7cb4ae7ff5f 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -5,8 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" -rustc-literal-escaper = "0.0.5" +bitflags.workspace = true +rustc-literal-escaper.workspace = true rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -18,8 +18,8 @@ rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true unicode-normalization = "0.1.11" unicode-width = "0.2.0" # tidy-alphabetical-end diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f0f58e901a9..7de4f6efd0b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2077,7 +2077,7 @@ impl<'a> Parser<'a> { (token::Lit { symbol: name, suffix: None, kind: token::Char }, span) } - pub fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit { + fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit { ast::MetaItemLit { symbol: name, suffix: None, @@ -2086,7 +2086,7 @@ impl<'a> Parser<'a> { } } - pub fn handle_missing_lit<L>( + fn handle_missing_lit<L>( &mut self, mk_lit_char: impl FnOnce(Symbol, Span) -> L, ) -> PResult<'a, L> { diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index d178fcda1fb..645e34b6e32 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -rustc-literal-escaper = "0.0.5" +rustc-literal-escaper.workspace = true rustc_lexer = { path = "../rustc_lexer" } # tidy-alphabetical-end diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index ba81ef3103b..c74608a6146 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -24,5 +24,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 3be06a3704c..498d9a405fa 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -145,6 +145,10 @@ passes_doc_alias_start_end = passes_doc_attr_not_crate_level = `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute +passes_doc_attribute_not_attribute = + nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]` + .help = only existing builtin attributes are allowed in core/std + passes_doc_cfg_hide_takes_list = `#[doc(cfg_hide(...))]` takes a list of attributes @@ -173,16 +177,16 @@ passes_doc_inline_only_use = passes_doc_invalid = invalid `doc` attribute -passes_doc_keyword_empty_mod = - `#[doc(keyword = "...")]` should be used on empty modules +passes_doc_keyword_attribute_empty_mod = + `#[doc({$attr_name} = "...")]` should be used on empty modules + +passes_doc_keyword_attribute_not_mod = + `#[doc({$attr_name} = "...")]` should be used on modules passes_doc_keyword_not_keyword = nonexistent keyword `{$keyword}` used in `#[doc(keyword = "...")]` .help = only existing keywords are allowed in core/std -passes_doc_keyword_not_mod = - `#[doc(keyword = "...")]` should be used on modules - passes_doc_keyword_only_impl = `#[doc(keyword = "...")]` should be used on impl blocks diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3a79176f914..2cd4830b5d9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -99,6 +99,21 @@ impl IntoDiagArg for ProcMacroKind { } } +#[derive(Clone, Copy)] +enum DocFakeItemKind { + Attribute, + Keyword, +} + +impl DocFakeItemKind { + fn name(self) -> &'static str { + match self { + Self::Attribute => "attribute", + Self::Keyword => "keyword", + } + } +} + struct CheckAttrVisitor<'tcx> { tcx: TyCtxt<'tcx>, @@ -200,6 +215,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, span: attr_span}) => { self.check_sanitize(attr_span, on_set | off_set, span, target); }, + Attribute::Parsed(AttributeKind::Link(_, attr_span)) => { + self.check_link(hir_id, *attr_span, span, target) + } Attribute::Parsed( AttributeKind::BodyStability { .. } | AttributeKind::ConstStabilityIndirect @@ -305,7 +323,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::rustc_has_incoherent_inherent_impls, ..] => { self.check_has_incoherent_inherent_impls(attr, span, target) } - [sym::link, ..] => self.check_link(hir_id, attr, span, target), [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target), [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) @@ -851,7 +868,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_doc_keyword(&self, meta: &MetaItemInner, hir_id: HirId) { + fn check_doc_keyword_and_attribute( + &self, + meta: &MetaItemInner, + hir_id: HirId, + attr_kind: DocFakeItemKind, + ) { fn is_doc_keyword(s: Symbol) -> bool { // FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we // can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the @@ -859,9 +881,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { s.is_reserved(|| edition::LATEST_STABLE_EDITION) || s.is_weak() || s == sym::SelfTy } - let doc_keyword = match meta.value_str() { + // FIXME: This should support attributes with namespace like `diagnostic::do_not_recommend`. + fn is_builtin_attr(s: Symbol) -> bool { + rustc_feature::BUILTIN_ATTRIBUTE_MAP.contains_key(&s) + } + + let value = match meta.value_str() { Some(value) if value != sym::empty => value, - _ => return self.doc_attr_str_error(meta, "keyword"), + _ => return self.doc_attr_str_error(meta, attr_kind.name()), }; let item_kind = match self.tcx.hir_node(hir_id) { @@ -871,20 +898,38 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match item_kind { Some(ItemKind::Mod(_, module)) => { if !module.item_ids.is_empty() { - self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() }); + self.dcx().emit_err(errors::DocKeywordAttributeEmptyMod { + span: meta.span(), + attr_name: attr_kind.name(), + }); return; } } _ => { - self.dcx().emit_err(errors::DocKeywordNotMod { span: meta.span() }); + self.dcx().emit_err(errors::DocKeywordAttributeNotMod { + span: meta.span(), + attr_name: attr_kind.name(), + }); return; } } - if !is_doc_keyword(doc_keyword) { - self.dcx().emit_err(errors::DocKeywordNotKeyword { - span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()), - keyword: doc_keyword, - }); + match attr_kind { + DocFakeItemKind::Keyword => { + if !is_doc_keyword(value) { + self.dcx().emit_err(errors::DocKeywordNotKeyword { + span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()), + keyword: value, + }); + } + } + DocFakeItemKind::Attribute => { + if !is_builtin_attr(value) { + self.dcx().emit_err(errors::DocAttributeNotAttribute { + span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()), + attribute: value, + }); + } + } } } @@ -1144,7 +1189,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Some(sym::keyword) => { if self.check_attr_not_crate_level(meta, hir_id, "keyword") { - self.check_doc_keyword(meta, hir_id); + self.check_doc_keyword_and_attribute( + meta, + hir_id, + DocFakeItemKind::Keyword, + ); + } + } + + Some(sym::attribute) => { + if self.check_attr_not_crate_level(meta, hir_id, "attribute") { + self.check_doc_keyword_and_attribute( + meta, + hir_id, + DocFakeItemKind::Attribute, + ); } } @@ -1324,7 +1383,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[link]` is applied to an item other than a foreign module. - fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + fn check_link(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { if target == Target::ForeignMod && let hir::Node::Item(item) = self.tcx.hir_node(hir_id) && let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item @@ -1336,7 +1395,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, - attr.span(), + attr_span, errors::Link { span: (target != Target::ForeignMod).then_some(span) }, ); } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 01972067978..680e2a26d84 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -195,10 +195,11 @@ pub(crate) struct DocAliasMalformed { } #[derive(Diagnostic)] -#[diag(passes_doc_keyword_empty_mod)] -pub(crate) struct DocKeywordEmptyMod { +#[diag(passes_doc_keyword_attribute_empty_mod)] +pub(crate) struct DocKeywordAttributeEmptyMod { #[primary_span] pub span: Span, + pub attr_name: &'static str, } #[derive(Diagnostic)] @@ -211,10 +212,20 @@ pub(crate) struct DocKeywordNotKeyword { } #[derive(Diagnostic)] -#[diag(passes_doc_keyword_not_mod)] -pub(crate) struct DocKeywordNotMod { +#[diag(passes_doc_attribute_not_attribute)] +#[help] +pub(crate) struct DocAttributeNotAttribute { + #[primary_span] + pub span: Span, + pub attribute: Symbol, +} + +#[derive(Diagnostic)] +#[diag(passes_doc_keyword_attribute_not_mod)] +pub(crate) struct DocKeywordAttributeNotMod { #[primary_span] pub span: Span, + pub attr_name: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index a59f7bbeb9e..e4909ab6d16 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -rustc-hash = "2.0.0" +rustc-hash.workspace = true rustc_abi = { path = "../rustc_abi", optional = true } -rustc_apfloat = "0.2.0" +rustc_apfloat.workspace = true rustc_arena = { path = "../rustc_arena", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_errors = { path = "../rustc_errors", optional = true } @@ -19,7 +19,7 @@ rustc_middle = { path = "../rustc_middle", optional = true } rustc_session = { path = "../rustc_session", optional = true } rustc_span = { path = "../rustc_span", optional = true } smallvec = { version = "1.8.1", features = ["union"] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [dev-dependencies] diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index c8bfdb91304..7de58132e13 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -15,5 +15,5 @@ rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_ty_utils = { path = "../rustc_ty_utils" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_proc_macro/Cargo.toml b/compiler/rustc_proc_macro/Cargo.toml index beb95aa3b52..99e7fc7abc6 100644 --- a/compiler/rustc_proc_macro/Cargo.toml +++ b/compiler/rustc_proc_macro/Cargo.toml @@ -16,7 +16,7 @@ doctest = false [dependencies] # tidy-alphabetical-start -rustc-literal-escaper = "0.0.5" +rustc-literal-escaper.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_public/Cargo.toml b/compiler/rustc_public/Cargo.toml index 70af30c1a5f..e67e4fe6739 100644 --- a/compiler/rustc_public/Cargo.toml +++ b/compiler/rustc_public/Cargo.toml @@ -12,9 +12,9 @@ rustc_public_bridge = { path = "../rustc_public_bridge" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -scoped-tls = "1.0" +scoped-tls.workspace = true serde = { version = "1.0.125", features = [ "derive" ] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index e5cceacf15d..3d5cf0eb72d 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -measureme = "12.0.1" +measureme.workspace = true rustc_data_structures = { path = "../rustc_data_structures" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } @@ -15,5 +15,5 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 7480ba03474..0df933bc81c 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -21,7 +21,7 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_thread_pool = { path = "../rustc_thread_pool" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [dependencies.hashbrown] diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index eb98a6e85c0..4da4c0840df 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" -indexmap = "2.4.0" -itertools = "0.12" +bitflags.workspace = true +indexmap.workspace = true +itertools.workspace = true pulldown-cmark = { version = "0.11", features = ["html"], default-features = false } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } @@ -27,6 +27,6 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 679e663f886..d4f7fb276a9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5016,7 +5016,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ResolveDocLinks::Exported if !maybe_exported.eval(self.r) - && !rustdoc::has_primitive_or_keyword_docs(attrs) => + && !rustdoc::has_primitive_or_keyword_or_attribute_docs(attrs) => { return; } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 6450f63472c..804792c6f28 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -207,8 +207,10 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( attrs: impl Iterator<Item = (&'a A, Option<DefId>)>, doc_only: bool, ) -> (Vec<DocFragment>, ThinVec<A>) { - let mut doc_fragments = Vec::new(); - let mut other_attrs = ThinVec::<A>::new(); + let (min_size, max_size) = attrs.size_hint(); + let size_hint = max_size.unwrap_or(min_size); + let mut doc_fragments = Vec::with_capacity(size_hint); + let mut other_attrs = ThinVec::<A>::with_capacity(if doc_only { 0 } else { size_hint }); for (attr, item_id) in attrs { if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() { let doc = beautify_doc_string(doc_str, comment_kind); @@ -230,6 +232,9 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( } } + doc_fragments.shrink_to_fit(); + other_attrs.shrink_to_fit(); + unindent_doc_fragments(&mut doc_fragments); (doc_fragments, other_attrs) @@ -368,8 +373,8 @@ pub fn inner_docs(attrs: &[impl AttributeExt]) -> bool { true } -/// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]`. -pub fn has_primitive_or_keyword_docs(attrs: &[impl AttributeExt]) -> bool { +/// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]` or `#[doc(attribute)]`. +pub fn has_primitive_or_keyword_or_attribute_docs(attrs: &[impl AttributeExt]) -> bool { for attr in attrs { if attr.has_name(sym::rustc_doc_primitive) { return true; @@ -377,7 +382,7 @@ pub fn has_primitive_or_keyword_docs(attrs: &[impl AttributeExt]) -> bool { && let Some(items) = attr.meta_item_list() { for item in items { - if item.has_name(sym::keyword) { + if item.has_name(sym::keyword) || item.has_name(sym::attribute) { return true; } } diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml index 9069d2c233d..3dbeaa435f3 100644 --- a/compiler/rustc_sanitizers/Cargo.toml +++ b/compiler/rustc_sanitizers/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.5.0" +bitflags.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } @@ -13,6 +13,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing = "0.1" +tracing.workspace = true twox-hash = "1.6.3" # tidy-alphabetical-end diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml index 948242352e7..853f87ebed9 100644 --- a/compiler/rustc_serialize/Cargo.toml +++ b/compiler/rustc_serialize/Cargo.toml @@ -5,14 +5,14 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -indexmap = "2.0.0" +indexmap.workspace = true rustc_hashes = { path = "../rustc_hashes" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" +thin-vec.workspace = true # tidy-alphabetical-end [dev-dependencies] # tidy-alphabetical-start rustc_macros = { path = "../rustc_macros" } -tempfile = "3.2" +tempfile.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 60d56b1b808..5870fb29ae8 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" +bitflags.workspace = true getopts = "0.2" rand = "0.9.0" rustc_abi = { path = "../rustc_abi" } @@ -23,14 +23,12 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } termize = "0.2" -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] -# FIXME: Remove this pin once this rustix issue is resolved -# https://github.com/bytecodealliance/rustix/issues/1496 # tidy-alphabetical-start -libc = "=0.2.174" +libc.workspace = true # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs index f1f0aeb5e59..50a0593f887 100644 --- a/compiler/rustc_session/src/config/native_libs.rs +++ b/compiler/rustc_session/src/config/native_libs.rs @@ -5,10 +5,11 @@ //! which have their own parser in `rustc_metadata`.) use rustc_feature::UnstableFeatures; +use rustc_hir::attrs::NativeLibKind; use crate::EarlyDiagCtxt; use crate::config::UnstableOptions; -use crate::utils::{NativeLib, NativeLibKind}; +use crate::utils::NativeLib; #[cfg(test)] mod tests; diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 4cfc745dec2..30f6256a75e 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -6,8 +6,8 @@ use std::any::Any; use std::path::PathBuf; use rustc_abi::ExternAbi; -use rustc_ast as ast; use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock}; +use rustc_hir::attrs::{CfgEntry, NativeLibKind, PeImportNameType}; use rustc_hir::def_id::{ CrateNum, DefId, LOCAL_CRATE, LocalDefId, StableCrateId, StableCrateIdMap, }; @@ -16,7 +16,6 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::{Span, Symbol}; use crate::search_paths::PathKind; -use crate::utils::NativeLibKind; // lonely orphan structs and enums looking for a better home @@ -72,7 +71,7 @@ pub struct NativeLib { pub name: Symbol, /// If packed_bundled_libs enabled, actual filename of library is stored. pub filename: Option<Symbol>, - pub cfg: Option<ast::MetaItemInner>, + pub cfg: Option<CfgEntry>, pub foreign_module: Option<DefId>, pub verbatim: Option<bool>, pub dll_imports: Vec<DllImport>, @@ -88,25 +87,6 @@ impl NativeLib { } } -/// Different ways that the PE Format can decorate a symbol name. -/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type> -#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic, PartialEq, Eq)] -pub enum PeImportNameType { - /// IMPORT_ORDINAL - /// Uses the ordinal (i.e., a number) rather than the name. - Ordinal(u16), - /// Same as IMPORT_NAME - /// Name is decorated with all prefixes and suffixes. - Decorated, - /// Same as IMPORT_NAME_NOPREFIX - /// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept. - NoPrefix, - /// Same as IMPORT_NAME_UNDECORATE - /// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all - /// trailing characters) are skipped. - Undecorated, -} - #[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)] pub struct DllImport { pub name: Symbol, diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 34da54a20bf..50bc7348dc9 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -384,6 +384,10 @@ pub fn report_lit_error( lit: token::Lit, span: Span, ) -> ErrorGuaranteed { + create_lit_error(psess, err, lit, span).emit() +} + +pub fn create_lit_error(psess: &ParseSess, err: LitError, lit: token::Lit, span: Span) -> Diag<'_> { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) @@ -414,32 +418,32 @@ pub fn report_lit_error( let dcx = psess.dcx(); match err { LitError::InvalidSuffix(suffix) => { - dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix }) + dcx.create_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix }) } LitError::InvalidIntSuffix(suffix) => { let suf = suffix.as_str(); if looks_like_width_suffix(&['i', 'u'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) + dcx.create_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) } else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) { - dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }) + dcx.create_err(InvalidNumLiteralBasePrefix { span, fixed }) } else { - dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) + dcx.create_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) } } LitError::InvalidFloatSuffix(suffix) => { let suf = suffix.as_str(); if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }) + dcx.create_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }) } else { - dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }) + dcx.create_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }) } } LitError::NonDecimalFloat(base) => match base { - 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }), - 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }), - 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }), + 16 => dcx.create_err(HexadecimalFloatLiteralNotSupported { span }), + 8 => dcx.create_err(OctalFloatLiteralNotSupported { span }), + 2 => dcx.create_err(BinaryFloatLiteralNotSupported { span }), _ => unreachable!(), }, LitError::IntTooLarge(base) => { @@ -450,7 +454,7 @@ pub fn report_lit_error( 16 => format!("{max:#x}"), _ => format!("{max}"), }; - dcx.emit_err(IntLiteralTooLarge { span, limit }) + dcx.create_err(IntLiteralTooLarge { span, limit }) } } } diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index e9ddd66b5e8..c64d9bc1efe 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -3,6 +3,7 @@ use std::sync::OnceLock; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_fs_util::try_canonicalize; +use rustc_hir::attrs::NativeLibKind; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use crate::session::Session; @@ -17,69 +18,6 @@ impl Session { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -#[derive(HashStable_Generic)] -pub enum NativeLibKind { - /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC) - Static { - /// Whether to bundle objects from static library into produced rlib - bundle: Option<bool>, - /// Whether to link static library without throwing any object files away - whole_archive: Option<bool>, - }, - /// Dynamic library (e.g. `libfoo.so` on Linux) - /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC). - Dylib { - /// Whether the dynamic library will be linked only if it satisfies some undefined symbols - as_needed: Option<bool>, - }, - /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library. - /// On Linux, it refers to a generated shared library stub. - RawDylib, - /// A macOS-specific kind of dynamic libraries. - Framework { - /// Whether the framework will be linked only if it satisfies some undefined symbols - as_needed: Option<bool>, - }, - /// Argument which is passed to linker, relative order with libraries and other arguments - /// is preserved - LinkArg, - - /// Module imported from WebAssembly - WasmImportModule, - - /// The library kind wasn't specified, `Dylib` is currently used as a default. - Unspecified, -} - -impl NativeLibKind { - pub fn has_modifiers(&self) -> bool { - match self { - NativeLibKind::Static { bundle, whole_archive } => { - bundle.is_some() || whole_archive.is_some() - } - NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => { - as_needed.is_some() - } - NativeLibKind::RawDylib - | NativeLibKind::Unspecified - | NativeLibKind::LinkArg - | NativeLibKind::WasmImportModule => false, - } - } - - pub fn is_statically_included(&self) -> bool { - matches!(self, NativeLibKind::Static { .. }) - } - - pub fn is_dllimport(&self) -> bool { - matches!( - self, - NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified - ) - } -} - #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[derive(HashStable_Generic)] pub struct NativeLib { diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 43a2d692577..da6f2101d23 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -6,8 +6,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start blake3 = "1.5.2" -derive-where = "1.2.7" -indexmap = { version = "2.0.0" } +derive-where.workspace = true +indexmap.workspace = true itoa = "1.0" md5 = { package = "md-5", version = "0.10.0" } rustc_arena = { path = "../rustc_arena" } @@ -16,9 +16,9 @@ rustc_hashes = { path = "../rustc_hashes" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } -scoped-tls = "1.0" +scoped-tls.workspace = true sha1 = "0.10.0" sha2 = "0.10.1" -tracing = "0.1" +tracing.workspace = true unicode-width = "0.2.0" # tidy-alphabetical-end diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index d647ec28aae..ae6755f0764 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -17,6 +17,7 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] @@ -26,7 +27,6 @@ #![feature(map_try_insert)] #![feature(negative_impls)] #![feature(read_buf)] -#![feature(round_char_boundary)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] // tidy-alphabetical-end diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 585968044bf..77260d07c99 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -466,6 +466,7 @@ symbols! { arm, arm_target_feature, array, + as_dash_needed: "as-needed", as_ptr, as_ref, as_str, @@ -540,6 +541,7 @@ symbols! { att_syntax, attr, attr_literals, + attribute, attributes, audit_that, augmented_assignments, @@ -592,6 +594,7 @@ symbols! { btreeset_iter, built, builtin_syntax, + bundle, c, c_dash_variadic, c_str, @@ -817,6 +820,7 @@ symbols! { decl_macro, declare_lint_pass, decode, + decorated, default_alloc_error_handler, default_field_values, default_fn, @@ -1075,6 +1079,7 @@ symbols! { format_macro, format_placeholder, format_unsafe_arg, + framework, freeze, freeze_impls, freg, @@ -1295,6 +1300,7 @@ symbols! { link_arg_attribute, link_args, link_cfg, + link_dash_arg: "link-arg", link_llvm_intrinsics, link_name, link_ordinal, @@ -1528,6 +1534,7 @@ symbols! { noop_method_borrow, noop_method_clone, noop_method_deref, + noprefix, noreturn, nostack, not, @@ -1741,6 +1748,7 @@ symbols! { quote, range_inclusive_new, range_step, + raw_dash_dylib: "raw-dylib", raw_dylib, raw_dylib_elf, raw_eq, @@ -2277,6 +2285,7 @@ symbols! { unchecked_shl, unchecked_shr, unchecked_sub, + undecorated, underscore_const_names, underscore_imports, underscore_lifetimes, @@ -2365,6 +2374,7 @@ symbols! { vecdeque_iter, vecdeque_reserve, vector, + verbatim, version, vfp2, vis, @@ -2389,6 +2399,7 @@ symbols! { weak_odr, where_clause_attrs, while_let, + whole_dash_archive: "whole-archive", width, windows, windows_subsystem, diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index 0df9c7682bf..0ceac4b3e1b 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start punycode = "0.4.0" -rustc-demangle = "0.1.21" +rustc-demangle.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -15,5 +15,5 @@ rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index 57c90a703f1..ed59ee2a575 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -5,7 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" +bitflags.workspace = true +object = { version = "0.37.0", default-features = false, features = ["elf", "macho"] } rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_error_messages = { path = "../rustc_error_messages" } @@ -15,14 +16,8 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } serde = "1.0.219" serde_derive = "1.0.219" -serde_json = "1.0.59" +serde_json.workspace = true serde_path_to_error = "0.1.17" -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end -[dependencies.object] -# tidy-alphabetical-start -default-features = false -features = ["elf", "macho"] -version = "0.37.0" -# tidy-alphabetical-end diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 5f2a6f7ba38..7a7c63c475b 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -114,7 +114,7 @@ mod attr_impl { bitflags::bitflags! { impl ArgAttribute: u8 { const NoAlias = 1 << 1; - const NoCapture = 1 << 2; + const CapturesAddress = 1 << 2; const NonNull = 1 << 3; const ReadOnly = 1 << 4; const InReg = 1 << 5; @@ -400,11 +400,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> { let mut attrs = ArgAttributes::new(); // For non-immediate arguments the callee gets its own copy of - // the value on the stack, so there are no aliases. It's also - // program-invisible so can't possibly capture + // the value on the stack, so there are no aliases. The function + // can capture the address of the argument, but not the provenance. attrs .set(ArgAttribute::NoAlias) - .set(ArgAttribute::NoCapture) + .set(ArgAttribute::CapturesAddress) .set(ArgAttribute::NonNull) .set(ArgAttribute::NoUndef); attrs.pointee_size = layout.size; diff --git a/compiler/rustc_thread_pool/Cargo.toml b/compiler/rustc_thread_pool/Cargo.toml index c92984470b7..8e8c6469512 100644 --- a/compiler/rustc_thread_pool/Cargo.toml +++ b/compiler/rustc_thread_pool/Cargo.toml @@ -20,10 +20,10 @@ smallvec = "1.8.1" [dev-dependencies] rand = "0.9" rand_xorshift = "0.4" -scoped-tls = "1.0" +scoped-tls.workspace = true [target.'cfg(unix)'.dev-dependencies] -libc = "0.2" +libc.workspace = true [[test]] name = "stack_overflow_crash" diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 1071105522d..6b79b98d1bf 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools = "0.12" +itertools.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -21,6 +21,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 3565c11249a..7e8a41457d4 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -153,7 +153,12 @@ fn prepare_vtable_segments_inner<'tcx, T>( // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level. while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() { - let has_entries = has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id); + // We don't need to emit a vptr for "truly-empty" supertraits, but we *do* need to emit a + // vptr for supertraits that have no methods, but that themselves have supertraits + // with methods, so we check if any transitive supertrait has entries here (this includes + // the trait itself). + let has_entries = ty::elaborate::supertrait_def_ids(tcx, inner_most_trait_ref.def_id) + .any(|def_id| has_own_existential_vtable_entries(tcx, def_id)); segment_visitor(VtblSegment::TraitOwnEntries { trait_ref: inner_most_trait_ref, diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index 9f40f4d5c23..24360a94cc7 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -10,5 +10,5 @@ rustc_infer = { path = "../rustc_infer" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index e61717e5e9c..2ac2b46cc58 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -11,12 +11,12 @@ rustc_hir = { path = "../rustc_hir", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } rustc_span = { path = "../rustc_span", optional = true } smallvec = "1.8.1" -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end [dev-dependencies] # tidy-alphabetical-start -itertools = "0.12" +itertools.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index ce08b300cc8..394cde5a323 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools = "0.12" +itertools.workspace = true rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -20,5 +20,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing = "0.1" +tracing.workspace = true # tidy-alphabetical-end diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index d55e9b3b1be..42860fa2d88 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -5,11 +5,11 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" -derive-where = "1.2.7" +bitflags.workspace = true +derive-where.workspace = true ena = "0.14.3" -indexmap = "2.0.0" -rustc-hash = "2.0.0" +indexmap.workspace = true +rustc-hash.workspace = true rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_error_messages = { path = "../rustc_error_messages", optional = true } @@ -19,8 +19,8 @@ rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } smallvec = { version = "1.8.1", default-features = false, features = ["const_generics"] } -thin-vec = "0.2.12" -tracing = "0.1" +thin-vec.workspace = true +tracing.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_type_ir_macros/Cargo.toml b/compiler/rustc_type_ir_macros/Cargo.toml index 15a55575099..29a2cc89033 100644 --- a/compiler/rustc_type_ir_macros/Cargo.toml +++ b/compiler/rustc_type_ir_macros/Cargo.toml @@ -8,8 +8,8 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -proc-macro2 = "1" -quote = "1" +proc-macro2.workspace = true +quote.workspace = true syn = { version = "2.0.9", features = ["full"] } synstructure = "0.13.0" # tidy-alphabetical-end diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 639c5d4c930..711092ae8eb 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -159,6 +159,7 @@ #![feature(unicode_internals)] #![feature(unsize)] #![feature(unwrap_infallible)] +#![feature(wtf8_internals)] // tidy-alphabetical-end // // Language features: @@ -232,6 +233,8 @@ pub mod sync; #[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))] pub mod task; pub mod vec; +#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))] +pub mod wtf8; #[doc(hidden)] #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 11fd4346ff5..1d0dd4be1b6 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2939,68 +2939,41 @@ impl SpecToString for i8 { } } -// Generic/generated code can sometimes have multiple, nested references -// for strings, including `&&&str`s that would never be written -// by hand. This macro generates twelve layers of nested `&`-impl -// for primitive strings. -#[cfg(not(no_global_oom_handling))] -macro_rules! to_string_str_wrap_in_ref { - {x $($x:ident)*} => { - &to_string_str_wrap_in_ref! { $($x)* } - }; - {} => { str }; -} -#[cfg(not(no_global_oom_handling))] -macro_rules! to_string_expr_wrap_in_deref { - {$self:expr ; x $($x:ident)*} => { - *(to_string_expr_wrap_in_deref! { $self ; $($x)* }) - }; - {$self:expr ;} => { $self }; -} #[cfg(not(no_global_oom_handling))] macro_rules! to_string_str { - {$($($x:ident)*),+} => { + {$($type:ty,)*} => { $( - impl SpecToString for to_string_str_wrap_in_ref!($($x)*) { + impl SpecToString for $type { #[inline] fn spec_to_string(&self) -> String { - String::from(to_string_expr_wrap_in_deref!(self ; $($x)*)) + let s: &str = self; + String::from(s) } } - )+ + )* }; } #[cfg(not(no_global_oom_handling))] to_string_str! { - x x x x x x x x x x x x, - x x x x x x x x x x x, - x x x x x x x x x x, - x x x x x x x x x, - x x x x x x x x, - x x x x x x x, - x x x x x x, - x x x x x, - x x x x, - x x x, - x x, - x, -} - -#[cfg(not(no_global_oom_handling))] -impl SpecToString for Cow<'_, str> { - #[inline] - fn spec_to_string(&self) -> String { - self[..].to_owned() - } -} - -#[cfg(not(no_global_oom_handling))] -impl SpecToString for String { - #[inline] - fn spec_to_string(&self) -> String { - self.to_owned() - } + Cow<'_, str>, + String, + // Generic/generated code can sometimes have multiple, nested references + // for strings, including `&&&str`s that would never be written + // by hand. + &&&&&&&&&&&&str, + &&&&&&&&&&&str, + &&&&&&&&&&str, + &&&&&&&&&str, + &&&&&&&&str, + &&&&&&&str, + &&&&&&str, + &&&&&str, + &&&&str, + &&&str, + &&str, + &str, + str, } #[cfg(not(no_global_oom_handling))] diff --git a/library/alloc/src/wtf8/mod.rs b/library/alloc/src/wtf8/mod.rs new file mode 100644 index 00000000000..047994adc44 --- /dev/null +++ b/library/alloc/src/wtf8/mod.rs @@ -0,0 +1,562 @@ +//! Heap-allocated counterpart to core `wtf8` module. +#![unstable( + feature = "wtf8_internals", + issue = "none", + reason = "this is internal code for representing OsStr on some platforms and not a public API" +)] +// rustdoc bug: doc(hidden) on the module won't stop types in the module from showing up in trait +// implementations, so, we'll have to add more doc(hidden)s anyway +#![doc(hidden)] + +// Note: This module is also included in the alloctests crate using #[path] to +// run the tests. See the comment there for an explanation why this is the case. + +#[cfg(test)] +mod tests; + +use core::char::{MAX_LEN_UTF8, encode_utf8_raw}; +use core::hash::{Hash, Hasher}; +pub use core::wtf8::{CodePoint, Wtf8}; +#[cfg(not(test))] +pub use core::wtf8::{EncodeWide, Wtf8CodePoints}; +use core::{fmt, mem, ops, str}; + +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +#[cfg(not(test))] +use crate::rc::Rc; +use crate::string::String; +#[cfg(all(not(test), target_has_atomic = "ptr"))] +use crate::sync::Arc; +use crate::vec::Vec; + +/// An owned, growable string of well-formed WTF-8 data. +/// +/// Similar to `String`, but can additionally contain surrogate code points +/// if they’re not in a surrogate pair. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)] +#[doc(hidden)] +pub struct Wtf8Buf { + bytes: Vec<u8>, + + /// Do we know that `bytes` holds a valid UTF-8 encoding? We can easily + /// know this if we're constructed from a `String` or `&str`. + /// + /// It is possible for `bytes` to have valid UTF-8 without this being + /// set, such as when we're concatenating `&Wtf8`'s and surrogates become + /// paired, as we don't bother to rescan the entire string. + is_known_utf8: bool, +} + +impl ops::Deref for Wtf8Buf { + type Target = Wtf8; + + fn deref(&self) -> &Wtf8 { + self.as_slice() + } +} + +impl ops::DerefMut for Wtf8Buf { + fn deref_mut(&mut self) -> &mut Wtf8 { + self.as_mut_slice() + } +} + +/// Formats the string in double quotes, with characters escaped according to +/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`, +/// where each `x` is a hexadecimal digit. +/// +/// For example, the code units [U+0061, U+D800, U+000A] are formatted as +/// `"a\u{D800}\n"`. +impl fmt::Debug for Wtf8Buf { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, formatter) + } +} + +/// Formats the string with unpaired surrogates substituted with the replacement +/// character, U+FFFD. +impl fmt::Display for Wtf8Buf { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(s) = self.as_known_utf8() { + fmt::Display::fmt(s, formatter) + } else { + fmt::Display::fmt(&**self, formatter) + } + } +} + +#[cfg_attr(test, allow(dead_code))] +impl Wtf8Buf { + /// Creates a new, empty WTF-8 string. + #[inline] + pub fn new() -> Wtf8Buf { + Wtf8Buf { bytes: Vec::new(), is_known_utf8: true } + } + + /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes. + #[inline] + pub fn with_capacity(capacity: usize) -> Wtf8Buf { + Wtf8Buf { bytes: Vec::with_capacity(capacity), is_known_utf8: true } + } + + /// Creates a WTF-8 string from a WTF-8 byte vec. + /// + /// Since the byte vec is not checked for valid WTF-8, this function is + /// marked unsafe. + #[inline] + pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf { + Wtf8Buf { bytes: value, is_known_utf8: false } + } + + /// Creates a WTF-8 string from a UTF-8 `String`. + /// + /// This takes ownership of the `String` and does not copy. + /// + /// Since WTF-8 is a superset of UTF-8, this always succeeds. + #[inline] + pub const fn from_string(string: String) -> Wtf8Buf { + Wtf8Buf { bytes: string.into_bytes(), is_known_utf8: true } + } + + /// Creates a WTF-8 string from a UTF-8 `&str` slice. + /// + /// This copies the content of the slice. + /// + /// Since WTF-8 is a superset of UTF-8, this always succeeds. + #[inline] + pub fn from_str(s: &str) -> Wtf8Buf { + Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true } + } + + pub fn clear(&mut self) { + self.bytes.clear(); + self.is_known_utf8 = true; + } + + /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units. + /// + /// This is lossless: calling `.encode_wide()` on the resulting string + /// will always return the original code units. + pub fn from_wide(v: &[u16]) -> Wtf8Buf { + let mut string = Wtf8Buf::with_capacity(v.len()); + for item in char::decode_utf16(v.iter().cloned()) { + match item { + Ok(ch) => string.push_char(ch), + Err(surrogate) => { + let surrogate = surrogate.unpaired_surrogate(); + // Surrogates are known to be in the code point range. + let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) }; + // The string will now contain an unpaired surrogate. + string.is_known_utf8 = false; + // Skip the WTF-8 concatenation check, + // surrogate pairs are already decoded by decode_utf16 + unsafe { + string.push_code_point_unchecked(code_point); + } + } + } + } + string + } + + /// Appends the given `char` to the end of this string. + /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check. + /// Copied from String::push. + unsafe fn push_code_point_unchecked(&mut self, code_point: CodePoint) { + let mut bytes = [0; MAX_LEN_UTF8]; + let bytes = encode_utf8_raw(code_point.to_u32(), &mut bytes); + self.bytes.extend_from_slice(bytes) + } + + #[inline] + pub fn as_slice(&self) -> &Wtf8 { + unsafe { Wtf8::from_bytes_unchecked(&self.bytes) } + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut Wtf8 { + // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would + // cause them to change from well-formed UTF-8 to ill-formed UTF-8, + // which would break the assumptions of the `is_known_utf8` field. + unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) } + } + + /// Converts the string to UTF-8 without validation, if it was created from + /// valid UTF-8. + #[inline] + fn as_known_utf8(&self) -> Option<&str> { + if self.is_known_utf8 { + // SAFETY: The buffer is known to be valid UTF-8. + Some(unsafe { str::from_utf8_unchecked(self.as_bytes()) }) + } else { + None + } + } + + /// Reserves capacity for at least `additional` more bytes to be inserted + /// in the given `Wtf8Buf`. + /// The collection may reserve more space to avoid frequent reallocations. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.bytes.reserve(additional) + } + + /// Tries to reserve capacity for at least `additional` more bytes to be + /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to + /// avoid frequent reallocations. After calling `try_reserve`, capacity will + /// be greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. This method preserves the contents even + /// if an error occurs. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.bytes.try_reserve(additional) + } + + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.bytes.reserve_exact(additional) + } + + /// Tries to reserve the minimum capacity for exactly `additional` more + /// bytes to be inserted in the given `Wtf8Buf`. After calling + /// `try_reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the `Wtf8Buf` more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: Wtf8Buf::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.bytes.try_reserve_exact(additional) + } + + #[inline] + pub fn shrink_to_fit(&mut self) { + self.bytes.shrink_to_fit() + } + + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.bytes.shrink_to(min_capacity) + } + + #[inline] + pub fn leak<'a>(self) -> &'a mut Wtf8 { + unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) } + } + + /// Returns the number of bytes that this string buffer can hold without reallocating. + #[inline] + pub fn capacity(&self) -> usize { + self.bytes.capacity() + } + + /// Append a UTF-8 slice at the end of the string. + #[inline] + pub fn push_str(&mut self, other: &str) { + self.bytes.extend_from_slice(other.as_bytes()) + } + + /// Append a WTF-8 slice at the end of the string. + /// + /// This replaces newly paired surrogates at the boundary + /// with a supplementary code point, + /// like concatenating ill-formed UTF-16 strings effectively would. + #[inline] + pub fn push_wtf8(&mut self, other: &Wtf8) { + match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) { + // Replace newly paired surrogates by a supplementary code point. + (Some(lead), Some(trail)) => { + let len_without_lead_surrogate = self.len() - 3; + self.bytes.truncate(len_without_lead_surrogate); + let other_without_trail_surrogate = &other.as_bytes()[3..]; + // 4 bytes for the supplementary code point + self.bytes.reserve(4 + other_without_trail_surrogate.len()); + self.push_char(decode_surrogate_pair(lead, trail)); + self.bytes.extend_from_slice(other_without_trail_surrogate); + } + _ => { + // If we'll be pushing a string containing a surrogate, we may + // no longer have UTF-8. + if self.is_known_utf8 && other.next_surrogate(0).is_some() { + self.is_known_utf8 = false; + } + + self.bytes.extend_from_slice(other.as_bytes()); + } + } + } + + /// Append a Unicode scalar value at the end of the string. + #[inline] + pub fn push_char(&mut self, c: char) { + // SAFETY: It's always safe to push a char. + unsafe { self.push_code_point_unchecked(CodePoint::from_char(c)) } + } + + /// Append a code point at the end of the string. + /// + /// This replaces newly paired surrogates at the boundary + /// with a supplementary code point, + /// like concatenating ill-formed UTF-16 strings effectively would. + #[inline] + pub fn push(&mut self, code_point: CodePoint) { + if let Some(trail) = code_point.to_trail_surrogate() { + if let Some(lead) = (&*self).final_lead_surrogate() { + let len_without_lead_surrogate = self.len() - 3; + self.bytes.truncate(len_without_lead_surrogate); + self.push_char(decode_surrogate_pair(lead, trail)); + return; + } + + // We're pushing a trailing surrogate. + self.is_known_utf8 = false; + } else if code_point.to_lead_surrogate().is_some() { + // We're pushing a leading surrogate. + self.is_known_utf8 = false; + } + + // No newly paired surrogates at the boundary. + unsafe { self.push_code_point_unchecked(code_point) } + } + + /// Shortens a string to the specified length. + /// + /// # Panics + /// + /// Panics if `new_len` > current length, + /// or if `new_len` is not a code point boundary. + #[inline] + pub fn truncate(&mut self, new_len: usize) { + assert!(self.is_code_point_boundary(new_len)); + self.bytes.truncate(new_len) + } + + /// Consumes the WTF-8 string and tries to convert it to a vec of bytes. + #[inline] + pub fn into_bytes(self) -> Vec<u8> { + self.bytes + } + + /// Consumes the WTF-8 string and tries to convert it to UTF-8. + /// + /// This does not copy the data. + /// + /// If the contents are not well-formed UTF-8 + /// (that is, if the string contains surrogates), + /// the original WTF-8 string is returned instead. + pub fn into_string(self) -> Result<String, Wtf8Buf> { + if self.is_known_utf8 || self.next_surrogate(0).is_none() { + Ok(unsafe { String::from_utf8_unchecked(self.bytes) }) + } else { + Err(self) + } + } + + /// Consumes the WTF-8 string and converts it lossily to UTF-8. + /// + /// This does not copy the data (but may overwrite parts of it in place). + /// + /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”) + pub fn into_string_lossy(mut self) -> String { + if !self.is_known_utf8 { + let mut pos = 0; + while let Some((surrogate_pos, _)) = self.next_surrogate(pos) { + pos = surrogate_pos + 3; + // Surrogates and the replacement character are all 3 bytes, so + // they can substituted in-place. + self.bytes[surrogate_pos..pos].copy_from_slice("\u{FFFD}".as_bytes()); + } + } + unsafe { String::from_utf8_unchecked(self.bytes) } + } + + /// Converts this `Wtf8Buf` into a boxed `Wtf8`. + #[inline] + pub fn into_box(self) -> Box<Wtf8> { + // SAFETY: relies on `Wtf8` being `repr(transparent)`. + unsafe { mem::transmute(self.bytes.into_boxed_slice()) } + } + + /// Converts a `Box<Wtf8>` into a `Wtf8Buf`. + pub fn from_box(boxed: Box<Wtf8>) -> Wtf8Buf { + let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) }; + Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false } + } + + /// Provides plumbing to core `Vec::extend_from_slice`. + /// More well behaving alternative to allowing outer types + /// full mutable access to the core `Vec`. + #[inline] + pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) { + self.bytes.extend_from_slice(other); + self.is_known_utf8 = false; + } +} + +/// Creates a new WTF-8 string from an iterator of code points. +/// +/// This replaces surrogate code point pairs with supplementary code points, +/// like concatenating ill-formed UTF-16 strings effectively would. +impl FromIterator<CodePoint> for Wtf8Buf { + fn from_iter<T: IntoIterator<Item = CodePoint>>(iter: T) -> Wtf8Buf { + let mut string = Wtf8Buf::new(); + string.extend(iter); + string + } +} + +/// Append code points from an iterator to the string. +/// +/// This replaces surrogate code point pairs with supplementary code points, +/// like concatenating ill-formed UTF-16 strings effectively would. +impl Extend<CodePoint> for Wtf8Buf { + fn extend<T: IntoIterator<Item = CodePoint>>(&mut self, iter: T) { + let iterator = iter.into_iter(); + let (low, _high) = iterator.size_hint(); + // Lower bound of one byte per code point (ASCII only) + self.bytes.reserve(low); + iterator.for_each(move |code_point| self.push(code_point)); + } + + #[inline] + fn extend_one(&mut self, code_point: CodePoint) { + self.push(code_point); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + // Lower bound of one byte per code point (ASCII only) + self.bytes.reserve(additional); + } +} + +/// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`. +pub(super) fn to_owned(slice: &Wtf8) -> Wtf8Buf { + Wtf8Buf { bytes: slice.as_bytes().to_vec(), is_known_utf8: false } +} + +/// Lossily converts the string to UTF-8. +/// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8. +/// +/// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”). +/// +/// This only copies the data if necessary (if it contains any surrogate). +pub(super) fn to_string_lossy(slice: &Wtf8) -> Cow<'_, str> { + let Some((surrogate_pos, _)) = slice.next_surrogate(0) else { + return Cow::Borrowed(unsafe { str::from_utf8_unchecked(slice.as_bytes()) }); + }; + let wtf8_bytes = slice.as_bytes(); + let mut utf8_bytes = Vec::with_capacity(slice.len()); + utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]); + utf8_bytes.extend_from_slice("\u{FFFD}".as_bytes()); + let mut pos = surrogate_pos + 3; + loop { + match slice.next_surrogate(pos) { + Some((surrogate_pos, _)) => { + utf8_bytes.extend_from_slice(&wtf8_bytes[pos..surrogate_pos]); + utf8_bytes.extend_from_slice("\u{FFFD}".as_bytes()); + pos = surrogate_pos + 3; + } + None => { + utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]); + return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) }); + } + } + } +} + +#[inline] +pub(super) fn clone_into(slice: &Wtf8, buf: &mut Wtf8Buf) { + buf.is_known_utf8 = false; + slice.as_bytes().clone_into(&mut buf.bytes); +} + +#[cfg(not(test))] +impl Wtf8 { + #[rustc_allow_incoherent_impl] + pub fn to_owned(&self) -> Wtf8Buf { + to_owned(self) + } + + #[rustc_allow_incoherent_impl] + pub fn clone_into(&self, buf: &mut Wtf8Buf) { + clone_into(self, buf) + } + + #[rustc_allow_incoherent_impl] + pub fn to_string_lossy(&self) -> Cow<'_, str> { + to_string_lossy(self) + } + + #[rustc_allow_incoherent_impl] + pub fn into_box(&self) -> Box<Wtf8> { + let boxed: Box<[u8]> = self.as_bytes().into(); + unsafe { mem::transmute(boxed) } + } + + #[rustc_allow_incoherent_impl] + pub fn empty_box() -> Box<Wtf8> { + let boxed: Box<[u8]> = Default::default(); + unsafe { mem::transmute(boxed) } + } + + #[cfg(target_has_atomic = "ptr")] + #[rustc_allow_incoherent_impl] + pub fn into_arc(&self) -> Arc<Wtf8> { + let arc: Arc<[u8]> = Arc::from(self.as_bytes()); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) } + } + + #[rustc_allow_incoherent_impl] + pub fn into_rc(&self) -> Rc<Wtf8> { + let rc: Rc<[u8]> = Rc::from(self.as_bytes()); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) } + } + + #[inline] + #[rustc_allow_incoherent_impl] + pub fn to_ascii_lowercase(&self) -> Wtf8Buf { + Wtf8Buf { bytes: self.as_bytes().to_ascii_lowercase(), is_known_utf8: false } + } + + #[inline] + #[rustc_allow_incoherent_impl] + pub fn to_ascii_uppercase(&self) -> Wtf8Buf { + Wtf8Buf { bytes: self.as_bytes().to_ascii_uppercase(), is_known_utf8: false } + } +} + +#[inline] +fn decode_surrogate_pair(lead: u16, trail: u16) -> char { + let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32); + unsafe { char::from_u32_unchecked(code_point) } +} + +impl Hash for Wtf8Buf { + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + state.write(&self.bytes); + 0xfeu8.hash(state) + } +} diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/alloc/src/wtf8/tests.rs index b57c99a8452..291f63f9f9e 100644 --- a/library/std/src/sys_common/wtf8/tests.rs +++ b/library/alloc/src/wtf8/tests.rs @@ -1,3 +1,5 @@ +use realalloc::string::ToString; + use super::*; #[test] @@ -82,82 +84,85 @@ fn code_point_to_char_lossy() { #[test] fn wtf8buf_new() { - assert_eq!(Wtf8Buf::new().bytes, b""); + assert_eq!(Wtf8Buf::new().as_bytes(), b""); } #[test] fn wtf8buf_from_str() { - assert_eq!(Wtf8Buf::from_str("").bytes, b""); - assert_eq!(Wtf8Buf::from_str("aé 💩").bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(Wtf8Buf::from_str("").as_bytes(), b""); + assert_eq!(Wtf8Buf::from_str("aé 💩").as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9"); } #[test] fn wtf8buf_from_string() { - assert_eq!(Wtf8Buf::from_string(String::from("")).bytes, b""); - assert_eq!(Wtf8Buf::from_string(String::from("aé 💩")).bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(Wtf8Buf::from_string(String::from("")).as_bytes(), b""); + assert_eq!( + Wtf8Buf::from_string(String::from("aé 💩")).as_bytes(), + b"a\xC3\xA9 \xF0\x9F\x92\xA9" + ); } #[test] fn wtf8buf_from_wide() { let buf = Wtf8Buf::from_wide(&[]); - assert_eq!(buf.bytes, b""); + assert_eq!(buf.as_bytes(), b""); assert!(buf.is_known_utf8); let buf = Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xDCA9]); - assert_eq!(buf.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(buf.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9"); assert!(buf.is_known_utf8); let buf = Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]); - assert_eq!(buf.bytes, b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9"); + assert_eq!(buf.as_bytes(), b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9"); assert!(!buf.is_known_utf8); let buf = Wtf8Buf::from_wide(&[0xD800]); - assert_eq!(buf.bytes, b"\xED\xA0\x80"); + assert_eq!(buf.as_bytes(), b"\xED\xA0\x80"); assert!(!buf.is_known_utf8); let buf = Wtf8Buf::from_wide(&[0xDBFF]); - assert_eq!(buf.bytes, b"\xED\xAF\xBF"); + assert_eq!(buf.as_bytes(), b"\xED\xAF\xBF"); assert!(!buf.is_known_utf8); let buf = Wtf8Buf::from_wide(&[0xDC00]); - assert_eq!(buf.bytes, b"\xED\xB0\x80"); + assert_eq!(buf.as_bytes(), b"\xED\xB0\x80"); assert!(!buf.is_known_utf8); let buf = Wtf8Buf::from_wide(&[0xDFFF]); - assert_eq!(buf.bytes, b"\xED\xBF\xBF"); + assert_eq!(buf.as_bytes(), b"\xED\xBF\xBF"); assert!(!buf.is_known_utf8); } #[test] fn wtf8buf_push_str() { let mut string = Wtf8Buf::new(); - assert_eq!(string.bytes, b""); + assert_eq!(string.as_bytes(), b""); assert!(string.is_known_utf8); string.push_str("aé 💩"); - assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9"); assert!(string.is_known_utf8); } #[test] fn wtf8buf_push_char() { let mut string = Wtf8Buf::from_str("aé "); - assert_eq!(string.bytes, b"a\xC3\xA9 "); + assert_eq!(string.as_bytes(), b"a\xC3\xA9 "); assert!(string.is_known_utf8); string.push_char('💩'); - assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9"); assert!(string.is_known_utf8); } #[test] fn wtf8buf_push() { let mut string = Wtf8Buf::from_str("aé "); - assert_eq!(string.bytes, b"a\xC3\xA9 "); + assert_eq!(string.as_bytes(), b"a\xC3\xA9 "); assert!(string.is_known_utf8); string.push(CodePoint::from_char('💩')); - assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9"); assert!(string.is_known_utf8); fn c(value: u32) -> CodePoint { @@ -168,53 +173,53 @@ fn wtf8buf_push() { string.push(c(0xD83D)); // lead assert!(!string.is_known_utf8); string.push(c(0xDCA9)); // trail - assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic! + assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic! let mut string = Wtf8Buf::new(); string.push(c(0xD83D)); // lead assert!(!string.is_known_utf8); string.push(c(0x20)); // not surrogate string.push(c(0xDCA9)); // trail - assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9"); + assert_eq!(string.as_bytes(), b"\xED\xA0\xBD \xED\xB2\xA9"); let mut string = Wtf8Buf::new(); string.push(c(0xD800)); // lead assert!(!string.is_known_utf8); string.push(c(0xDBFF)); // lead - assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF"); + assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xED\xAF\xBF"); let mut string = Wtf8Buf::new(); string.push(c(0xD800)); // lead assert!(!string.is_known_utf8); string.push(c(0xE000)); // not surrogate - assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80"); + assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xEE\x80\x80"); let mut string = Wtf8Buf::new(); string.push(c(0xD7FF)); // not surrogate assert!(string.is_known_utf8); string.push(c(0xDC00)); // trail assert!(!string.is_known_utf8); - assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80"); + assert_eq!(string.as_bytes(), b"\xED\x9F\xBF\xED\xB0\x80"); let mut string = Wtf8Buf::new(); string.push(c(0x61)); // not surrogate, < 3 bytes assert!(string.is_known_utf8); string.push(c(0xDC00)); // trail assert!(!string.is_known_utf8); - assert_eq!(string.bytes, b"\x61\xED\xB0\x80"); + assert_eq!(string.as_bytes(), b"\x61\xED\xB0\x80"); let mut string = Wtf8Buf::new(); string.push(c(0xDC00)); // trail assert!(!string.is_known_utf8); - assert_eq!(string.bytes, b"\xED\xB0\x80"); + assert_eq!(string.as_bytes(), b"\xED\xB0\x80"); } #[test] fn wtf8buf_push_wtf8() { let mut string = Wtf8Buf::from_str("aé"); - assert_eq!(string.bytes, b"a\xC3\xA9"); + assert_eq!(string.as_bytes(), b"a\xC3\xA9"); string.push_wtf8(Wtf8::from_str(" 💩")); - assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9"); assert!(string.is_known_utf8); fn w(v: &[u8]) -> &Wtf8 { @@ -224,42 +229,42 @@ fn wtf8buf_push_wtf8() { let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xA0\xBD")); // lead string.push_wtf8(w(b"\xED\xB2\xA9")); // trail - assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic! + assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic! let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xA0\xBD")); // lead string.push_wtf8(w(b" ")); // not surrogate string.push_wtf8(w(b"\xED\xB2\xA9")); // trail - assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9"); + assert_eq!(string.as_bytes(), b"\xED\xA0\xBD \xED\xB2\xA9"); assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xA0\x80")); // lead string.push_wtf8(w(b"\xED\xAF\xBF")); // lead - assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF"); + assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xED\xAF\xBF"); assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xA0\x80")); // lead string.push_wtf8(w(b"\xEE\x80\x80")); // not surrogate - assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80"); + assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xEE\x80\x80"); assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\x9F\xBF")); // not surrogate string.push_wtf8(w(b"\xED\xB0\x80")); // trail - assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80"); + assert_eq!(string.as_bytes(), b"\xED\x9F\xBF\xED\xB0\x80"); assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"a")); // not surrogate, < 3 bytes string.push_wtf8(w(b"\xED\xB0\x80")); // trail - assert_eq!(string.bytes, b"\x61\xED\xB0\x80"); + assert_eq!(string.as_bytes(), b"\x61\xED\xB0\x80"); assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xB0\x80")); // trail - assert_eq!(string.bytes, b"\xED\xB0\x80"); + assert_eq!(string.as_bytes(), b"\xED\xB0\x80"); assert!(!string.is_known_utf8); } @@ -269,15 +274,15 @@ fn wtf8buf_truncate() { assert!(string.is_known_utf8); string.truncate(3); - assert_eq!(string.bytes, b"a\xC3\xA9"); + assert_eq!(string.as_bytes(), b"a\xC3\xA9"); assert!(string.is_known_utf8); string.truncate(1); - assert_eq!(string.bytes, b"a"); + assert_eq!(string.as_bytes(), b"a"); assert!(string.is_known_utf8); string.truncate(0); - assert_eq!(string.bytes, b""); + assert_eq!(string.as_bytes(), b""); assert!(string.is_known_utf8); } @@ -287,11 +292,11 @@ fn wtf8buf_truncate_around_non_bmp() { assert!(string.is_known_utf8); string.truncate(4); - assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); + assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9"); assert!(string.is_known_utf8); string.truncate(0); - assert_eq!(string.bytes, b""); + assert_eq!(string.as_bytes(), b""); assert!(string.is_known_utf8); } @@ -361,7 +366,7 @@ fn wtf8buf_from_iterator() { Wtf8Buf { bytes: b"a\xC3\xA9 \xF0\x9F\x92\xA9".to_vec(), is_known_utf8: true } ); - assert_eq!(f(&[0xD83D, 0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic! + assert_eq!(f(&[0xD83D, 0xDCA9]).as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic! assert_eq!( f(&[0xD83D, 0x20, 0xDCA9]), Wtf8Buf { bytes: b"\xED\xA0\xBD \xED\xB2\xA9".to_vec(), is_known_utf8: false } @@ -401,7 +406,7 @@ fn wtf8buf_extend() { Wtf8Buf { bytes: b"a\xC3\xA9 \xF0\x9F\x92\xA9".to_vec(), is_known_utf8: true } ); - assert_eq!(e(&[0xD83D], &[0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic! + assert_eq!(e(&[0xD83D], &[0xDCA9]).as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic! assert_eq!( e(&[0xD83D, 0x20], &[0xDCA9]), Wtf8Buf { bytes: b"\xED\xA0\xBD \xED\xB2\xA9".to_vec(), is_known_utf8: false } @@ -449,8 +454,8 @@ fn wtf8buf_show_str() { #[test] fn wtf8_from_str() { - assert_eq!(&Wtf8::from_str("").bytes, b""); - assert_eq!(&Wtf8::from_str("aé 💩").bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(&Wtf8::from_str("").as_bytes(), b""); + assert_eq!(&Wtf8::from_str("aé 💩").as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9"); } #[test] @@ -461,7 +466,7 @@ fn wtf8_len() { #[test] fn wtf8_slice() { - assert_eq!(&Wtf8::from_str("aé 💩")[1..4].bytes, b"\xC3\xA9 "); + assert_eq!(&Wtf8::from_str("aé 💩")[1..4].as_bytes(), b"\xC3\xA9 "); } #[test] @@ -472,7 +477,7 @@ fn wtf8_slice_not_code_point_boundary() { #[test] fn wtf8_slice_from() { - assert_eq!(&Wtf8::from_str("aé 💩")[1..].bytes, b"\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!(&Wtf8::from_str("aé 💩")[1..].as_bytes(), b"\xC3\xA9 \xF0\x9F\x92\xA9"); } #[test] @@ -483,7 +488,7 @@ fn wtf8_slice_from_not_code_point_boundary() { #[test] fn wtf8_slice_to() { - assert_eq!(&Wtf8::from_str("aé 💩")[..4].bytes, b"a\xC3\xA9 "); + assert_eq!(&Wtf8::from_str("aé 💩")[..4].as_bytes(), b"a\xC3\xA9 "); } #[test] @@ -529,12 +534,12 @@ fn wtf8_as_str() { #[test] fn wtf8_to_string_lossy() { - assert_eq!(Wtf8::from_str("").to_string_lossy(), Cow::Borrowed("")); - assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(), Cow::Borrowed("aé 💩")); + assert_eq!(to_string_lossy(Wtf8::from_str("")), Cow::Borrowed("")); + assert_eq!(to_string_lossy(Wtf8::from_str("aé 💩")), Cow::Borrowed("aé 💩")); let mut string = Wtf8Buf::from_str("aé 💩"); string.push(CodePoint::from_u32(0xD800).unwrap()); let expected: Cow<'_, str> = Cow::Owned(String::from("aé 💩�")); - assert_eq!(string.to_string_lossy(), expected); + assert_eq!(to_string_lossy(&string), expected); } #[test] @@ -548,7 +553,7 @@ fn wtf8_display() { let mut string = Wtf8Buf::from_str("aé 💩"); string.push(CodePoint::from_u32(0xD800).unwrap()); - assert_eq!("aé 💩�", d(string.as_inner())); + assert_eq!("aé 💩�", d(string.as_ref())); } #[test] @@ -577,67 +582,41 @@ fn wtf8_encode_wide_size_hint() { #[test] fn wtf8_clone_into() { let mut string = Wtf8Buf::new(); - Wtf8::from_str("green").clone_into(&mut string); - assert_eq!(string.bytes, b"green"); + clone_into(Wtf8::from_str("green"), &mut string); + assert_eq!(string.as_bytes(), b"green"); let mut string = Wtf8Buf::from_str("green"); - Wtf8::from_str("").clone_into(&mut string); - assert_eq!(string.bytes, b""); + clone_into(Wtf8::from_str(""), &mut string); + assert_eq!(string.as_bytes(), b""); let mut string = Wtf8Buf::from_str("red"); - Wtf8::from_str("green").clone_into(&mut string); - assert_eq!(string.bytes, b"green"); + clone_into(Wtf8::from_str("green"), &mut string); + assert_eq!(string.as_bytes(), b"green"); let mut string = Wtf8Buf::from_str("green"); - Wtf8::from_str("red").clone_into(&mut string); - assert_eq!(string.bytes, b"red"); + clone_into(Wtf8::from_str("red"), &mut string); + assert_eq!(string.as_bytes(), b"red"); let mut string = Wtf8Buf::from_str("green"); assert!(string.is_known_utf8); - unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").clone_into(&mut string) }; - assert_eq!(string.bytes, b"\xED\xA0\x80"); + clone_into(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") }, &mut string); + assert_eq!(string.as_bytes(), b"\xED\xA0\x80"); assert!(!string.is_known_utf8); } #[test] -fn wtf8_to_ascii_lowercase() { - let lowercase = Wtf8::from_str("").to_ascii_lowercase(); - assert_eq!(lowercase.bytes, b""); - - let lowercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_lowercase(); - assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87"); - - let lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_lowercase() }; - assert_eq!(lowercase.bytes, b"\xED\xA0\x80"); - assert!(!lowercase.is_known_utf8); -} - -#[test] -fn wtf8_to_ascii_uppercase() { - let uppercase = Wtf8::from_str("").to_ascii_uppercase(); - assert_eq!(uppercase.bytes, b""); - - let uppercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_uppercase(); - assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87"); - - let uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_uppercase() }; - assert_eq!(uppercase.bytes, b"\xED\xA0\x80"); - assert!(!uppercase.is_known_utf8); -} - -#[test] fn wtf8_make_ascii_lowercase() { let mut lowercase = Wtf8Buf::from_str(""); lowercase.make_ascii_lowercase(); - assert_eq!(lowercase.bytes, b""); + assert_eq!(lowercase.as_bytes(), b""); let mut lowercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇"); lowercase.make_ascii_lowercase(); - assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87"); + assert_eq!(lowercase.as_bytes(), b"green grapes! \xf0\x9f\x8d\x87"); - let mut lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + let mut lowercase = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") }); lowercase.make_ascii_lowercase(); - assert_eq!(lowercase.bytes, b"\xED\xA0\x80"); + assert_eq!(lowercase.as_bytes(), b"\xED\xA0\x80"); assert!(!lowercase.is_known_utf8); } @@ -645,22 +624,22 @@ fn wtf8_make_ascii_lowercase() { fn wtf8_make_ascii_uppercase() { let mut uppercase = Wtf8Buf::from_str(""); uppercase.make_ascii_uppercase(); - assert_eq!(uppercase.bytes, b""); + assert_eq!(uppercase.as_bytes(), b""); let mut uppercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇"); uppercase.make_ascii_uppercase(); - assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87"); + assert_eq!(uppercase.as_bytes(), b"GREEN GRAPES! \xf0\x9f\x8d\x87"); - let mut uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + let mut uppercase = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") }); uppercase.make_ascii_uppercase(); - assert_eq!(uppercase.bytes, b"\xED\xA0\x80"); + assert_eq!(uppercase.as_bytes(), b"\xED\xA0\x80"); assert!(!uppercase.is_known_utf8); } #[test] fn wtf8_to_owned() { - let string = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; - assert_eq!(string.bytes, b"\xED\xA0\x80"); + let string = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") }); + assert_eq!(string.as_bytes(), b"\xED\xA0\x80"); assert!(!string.is_known_utf8); } @@ -669,44 +648,44 @@ fn wtf8_valid_utf8_boundaries() { let mut string = Wtf8Buf::from_str("aé 💩"); string.push(CodePoint::from_u32(0xD800).unwrap()); string.push(CodePoint::from_u32(0xD800).unwrap()); - check_utf8_boundary(&string, 0); - check_utf8_boundary(&string, 1); - check_utf8_boundary(&string, 3); - check_utf8_boundary(&string, 4); - check_utf8_boundary(&string, 8); - check_utf8_boundary(&string, 14); + string.check_utf8_boundary(0); + string.check_utf8_boundary(1); + string.check_utf8_boundary(3); + string.check_utf8_boundary(4); + string.check_utf8_boundary(8); + string.check_utf8_boundary(14); assert_eq!(string.len(), 14); string.push_char('a'); - check_utf8_boundary(&string, 14); - check_utf8_boundary(&string, 15); + string.check_utf8_boundary(14); + string.check_utf8_boundary(15); let mut string = Wtf8Buf::from_str("a"); string.push(CodePoint::from_u32(0xD800).unwrap()); - check_utf8_boundary(&string, 1); + string.check_utf8_boundary(1); let mut string = Wtf8Buf::from_str("\u{D7FF}"); string.push(CodePoint::from_u32(0xD800).unwrap()); - check_utf8_boundary(&string, 3); + string.check_utf8_boundary(3); let mut string = Wtf8Buf::new(); string.push(CodePoint::from_u32(0xD800).unwrap()); string.push_char('\u{D7FF}'); - check_utf8_boundary(&string, 3); + string.check_utf8_boundary(3); } #[test] #[should_panic(expected = "byte index 4 is out of bounds")] fn wtf8_utf8_boundary_out_of_bounds() { let string = Wtf8::from_str("aé"); - check_utf8_boundary(&string, 4); + string.check_utf8_boundary(4); } #[test] #[should_panic(expected = "byte index 1 is not a codepoint boundary")] fn wtf8_utf8_boundary_inside_codepoint() { let string = Wtf8::from_str("é"); - check_utf8_boundary(&string, 1); + string.check_utf8_boundary(1); } #[test] @@ -714,7 +693,7 @@ fn wtf8_utf8_boundary_inside_codepoint() { fn wtf8_utf8_boundary_inside_surrogate() { let mut string = Wtf8Buf::new(); string.push(CodePoint::from_u32(0xD800).unwrap()); - check_utf8_boundary(&string, 1); + string.check_utf8_boundary(1); } #[test] @@ -723,20 +702,22 @@ fn wtf8_utf8_boundary_between_surrogates() { let mut string = Wtf8Buf::new(); string.push(CodePoint::from_u32(0xD800).unwrap()); string.push(CodePoint::from_u32(0xD800).unwrap()); - check_utf8_boundary(&string, 3); + string.check_utf8_boundary(3); } #[test] fn wobbled_wtf8_plus_bytes_isnt_utf8() { - let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + let mut string: Wtf8Buf = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") }); assert!(!string.is_known_utf8); - string.extend_from_slice(b"some utf-8"); + unsafe { + string.extend_from_slice_unchecked(b"some utf-8"); + } assert!(!string.is_known_utf8); } #[test] fn wobbled_wtf8_plus_str_isnt_utf8() { - let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + let mut string: Wtf8Buf = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") }); assert!(!string.is_known_utf8); string.push_str("some utf-8"); assert!(!string.is_known_utf8); diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 3241b4b0045..97de7d6a701 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -18,6 +18,8 @@ #![feature(allocator_api)] #![feature(array_into_iter_constructors)] #![feature(assert_matches)] +#![feature(char_internals)] +#![feature(char_max_len)] #![feature(core_intrinsics)] #![feature(exact_size_is_empty)] #![feature(extend_one)] @@ -41,6 +43,7 @@ #![feature(trusted_random_access)] #![feature(try_reserve_kind)] #![feature(try_trait_v2)] +#![feature(wtf8_internals)] // tidy-alphabetical-end // // Language features: @@ -68,15 +71,18 @@ extern crate test; mod testing; use realalloc::*; -// We are directly including collections and raw_vec here as both use non-public -// methods and fields in tests and as such need to have the types to test in the -// same crate as the tests themself. +// We are directly including collections, raw_vec, and wtf8 here as they use non-public +// methods and fields in tests and as such need to have the types to test in the same +// crate as the tests themself. #[path = "../alloc/src/collections/mod.rs"] mod collections; #[path = "../alloc/src/raw_vec/mod.rs"] mod raw_vec; +#[path = "../alloc/src/wtf8/mod.rs"] +mod wtf8; + #[allow(dead_code)] // Not used in all configurations pub(crate) mod test_helpers { /// Copied from `std::test_helpers::test_rng`, since these tests rely on the diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index fcfc7f8dd29..bf446ae1ba4 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -3,6 +3,7 @@ #![feature(iter_array_chunks)] #![feature(assert_matches)] #![feature(btree_extract_if)] +#![feature(wtf8_internals)] #![feature(char_max_len)] #![feature(cow_is_borrowed)] #![feature(core_intrinsics)] @@ -23,7 +24,6 @@ #![feature(inplace_iteration)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] -#![feature(round_char_boundary)] #![feature(slice_partition_dedup)] #![feature(string_from_utf8_lossy_owned)] #![feature(string_remove_matches)] diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index c54df2e90b7..3afadbfe894 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -51,8 +51,7 @@ jobs: - target: aarch64-unknown-linux-gnu os: ubuntu-24.04-arm - target: aarch64-pc-windows-msvc - os: windows-2025 - build_only: 1 + os: windows-11-arm - target: arm-unknown-linux-gnueabi os: ubuntu-24.04 - target: arm-unknown-linux-gnueabihf diff --git a/library/compiler-builtins/builtins-test/benches/float_conv.rs b/library/compiler-builtins/builtins-test/benches/float_conv.rs index e0f488eb685..40c13d270ac 100644 --- a/library/compiler-builtins/builtins-test/benches/float_conv.rs +++ b/library/compiler-builtins/builtins-test/benches/float_conv.rs @@ -1,4 +1,3 @@ -#![allow(improper_ctypes)] #![cfg_attr(f128_enabled, feature(f128))] use builtins_test::float_bench; diff --git a/library/compiler-builtins/builtins-test/tests/addsub.rs b/library/compiler-builtins/builtins-test/tests/addsub.rs index abe7dde645e..f3334bd0e2d 100644 --- a/library/compiler-builtins/builtins-test/tests/addsub.rs +++ b/library/compiler-builtins/builtins-test/tests/addsub.rs @@ -1,4 +1,5 @@ #![allow(unused_macros)] +#![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] use builtins_test::*; @@ -115,28 +116,25 @@ macro_rules! float_sum { mod float_addsub { use super::*; + #[cfg(f16_enabled)] + float_sum! { + f16, __addhf3, __subhf3, Half, all(); + } + float_sum! { f32, __addsf3, __subsf3, Single, all(); f64, __adddf3, __subdf3, Double, all(); } -} - -#[cfg(f128_enabled)] -#[cfg(not(x86_no_sse))] -#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] -mod float_addsub_f128 { - use super::*; + #[cfg(f128_enabled)] + #[cfg(not(x86_no_sse))] + #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] float_sum! { f128, __addtf3, __subtf3, Quad, not(feature = "no-sys-f128"); } -} - -#[cfg(f128_enabled)] -#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] -mod float_addsub_f128_ppc { - use super::*; + #[cfg(f128_enabled)] + #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] float_sum! { f128, __addkf3, __subkf3, Quad, not(feature = "no-sys-f128"); } diff --git a/library/compiler-builtins/builtins-test/tests/cmp.rs b/library/compiler-builtins/builtins-test/tests/cmp.rs index a904dc5f7de..4b01b6ca1c7 100644 --- a/library/compiler-builtins/builtins-test/tests/cmp.rs +++ b/library/compiler-builtins/builtins-test/tests/cmp.rs @@ -1,5 +1,6 @@ #![allow(unused_macros)] #![allow(unreachable_code)] +#![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] use builtins_test::*; @@ -52,6 +53,26 @@ mod float_comparisons { } #[test] + #[cfg(f16_enabled)] + fn cmp_f16() { + use compiler_builtins::float::cmp::{ + __eqhf2, __gehf2, __gthf2, __lehf2, __lthf2, __nehf2, __unordhf2, + }; + + fuzz_float_2(N, |x: f16, y: f16| { + assert_eq!(__unordhf2(x, y) != 0, x.is_nan() || y.is_nan()); + cmp!(f16, x, y, Half, all(), + 1, __lthf2; + 1, __lehf2; + 1, __eqhf2; + -1, __gehf2; + -1, __gthf2; + 1, __nehf2; + ); + }); + } + + #[test] fn cmp_f32() { use compiler_builtins::float::cmp::{ __eqsf2, __gesf2, __gtsf2, __lesf2, __ltsf2, __nesf2, __unordsf2, diff --git a/library/compiler-builtins/builtins-test/tests/mul.rs b/library/compiler-builtins/builtins-test/tests/mul.rs index 3072b45dca0..bbf1157db42 100644 --- a/library/compiler-builtins/builtins-test/tests/mul.rs +++ b/library/compiler-builtins/builtins-test/tests/mul.rs @@ -1,5 +1,6 @@ -#![allow(unused_macros)] +#![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] +#![allow(unused_macros)] use builtins_test::*; @@ -117,6 +118,11 @@ macro_rules! float_mul { mod float_mul { use super::*; + #[cfg(f16_enabled)] + float_mul! { + f16, __mulhf3, Half, all(); + } + // FIXME(#616): Stop ignoring arches that don't have native support once fix for builtins is in // nightly. float_mul! { diff --git a/library/compiler-builtins/compiler-builtins/src/float/add.rs b/library/compiler-builtins/compiler-builtins/src/float/add.rs index 0cc362f705b..acdcd2ebe31 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/add.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/add.rs @@ -130,7 +130,7 @@ where return F::from_bits(MinInt::ZERO); } - // If partial cancellation occured, we need to left-shift the result + // If partial cancellation occurred, we need to left-shift the result // and adjust the exponent: if a_significand < implicit_bit << 3 { let shift = a_significand.leading_zeros() as i32 @@ -191,6 +191,11 @@ where } intrinsics! { + #[cfg(f16_enabled)] + pub extern "C" fn __addhf3(a: f16, b: f16) -> f16 { + add(a, b) + } + #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_fadd] pub extern "C" fn __addsf3(a: f32, b: f32) -> f32 { diff --git a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs index f1e54dc1c83..8ab39c2b591 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs @@ -115,6 +115,37 @@ fn unord<F: Float>(a: F, b: F) -> bool { a_abs > inf_rep || b_abs > inf_rep } +#[cfg(f16_enabled)] +intrinsics! { + pub extern "C" fn __lehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_le_abi() + } + + pub extern "C" fn __gehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_ge_abi() + } + + pub extern "C" fn __unordhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + unord(a, b) as crate::float::cmp::CmpResult + } + + pub extern "C" fn __eqhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_le_abi() + } + + pub extern "C" fn __lthf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_le_abi() + } + + pub extern "C" fn __nehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_le_abi() + } + + pub extern "C" fn __gthf2(a: f16, b: f16) -> crate::float::cmp::CmpResult { + cmp(a, b).to_ge_abi() + } +} + intrinsics! { pub extern "C" fn __lesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult { cmp(a, b).to_le_abi() diff --git a/library/compiler-builtins/compiler-builtins/src/float/mul.rs b/library/compiler-builtins/compiler-builtins/src/float/mul.rs index dbed3095cda..49a2414eb5c 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/mul.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/mul.rs @@ -180,6 +180,11 @@ where } intrinsics! { + #[cfg(f16_enabled)] + pub extern "C" fn __mulhf3(a: f16, b: f16) -> f16 { + mul(a, b) + } + #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_fmul] pub extern "C" fn __mulsf3(a: f32, b: f32) -> f32 { diff --git a/library/compiler-builtins/compiler-builtins/src/float/sub.rs b/library/compiler-builtins/compiler-builtins/src/float/sub.rs index a0fd9dff97f..48ef33b0b82 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/sub.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/sub.rs @@ -1,6 +1,11 @@ use crate::float::Float; intrinsics! { + #[cfg(f16_enabled)] + pub extern "C" fn __subhf3(a: f16, b: f16) -> f16 { + crate::float::add::__addhf3(a, f16::from_bits(b.to_bits() ^ f16::SIGN_MASK)) + } + #[arm_aeabi_alias = __aeabi_fsub] pub extern "C" fn __subsf3(a: f32, b: f32) -> f32 { crate::float::add::__addsf3(a, f32::from_bits(b.to_bits() ^ f32::SIGN_MASK)) diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index ca75f44e02a..b111dc0bd18 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -18,10 +18,6 @@ #![no_std] #![allow(unused_features)] #![allow(internal_features)] -// We use `u128` in a whole bunch of places which we currently agree with the -// compiler on ABIs and such, so we should be "good enough" for now and changes -// to the `u128` ABI will be reflected here. -#![allow(improper_ctypes, improper_ctypes_definitions)] // `mem::swap` cannot be used because it may generate references to memcpy in unoptimized code. #![allow(clippy::manual_swap)] // Support compiling on both stage0 and stage1 which may differ in supported stable features. diff --git a/library/compiler-builtins/compiler-builtins/src/probestack.rs b/library/compiler-builtins/compiler-builtins/src/probestack.rs index 9a18216da99..72975485a77 100644 --- a/library/compiler-builtins/compiler-builtins/src/probestack.rs +++ b/library/compiler-builtins/compiler-builtins/src/probestack.rs @@ -73,7 +73,7 @@ pub unsafe extern "custom" fn __rust_probestack() { // page needed. // // Note that we're also testing against `8(%rsp)` to account for the 8 - // bytes pushed on the stack orginally with our return address. Using + // bytes pushed on the stack originally with our return address. Using // `8(%rsp)` simulates us testing the stack pointer in the caller's // context. diff --git a/library/compiler-builtins/crates/symbol-check/src/main.rs b/library/compiler-builtins/crates/symbol-check/src/main.rs index 1312a717970..4e94552331a 100644 --- a/library/compiler-builtins/crates/symbol-check/src/main.rs +++ b/library/compiler-builtins/crates/symbol-check/src/main.rs @@ -9,7 +9,7 @@ use std::process::{Command, Stdio}; use object::read::archive::{ArchiveFile, ArchiveMember}; use object::{ - File as ObjFile, Object, ObjectSymbol, Symbol, SymbolKind, SymbolScope, SymbolSection, + File as ObjFile, Object, ObjectSection, ObjectSymbol, Symbol, SymbolKind, SymbolScope, }; use serde_json::Value; @@ -154,7 +154,7 @@ struct SymInfo { name: String, kind: SymbolKind, scope: SymbolScope, - section: SymbolSection, + section: String, is_undefined: bool, is_global: bool, is_local: bool, @@ -165,12 +165,22 @@ struct SymInfo { } impl SymInfo { - fn new(sym: &Symbol, member: &ArchiveMember) -> Self { + fn new(sym: &Symbol, obj: &ObjFile, member: &ArchiveMember) -> Self { + // Include the section name if possible. Fall back to the `Section` debug impl if not. + let section = sym.section(); + let section_name = sym + .section() + .index() + .and_then(|idx| obj.section_by_index(idx).ok()) + .and_then(|sec| sec.name().ok()) + .map(ToString::to_string) + .unwrap_or_else(|| format!("{section:?}")); + Self { name: sym.name().expect("missing name").to_owned(), kind: sym.kind(), scope: sym.scope(), - section: sym.section(), + section: section_name, is_undefined: sym.is_undefined(), is_global: sym.is_global(), is_local: sym.is_local(), @@ -192,22 +202,27 @@ fn verify_no_duplicates(archive: &Archive) { let mut dups = Vec::new(); let mut found_any = false; - archive.for_each_symbol(|symbol, member| { + archive.for_each_symbol(|symbol, obj, member| { // Only check defined globals if !symbol.is_global() || symbol.is_undefined() { return; } - let sym = SymInfo::new(&symbol, member); + let sym = SymInfo::new(&symbol, obj, member); // x86-32 includes multiple copies of thunk symbols if sym.name.starts_with("__x86.get_pc_thunk") { return; } + // GDB pretty printing symbols may show up more than once but are weak. + if sym.section == ".debug_gdb_scripts" && sym.is_weak { + return; + } + // Windows has symbols for literal numeric constants, string literals, and MinGW pseudo- // relocations. These are allowed to have repeated definitions. - let win_allowed_dup_pfx = ["__real@", "__xmm@", "??_C@_", ".refptr"]; + let win_allowed_dup_pfx = ["__real@", "__xmm@", "__ymm@", "??_C@_", ".refptr"]; if win_allowed_dup_pfx .iter() .any(|pfx| sym.name.starts_with(pfx)) @@ -244,7 +259,7 @@ fn verify_core_symbols(archive: &Archive) { let mut undefined = Vec::new(); let mut has_symbols = false; - archive.for_each_symbol(|symbol, member| { + archive.for_each_symbol(|symbol, obj, member| { has_symbols = true; // Find only symbols from `core` @@ -252,7 +267,7 @@ fn verify_core_symbols(archive: &Archive) { return; } - let sym = SymInfo::new(&symbol, member); + let sym = SymInfo::new(&symbol, obj, member); if sym.is_undefined { undefined.push(sym); } else { @@ -304,9 +319,9 @@ impl Archive { } /// For a given archive, do something with each symbol. - fn for_each_symbol(&self, mut f: impl FnMut(Symbol, &ArchiveMember)) { + fn for_each_symbol(&self, mut f: impl FnMut(Symbol, &ObjFile, &ArchiveMember)) { self.for_each_object(|obj, member| { - obj.symbols().for_each(|sym| f(sym, member)); + obj.symbols().for_each(|sym| f(sym, &obj, member)); }); } } diff --git a/library/compiler-builtins/etc/update-api-list.py b/library/compiler-builtins/etc/update-api-list.py index 28ff22f4cbb..76c75cbf4dc 100755 --- a/library/compiler-builtins/etc/update-api-list.py +++ b/library/compiler-builtins/etc/update-api-list.py @@ -34,7 +34,7 @@ def eprint(*args, **kwargs): @dataclass class Crate: - """Representation of public interfaces and function defintion locations in + """Representation of public interfaces and function definition locations in `libm`. """ diff --git a/library/compiler-builtins/libm/src/math/rem_pio2_large.rs b/library/compiler-builtins/libm/src/math/rem_pio2_large.rs index f1fdf3673a8..bb2c532916b 100644 --- a/library/compiler-builtins/libm/src/math/rem_pio2_large.rs +++ b/library/compiler-builtins/libm/src/math/rem_pio2_large.rs @@ -146,7 +146,7 @@ const PIO2: [f64; 8] = [ // x[i] = floor(z) // z = (z-x[i])*2**24 // -// y[] ouput result in an array of double precision numbers. +// y[] output result in an array of double precision numbers. // The dimension of y[] is: // 24-bit precision 1 // 53-bit precision 2 diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version index a4db05a8796..8489eacfcda 100644 --- a/library/compiler-builtins/rust-version +++ b/library/compiler-builtins/rust-version @@ -1 +1 @@ -82310651b93a594a3fd69015e1562186a080d94c +d36f964125163c2e698de5559efefb8217b8b7f0 diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index c72eeb9a9c9..535c5a8e77b 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -267,39 +267,29 @@ pub const unsafe fn assert_unchecked(cond: bool) { #[inline(always)] #[stable(feature = "renamed_spin_loop", since = "1.49.0")] pub fn spin_loop() { - #[cfg(target_arch = "x86")] - { - // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets. - unsafe { crate::arch::x86::_mm_pause() }; - } - - #[cfg(target_arch = "x86_64")] - { - // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets. - unsafe { crate::arch::x86_64::_mm_pause() }; - } - - #[cfg(target_arch = "riscv32")] - { - crate::arch::riscv32::pause(); - } - - #[cfg(target_arch = "riscv64")] - { - crate::arch::riscv64::pause(); - } - - #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] - { - // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. - unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }; - } - - #[cfg(all(target_arch = "arm", target_feature = "v6"))] - { - // SAFETY: the `cfg` attr ensures that we only execute this on arm targets - // with support for the v6 feature. - unsafe { crate::arch::arm::__yield() }; + crate::cfg_select! { + target_arch = "x86" => { + // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets. + unsafe { crate::arch::x86::_mm_pause() } + } + target_arch = "x86_64" => { + // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets. + unsafe { crate::arch::x86_64::_mm_pause() } + } + target_arch = "riscv32" => crate::arch::riscv32::pause(), + target_arch = "riscv64" => crate::arch::riscv64::pause(), + any(target_arch = "aarch64", target_arch = "arm64ec") => { + // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. + unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) } + } + all(target_arch = "arm", target_feature = "v6") => { + // SAFETY: the `cfg` attr ensures that we only execute this on arm targets + // with support for the v6 feature. + unsafe { crate::arch::arm::__yield() } + } + target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(), + target_arch = "loongarch64" => crate::arch::loongarch64::ibar::<0>(), + _ => { /* do nothing */ } } } diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 12e2b8b393a..73122369b41 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -1,5 +1,5 @@ use crate::iter; -use crate::num::Wrapping; +use crate::num::{Saturating, Wrapping}; /// Trait to represent types that can be created by summing up an iterator. /// @@ -98,6 +98,61 @@ macro_rules! integer_sum_product { ); } +macro_rules! saturating_integer_sum_product { + (@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($( + #[$attr] + #[doc = $doc] + impl Sum for $a { + fn sum<I: Iterator<Item=Self>>(iter: I) -> Self { + iter.fold( + $zero, + |a, b| a + b, + ) + } + } + + #[$attr] + #[doc = $doc] + impl Product for $a { + fn product<I: Iterator<Item=Self>>(iter: I) -> Self { + iter.fold( + $one, + |a, b| a * b, + ) + } + } + + #[$attr] + #[doc = $doc] + impl<'a> Sum<&'a $a> for $a { + fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self { + iter.fold( + $zero, + |a, b| a + b, + ) + } + } + + #[$attr] + #[doc = $doc] + impl<'a> Product<&'a $a> for $a { + fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self { + iter.fold( + $one, + |a, b| a * b, + ) + } + } + )*); + ($($a:ty)*) => ( + saturating_integer_sum_product!(@impls Saturating(0), Saturating(1), + "The short-circuiting behavior of this implementation is unspecified. If you care about \ + short-circuiting, use [`Iterator::fold`] directly.", + #[stable(feature = "saturating_iter_arith", since = "CURRENT_RUSTC_VERSION")], + $(Saturating<$a>)*); + ); +} + macro_rules! float_sum_product { ($($a:ident)*) => ($( #[stable(feature = "iter_arith_traits", since = "1.12.0")] @@ -147,6 +202,7 @@ macro_rules! float_sum_product { } integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } +saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize } float_sum_product! { f32 f64 } #[stable(feature = "iter_arith_traits_result", since = "1.16.0")] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f69d6a98592..82506379cac 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -363,6 +363,8 @@ pub mod slice; pub mod str; pub mod time; +pub mod wtf8; + pub mod unicode; /* Async */ diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 8ad58599c68..73aad27afef 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1049,7 +1049,7 @@ marker_impls! { /// A marker for types that can be dropped. /// -/// This should be used for `~const` bounds, +/// This should be used for `[const]` bounds, /// as non-const bounds will always hold for every type. #[unstable(feature = "const_destruct", issue = "133214")] #[rustc_const_unstable(feature = "const_destruct", issue = "133214")] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 69e6c100e76..4282b1af9f2 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -630,6 +630,13 @@ impl f128 { /// Converts radians to degrees. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// #![feature(f128)] /// # // FIXME(f16_f128): remove when `eqtf2` is available @@ -645,13 +652,22 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_degrees(self) -> Self { - // Use a literal for better precision. - const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128; + // The division here is correctly rounded with respect to the true value of 180/π. + // Although π is irrational and already rounded, the double rounding happens + // to produce correct result for f128. + const PIS_IN_180: f128 = 180.0 / consts::PI; self * PIS_IN_180 } /// Converts degrees to radians. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// #![feature(f128)] /// # // FIXME(f16_f128): remove when `eqtf2` is available @@ -668,7 +684,8 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_radians(self) -> f128 { - // Use a literal for better precision. + // Use a literal to avoid double rounding, consts::PI is already rounded, + // and dividing would round again. const RADS_PER_DEG: f128 = 0.0174532925199432957692369076848861271344287188854172545609719_f128; self * RADS_PER_DEG diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index b66cef03d20..23a8661c14b 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -625,6 +625,13 @@ impl f16 { /// Converts radians to degrees. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// #![feature(f16)] /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms @@ -640,13 +647,21 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_degrees(self) -> Self { - // Use a literal for better precision. + // Use a literal to avoid double rounding, consts::PI is already rounded, + // and dividing would round again. const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16; self * PIS_IN_180 } /// Converts degrees to radians. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// #![feature(f16)] /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms @@ -663,7 +678,8 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_radians(self) -> f16 { - // Use a literal for better precision. + // Use a literal to avoid double rounding, consts::PI is already rounded, + // and dividing would round again. const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16; self * RADS_PER_DEG } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index f8344da79ad..da08bfc5950 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -839,6 +839,13 @@ impl f32 { /// Converts radians to degrees. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// let angle = std::f32::consts::PI; /// @@ -852,13 +859,21 @@ impl f32 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_degrees(self) -> f32 { - // Use a constant for better precision. + // Use a literal to avoid double rounding, consts::PI is already rounded, + // and dividing would round again. const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32; self * PIS_IN_180 } /// Converts degrees to radians. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// let angle = 180.0f32; /// @@ -872,6 +887,9 @@ impl f32 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_radians(self) -> f32 { + // The division here is correctly rounded with respect to the true value of π/180. + // Although π is irrational and already rounded, the double rounding happens + // to produce correct result for f32. const RADS_PER_DEG: f32 = consts::PI / 180.0; self * RADS_PER_DEG } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 93da63c896e..dc0977cb147 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -856,6 +856,13 @@ impl f64 { /// Converts radians to degrees. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// let angle = std::f64::consts::PI; /// @@ -869,14 +876,22 @@ impl f64 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_degrees(self) -> f64 { - // The division here is correctly rounded with respect to the true - // value of 180/π. (This differs from f32, where a constant must be - // used to ensure a correctly rounded result.) - self * (180.0f64 / consts::PI) + // The division here is correctly rounded with respect to the true value of 180/π. + // Although π is irrational and already rounded, the double rounding happens + // to produce correct result for f64. + const PIS_IN_180: f64 = 180.0 / consts::PI; + self * PIS_IN_180 } /// Converts degrees to radians. /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, + /// Rust version, and can even differ within the same execution from one invocation to the next. + /// + /// # Examples + /// /// ``` /// let angle = 180.0_f64; /// @@ -890,6 +905,9 @@ impl f64 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn to_radians(self) -> f64 { + // The division here is correctly rounded with respect to the true value of π/180. + // Although π is irrational and already rounded, the double rounding happens + // to produce correct result for f64. const RADS_PER_DEG: f64 = consts::PI / 180.0; self * RADS_PER_DEG } diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index d57b1d433e5..610d9d8cf92 100644 --- a/library/core/src/num/niche_types.rs +++ b/library/core/src/num/niche_types.rs @@ -178,3 +178,18 @@ impl NotAllOnesHelper for u64 { impl NotAllOnesHelper for i64 { type Type = I64NotAllOnes; } + +define_valid_range_type! { + pub struct CodePointInner(u32 as u32 in 0..=0x10ffff); +} + +impl CodePointInner { + pub const ZERO: Self = CodePointInner::new(0).unwrap(); +} + +impl Default for CodePointInner { + #[inline] + fn default() -> Self { + Self::ZERO + } +} diff --git a/library/core/src/option.rs b/library/core/src/option.rs index e83e77344cf..fa09409b6da 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1961,6 +1961,42 @@ impl<T> Option<T> { _ => None, } } + + /// Reduces two options into one, using the provided function if both are `Some`. + /// + /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`. + /// Otherwise, if only one of `self` and `other` is `Some`, that one is returned. + /// If both `self` and `other` are `None`, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_reduce)] + /// + /// let s12 = Some(12); + /// let s17 = Some(17); + /// let n = None; + /// let f = |a, b| a + b; + /// + /// assert_eq!(s12.reduce(s17, f), Some(29)); + /// assert_eq!(s12.reduce(n, f), Some(12)); + /// assert_eq!(n.reduce(s17, f), Some(17)); + /// assert_eq!(n.reduce(n, f), None); + /// ``` + #[unstable(feature = "option_reduce", issue = "144273")] + pub fn reduce<U, R, F>(self, other: Option<U>, f: F) -> Option<R> + where + T: Into<R>, + U: Into<R>, + F: FnOnce(T, U) -> R, + { + match (self, other) { + (Some(a), Some(b)) => Some(f(a, b)), + (Some(a), _) => Some(a.into()), + (_, Some(b)) => Some(b.into()), + _ => None, + } + } } impl<T, U> Option<(T, U)> { diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index cafdcfa2c2e..7a68d393906 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -39,7 +39,7 @@ use crate::ptr::NonNull; pub struct Location<'a> { // A raw pointer is used rather than a reference because the pointer is valid for one more byte // than the length stored in this pointer; the additional byte is the NUL-terminator used by - // `Location::file_with_nul`. + // `Location::file_as_c_str`. filename: NonNull<str>, line: u32, col: u32, @@ -195,7 +195,7 @@ impl<'a> Location<'a> { #[must_use] #[unstable(feature = "file_with_nul", issue = "141727")] #[inline] - pub const fn file_with_nul(&self) -> &'a CStr { + pub const fn file_as_c_str(&self) -> &'a CStr { let filename = self.filename.as_ptr(); // SAFETY: The filename is valid for `filename_len+1` bytes, so this addition can't diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 0deac3621e8..dc3ec3fd199 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -106,6 +106,9 @@ pub const fn metadata<T: PointeeSized>(ptr: *const T) -> <T as Pointee>::Metadat /// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements. /// For trait objects, the metadata must come from a pointer to the same underlying erased type. /// +/// If you are attempting to deconstruct a DST in a generic context to be reconstructed later, +/// a thin pointer can always be obtained by casting `*const T` to `*const ()`. +/// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] #[inline] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 1b6e84175b9..f1db385e212 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -396,7 +396,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(round_char_boundary)] /// let s = "❤️🧡💛💚💙💜"; /// assert_eq!(s.len(), 26); /// assert!(!s.is_char_boundary(13)); @@ -405,7 +404,8 @@ impl str { /// assert_eq!(closest, 10); /// assert_eq!(&s[..closest], "❤️🧡"); /// ``` - #[unstable(feature = "round_char_boundary", issue = "93743")] + #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn floor_char_boundary(&self, index: usize) -> usize { if index >= self.len() { @@ -439,7 +439,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(round_char_boundary)] /// let s = "❤️🧡💛💚💙💜"; /// assert_eq!(s.len(), 26); /// assert!(!s.is_char_boundary(13)); @@ -448,7 +447,8 @@ impl str { /// assert_eq!(closest, 14); /// assert_eq!(&s[..closest], "❤️🧡💛"); /// ``` - #[unstable(feature = "round_char_boundary", issue = "93743")] + #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn ceil_char_boundary(&self, index: usize) -> usize { if index >= self.len() { @@ -3072,7 +3072,7 @@ impl str { /// for example references to `Box<str>` or `Arc<str>`. #[inline] #[unstable(feature = "str_as_str", issue = "130366")] - pub fn as_str(&self) -> &str { + pub const fn as_str(&self) -> &str { self } } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 44a6895f90a..7bd68bcd0bc 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2199,7 +2199,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); @@ -2209,7 +2208,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_add(val.wrapping_mul(size_of::<T>()), order) @@ -2240,7 +2239,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let array = [1i32, 2i32]; @@ -2254,7 +2252,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_sub(val.wrapping_mul(size_of::<T>()), order) @@ -2279,7 +2277,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut()); @@ -2289,7 +2286,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2315,7 +2312,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let mut arr = [0i64, 1]; @@ -2325,7 +2321,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2361,7 +2357,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2376,7 +2371,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2412,7 +2407,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2426,7 +2420,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2462,7 +2456,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2474,7 +2467,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. diff --git a/library/core/src/wtf8.rs b/library/core/src/wtf8.rs new file mode 100644 index 00000000000..de0dfa560a3 --- /dev/null +++ b/library/core/src/wtf8.rs @@ -0,0 +1,597 @@ +//! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/). +//! +//! This library uses Rust’s type system to maintain +//! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed), +//! like the `String` and `&str` types do for UTF-8. +//! +//! Since [WTF-8 must not be used +//! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience), +//! this library deliberately does not provide access to the underlying bytes +//! of WTF-8 strings, +//! nor can it decode WTF-8 from arbitrary bytes. +//! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points. +#![unstable( + feature = "wtf8_internals", + issue = "none", + reason = "this is internal code for representing OsStr on some platforms and not a public API" +)] +// rustdoc bug: doc(hidden) on the module won't stop types in the module from showing up in trait +// implementations, so, we'll have to add more doc(hidden)s anyway +#![doc(hidden)] + +use crate::char::{MAX_LEN_UTF16, encode_utf16_raw}; +use crate::clone::CloneToUninit; +use crate::fmt::{self, Write}; +use crate::hash::{Hash, Hasher}; +use crate::iter::FusedIterator; +use crate::num::niche_types::CodePointInner; +use crate::str::next_code_point; +use crate::{ops, slice, str}; + +/// A Unicode code point: from U+0000 to U+10FFFF. +/// +/// Compares with the `char` type, +/// which represents a Unicode scalar value: +/// a code point that is not a surrogate (U+D800 to U+DFFF). +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)] +#[doc(hidden)] +pub struct CodePoint(CodePointInner); + +/// Format the code point as `U+` followed by four to six hexadecimal digits. +/// Example: `U+1F4A9` +impl fmt::Debug for CodePoint { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(formatter, "U+{:04X}", self.0.as_inner()) + } +} + +impl CodePoint { + /// Unsafely creates a new `CodePoint` without checking the value. + /// + /// Only use when `value` is known to be less than or equal to 0x10FFFF. + #[inline] + pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint { + // SAFETY: Guaranteed by caller. + CodePoint(unsafe { CodePointInner::new_unchecked(value) }) + } + + /// Creates a new `CodePoint` if the value is a valid code point. + /// + /// Returns `None` if `value` is above 0x10FFFF. + #[inline] + pub fn from_u32(value: u32) -> Option<CodePoint> { + Some(CodePoint(CodePointInner::new(value)?)) + } + + /// Creates a new `CodePoint` from a `char`. + /// + /// Since all Unicode scalar values are code points, this always succeeds. + #[inline] + pub fn from_char(value: char) -> CodePoint { + // SAFETY: All char are valid for this type. + unsafe { CodePoint::from_u32_unchecked(value as u32) } + } + + /// Returns the numeric value of the code point. + #[inline] + pub fn to_u32(&self) -> u32 { + self.0.as_inner() + } + + /// Returns the numeric value of the code point if it is a leading surrogate. + #[inline] + pub fn to_lead_surrogate(&self) -> Option<u16> { + match self.to_u32() { + lead @ 0xD800..=0xDBFF => Some(lead as u16), + _ => None, + } + } + + /// Returns the numeric value of the code point if it is a trailing surrogate. + #[inline] + pub fn to_trail_surrogate(&self) -> Option<u16> { + match self.to_u32() { + trail @ 0xDC00..=0xDFFF => Some(trail as u16), + _ => None, + } + } + + /// Optionally returns a Unicode scalar value for the code point. + /// + /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF). + #[inline] + pub fn to_char(&self) -> Option<char> { + match self.to_u32() { + 0xD800..=0xDFFF => None, + // SAFETY: We explicitly check that the char is valid. + valid => Some(unsafe { char::from_u32_unchecked(valid) }), + } + } + + /// Returns a Unicode scalar value for the code point. + /// + /// Returns `'\u{FFFD}'` (the replacement character “�”) + /// if the code point is a surrogate (from U+D800 to U+DFFF). + #[inline] + pub fn to_char_lossy(&self) -> char { + self.to_char().unwrap_or(char::REPLACEMENT_CHARACTER) + } +} + +/// A borrowed slice of well-formed WTF-8 data. +/// +/// Similar to `&str`, but can additionally contain surrogate code points +/// if they’re not in a surrogate pair. +#[derive(Eq, Ord, PartialEq, PartialOrd)] +#[repr(transparent)] +#[rustc_has_incoherent_inherent_impls] +#[doc(hidden)] +pub struct Wtf8 { + bytes: [u8], +} + +impl AsRef<[u8]> for Wtf8 { + #[inline] + fn as_ref(&self) -> &[u8] { + &self.bytes + } +} + +/// Formats the string in double quotes, with characters escaped according to +/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`, +/// where each `x` is a hexadecimal digit. +impl fmt::Debug for Wtf8 { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result { + use crate::fmt::Write; + for c in s.chars().flat_map(|c| c.escape_debug()) { + f.write_char(c)? + } + Ok(()) + } + + formatter.write_str("\"")?; + let mut pos = 0; + while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) { + // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes. + write_str_escaped(formatter, unsafe { + str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos]) + })?; + write!(formatter, "\\u{{{:x}}}", surrogate)?; + pos = surrogate_pos + 3; + } + + // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8. + write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?; + formatter.write_str("\"") + } +} + +/// Formats the string with unpaired surrogates substituted with the replacement +/// character, U+FFFD. +impl fmt::Display for Wtf8 { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + let wtf8_bytes = &self.bytes; + let mut pos = 0; + loop { + match self.next_surrogate(pos) { + Some((surrogate_pos, _)) => { + // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes. + formatter.write_str(unsafe { + str::from_utf8_unchecked(&wtf8_bytes[pos..surrogate_pos]) + })?; + formatter.write_char(char::REPLACEMENT_CHARACTER)?; + pos = surrogate_pos + 3; + } + None => { + // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8. + let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) }; + if pos == 0 { return s.fmt(formatter) } else { return formatter.write_str(s) } + } + } + } + } +} + +impl Wtf8 { + /// Creates a WTF-8 slice from a UTF-8 `&str` slice. + #[inline] + pub fn from_str(value: &str) -> &Wtf8 { + // SAFETY: Since WTF-8 is a superset of UTF-8, this always is valid. + unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) } + } + + /// Creates a WTF-8 slice from a WTF-8 byte slice. + /// + /// Since the byte slice is not checked for valid WTF-8, this functions is + /// marked unsafe. + #[inline] + pub unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 { + // SAFETY: start with &[u8], end with fancy &[u8] + unsafe { &*(value as *const [u8] as *const Wtf8) } + } + + /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice. + /// + /// Since the byte slice is not checked for valid WTF-8, this functions is + /// marked unsafe. + #[inline] + pub unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 { + // SAFETY: start with &mut [u8], end with fancy &mut [u8] + unsafe { &mut *(value as *mut [u8] as *mut Wtf8) } + } + + /// Returns the length, in WTF-8 bytes. + #[inline] + pub fn len(&self) -> usize { + self.bytes.len() + } + + #[inline] + pub fn is_empty(&self) -> bool { + self.bytes.is_empty() + } + + /// Returns the code point at `position` if it is in the ASCII range, + /// or `b'\xFF'` otherwise. + /// + /// # Panics + /// + /// Panics if `position` is beyond the end of the string. + #[inline] + pub fn ascii_byte_at(&self, position: usize) -> u8 { + match self.bytes[position] { + ascii_byte @ 0x00..=0x7F => ascii_byte, + _ => 0xFF, + } + } + + /// Returns an iterator for the string’s code points. + #[inline] + pub fn code_points(&self) -> Wtf8CodePoints<'_> { + Wtf8CodePoints { bytes: self.bytes.iter() } + } + + /// Access raw bytes of WTF-8 data + #[inline] + pub fn as_bytes(&self) -> &[u8] { + &self.bytes + } + + /// Tries to convert the string to UTF-8 and return a `&str` slice. + /// + /// Returns `None` if the string contains surrogates. + /// + /// This does not copy the data. + #[inline] + pub fn as_str(&self) -> Result<&str, str::Utf8Error> { + str::from_utf8(&self.bytes) + } + + /// Converts the WTF-8 string to potentially ill-formed UTF-16 + /// and return an iterator of 16-bit code units. + /// + /// This is lossless: + /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units + /// would always return the original WTF-8 string. + #[inline] + pub fn encode_wide(&self) -> EncodeWide<'_> { + EncodeWide { code_points: self.code_points(), extra: 0 } + } + + #[inline] + pub fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> { + let mut iter = self.bytes[pos..].iter(); + loop { + let b = *iter.next()?; + if b < 0x80 { + pos += 1; + } else if b < 0xE0 { + iter.next(); + pos += 2; + } else if b == 0xED { + match (iter.next(), iter.next()) { + (Some(&b2), Some(&b3)) if b2 >= 0xA0 => { + return Some((pos, decode_surrogate(b2, b3))); + } + _ => pos += 3, + } + } else if b < 0xF0 { + iter.next(); + iter.next(); + pos += 3; + } else { + iter.next(); + iter.next(); + iter.next(); + pos += 4; + } + } + } + + #[inline] + pub fn final_lead_surrogate(&self) -> Option<u16> { + match self.bytes { + [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), + _ => None, + } + } + + #[inline] + pub fn initial_trail_surrogate(&self) -> Option<u16> { + match self.bytes { + [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)), + _ => None, + } + } + + #[inline] + pub fn make_ascii_lowercase(&mut self) { + self.bytes.make_ascii_lowercase() + } + + #[inline] + pub fn make_ascii_uppercase(&mut self) { + self.bytes.make_ascii_uppercase() + } + + #[inline] + pub fn is_ascii(&self) -> bool { + self.bytes.is_ascii() + } + + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + self.bytes.eq_ignore_ascii_case(&other.bytes) + } +} + +/// Returns a slice of the given string for the byte range \[`begin`..`end`). +/// +/// # Panics +/// +/// Panics when `begin` and `end` do not point to code point boundaries, +/// or point beyond the end of the string. +impl ops::Index<ops::Range<usize>> for Wtf8 { + type Output = Wtf8; + + #[inline] + fn index(&self, range: ops::Range<usize>) -> &Wtf8 { + if range.start <= range.end + && self.is_code_point_boundary(range.start) + && self.is_code_point_boundary(range.end) + { + // SAFETY: is_code_point_boundary checks that the index is valid + unsafe { slice_unchecked(self, range.start, range.end) } + } else { + slice_error_fail(self, range.start, range.end) + } + } +} + +/// Returns a slice of the given string from byte `begin` to its end. +/// +/// # Panics +/// +/// Panics when `begin` is not at a code point boundary, +/// or is beyond the end of the string. +impl ops::Index<ops::RangeFrom<usize>> for Wtf8 { + type Output = Wtf8; + + #[inline] + fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 { + if self.is_code_point_boundary(range.start) { + // SAFETY: is_code_point_boundary checks that the index is valid + unsafe { slice_unchecked(self, range.start, self.len()) } + } else { + slice_error_fail(self, range.start, self.len()) + } + } +} + +/// Returns a slice of the given string from its beginning to byte `end`. +/// +/// # Panics +/// +/// Panics when `end` is not at a code point boundary, +/// or is beyond the end of the string. +impl ops::Index<ops::RangeTo<usize>> for Wtf8 { + type Output = Wtf8; + + #[inline] + fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 { + if self.is_code_point_boundary(range.end) { + // SAFETY: is_code_point_boundary checks that the index is valid + unsafe { slice_unchecked(self, 0, range.end) } + } else { + slice_error_fail(self, 0, range.end) + } + } +} + +impl ops::Index<ops::RangeFull> for Wtf8 { + type Output = Wtf8; + + #[inline] + fn index(&self, _range: ops::RangeFull) -> &Wtf8 { + self + } +} + +#[inline] +fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 { + // The first byte is assumed to be 0xED + 0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F +} + +impl Wtf8 { + /// Copied from str::is_char_boundary + #[inline] + pub fn is_code_point_boundary(&self, index: usize) -> bool { + if index == 0 { + return true; + } + match self.bytes.get(index) { + None => index == self.len(), + Some(&b) => (b as i8) >= -0x40, + } + } + + /// Verify that `index` is at the edge of either a valid UTF-8 codepoint + /// (i.e. a codepoint that's not a surrogate) or of the whole string. + /// + /// These are the cases currently permitted by `OsStr::self_encoded_bytes`. + /// Splitting between surrogates is valid as far as WTF-8 is concerned, but + /// we do not permit it in the public API because WTF-8 is considered an + /// implementation detail. + #[track_caller] + #[inline] + pub fn check_utf8_boundary(&self, index: usize) { + if index == 0 { + return; + } + match self.bytes.get(index) { + Some(0xED) => (), // Might be a surrogate + Some(&b) if (b as i8) >= -0x40 => return, + Some(_) => panic!("byte index {index} is not a codepoint boundary"), + None if index == self.len() => return, + None => panic!("byte index {index} is out of bounds"), + } + if self.bytes[index + 1] >= 0xA0 { + // There's a surrogate after index. Now check before index. + if index >= 3 && self.bytes[index - 3] == 0xED && self.bytes[index - 2] >= 0xA0 { + panic!("byte index {index} lies between surrogate codepoints"); + } + } + } +} + +/// Copied from core::str::raw::slice_unchecked +#[inline] +unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 { + // SAFETY: memory layout of a &[u8] and &Wtf8 are the same + unsafe { + let len = end - begin; + let start = s.as_bytes().as_ptr().add(begin); + Wtf8::from_bytes_unchecked(slice::from_raw_parts(start, len)) + } +} + +/// Copied from core::str::raw::slice_error_fail +#[inline(never)] +fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! { + assert!(begin <= end); + panic!("index {begin} and/or {end} in `{s:?}` do not lie on character boundary"); +} + +/// Iterator for the code points of a WTF-8 string. +/// +/// Created with the method `.code_points()`. +#[derive(Clone)] +#[doc(hidden)] +pub struct Wtf8CodePoints<'a> { + bytes: slice::Iter<'a, u8>, +} + +impl Iterator for Wtf8CodePoints<'_> { + type Item = CodePoint; + + #[inline] + fn next(&mut self) -> Option<CodePoint> { + // SAFETY: `self.bytes` has been created from a WTF-8 string + unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint::from_u32_unchecked(c)) } + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.bytes.len(); + (len.saturating_add(3) / 4, Some(len)) + } +} + +impl fmt::Debug for Wtf8CodePoints<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Wtf8CodePoints") + // SAFETY: We always leave the string in a valid state after each iteration. + .field(&unsafe { Wtf8::from_bytes_unchecked(self.bytes.as_slice()) }) + .finish() + } +} + +/// Generates a wide character sequence for potentially ill-formed UTF-16. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +#[doc(hidden)] +pub struct EncodeWide<'a> { + code_points: Wtf8CodePoints<'a>, + extra: u16, +} + +// Copied from libunicode/u_str.rs +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for EncodeWide<'_> { + type Item = u16; + + #[inline] + fn next(&mut self) -> Option<u16> { + if self.extra != 0 { + let tmp = self.extra; + self.extra = 0; + return Some(tmp); + } + + let mut buf = [0; MAX_LEN_UTF16]; + self.code_points.next().map(|code_point| { + let n = encode_utf16_raw(code_point.to_u32(), &mut buf).len(); + if n == 2 { + self.extra = buf[1]; + } + buf[0] + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let (low, high) = self.code_points.size_hint(); + let ext = (self.extra != 0) as usize; + // every code point gets either one u16 or two u16, + // so this iterator is between 1 or 2 times as + // long as the underlying iterator. + (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext))) + } +} + +impl fmt::Debug for EncodeWide<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EncodeWide").finish_non_exhaustive() + } +} + +#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")] +impl FusedIterator for EncodeWide<'_> {} + +impl Hash for CodePoint { + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + self.0.hash(state) + } +} + +impl Hash for Wtf8 { + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + state.write(&self.bytes); + 0xfeu8.hash(state) + } +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for Wtf8 { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut u8) { + // SAFETY: we're just a transparent wrapper around [u8] + unsafe { self.bytes.clone_to_uninit(dst) } + } +} diff --git a/library/coretests/tests/iter/traits/accum.rs b/library/coretests/tests/iter/traits/accum.rs index f3eeb31fe58..95f299d2680 100644 --- a/library/coretests/tests/iter/traits/accum.rs +++ b/library/coretests/tests/iter/traits/accum.rs @@ -1,4 +1,5 @@ use core::iter::*; +use std::num::Saturating; #[test] fn test_iterator_sum() { @@ -64,3 +65,38 @@ fn test_iterator_product_option() { let v: &[Option<i32>] = &[Some(1), None, Some(3), Some(4)]; assert_eq!(v.iter().cloned().product::<Option<i32>>(), None); } + +#[test] +fn test_saturating_sum_product() { + let v = (1u32..=10).map(|i| Saturating(i)); + assert_eq!(v.sum::<Saturating<u32>>(), Saturating(55)); + let v = (1u32..=10).map(|i| Saturating(i)); + assert_eq!(v.product::<Saturating<u32>>(), Saturating(3628800)); + let v = [Saturating(usize::MAX), Saturating(2)]; + assert_eq!(v.iter().copied().sum::<Saturating<usize>>(), Saturating(usize::MAX)); + assert_eq!(v.iter().copied().product::<Saturating<usize>>(), Saturating(usize::MAX)); + + let mut cnt = 0; + let v = 250..=u8::MAX; + assert_eq!( + v.map(|i| { + cnt += 1; + Saturating(i) + }) + .sum::<Saturating<u8>>(), + Saturating(u8::MAX) + ); + assert_eq!(cnt, 6); // no short-circuiting + + let mut cnt = 0; + let v = (250..=u8::MAX).chain(0..5); + assert_eq!( + v.map(|i| { + cnt += 1; + Saturating(i) + }) + .product::<Saturating<u8>>(), + Saturating(0) + ); + assert_eq!(cnt, 11); // no short-circuiting +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index d2281b1df2f..a260c4743d7 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -80,6 +80,7 @@ #![feature(next_index)] #![feature(non_exhaustive_omitted_patterns_lint)] #![feature(numfmt)] +#![feature(option_reduce)] #![feature(pattern)] #![feature(pointer_is_aligned_to)] #![feature(portable_simd)] @@ -94,7 +95,6 @@ #![feature(std_internals)] #![feature(step_trait)] #![feature(str_internals)] -#![feature(strict_provenance_atomic_ptr)] #![feature(strict_provenance_lints)] #![feature(test)] #![feature(trusted_len)] @@ -194,6 +194,7 @@ mod time; mod tuple; mod unicode; mod waker; +mod wtf8; /// Copied from `std::test_helpers::test_rng`, see that function for rationale. #[track_caller] diff --git a/library/coretests/tests/wtf8.rs b/library/coretests/tests/wtf8.rs new file mode 100644 index 00000000000..9f187e70630 --- /dev/null +++ b/library/coretests/tests/wtf8.rs @@ -0,0 +1 @@ +// All `wtf8` tests live in library/alloctests/tests/wtf8.rs diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 1ed4f2f9f0c..d9c9606fc1c 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -3036,6 +3036,9 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> { /// Entries for the current and parent directories (typically `.` and `..`) are /// skipped. /// +/// The order in which `read_dir` returns entries can change between calls. If reproducible +/// ordering is required, the entries should be explicitly sorted. +/// /// # Platform-specific behavior /// /// This function currently corresponds to the `opendir` function on Unix diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f0de03c9a28..3771699c59f 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -263,7 +263,6 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) )] -#![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] #![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] // @@ -371,7 +370,6 @@ #![feature(slice_range)] #![feature(std_internals)] #![feature(str_internals)] -#![feature(strict_provenance_atomic_ptr)] #![feature(sync_unsafe_cell)] #![feature(temporary_niche_types)] #![feature(ub_checks)] @@ -391,6 +389,7 @@ #![feature(try_with_capacity)] #![feature(unique_rc_arc)] #![feature(vec_into_raw_parts)] +#![feature(wtf8_internals)] // tidy-alphabetical-end // // Library features (unwind): diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs index 496443dbbc3..345d5b74285 100644 --- a/library/std/src/os/windows/ffi.rs +++ b/library/std/src/os/windows/ffi.rs @@ -53,12 +53,13 @@ #![stable(feature = "rust1", since = "1.0.0")] +use alloc::wtf8::Wtf8Buf; + use crate::ffi::{OsStr, OsString}; +use crate::fmt; +use crate::iter::FusedIterator; use crate::sealed::Sealed; use crate::sys::os_str::Buf; -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::wtf8::EncodeWide; -use crate::sys_common::wtf8::Wtf8Buf; use crate::sys_common::{AsInner, FromInner}; /// Windows-specific extensions to [`OsString`]. @@ -130,6 +131,35 @@ pub trait OsStrExt: Sealed { impl OsStrExt for OsStr { #[inline] fn encode_wide(&self) -> EncodeWide<'_> { - self.as_inner().inner.encode_wide() + EncodeWide { inner: self.as_inner().inner.encode_wide() } + } +} + +/// Iterator returned by [`OsStrExt::encode_wide`]. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct EncodeWide<'a> { + inner: alloc::wtf8::EncodeWide<'a>, +} +#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")] +impl fmt::Debug for EncodeWide<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.inner, f) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for EncodeWide<'_> { + type Item = u16; + + #[inline] + fn next(&mut self) -> Option<u16> { + self.inner.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + self.inner.size_hint() } } +#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")] +impl FusedIterator for EncodeWide<'_> {} diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs index 0cbc61160f7..e3bcb149f64 100644 --- a/library/std/src/sync/mpmc/utils.rs +++ b/library/std/src/sync/mpmc/utils.rs @@ -23,14 +23,13 @@ use crate::ops::{Deref, DerefMut}; any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64",), repr(align(128)) )] -// arm, mips, mips64, and riscv64 have 32-byte cache line size. +// arm, mips and mips64 have 32-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9 -// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7 #[cfg_attr( any( target_arch = "arm", @@ -38,7 +37,6 @@ use crate::ops::{Deref, DerefMut}; target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", - target_arch = "riscv64", ), repr(align(32)) )] @@ -47,11 +45,12 @@ use crate::ops::{Deref, DerefMut}; // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7 #[cfg_attr(target_arch = "s390x", repr(align(256)))] -// x86 and wasm have 64-byte cache line size. +// x86, wasm and riscv have 64-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7 +// - https://github.com/golang/go/blob/5e31f78c8a4ed1b872ddc194f0cd1ae931b37d7e/src/internal/cpu/cpu_riscv64.go#L7 // // All others are assumed to have 64-byte cache line size. #[cfg_attr( @@ -64,7 +63,6 @@ use crate::ops::{Deref, DerefMut}; target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", - target_arch = "riscv64", target_arch = "s390x", )), repr(align(64)) diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs index c8fab992a88..48e2fdd4ecc 100644 --- a/library/std/src/sys/alloc/wasm.rs +++ b/library/std/src/sys/alloc/wasm.rs @@ -16,12 +16,15 @@ //! The crate itself provides a global allocator which on wasm has no //! synchronization as there are no threads! -// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#![allow(static_mut_refs)] +use core::cell::SyncUnsafeCell; use crate::alloc::{GlobalAlloc, Layout, System}; -static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new(); +struct SyncDlmalloc(dlmalloc::Dlmalloc); +unsafe impl Sync for SyncDlmalloc {} + +static DLMALLOC: SyncUnsafeCell<SyncDlmalloc> = + SyncUnsafeCell::new(SyncDlmalloc(dlmalloc::Dlmalloc::new())); #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { @@ -30,7 +33,7 @@ unsafe impl GlobalAlloc for System { // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. // Calling malloc() is safe because preconditions on this function match the trait method preconditions. let _lock = lock::lock(); - unsafe { DLMALLOC.malloc(layout.size(), layout.align()) } + unsafe { (*DLMALLOC.get()).0.malloc(layout.size(), layout.align()) } } #[inline] @@ -38,7 +41,7 @@ unsafe impl GlobalAlloc for System { // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. // Calling calloc() is safe because preconditions on this function match the trait method preconditions. let _lock = lock::lock(); - unsafe { DLMALLOC.calloc(layout.size(), layout.align()) } + unsafe { (*DLMALLOC.get()).0.calloc(layout.size(), layout.align()) } } #[inline] @@ -46,7 +49,7 @@ unsafe impl GlobalAlloc for System { // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. // Calling free() is safe because preconditions on this function match the trait method preconditions. let _lock = lock::lock(); - unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) } + unsafe { (*DLMALLOC.get()).0.free(ptr, layout.size(), layout.align()) } } #[inline] @@ -54,7 +57,7 @@ unsafe impl GlobalAlloc for System { // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. // Calling realloc() is safe because preconditions on this function match the trait method preconditions. let _lock = lock::lock(); - unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } + unsafe { (*DLMALLOC.get()).0.realloc(ptr, layout.size(), layout.align(), new_size) } } } diff --git a/library/std/src/sys/backtrace.rs b/library/std/src/sys/backtrace.rs index 272d0fa4d1a..57682207e07 100644 --- a/library/std/src/sys/backtrace.rs +++ b/library/std/src/sys/backtrace.rs @@ -113,7 +113,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: res = bt_fmt.frame().symbol(frame, symbol); } }); - #[cfg(target_os = "nto")] + #[cfg(all(target_os = "nto", any(target_env = "nto70", target_env = "nto71")))] if libc::__my_thread_exit as *mut libc::c_void == frame.ip() { if !hit && print { use crate::backtrace_rs::SymbolName; diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index dbd782f5018..0276bf6e64c 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -117,9 +117,18 @@ pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> { #[cfg(unix)] pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> { use crate::fs::OpenOptions; - use crate::os::unix::fs::OpenOptionsExt; - OpenOptions::new().custom_flags(libc::O_NOFOLLOW).open(path)?.set_permissions(perm) + let mut options = OpenOptions::new(); + + // ESP-IDF and Horizon do not support O_NOFOLLOW, so we skip setting it. + // Their filesystems do not have symbolic links, so no special handling is required. + #[cfg(not(any(target_os = "espidf", target_os = "horizon")))] + { + use crate::os::unix::fs::OpenOptionsExt; + options.custom_flags(libc::O_NOFOLLOW); + } + + options.open(path)?.set_permissions(perm) } #[cfg(not(unix))] diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs index bbc704ebf86..96da891874e 100644 --- a/library/std/src/sys/os_str/wtf8.rs +++ b/library/std/src/sys/os_str/wtf8.rs @@ -1,12 +1,12 @@ //! The underlying OsString/OsStr implementation on Windows is a //! wrapper around the "WTF-8" encoding; see the `wtf8` module for more. +use alloc::wtf8::{Wtf8, Wtf8Buf}; use core::clone::CloneToUninit; use crate::borrow::Cow; use crate::collections::TryReserveError; use crate::rc::Rc; use crate::sync::Arc; -use crate::sys_common::wtf8::{Wtf8, Wtf8Buf, check_utf8_boundary}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fmt, mem}; @@ -220,7 +220,9 @@ impl Buf { /// trailing surrogate half. #[inline] pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) { - self.inner.extend_from_slice(other); + unsafe { + self.inner.extend_from_slice_unchecked(other); + } } } @@ -238,7 +240,7 @@ impl Slice { #[track_caller] #[inline] pub fn check_public_boundary(&self, index: usize) { - check_utf8_boundary(&self.inner, index); + self.inner.check_utf8_boundary(index); } #[inline] diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index aef7ab55088..400128acf12 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -382,6 +382,7 @@ cfg_select! { unsafe extern "C" {} } target_os = "netbsd" => { + #[link(name = "execinfo")] #[link(name = "pthread")] #[link(name = "rt")] unsafe extern "C" {} diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 81275afa707..aec089f7e5c 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -16,10 +16,7 @@ use crate::{fmt, io, iter, mem, ptr, slice, str}; const TMPBUF_SZ: usize = 128; -const PATH_SEPARATOR: u8 = cfg_select! { - target_os = "redox" => b';', - _ => b':', -}; +const PATH_SEPARATOR: u8 = if cfg!(target_os = "redox") { b';' } else { b':' }; unsafe extern "C" { #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] @@ -189,33 +186,14 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { if result == 0 { Ok(()) } else { Err(io::Error::last_os_error()) } } -pub struct SplitPaths<'a> { - iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>, fn(&'a [u8]) -> PathBuf>, -} +pub type SplitPaths<'a> = impl Iterator<Item = PathBuf>; +#[define_opaque(SplitPaths)] pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { - fn bytes_to_path(b: &[u8]) -> PathBuf { - PathBuf::from(<OsStr as OsStrExt>::from_bytes(b)) - } - fn is_separator(b: &u8) -> bool { - *b == PATH_SEPARATOR - } - let unparsed = unparsed.as_bytes(); - SplitPaths { - iter: unparsed - .split(is_separator as fn(&u8) -> bool) - .map(bytes_to_path as fn(&[u8]) -> PathBuf), - } -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option<PathBuf> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } + unparsed + .as_bytes() + .split(|&b| b == PATH_SEPARATOR) + .map(|part| PathBuf::from(OsStr::from_bytes(part))) } #[derive(Debug)] @@ -469,7 +447,7 @@ pub fn current_exe() -> io::Result<PathBuf> { unsafe { let result = libc::find_path( crate::ptr::null_mut(), - libc::path_base_directory::B_FIND_PATH_IMAGE_PATH, + libc::B_FIND_PATH_IMAGE_PATH, crate::ptr::null_mut(), name.as_mut_ptr(), name.len(), diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index 6b0cd14da4f..4798acf9dad 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -20,6 +20,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { // and musl 0.9.3, and some other targets also have it. cfg_select! { any( + target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "hurd", diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 24b6cff1309..ec45c723e0d 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -21,7 +21,6 @@ mod tests; pub mod wstr; -pub mod wtf8; // common error constructors diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs deleted file mode 100644 index 50bde88b5a4..00000000000 --- a/library/std/src/sys_common/wtf8.rs +++ /dev/null @@ -1,1083 +0,0 @@ -//! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/). -//! -//! This library uses Rust’s type system to maintain -//! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed), -//! like the `String` and `&str` types do for UTF-8. -//! -//! Since [WTF-8 must not be used -//! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience), -//! this library deliberately does not provide access to the underlying bytes -//! of WTF-8 strings, -//! nor can it decode WTF-8 from arbitrary bytes. -//! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points. - -// this module is imported from @SimonSapin's repo and has tons of dead code on -// unix (it's mostly used on windows), so don't worry about dead code here. -#![allow(dead_code)] - -#[cfg(test)] -mod tests; - -use core::char::{MAX_LEN_UTF8, MAX_LEN_UTF16, encode_utf8_raw, encode_utf16_raw}; -use core::clone::CloneToUninit; -use core::str::next_code_point; - -use crate::borrow::Cow; -use crate::collections::TryReserveError; -use crate::hash::{Hash, Hasher}; -use crate::iter::FusedIterator; -use crate::rc::Rc; -use crate::sync::Arc; -use crate::sys_common::AsInner; -use crate::{fmt, mem, ops, slice, str}; - -const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}"; - -/// A Unicode code point: from U+0000 to U+10FFFF. -/// -/// Compares with the `char` type, -/// which represents a Unicode scalar value: -/// a code point that is not a surrogate (U+D800 to U+DFFF). -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)] -pub struct CodePoint { - value: u32, -} - -/// Format the code point as `U+` followed by four to six hexadecimal digits. -/// Example: `U+1F4A9` -impl fmt::Debug for CodePoint { - #[inline] - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(formatter, "U+{:04X}", self.value) - } -} - -impl CodePoint { - /// Unsafely creates a new `CodePoint` without checking the value. - /// - /// Only use when `value` is known to be less than or equal to 0x10FFFF. - #[inline] - pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint { - CodePoint { value } - } - - /// Creates a new `CodePoint` if the value is a valid code point. - /// - /// Returns `None` if `value` is above 0x10FFFF. - #[inline] - pub fn from_u32(value: u32) -> Option<CodePoint> { - match value { - 0..=0x10FFFF => Some(CodePoint { value }), - _ => None, - } - } - - /// Creates a new `CodePoint` from a `char`. - /// - /// Since all Unicode scalar values are code points, this always succeeds. - #[inline] - pub fn from_char(value: char) -> CodePoint { - CodePoint { value: value as u32 } - } - - /// Returns the numeric value of the code point. - #[inline] - pub fn to_u32(&self) -> u32 { - self.value - } - - /// Returns the numeric value of the code point if it is a leading surrogate. - #[inline] - pub fn to_lead_surrogate(&self) -> Option<u16> { - match self.value { - lead @ 0xD800..=0xDBFF => Some(lead as u16), - _ => None, - } - } - - /// Returns the numeric value of the code point if it is a trailing surrogate. - #[inline] - pub fn to_trail_surrogate(&self) -> Option<u16> { - match self.value { - trail @ 0xDC00..=0xDFFF => Some(trail as u16), - _ => None, - } - } - - /// Optionally returns a Unicode scalar value for the code point. - /// - /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF). - #[inline] - pub fn to_char(&self) -> Option<char> { - match self.value { - 0xD800..=0xDFFF => None, - _ => Some(unsafe { char::from_u32_unchecked(self.value) }), - } - } - - /// Returns a Unicode scalar value for the code point. - /// - /// Returns `'\u{FFFD}'` (the replacement character “�”) - /// if the code point is a surrogate (from U+D800 to U+DFFF). - #[inline] - pub fn to_char_lossy(&self) -> char { - self.to_char().unwrap_or('\u{FFFD}') - } -} - -/// An owned, growable string of well-formed WTF-8 data. -/// -/// Similar to `String`, but can additionally contain surrogate code points -/// if they’re not in a surrogate pair. -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)] -pub struct Wtf8Buf { - bytes: Vec<u8>, - - /// Do we know that `bytes` holds a valid UTF-8 encoding? We can easily - /// know this if we're constructed from a `String` or `&str`. - /// - /// It is possible for `bytes` to have valid UTF-8 without this being - /// set, such as when we're concatenating `&Wtf8`'s and surrogates become - /// paired, as we don't bother to rescan the entire string. - is_known_utf8: bool, -} - -impl ops::Deref for Wtf8Buf { - type Target = Wtf8; - - fn deref(&self) -> &Wtf8 { - self.as_slice() - } -} - -impl ops::DerefMut for Wtf8Buf { - fn deref_mut(&mut self) -> &mut Wtf8 { - self.as_mut_slice() - } -} - -/// Formats the string in double quotes, with characters escaped according to -/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`, -/// where each `x` is a hexadecimal digit. -/// -/// For example, the code units [U+0061, U+D800, U+000A] are formatted as -/// `"a\u{D800}\n"`. -impl fmt::Debug for Wtf8Buf { - #[inline] - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, formatter) - } -} - -/// Formats the string with unpaired surrogates substituted with the replacement -/// character, U+FFFD. -impl fmt::Display for Wtf8Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(s) = self.as_known_utf8() { - fmt::Display::fmt(s, formatter) - } else { - fmt::Display::fmt(&**self, formatter) - } - } -} - -impl Wtf8Buf { - /// Creates a new, empty WTF-8 string. - #[inline] - pub fn new() -> Wtf8Buf { - Wtf8Buf { bytes: Vec::new(), is_known_utf8: true } - } - - /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes. - #[inline] - pub fn with_capacity(capacity: usize) -> Wtf8Buf { - Wtf8Buf { bytes: Vec::with_capacity(capacity), is_known_utf8: true } - } - - /// Creates a WTF-8 string from a WTF-8 byte vec. - /// - /// Since the byte vec is not checked for valid WTF-8, this function is - /// marked unsafe. - #[inline] - pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf { - Wtf8Buf { bytes: value, is_known_utf8: false } - } - - /// Creates a WTF-8 string from a UTF-8 `String`. - /// - /// This takes ownership of the `String` and does not copy. - /// - /// Since WTF-8 is a superset of UTF-8, this always succeeds. - #[inline] - pub const fn from_string(string: String) -> Wtf8Buf { - Wtf8Buf { bytes: string.into_bytes(), is_known_utf8: true } - } - - /// Creates a WTF-8 string from a UTF-8 `&str` slice. - /// - /// This copies the content of the slice. - /// - /// Since WTF-8 is a superset of UTF-8, this always succeeds. - #[inline] - pub fn from_str(s: &str) -> Wtf8Buf { - Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true } - } - - pub fn clear(&mut self) { - self.bytes.clear(); - self.is_known_utf8 = true; - } - - /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units. - /// - /// This is lossless: calling `.encode_wide()` on the resulting string - /// will always return the original code units. - pub fn from_wide(v: &[u16]) -> Wtf8Buf { - let mut string = Wtf8Buf::with_capacity(v.len()); - for item in char::decode_utf16(v.iter().cloned()) { - match item { - Ok(ch) => string.push_char(ch), - Err(surrogate) => { - let surrogate = surrogate.unpaired_surrogate(); - // Surrogates are known to be in the code point range. - let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) }; - // The string will now contain an unpaired surrogate. - string.is_known_utf8 = false; - // Skip the WTF-8 concatenation check, - // surrogate pairs are already decoded by decode_utf16 - string.push_code_point_unchecked(code_point); - } - } - } - string - } - - /// Appends the given `char` to the end of this string. - /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check. - /// Copied from String::push. - fn push_code_point_unchecked(&mut self, code_point: CodePoint) { - let mut bytes = [0; MAX_LEN_UTF8]; - let bytes = encode_utf8_raw(code_point.value, &mut bytes); - self.bytes.extend_from_slice(bytes) - } - - #[inline] - pub fn as_slice(&self) -> &Wtf8 { - unsafe { Wtf8::from_bytes_unchecked(&self.bytes) } - } - - #[inline] - pub fn as_mut_slice(&mut self) -> &mut Wtf8 { - // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would - // cause them to change from well-formed UTF-8 to ill-formed UTF-8, - // which would break the assumptions of the `is_known_utf8` field. - unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) } - } - - /// Converts the string to UTF-8 without validation, if it was created from - /// valid UTF-8. - #[inline] - fn as_known_utf8(&self) -> Option<&str> { - if self.is_known_utf8 { - // SAFETY: The buffer is known to be valid UTF-8. - Some(unsafe { str::from_utf8_unchecked(self.as_bytes()) }) - } else { - None - } - } - - /// Reserves capacity for at least `additional` more bytes to be inserted - /// in the given `Wtf8Buf`. - /// The collection may reserve more space to avoid frequent reallocations. - /// - /// # Panics - /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. - #[inline] - pub fn reserve(&mut self, additional: usize) { - self.bytes.reserve(additional) - } - - /// Tries to reserve capacity for at least `additional` more bytes to be - /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to - /// avoid frequent reallocations. After calling `try_reserve`, capacity will - /// be greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. This method preserves the contents even - /// if an error occurs. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - #[inline] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.bytes.try_reserve(additional) - } - - #[inline] - pub fn reserve_exact(&mut self, additional: usize) { - self.bytes.reserve_exact(additional) - } - - /// Tries to reserve the minimum capacity for exactly `additional` more - /// bytes to be inserted in the given `Wtf8Buf`. After calling - /// `try_reserve_exact`, capacity will be greater than or equal to - /// `self.len() + additional` if it returns `Ok(())`. - /// Does nothing if the capacity is already sufficient. - /// - /// Note that the allocator may give the `Wtf8Buf` more space than it - /// requests. Therefore, capacity can not be relied upon to be precisely - /// minimal. Prefer [`try_reserve`] if future insertions are expected. - /// - /// [`try_reserve`]: Wtf8Buf::try_reserve - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - #[inline] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.bytes.try_reserve_exact(additional) - } - - #[inline] - pub fn shrink_to_fit(&mut self) { - self.bytes.shrink_to_fit() - } - - #[inline] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.bytes.shrink_to(min_capacity) - } - - #[inline] - pub fn leak<'a>(self) -> &'a mut Wtf8 { - unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) } - } - - /// Returns the number of bytes that this string buffer can hold without reallocating. - #[inline] - pub fn capacity(&self) -> usize { - self.bytes.capacity() - } - - /// Append a UTF-8 slice at the end of the string. - #[inline] - pub fn push_str(&mut self, other: &str) { - self.bytes.extend_from_slice(other.as_bytes()) - } - - /// Append a WTF-8 slice at the end of the string. - /// - /// This replaces newly paired surrogates at the boundary - /// with a supplementary code point, - /// like concatenating ill-formed UTF-16 strings effectively would. - #[inline] - pub fn push_wtf8(&mut self, other: &Wtf8) { - match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) { - // Replace newly paired surrogates by a supplementary code point. - (Some(lead), Some(trail)) => { - let len_without_lead_surrogate = self.len() - 3; - self.bytes.truncate(len_without_lead_surrogate); - let other_without_trail_surrogate = &other.bytes[3..]; - // 4 bytes for the supplementary code point - self.bytes.reserve(4 + other_without_trail_surrogate.len()); - self.push_char(decode_surrogate_pair(lead, trail)); - self.bytes.extend_from_slice(other_without_trail_surrogate); - } - _ => { - // If we'll be pushing a string containing a surrogate, we may - // no longer have UTF-8. - if self.is_known_utf8 && other.next_surrogate(0).is_some() { - self.is_known_utf8 = false; - } - - self.bytes.extend_from_slice(&other.bytes); - } - } - } - - /// Append a Unicode scalar value at the end of the string. - #[inline] - pub fn push_char(&mut self, c: char) { - self.push_code_point_unchecked(CodePoint::from_char(c)) - } - - /// Append a code point at the end of the string. - /// - /// This replaces newly paired surrogates at the boundary - /// with a supplementary code point, - /// like concatenating ill-formed UTF-16 strings effectively would. - #[inline] - pub fn push(&mut self, code_point: CodePoint) { - if let Some(trail) = code_point.to_trail_surrogate() { - if let Some(lead) = (&*self).final_lead_surrogate() { - let len_without_lead_surrogate = self.len() - 3; - self.bytes.truncate(len_without_lead_surrogate); - self.push_char(decode_surrogate_pair(lead, trail)); - return; - } - - // We're pushing a trailing surrogate. - self.is_known_utf8 = false; - } else if code_point.to_lead_surrogate().is_some() { - // We're pushing a leading surrogate. - self.is_known_utf8 = false; - } - - // No newly paired surrogates at the boundary. - self.push_code_point_unchecked(code_point) - } - - /// Shortens a string to the specified length. - /// - /// # Panics - /// - /// Panics if `new_len` > current length, - /// or if `new_len` is not a code point boundary. - #[inline] - pub fn truncate(&mut self, new_len: usize) { - assert!(is_code_point_boundary(self, new_len)); - self.bytes.truncate(new_len) - } - - /// Consumes the WTF-8 string and tries to convert it to a vec of bytes. - #[inline] - pub fn into_bytes(self) -> Vec<u8> { - self.bytes - } - - /// Consumes the WTF-8 string and tries to convert it to UTF-8. - /// - /// This does not copy the data. - /// - /// If the contents are not well-formed UTF-8 - /// (that is, if the string contains surrogates), - /// the original WTF-8 string is returned instead. - pub fn into_string(self) -> Result<String, Wtf8Buf> { - if self.is_known_utf8 || self.next_surrogate(0).is_none() { - Ok(unsafe { String::from_utf8_unchecked(self.bytes) }) - } else { - Err(self) - } - } - - /// Consumes the WTF-8 string and converts it lossily to UTF-8. - /// - /// This does not copy the data (but may overwrite parts of it in place). - /// - /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”) - pub fn into_string_lossy(mut self) -> String { - if !self.is_known_utf8 { - let mut pos = 0; - while let Some((surrogate_pos, _)) = self.next_surrogate(pos) { - pos = surrogate_pos + 3; - // Surrogates and the replacement character are all 3 bytes, so - // they can substituted in-place. - self.bytes[surrogate_pos..pos] - .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); - } - } - unsafe { String::from_utf8_unchecked(self.bytes) } - } - - /// Converts this `Wtf8Buf` into a boxed `Wtf8`. - #[inline] - pub fn into_box(self) -> Box<Wtf8> { - // SAFETY: relies on `Wtf8` being `repr(transparent)`. - unsafe { mem::transmute(self.bytes.into_boxed_slice()) } - } - - /// Converts a `Box<Wtf8>` into a `Wtf8Buf`. - pub fn from_box(boxed: Box<Wtf8>) -> Wtf8Buf { - let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) }; - Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false } - } - - /// Provides plumbing to core `Vec::extend_from_slice`. - /// More well behaving alternative to allowing outer types - /// full mutable access to the core `Vec`. - #[inline] - pub(crate) fn extend_from_slice(&mut self, other: &[u8]) { - self.bytes.extend_from_slice(other); - self.is_known_utf8 = false; - } -} - -/// Creates a new WTF-8 string from an iterator of code points. -/// -/// This replaces surrogate code point pairs with supplementary code points, -/// like concatenating ill-formed UTF-16 strings effectively would. -impl FromIterator<CodePoint> for Wtf8Buf { - fn from_iter<T: IntoIterator<Item = CodePoint>>(iter: T) -> Wtf8Buf { - let mut string = Wtf8Buf::new(); - string.extend(iter); - string - } -} - -/// Append code points from an iterator to the string. -/// -/// This replaces surrogate code point pairs with supplementary code points, -/// like concatenating ill-formed UTF-16 strings effectively would. -impl Extend<CodePoint> for Wtf8Buf { - fn extend<T: IntoIterator<Item = CodePoint>>(&mut self, iter: T) { - let iterator = iter.into_iter(); - let (low, _high) = iterator.size_hint(); - // Lower bound of one byte per code point (ASCII only) - self.bytes.reserve(low); - iterator.for_each(move |code_point| self.push(code_point)); - } - - #[inline] - fn extend_one(&mut self, code_point: CodePoint) { - self.push(code_point); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - // Lower bound of one byte per code point (ASCII only) - self.bytes.reserve(additional); - } -} - -/// A borrowed slice of well-formed WTF-8 data. -/// -/// Similar to `&str`, but can additionally contain surrogate code points -/// if they’re not in a surrogate pair. -#[derive(Eq, Ord, PartialEq, PartialOrd)] -#[repr(transparent)] -pub struct Wtf8 { - bytes: [u8], -} - -impl AsInner<[u8]> for Wtf8 { - #[inline] - fn as_inner(&self) -> &[u8] { - &self.bytes - } -} - -/// Formats the string in double quotes, with characters escaped according to -/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`, -/// where each `x` is a hexadecimal digit. -impl fmt::Debug for Wtf8 { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result { - use crate::fmt::Write; - for c in s.chars().flat_map(|c| c.escape_debug()) { - f.write_char(c)? - } - Ok(()) - } - - formatter.write_str("\"")?; - let mut pos = 0; - while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) { - write_str_escaped(formatter, unsafe { - str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos]) - })?; - write!(formatter, "\\u{{{:x}}}", surrogate)?; - pos = surrogate_pos + 3; - } - write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?; - formatter.write_str("\"") - } -} - -/// Formats the string with unpaired surrogates substituted with the replacement -/// character, U+FFFD. -impl fmt::Display for Wtf8 { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - let wtf8_bytes = &self.bytes; - let mut pos = 0; - loop { - match self.next_surrogate(pos) { - Some((surrogate_pos, _)) => { - formatter.write_str(unsafe { - str::from_utf8_unchecked(&wtf8_bytes[pos..surrogate_pos]) - })?; - formatter.write_str(UTF8_REPLACEMENT_CHARACTER)?; - pos = surrogate_pos + 3; - } - None => { - let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) }; - if pos == 0 { return s.fmt(formatter) } else { return formatter.write_str(s) } - } - } - } - } -} - -impl Wtf8 { - /// Creates a WTF-8 slice from a UTF-8 `&str` slice. - /// - /// Since WTF-8 is a superset of UTF-8, this always succeeds. - #[inline] - pub fn from_str(value: &str) -> &Wtf8 { - unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) } - } - - /// Creates a WTF-8 slice from a WTF-8 byte slice. - /// - /// Since the byte slice is not checked for valid WTF-8, this functions is - /// marked unsafe. - #[inline] - pub unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 { - // SAFETY: start with &[u8], end with fancy &[u8] - unsafe { &*(value as *const [u8] as *const Wtf8) } - } - - /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice. - /// - /// Since the byte slice is not checked for valid WTF-8, this functions is - /// marked unsafe. - #[inline] - unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 { - // SAFETY: start with &mut [u8], end with fancy &mut [u8] - unsafe { &mut *(value as *mut [u8] as *mut Wtf8) } - } - - /// Returns the length, in WTF-8 bytes. - #[inline] - pub fn len(&self) -> usize { - self.bytes.len() - } - - #[inline] - pub fn is_empty(&self) -> bool { - self.bytes.is_empty() - } - - /// Returns the code point at `position` if it is in the ASCII range, - /// or `b'\xFF'` otherwise. - /// - /// # Panics - /// - /// Panics if `position` is beyond the end of the string. - #[inline] - pub fn ascii_byte_at(&self, position: usize) -> u8 { - match self.bytes[position] { - ascii_byte @ 0x00..=0x7F => ascii_byte, - _ => 0xFF, - } - } - - /// Returns an iterator for the string’s code points. - #[inline] - pub fn code_points(&self) -> Wtf8CodePoints<'_> { - Wtf8CodePoints { bytes: self.bytes.iter() } - } - - /// Access raw bytes of WTF-8 data - #[inline] - pub fn as_bytes(&self) -> &[u8] { - &self.bytes - } - - /// Tries to convert the string to UTF-8 and return a `&str` slice. - /// - /// Returns `None` if the string contains surrogates. - /// - /// This does not copy the data. - #[inline] - pub fn as_str(&self) -> Result<&str, str::Utf8Error> { - str::from_utf8(&self.bytes) - } - - /// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`. - pub fn to_owned(&self) -> Wtf8Buf { - Wtf8Buf { bytes: self.bytes.to_vec(), is_known_utf8: false } - } - - /// Lossily converts the string to UTF-8. - /// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8. - /// - /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”). - /// - /// This only copies the data if necessary (if it contains any surrogate). - pub fn to_string_lossy(&self) -> Cow<'_, str> { - let Some((surrogate_pos, _)) = self.next_surrogate(0) else { - return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }); - }; - let wtf8_bytes = &self.bytes; - let mut utf8_bytes = Vec::with_capacity(self.len()); - utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]); - utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); - let mut pos = surrogate_pos + 3; - loop { - match self.next_surrogate(pos) { - Some((surrogate_pos, _)) => { - utf8_bytes.extend_from_slice(&wtf8_bytes[pos..surrogate_pos]); - utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); - pos = surrogate_pos + 3; - } - None => { - utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]); - return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) }); - } - } - } - } - - /// Converts the WTF-8 string to potentially ill-formed UTF-16 - /// and return an iterator of 16-bit code units. - /// - /// This is lossless: - /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units - /// would always return the original WTF-8 string. - #[inline] - pub fn encode_wide(&self) -> EncodeWide<'_> { - EncodeWide { code_points: self.code_points(), extra: 0 } - } - - #[inline] - fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> { - let mut iter = self.bytes[pos..].iter(); - loop { - let b = *iter.next()?; - if b < 0x80 { - pos += 1; - } else if b < 0xE0 { - iter.next(); - pos += 2; - } else if b == 0xED { - match (iter.next(), iter.next()) { - (Some(&b2), Some(&b3)) if b2 >= 0xA0 => { - return Some((pos, decode_surrogate(b2, b3))); - } - _ => pos += 3, - } - } else if b < 0xF0 { - iter.next(); - iter.next(); - pos += 3; - } else { - iter.next(); - iter.next(); - iter.next(); - pos += 4; - } - } - } - - #[inline] - fn final_lead_surrogate(&self) -> Option<u16> { - match self.bytes { - [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), - _ => None, - } - } - - #[inline] - fn initial_trail_surrogate(&self) -> Option<u16> { - match self.bytes { - [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)), - _ => None, - } - } - - pub fn clone_into(&self, buf: &mut Wtf8Buf) { - buf.is_known_utf8 = false; - self.bytes.clone_into(&mut buf.bytes); - } - - /// Boxes this `Wtf8`. - #[inline] - pub fn into_box(&self) -> Box<Wtf8> { - let boxed: Box<[u8]> = self.bytes.into(); - unsafe { mem::transmute(boxed) } - } - - /// Creates a boxed, empty `Wtf8`. - pub fn empty_box() -> Box<Wtf8> { - let boxed: Box<[u8]> = Default::default(); - unsafe { mem::transmute(boxed) } - } - - #[inline] - pub fn into_arc(&self) -> Arc<Wtf8> { - let arc: Arc<[u8]> = Arc::from(&self.bytes); - unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) } - } - - #[inline] - pub fn into_rc(&self) -> Rc<Wtf8> { - let rc: Rc<[u8]> = Rc::from(&self.bytes); - unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) } - } - - #[inline] - pub fn make_ascii_lowercase(&mut self) { - self.bytes.make_ascii_lowercase() - } - - #[inline] - pub fn make_ascii_uppercase(&mut self) { - self.bytes.make_ascii_uppercase() - } - - #[inline] - pub fn to_ascii_lowercase(&self) -> Wtf8Buf { - Wtf8Buf { bytes: self.bytes.to_ascii_lowercase(), is_known_utf8: false } - } - - #[inline] - pub fn to_ascii_uppercase(&self) -> Wtf8Buf { - Wtf8Buf { bytes: self.bytes.to_ascii_uppercase(), is_known_utf8: false } - } - - #[inline] - pub fn is_ascii(&self) -> bool { - self.bytes.is_ascii() - } - - #[inline] - pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { - self.bytes.eq_ignore_ascii_case(&other.bytes) - } -} - -/// Returns a slice of the given string for the byte range \[`begin`..`end`). -/// -/// # Panics -/// -/// Panics when `begin` and `end` do not point to code point boundaries, -/// or point beyond the end of the string. -impl ops::Index<ops::Range<usize>> for Wtf8 { - type Output = Wtf8; - - #[inline] - fn index(&self, range: ops::Range<usize>) -> &Wtf8 { - // is_code_point_boundary checks that the index is in [0, .len()] - if range.start <= range.end - && is_code_point_boundary(self, range.start) - && is_code_point_boundary(self, range.end) - { - unsafe { slice_unchecked(self, range.start, range.end) } - } else { - slice_error_fail(self, range.start, range.end) - } - } -} - -/// Returns a slice of the given string from byte `begin` to its end. -/// -/// # Panics -/// -/// Panics when `begin` is not at a code point boundary, -/// or is beyond the end of the string. -impl ops::Index<ops::RangeFrom<usize>> for Wtf8 { - type Output = Wtf8; - - #[inline] - fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 { - // is_code_point_boundary checks that the index is in [0, .len()] - if is_code_point_boundary(self, range.start) { - unsafe { slice_unchecked(self, range.start, self.len()) } - } else { - slice_error_fail(self, range.start, self.len()) - } - } -} - -/// Returns a slice of the given string from its beginning to byte `end`. -/// -/// # Panics -/// -/// Panics when `end` is not at a code point boundary, -/// or is beyond the end of the string. -impl ops::Index<ops::RangeTo<usize>> for Wtf8 { - type Output = Wtf8; - - #[inline] - fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 { - // is_code_point_boundary checks that the index is in [0, .len()] - if is_code_point_boundary(self, range.end) { - unsafe { slice_unchecked(self, 0, range.end) } - } else { - slice_error_fail(self, 0, range.end) - } - } -} - -impl ops::Index<ops::RangeFull> for Wtf8 { - type Output = Wtf8; - - #[inline] - fn index(&self, _range: ops::RangeFull) -> &Wtf8 { - self - } -} - -#[inline] -fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 { - // The first byte is assumed to be 0xED - 0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F -} - -#[inline] -fn decode_surrogate_pair(lead: u16, trail: u16) -> char { - let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32); - unsafe { char::from_u32_unchecked(code_point) } -} - -/// Copied from str::is_char_boundary -#[inline] -pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool { - if index == 0 { - return true; - } - match slice.bytes.get(index) { - None => index == slice.len(), - Some(&b) => (b as i8) >= -0x40, - } -} - -/// Verify that `index` is at the edge of either a valid UTF-8 codepoint -/// (i.e. a codepoint that's not a surrogate) or of the whole string. -/// -/// These are the cases currently permitted by `OsStr::slice_encoded_bytes`. -/// Splitting between surrogates is valid as far as WTF-8 is concerned, but -/// we do not permit it in the public API because WTF-8 is considered an -/// implementation detail. -#[track_caller] -#[inline] -pub fn check_utf8_boundary(slice: &Wtf8, index: usize) { - if index == 0 { - return; - } - match slice.bytes.get(index) { - Some(0xED) => (), // Might be a surrogate - Some(&b) if (b as i8) >= -0x40 => return, - Some(_) => panic!("byte index {index} is not a codepoint boundary"), - None if index == slice.len() => return, - None => panic!("byte index {index} is out of bounds"), - } - if slice.bytes[index + 1] >= 0xA0 { - // There's a surrogate after index. Now check before index. - if index >= 3 && slice.bytes[index - 3] == 0xED && slice.bytes[index - 2] >= 0xA0 { - panic!("byte index {index} lies between surrogate codepoints"); - } - } -} - -/// Copied from core::str::raw::slice_unchecked -#[inline] -pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 { - // SAFETY: memory layout of a &[u8] and &Wtf8 are the same - unsafe { - let len = end - begin; - let start = s.as_bytes().as_ptr().add(begin); - Wtf8::from_bytes_unchecked(slice::from_raw_parts(start, len)) - } -} - -/// Copied from core::str::raw::slice_error_fail -#[inline(never)] -pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! { - assert!(begin <= end); - panic!("index {begin} and/or {end} in `{s:?}` do not lie on character boundary"); -} - -/// Iterator for the code points of a WTF-8 string. -/// -/// Created with the method `.code_points()`. -#[derive(Clone)] -pub struct Wtf8CodePoints<'a> { - bytes: slice::Iter<'a, u8>, -} - -impl Iterator for Wtf8CodePoints<'_> { - type Item = CodePoint; - - #[inline] - fn next(&mut self) -> Option<CodePoint> { - // SAFETY: `self.bytes` has been created from a WTF-8 string - unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint { value: c }) } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let len = self.bytes.len(); - (len.saturating_add(3) / 4, Some(len)) - } -} - -/// Generates a wide character sequence for potentially ill-formed UTF-16. -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Clone)] -pub struct EncodeWide<'a> { - code_points: Wtf8CodePoints<'a>, - extra: u16, -} - -// Copied from libunicode/u_str.rs -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for EncodeWide<'_> { - type Item = u16; - - #[inline] - fn next(&mut self) -> Option<u16> { - if self.extra != 0 { - let tmp = self.extra; - self.extra = 0; - return Some(tmp); - } - - let mut buf = [0; MAX_LEN_UTF16]; - self.code_points.next().map(|code_point| { - let n = encode_utf16_raw(code_point.value, &mut buf).len(); - if n == 2 { - self.extra = buf[1]; - } - buf[0] - }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let (low, high) = self.code_points.size_hint(); - let ext = (self.extra != 0) as usize; - // every code point gets either one u16 or two u16, - // so this iterator is between 1 or 2 times as - // long as the underlying iterator. - (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext))) - } -} - -#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")] -impl FusedIterator for EncodeWide<'_> {} - -impl Hash for CodePoint { - #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { - self.value.hash(state) - } -} - -impl Hash for Wtf8Buf { - #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { - state.write(&self.bytes); - 0xfeu8.hash(state) - } -} - -impl Hash for Wtf8 { - #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { - state.write(&self.bytes); - 0xfeu8.hash(state) - } -} - -#[unstable(feature = "clone_to_uninit", issue = "126799")] -unsafe impl CloneToUninit for Wtf8 { - #[inline] - #[cfg_attr(debug_assertions, track_caller)] - unsafe fn clone_to_uninit(&self, dst: *mut u8) { - // SAFETY: we're just a transparent wrapper around [u8] - unsafe { self.bytes.clone_to_uninit(dst) } - } -} diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index d30005c8d51..0b75e85772f 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -99,28 +99,12 @@ impl Std { deps } - /// Returns true if the standard library will be uplifted from stage 1 for the given - /// `build_compiler` (which determines the stdlib stage) and `target`. + /// Returns true if the standard library should be uplifted from stage 1. /// - /// Uplifting is enabled if we're building a stage2+ libstd, full bootstrap is - /// disabled and we have a stage1 libstd already compiled for the given target. - pub fn should_be_uplifted_from_stage_1( - builder: &Builder<'_>, - stage: u32, - target: TargetSelection, - ) -> bool { - stage > 1 - && !builder.config.full_bootstrap - // This estimates if a stage1 libstd exists for the given target. If we're not - // cross-compiling, it should definitely exist by the time we're building a stage2 - // libstd. - // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that - // rustc needs to link to a cross-compiled libstd, so again we should have a stage1 - // libstd for the given target prepared. - // Even if we guess wrong in the cross-compiled case, the worst that should happen is - // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we - // don't pay the libstd build cost twice. - && (target == builder.host_target || builder.config.hosts.contains(&target)) + /// Uplifting is enabled if we're building a stage2+ libstd and full bootstrap is + /// disabled. + pub fn should_be_uplifted_from_stage_1(builder: &Builder<'_>, stage: u32) -> bool { + stage > 1 && !builder.config.full_bootstrap } } @@ -150,7 +134,9 @@ impl Step for Std { trace!(force_recompile); run.builder.ensure(Std { - build_compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), + // Note: we don't use compiler_for_std here, so that `x build library --stage 2` + // builds a stage2 rustc. + build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target), target: run.target, crates, force_recompile, @@ -226,7 +212,7 @@ impl Step for Std { // Stage of the stdlib that we're building let stage = build_compiler.stage; - if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage, target) { + if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) { let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target); let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target); diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 778c3beb50f..f113dd7683d 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -96,6 +96,8 @@ impl Step for Docs { } } +/// Builds the `rust-docs-json` installer component. +/// It contains the documentation of the standard library in JSON format. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct JsonDocs { build_compiler: Compiler, @@ -113,12 +115,11 @@ impl Step for JsonDocs { fn make_run(run: RunConfig<'_>) { run.builder.ensure(JsonDocs { - build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target), + build_compiler: run.builder.compiler_for_std(run.builder.top_stage), target: run.target, }); } - /// Builds the `rust-docs-json` installer component. fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> { let target = self.target; let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler( @@ -135,6 +136,10 @@ impl Step for JsonDocs { tarball.add_bulk_dir(directory, dest); Some(tarball.generate()) } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler)) + } } /// Builds the `rustc-docs` installer component. @@ -764,22 +769,7 @@ pub struct Std { impl Std { pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self { - // This is an important optimization mainly for CI. - // Normally, to build stage N libstd, we need stage N rustc. - // However, if we know that we will uplift libstd from stage 1 anyway, building the stage N - // rustc can be wasteful. - // In particular, if we do a cross-compiling dist stage 2 build from T1 to T2, we need: - // - stage 2 libstd for T2 (uplifted from stage 1, where it was built by T1 rustc) - // - stage 2 rustc for T2 - // However, without this optimization, we would also build stage 2 rustc for **T1**, which - // is completely wasteful. - let build_compiler = - if compile::Std::should_be_uplifted_from_stage_1(builder, builder.top_stage, target) { - builder.compiler(1, builder.host_target) - } else { - builder.compiler(builder.top_stage, builder.host_target) - }; - Std { build_compiler, target } + Std { build_compiler: builder.compiler_for_std(builder.top_stage), target } } } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 8c20c8c479a..9ef1fee1fec 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -616,7 +616,7 @@ impl Step for Std { return; } run.builder.ensure(Std { - build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target), + build_compiler: run.builder.compiler_for_std(run.builder.top_stage), target: run.target, format: if run.builder.config.cmd.json() { DocumentationFormat::Json diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index abe79405984..26b4aaa8b5b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2025,8 +2025,6 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?} cmd.arg("--verbose"); } - cmd.arg("--json"); - if builder.config.rustc_debug_assertions { cmd.arg("--with-rustc-debug-assertions"); } diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index f794f4e079a..b224a7e7322 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1360,6 +1360,30 @@ impl<'a> Builder<'a> { self.ensure(compile::Assemble { target_compiler: Compiler::new(stage, host) }) } + /// This function can be used to provide a build compiler for building + /// the standard library, in order to avoid unnecessary rustc builds in case where std uplifting + /// would happen anyway. + /// + /// This is an important optimization mainly for CI. + /// + /// Normally, to build stage N libstd, we need stage N rustc. + /// However, if we know that we will uplift libstd from stage 1 anyway, building the stage N + /// rustc can be wasteful. + /// In particular, if we do a cross-compiling dist stage 2 build from target1 to target2, + /// we need: + /// - stage 2 libstd for target2 (uplifted from stage 1, where it was built by target1 rustc) + /// - stage 2 rustc for target2 + /// + /// However, without this optimization, we would also build stage 2 rustc for **target1**, + /// which is completely wasteful. + pub fn compiler_for_std(&self, stage: u32) -> Compiler { + if compile::Std::should_be_uplifted_from_stage_1(self, stage) { + self.compiler(1, self.host_target) + } else { + self.compiler(stage, self.host_target) + } + } + /// Similar to `compiler`, except handles the full-bootstrap option to /// silently use the stage1 compiler instead of a stage2 compiler if one is /// requested. diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 3c2cb782850..b079117c5a7 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1066,6 +1066,7 @@ mod snapshot { [build] rustc 1 <host> -> rustc 2 <target1> [build] rustc 2 <host> -> std 2 <host> [build] rustc 2 <host> -> std 2 <target1> + [build] rustc 1 <host> -> std 1 <target2> [build] rustc 2 <host> -> std 2 <target2> "); } @@ -1122,9 +1123,8 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -1141,8 +1141,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <host> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> [dist] mingw <host> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [dist] rustc 1 <host> -> std 1 <host> @@ -1182,12 +1184,11 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> [build] rustc 1 <host> -> LldWrapper 2 <host> [build] rustc 1 <host> -> WasmComponentLd 2 <host> [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -1204,8 +1205,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <host> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> [dist] mingw <host> + [build] rustdoc 2 <host> [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> @@ -1226,6 +1229,8 @@ mod snapshot { [build] rustc 1 <host> -> miri 2 <host> [build] rustc 1 <host> -> cargo-miri 2 <host> [dist] rustc 1 <host> -> miri 2 <host> + [doc] rustc 2 <host> -> std 2 <host> crates=[] + [dist] rustc 2 <host> -> json-docs 3 <host> [dist] rustc 1 <host> -> extended 2 <host> [dist] reproducible-artifacts <host> "); @@ -1259,10 +1264,9 @@ mod snapshot { [doc] book/2018-edition (book) <target1> [doc] rustc 1 <host> -> standalone 2 <host> [doc] rustc 1 <host> -> standalone 2 <target1> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -1290,15 +1294,17 @@ mod snapshot { [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [dist] docs <target1> - [doc] rustc 2 <host> -> std 2 <host> crates=[] - [doc] rustc 2 <host> -> std 2 <target1> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> + [doc] rustc 1 <host> -> std 1 <target1> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <target1> [dist] mingw <host> [dist] mingw <target1> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [dist] rustc 1 <host> -> std 1 <host> - [build] rustc 2 <host> -> std 2 <target1> - [dist] rustc 2 <host> -> std 2 <target1> + [dist] rustc 1 <host> -> std 1 <target1> [dist] rustc 1 <host> -> rustc-dev 2 <host> [dist] src <> [dist] reproducible-artifacts <host> @@ -1327,9 +1333,8 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [build] llvm <target1> @@ -1352,8 +1357,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <host> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> [dist] mingw <host> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [build] rustdoc 2 <target1> @@ -1396,10 +1403,9 @@ mod snapshot { [doc] book/2018-edition (book) <target1> [doc] rustc 1 <host> -> standalone 2 <host> [doc] rustc 1 <host> -> standalone 2 <target1> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [build] llvm <target1> @@ -1432,10 +1438,13 @@ mod snapshot { [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [dist] docs <target1> - [doc] rustc 2 <host> -> std 2 <host> crates=[] - [doc] rustc 2 <host> -> std 2 <target1> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> + [doc] rustc 1 <host> -> std 1 <target1> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <target1> [dist] mingw <host> [dist] mingw <target1> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [build] rustdoc 2 <target1> @@ -1473,9 +1482,7 @@ mod snapshot { [build] rustdoc 1 <host> [build] rustc 1 <host> -> std 1 <host> [doc] rustc 1 <host> -> standalone 2 <target1> - [build] rustc 1 <host> -> rustc 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [doc] nomicon (book) <target1> [doc] rustc 1 <host> -> reference (book) 2 <target1> [doc] rustdoc (book) <target1> @@ -1488,10 +1495,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <target1> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <target1> - [doc] rustc 2 <host> -> std 2 <target1> crates=[] + [doc] rustc 1 <host> -> std 1 <target1> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <target1> [dist] mingw <target1> - [build] rustc 2 <host> -> std 2 <target1> - [dist] rustc 2 <host> -> std 2 <target1> + [dist] rustc 1 <host> -> std 1 <target1> "); } @@ -1519,10 +1526,7 @@ mod snapshot { [build] rustdoc 1 <host> [build] rustc 1 <host> -> std 1 <host> [doc] rustc 1 <host> -> standalone 2 <target1> - [build] rustc 1 <host> -> rustc 2 <host> - [build] rustc 1 <host> -> WasmComponentLd 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 <host> -> std 1 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] llvm <target1> [build] rustc 1 <host> -> rustc 2 <target1> [build] rustc 1 <host> -> WasmComponentLd 2 <target1> @@ -1542,7 +1546,8 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <target1> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <target1> - [doc] rustc 2 <host> -> std 2 <target1> crates=[] + [doc] rustc 1 <host> -> std 1 <target1> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <target1> [dist] mingw <target1> [build] rustdoc 2 <target1> [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <target1> @@ -1567,13 +1572,14 @@ mod snapshot { [dist] rustc 1 <host> -> miri 2 <target1> [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1> [doc] rustc 2 <target1> -> std 2 <target1> crates=[] + [dist] rustc 2 <target1> -> json-docs 3 <target1> [dist] rustc 1 <host> -> extended 2 <target1> [dist] reproducible-artifacts <target1> "); } /// Simulates e.g. the powerpc64 builder, which is fully cross-compiled from x64, but it does - /// not build docs. Crutically, it shouldn't build host stage 2 rustc. + /// not build docs. Crucially, it shouldn't build host stage 2 rustc. /// /// This is a regression test for <https://github.com/rust-lang/rust/issues/138123> /// and <https://github.com/rust-lang/rust/issues/138004>. @@ -1663,10 +1669,9 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> [build] rustc 1 <host> -> rustc_codegen_cranelift 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -1683,8 +1688,10 @@ mod snapshot { [doc] rustc 1 <host> -> releases 2 <host> [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[] + [doc] rustc 1 <host> -> std 1 <host> crates=[] + [dist] rustc 1 <host> -> json-docs 2 <host> [dist] mingw <host> + [build] rustdoc 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> [dist] rustc 1 <host> -> rustc_codegen_cranelift 2 <host> @@ -1725,6 +1732,46 @@ mod snapshot { } #[test] + fn dist_rustc_docs() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx + .config("dist") + .path("rustc-docs") + .render_steps(), @r" + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> + [doc] unstable-book (book) <host> + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [doc] book (book) <host> + [doc] book/first-edition (book) <host> + [doc] book/second-edition (book) <host> + [doc] book/2018-edition (book) <host> + [build] rustdoc 1 <host> + [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 1 <host> -> error-index 2 <host> + [doc] rustc 1 <host> -> error-index 2 <host> + [doc] nomicon (book) <host> + [doc] rustc 1 <host> -> reference (book) 2 <host> + [doc] rustdoc (book) <host> + [doc] rust-by-example (book) <host> + [build] rustc 0 <host> -> LintDocs 1 <host> + [doc] rustc (book) <host> + [doc] cargo (book) <host> + [doc] clippy (book) <host> + [doc] embedded-book (book) <host> + [doc] edition-guide (book) <host> + [doc] style-guide (book) <host> + [doc] rustc 1 <host> -> releases 2 <host> + [build] rustc 0 <host> -> RustInstaller 1 <host> + "); + } + + #[test] fn check_compiler_no_explicit_stage() { let ctx = TestCtx::new(); insta::assert_snapshot!( @@ -2415,10 +2462,9 @@ mod snapshot { [doc] book/2018-edition (book) <host> [build] rustdoc 1 <host> [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> rustc 2 <host> [build] rustc 1 <host> -> WasmComponentLd 2 <host> - [build] rustdoc 2 <host> - [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 1 <host> -> error-index 2 <host> [doc] rustc 1 <host> -> error-index 2 <host> [doc] nomicon (book) <host> @@ -2436,6 +2482,7 @@ mod snapshot { [build] rustc 0 <host> -> RustInstaller 1 <host> [dist] docs <host> [dist] rustc 1 <host> -> std 1 <host> + [build] rustdoc 2 <host> [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <host> [build] rustc 0 <host> -> GenerateCopyright 1 <host> [dist] rustc <host> diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index 40006aca5c5..90fd57d976d 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -250,8 +250,14 @@ impl<'a> Renderer<'a> { if failure.stdout.is_some() || failure.message.is_some() { println!("---- {} stdout ----", failure.name); if let Some(stdout) = &failure.stdout { - println!("{stdout}"); + // Captured test output normally ends with a newline, + // so only use `println!` if it doesn't. + print!("{stdout}"); + if !stdout.ends_with('\n') { + println!("\n\\ (no newline at end of output)"); + } } + println!("---- {} stdout end ----", failure.name); if let Some(message) = &failure.message { println!("NOTE: {message}"); } diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 2f815bcd141..edfc2db7d6f 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -103,7 +103,6 @@ target | notes [`powerpc64le-unknown-linux-gnu`](platform-support/powerpc64le-unknown-linux-gnu.md) | PPC64LE Linux (kernel 3.10+, glibc 2.17) [`powerpc64le-unknown-linux-musl`](platform-support/powerpc64le-unknown-linux-musl.md) | PPC64LE Linux (kernel 4.19+, musl 1.2.3) [`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20+, glibc 2.29) -[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20+, musl 1.2.3) [`s390x-unknown-linux-gnu`](platform-support/s390x-unknown-linux-gnu.md) | S390x Linux (kernel 3.2+, glibc 2.17) [`x86_64-apple-darwin`](platform-support/apple-darwin.md) | 64-bit macOS (10.12+, Sierra+) [`x86_64-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | 64-bit x86 MinGW (Windows 10+), LLVM ABI @@ -183,6 +182,7 @@ target | std | notes [`riscv32imac-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA) [`riscv32imafc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA) [`riscv32imc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA) +[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20+, musl 1.2.3) `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA) `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA) `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4+, glibc 2.23) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index bb28e3abbf3..25c929a1dba 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -196,7 +196,7 @@ to enable. ### Document keywords -This is for Rust compiler internal use only. +This is for internal use in the std library. Rust keywords are documented in the standard library (look for `match` for example). @@ -211,6 +211,23 @@ To do so, the `#[doc(keyword = "...")]` attribute is used. Example: mod empty_mod {} ``` +### Document builtin attributes + +This is for internal use in the std library. + +Rust builtin attributes are documented in the standard library (look for `repr` for example). + +To do so, the `#[doc(attribute = "...")]` attribute is used. Example: + +```rust +#![feature(rustdoc_internals)] +#![allow(internal_features)] + +/// Some documentation about the attribute. +#[doc(attribute = "repr")] +mod empty_mod {} +``` + ### Use the Rust logo as the crate logo This is for official Rust project use only. diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 5d36ffc2d3a..2985971a053 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -12,20 +12,20 @@ path = "lib.rs" arrayvec = { version = "0.7", default-features = false } askama = { version = "0.14", default-features = false, features = ["alloc", "config", "derive"] } base64 = "0.21.7" -indexmap = "2" -itertools = "0.12" +indexmap.workspace = true +itertools.workspace = true minifier = { version = "0.3.5", default-features = false } pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] } regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +serde_json.workspace = true smallvec = "1.8.1" stringdex = { version = "0.0.1-alpha4" } -tempfile = "3" +tempfile.workspace = true threadpool = "1.8.1" -tracing = "0.1" tracing-tree = "0.3.0" +tracing.workspace = true unicode-segmentation = "1.9" # tidy-alphabetical-end diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0d98c64bbde..8461e15c6c3 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -572,30 +572,30 @@ pub(crate) fn build_impl( super::build_deref_target_impls(cx, &trait_items, ret); } - // Return if the trait itself or any types of the generic parameters are doc(hidden). - let mut stack: Vec<&Type> = vec![&for_]; + if !document_hidden { + // Return if the trait itself or any types of the generic parameters are doc(hidden). + let mut stack: Vec<&Type> = vec![&for_]; - if let Some(did) = trait_.as_ref().map(|t| t.def_id()) - && !document_hidden - && tcx.is_doc_hidden(did) - { - return; - } - - if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) { - stack.extend(generics); - } - - while let Some(ty) = stack.pop() { - if let Some(did) = ty.def_id(&cx.cache) - && !document_hidden + if let Some(did) = trait_.as_ref().map(|t| t.def_id()) && tcx.is_doc_hidden(did) { return; } - if let Some(generics) = ty.generics() { + + if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) { stack.extend(generics); } + + while let Some(ty) = stack.pop() { + if let Some(did) = ty.def_id(&cx.cache) + && tcx.is_doc_hidden(did) + { + return; + } + if let Some(generics) = ty.generics() { + stack.extend(generics); + } + } } if let Some(did) = trait_.as_ref().map(|t| t.def_id()) { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 92bd4a498ca..fcff15650ce 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -226,15 +226,28 @@ impl ExternalCrate { } pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> { - fn as_keyword(did: DefId, tcx: TyCtxt<'_>) -> Option<(DefId, Symbol)> { + self.retrieve_keywords_or_documented_attributes(tcx, sym::keyword) + } + pub(crate) fn documented_attributes( + &self, + tcx: TyCtxt<'_>, + ) -> impl Iterator<Item = (DefId, Symbol)> { + self.retrieve_keywords_or_documented_attributes(tcx, sym::attribute) + } + + fn retrieve_keywords_or_documented_attributes( + &self, + tcx: TyCtxt<'_>, + name: Symbol, + ) -> impl Iterator<Item = (DefId, Symbol)> { + let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> { tcx.get_attrs(did, sym::doc) .flat_map(|attr| attr.meta_item_list().unwrap_or_default()) - .filter(|meta| meta.has_name(sym::keyword)) + .filter(|meta| meta.has_name(name)) .find_map(|meta| meta.value_str()) .map(|value| (did, value)) - } - - self.mapped_root_modules(tcx, as_keyword) + }; + self.mapped_root_modules(tcx, as_target) } pub(crate) fn primitives( @@ -592,6 +605,20 @@ impl Item { pub(crate) fn is_keyword(&self) -> bool { self.type_() == ItemType::Keyword } + pub(crate) fn is_attribute(&self) -> bool { + self.type_() == ItemType::Attribute + } + /// Returns `true` if the item kind is one of the following: + /// + /// * `ItemType::Primitive` + /// * `ItemType::Keyword` + /// * `ItemType::Attribute` + /// + /// They are considered fake because they only exist thanks to their + /// `#[doc(primitive|keyword|attribute)]` attribute. + pub(crate) fn is_fake_item(&self) -> bool { + matches!(self.type_(), ItemType::Primitive | ItemType::Keyword | ItemType::Attribute) + } pub(crate) fn is_stripped(&self) -> bool { match self.kind { StrippedItem(..) => true, @@ -735,7 +762,9 @@ impl Item { // Primitives and Keywords are written in the source code as private modules. // The modules need to be private so that nobody actually uses them, but the // keywords and primitives that they are documenting are public. - ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public), + ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) | ItemKind::AttributeItem => { + return Some(Visibility::Public); + } // Variant fields inherit their enum's visibility. StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => { return None; @@ -942,7 +971,12 @@ pub(crate) enum ItemKind { AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>), /// An item that has been stripped by a rustdoc pass StrippedItem(Box<ItemKind>), + /// This item represents a module with a `#[doc(keyword = "...")]` attribute which is used + /// to generate documentation for Rust keywords. KeywordItem, + /// This item represents a module with a `#[doc(attribute = "...")]` attribute which is used + /// to generate documentation for Rust builtin attributes. + AttributeItem, } impl ItemKind { @@ -983,7 +1017,8 @@ impl ItemKind { | RequiredAssocTypeItem(..) | AssocTypeItem(..) | StrippedItem(_) - | KeywordItem => [].iter(), + | KeywordItem + | AttributeItem => [].iter(), } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 813fdee57e1..6fc1e43c724 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -60,6 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { let local_crate = ExternalCrate { crate_num: LOCAL_CRATE }; let primitives = local_crate.primitives(cx.tcx); let keywords = local_crate.keywords(cx.tcx); + let documented_attributes = local_crate.documented_attributes(cx.tcx); { let ItemKind::ModuleItem(m) = &mut module.inner.kind else { unreachable!() }; m.items.extend(primitives.map(|(def_id, prim)| { @@ -73,6 +74,9 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { m.items.extend(keywords.map(|(def_id, kw)| { Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem, cx) })); + m.items.extend(documented_attributes.into_iter().map(|(def_id, kw)| { + Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::AttributeItem, cx) + })); } Crate { module, external_traits: Box::new(mem::take(&mut cx.external_traits)) } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index c03d16ad081..ee5f260615d 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -96,7 +96,8 @@ pub(crate) trait DocFolder: Sized { | ImplAssocConstItem(..) | RequiredAssocTypeItem(..) | AssocTypeItem(..) - | KeywordItem => kind, + | KeywordItem + | AttributeItem => kind, } } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index cb6837dd614..29b4c4caaf8 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -372,7 +372,8 @@ impl DocFolder for CacheBuilder<'_, '_> { | clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) | clean::StrippedItem(..) - | clean::KeywordItem => { + | clean::KeywordItem + | clean::AttributeItem => { // FIXME: Do these need handling? // The person writing this comment doesn't know. // So would rather leave them to an expert, diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 142a9d7d8af..e94ef517309 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -57,6 +57,7 @@ pub(crate) enum ItemType { TraitAlias = 25, // This number is reserved for use in JavaScript // Generic = 26, + Attribute = 27, } impl Serialize for ItemType { @@ -148,6 +149,7 @@ impl<'a> From<&'a clean::Item> for ItemType { clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType, clean::ForeignTypeItem => ItemType::ForeignType, clean::KeywordItem => ItemType::Keyword, + clean::AttributeItem => ItemType::Attribute, clean::TraitAliasItem(..) => ItemType::TraitAlias, clean::ProcMacroItem(mac) => match mac.kind { MacroKind::Bang => ItemType::Macro, @@ -236,6 +238,7 @@ impl ItemType { ItemType::ProcAttribute => "attr", ItemType::ProcDerive => "derive", ItemType::TraitAlias => "traitalias", + ItemType::Attribute => "attribute", } } pub(crate) fn is_method(&self) -> bool { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index faaecaf0cbb..5f92ab2fada 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -218,7 +218,7 @@ impl<'tcx> Context<'tcx> { } else { it.name.as_ref().unwrap().as_str() }; - if !it.is_primitive() && !it.is_keyword() { + if !it.is_fake_item() { if !is_module { title.push_str(" in "); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 673947ad308..6db90c9bf2a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2535,6 +2535,7 @@ pub(crate) enum ItemSection { AssociatedConstants, ForeignTypes, Keywords, + Attributes, AttributeMacros, DeriveMacros, TraitAliases, @@ -2567,6 +2568,7 @@ impl ItemSection { AssociatedConstants, ForeignTypes, Keywords, + Attributes, AttributeMacros, DeriveMacros, TraitAliases, @@ -2596,6 +2598,7 @@ impl ItemSection { Self::AssociatedConstants => "associated-consts", Self::ForeignTypes => "foreign-types", Self::Keywords => "keywords", + Self::Attributes => "attributes", Self::AttributeMacros => "attributes", Self::DeriveMacros => "derives", Self::TraitAliases => "trait-aliases", @@ -2625,6 +2628,7 @@ impl ItemSection { Self::AssociatedConstants => "Associated Constants", Self::ForeignTypes => "Foreign Types", Self::Keywords => "Keywords", + Self::Attributes => "Attributes", Self::AttributeMacros => "Attribute Macros", Self::DeriveMacros => "Derive Macros", Self::TraitAliases => "Trait Aliases", @@ -2655,6 +2659,7 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection { ItemType::AssocConst => ItemSection::AssociatedConstants, ItemType::ForeignType => ItemSection::ForeignTypes, ItemType::Keyword => ItemSection::Keywords, + ItemType::Attribute => ItemSection::Attributes, ItemType::ProcAttribute => ItemSection::AttributeMacros, ItemType::ProcDerive => ItemSection::DeriveMacros, ItemType::TraitAlias => ItemSection::TraitAliases, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index b86a2c94697..afa438f2596 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -173,6 +173,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp clean::ConstantItem(..) => "Constant ", clean::ForeignTypeItem => "Foreign Type ", clean::KeywordItem => "Keyword ", + clean::AttributeItem => "Attribute ", clean::TraitAliasItem(..) => "Trait Alias ", _ => { // We don't generate pages for any other type. @@ -193,7 +194,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp let src_href = if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None }; - let path_components = if item.is_primitive() || item.is_keyword() { + let path_components = if item.is_fake_item() { vec![] } else { let cur = &cx.current; @@ -252,7 +253,9 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Disp clean::ForeignTypeItem => { write!(buf, "{}", item_foreign_type(cx, item)) } - clean::KeywordItem => write!(buf, "{}", item_keyword(cx, item)), + clean::KeywordItem | clean::AttributeItem => { + write!(buf, "{}", item_keyword_or_attribute(cx, item)) + } clean::TraitAliasItem(ta) => { write!(buf, "{}", item_trait_alias(cx, item, ta)) } @@ -2151,7 +2154,7 @@ fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display { }) } -fn item_keyword(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display { +fn item_keyword_or_attribute(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display { document(cx, it, None, HeadingOffset::H2) } diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css index a3c6bf98161..5c02e2eb26a 100644 --- a/src/librustdoc/html/static/css/noscript.css +++ b/src/librustdoc/html/static/css/noscript.css @@ -75,6 +75,7 @@ nav.sub { --function-link-color: #ad7c37; --macro-link-color: #068000; --keyword-link-color: #3873ad; + --attribute-link-color: #3873ad; --mod-link-color: #3873ad; --link-color: #3873ad; --sidebar-link-color: #356da4; @@ -180,6 +181,7 @@ nav.sub { --function-link-color: #2bab63; --macro-link-color: #09bd00; --keyword-link-color: #d2991d; + --attribute-link-color: #d2991d; --mod-link-color: #d2991d; --link-color: #d2991d; --sidebar-link-color: #fdbf35; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 86f1a42bc01..09d289d570c 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -400,6 +400,10 @@ span.keyword, a.keyword { color: var(--keyword-link-color); } +span.attribute, a.attribute { + color: var(--attribute-link-color); +} + a { color: var(--link-color); text-decoration: none; @@ -3190,6 +3194,7 @@ by default. --function-link-color: #ad7c37; --macro-link-color: #068000; --keyword-link-color: #3873ad; + --attribute-link-color: #3873ad; --mod-link-color: #3873ad; --link-color: #3873ad; --sidebar-link-color: #356da4; @@ -3294,6 +3299,7 @@ by default. --function-link-color: #2bab63; --macro-link-color: #09bd00; --keyword-link-color: #d2991d; + --attribute-link-color: #d2991d; --mod-link-color: #d2991d; --link-color: #d2991d; --sidebar-link-color: #fdbf35; @@ -3407,6 +3413,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) --function-link-color: #fdd687; --macro-link-color: #a37acc; --keyword-link-color: #39afd7; + --attribute-link-color: #39afd7; --mod-link-color: #39afd7; --link-color: #39afd7; --sidebar-link-color: #53b1db; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 4fcba5f120b..75febd6f737 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -790,6 +790,7 @@ function preLoadCss(cssUrl) { //block("associatedconstant", "associated-consts", "Associated Constants"); block("foreigntype", "foreign-types", "Foreign Types"); block("keyword", "keywords", "Keywords"); + block("attribute", "attributes", "Attributes"); block("attr", "attributes", "Attribute Macros"); block("derive", "derives", "Derive Macros"); block("traitalias", "trait-aliases", "Trait Aliases"); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 3fb4db3a89c..b003bcc7bf9 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -119,6 +119,7 @@ const itemTypes = [ "derive", "traitalias", // 25 "generic", + "attribute", ]; // used for special search precedence @@ -2058,7 +2059,7 @@ class DocSearch { displayPath = item.modulePath + "::"; href = this.rootPath + item.modulePath.replace(/::/g, "/") + "/index.html#reexport." + name; - } else if (type === "primitive" || type === "keyword") { + } else if (type === "primitive" || type === "keyword" || type === "attribute") { displayPath = ""; exactPath = ""; href = this.rootPath + path.replace(/::/g, "/") + @@ -4560,6 +4561,8 @@ const longItemTypes = [ "attribute macro", "derive macro", "trait alias", + "", + "attribute", ]; // @ts-expect-error let currentResults; diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 5fab8ad2a4b..f0520716228 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -52,7 +52,7 @@ impl JsonRenderer<'_> { let clean::ItemInner { name, item_id, .. } = *item.inner; let id = self.id_from_item(item); let inner = match item.kind { - clean::KeywordItem => return None, + clean::KeywordItem | clean::AttributeItem => return None, clean::StrippedItem(ref inner) => { match &**inner { // We document stripped modules as with `Module::is_stripped` set to @@ -85,7 +85,7 @@ impl JsonRenderer<'_> { fn ids(&self, items: &[clean::Item]) -> Vec<Id> { items .iter() - .filter(|i| !i.is_stripped() && !i.is_keyword()) + .filter(|i| !i.is_stripped() && !i.is_keyword() && !i.is_attribute()) .map(|i| self.id_from_item(i)) .collect() } @@ -93,7 +93,10 @@ impl JsonRenderer<'_> { fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> { items .iter() - .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(i))) + .map(|i| { + (!i.is_stripped() && !i.is_keyword() && !i.is_attribute()) + .then(|| self.id_from_item(i)) + }) .collect() } } @@ -332,8 +335,8 @@ fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum bounds: b.into_json(renderer), type_: Some(t.item_type.as_ref().unwrap_or(&t.type_).into_json(renderer)), }, - // `convert_item` early returns `None` for stripped items and keywords. - KeywordItem => unreachable!(), + // `convert_item` early returns `None` for stripped items, keywords and attributes. + KeywordItem | AttributeItem => unreachable!(), StrippedItem(inner) => { match inner.as_ref() { ModuleItem(m) => ItemEnum::Module(Module { @@ -887,6 +890,7 @@ impl FromClean<ItemType> for ItemKind { AssocType => ItemKind::AssocType, ForeignType => ItemKind::ExternType, Keyword => ItemKind::Keyword, + Attribute => ItemKind::Attribute, TraitAlias => ItemKind::TraitAlias, ProcAttribute => ItemKind::ProcAttribute, ProcDerive => ItemKind::ProcDerive, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e2682045ab4..f62eba4b3c1 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1,4 +1,5 @@ // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![doc( html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/" @@ -13,7 +14,6 @@ #![feature(if_let_guard)] #![feature(iter_advance_by)] #![feature(iter_intersperse)] -#![feature(round_char_boundary)] #![feature(rustc_private)] #![feature(test)] #![warn(rustc::internal)] @@ -760,7 +760,9 @@ fn run_renderer< tcx.dcx().struct_fatal(format!("couldn't generate documentation: {}", e.error)); let file = e.file.display().to_string(); if !file.is_empty() { - msg.note(format!("failed to create or modify \"{file}\"")); + msg.note(format!("failed to create or modify {e}")); + } else { + msg.note(format!("failed to create or modify file: {e}")); } msg.emit(); } diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 8028afea363..e0ea760cf3b 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -67,6 +67,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - | clean::ImportItem(_) | clean::PrimitiveItem(_) | clean::KeywordItem + | clean::AttributeItem | clean::ModuleItem(_) | clean::TraitAliasItem(_) | clean::ForeignFunctionItem(..) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index bad51d7f5b2..719b7c6ab89 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -19,7 +19,7 @@ use rustc_hir::{Mutability, Safety}; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::{bug, span_bug, ty}; use rustc_resolve::rustdoc::{ - MalformedGenerics, has_primitive_or_keyword_docs, prepare_to_doc_link_resolution, + MalformedGenerics, has_primitive_or_keyword_or_attribute_docs, prepare_to_doc_link_resolution, source_span_for_markdown_range, strip_generics_from_path, }; use rustc_session::config::CrateType; @@ -1073,7 +1073,7 @@ impl LinkCollector<'_, '_> { && let Some(def_id) = item.item_id.as_def_id() && let Some(def_id) = def_id.as_local() && !self.cx.tcx.effective_visibilities(()).is_exported(def_id) - && !has_primitive_or_keyword_docs(&item.attrs.other_attrs) + && !has_primitive_or_keyword_or_attribute_docs(&item.attrs.other_attrs) { // Skip link resolution for non-exported items. return; diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index 14ec58702e3..5139ca301dd 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -106,7 +106,8 @@ impl DocFolder for StabilityPropagator<'_, '_> { | ItemKind::RequiredAssocTypeItem(..) | ItemKind::AssocTypeItem(..) | ItemKind::PrimitiveItem(..) - | ItemKind::KeywordItem => own_stability, + | ItemKind::KeywordItem + | ItemKind::AttributeItem => own_stability, ItemKind::StrippedItem(..) => unreachable!(), } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index eedbbca0f8d..99d22526f85 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -133,6 +133,8 @@ impl DocFolder for Stripper<'_, '_> { // Keywords are never stripped clean::KeywordItem => {} + // Attributes are never stripped + clean::AttributeItem => {} } let fastreturn = match i.kind { diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index b8b619514aa..4d31409afe8 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -49,7 +49,8 @@ pub(crate) trait DocVisitor<'a>: Sized { | ImplAssocConstItem(..) | RequiredAssocTypeItem(..) | AssocTypeItem(..) - | KeywordItem => {} + | KeywordItem + | AttributeItem => {} } } diff --git a/src/llvm-project b/src/llvm-project -Subproject 9a1f898064f52269bc94675dcbd620b46d45d17 +Subproject 19f0a49c5c3f4ba88b5e7ac620b9a0d8574c09c diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 40f89009a43..658d3791d25 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -37,8 +37,8 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc // will instead cause conflicts. See #94591 for more. (This paragraph and the "Latest feature" line // are deliberately not in a doc comment, because they need not be in public docs.) // -// Latest feature: Add Attribute::MacroUse -pub const FORMAT_VERSION: u32 = 55; +// Latest feature: Add `ItemKind::Attribute`. +pub const FORMAT_VERSION: u32 = 56; /// The root of the emitted JSON blob. /// @@ -552,6 +552,11 @@ pub enum ItemKind { /// [`Item`]s of this kind only come from the come library and exist solely /// to carry documentation for the respective keywords. Keyword, + /// An attribute declaration. + /// + /// [`Item`]s of this kind only come from the core library and exist solely + /// to carry documentation for the respective builtin attributes. + Attribute, } /// Specific fields of an item. diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index efa99f181b3..05d5f21c12c 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] toml = "0.7" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +serde_json.workspace = true anyhow = "1.0.32" flate2 = "1.0.26" xz2 = "0.1.7" diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 623d536836b4cde09ce38609232a024d5b25da8 +Subproject a6c58d43051d01d83f55a3e61ef5f5b2b0dd6bd diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index d468993e744..c8594cf35e2 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -7,7 +7,7 @@ #![feature(iter_intersperse)] #![feature(iter_partition_in_place)] #![feature(never_type)] -#![feature(round_char_boundary)] +#![cfg_attr(bootstrap, feature(round_char_boundary))] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] #![feature(unwrap_infallible)] diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed index 04c8f6782c5..375a101c2e3 100644 --- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed +++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed @@ -1,4 +1,3 @@ -#![feature(round_char_boundary)] #![warn(clippy::char_indices_as_byte_indices)] trait StrExt { diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs index 773a4fc65f1..eebc39962a2 100644 --- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs +++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs @@ -1,4 +1,3 @@ -#![feature(round_char_boundary)] #![warn(clippy::char_indices_as_byte_indices)] trait StrExt { diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr index e2b4c1db78c..fae81fd772d 100644 --- a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr +++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr @@ -1,12 +1,12 @@ error: indexing into a string with a character position where a byte index is expected - --> tests/ui/char_indices_as_byte_indices.rs:13:24 + --> tests/ui/char_indices_as_byte_indices.rs:12:24 | LL | let _ = prim[..idx]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:11:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -19,14 +19,14 @@ LL + for (idx, _) in prim.char_indices() { | error: passing a character position to a method that expects a byte index - --> tests/ui/char_indices_as_byte_indices.rs:15:23 + --> tests/ui/char_indices_as_byte_indices.rs:14:23 | LL | prim.split_at(idx); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:11:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -37,14 +37,14 @@ LL + for (idx, _) in prim.char_indices() { | error: passing a character position to a method that expects a byte index - --> tests/ui/char_indices_as_byte_indices.rs:19:49 + --> tests/ui/char_indices_as_byte_indices.rs:18:49 | LL | let _ = prim[..prim.floor_char_boundary(idx)]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:12:10 + --> tests/ui/char_indices_as_byte_indices.rs:11:10 | LL | for (idx, _) in prim.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -55,14 +55,14 @@ LL + for (idx, _) in prim.char_indices() { | error: indexing into a string with a character position where a byte index is expected - --> tests/ui/char_indices_as_byte_indices.rs:29:24 + --> tests/ui/char_indices_as_byte_indices.rs:28:24 | LL | let _ = prim[..c.0]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:28:9 + --> tests/ui/char_indices_as_byte_indices.rs:27:9 | LL | for c in prim.chars().enumerate() { | ^ ^^^^^^^^^^^ @@ -73,14 +73,14 @@ LL + for c in prim.char_indices() { | error: passing a character position to a method that expects a byte index - --> tests/ui/char_indices_as_byte_indices.rs:31:23 + --> tests/ui/char_indices_as_byte_indices.rs:30:23 | LL | prim.split_at(c.0); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:28:9 + --> tests/ui/char_indices_as_byte_indices.rs:27:9 | LL | for c in prim.chars().enumerate() { | ^ ^^^^^^^^^^^ @@ -91,14 +91,14 @@ LL + for c in prim.char_indices() { | error: indexing into a string with a character position where a byte index is expected - --> tests/ui/char_indices_as_byte_indices.rs:36:26 + --> tests/ui/char_indices_as_byte_indices.rs:35:26 | LL | let _ = string[..idx]; | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:35:10 + --> tests/ui/char_indices_as_byte_indices.rs:34:10 | LL | for (idx, _) in string.chars().enumerate() { | ^^^ ^^^^^^^^^^^ @@ -109,14 +109,14 @@ LL + for (idx, _) in string.char_indices() { | error: passing a character position to a method that expects a byte index - --> tests/ui/char_indices_as_byte_indices.rs:38:25 + --> tests/ui/char_indices_as_byte_indices.rs:37:25 | LL | string.split_at(idx); | ^^^ | = note: a character can take up more than one byte, so they are not interchangeable note: position comes from the enumerate iterator - --> tests/ui/char_indices_as_byte_indices.rs:35:10 + --> tests/ui/char_indices_as_byte_indices.rs:34:10 | LL | for (idx, _) in string.chars().enumerate() { | ^^^ ^^^^^^^^^^^ diff --git a/src/tools/collect-license-metadata/Cargo.toml b/src/tools/collect-license-metadata/Cargo.toml index edf9e5c5393..7f2e57ced05 100644 --- a/src/tools/collect-license-metadata/Cargo.toml +++ b/src/tools/collect-license-metadata/Cargo.toml @@ -8,5 +8,5 @@ license = "MIT OR Apache-2.0" [dependencies] anyhow = "1.0.65" serde = { version = "1.0.147", features = ["derive"] } -serde_json = "1.0.85" +serde_json.workspace = true spdx-rs = "0.5.1" diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index cdada5a2230..fb71275b03c 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -20,22 +20,22 @@ diff = "0.1.10" getopts = "0.2" glob = "0.3.0" home = "0.5.5" -indexmap = "2.0.0" +indexmap.workspace = true miropt-test-tools = { path = "../miropt-test-tools" } rayon = "1.10.0" regex = "1.0" rustfix = "0.8.1" semver = { version = "1.0.23", features = ["serde"] } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -tracing = "0.1" +serde_json.workspace = true tracing-subscriber = { version = "0.3.3", default-features = false, features = ["ansi", "env-filter", "fmt", "parking_lot", "smallvec"] } +tracing.workspace = true unified-diff = "0.2.1" walkdir = "2" # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] -libc = "0.2" +libc.workspace = true [target.'cfg(windows)'.dependencies] miow = "0.6" diff --git a/src/tools/compiletest/src/bin/main.rs b/src/tools/compiletest/src/bin/main.rs index 1f777e71cf9..8fac6ccdc58 100644 --- a/src/tools/compiletest/src/bin/main.rs +++ b/src/tools/compiletest/src/bin/main.rs @@ -2,7 +2,7 @@ use std::env; use std::io::IsTerminal; use std::sync::Arc; -use compiletest::{early_config_check, log_config, parse_config, run_tests}; +use compiletest::{early_config_check, parse_config, run_tests}; fn main() { tracing_subscriber::fmt::init(); @@ -19,6 +19,5 @@ fn main() { early_config_check(&config); - log_config(&config); run_tests(config); } diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 7fc80c1edb1..b72c0b7ed20 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -8,7 +8,7 @@ use camino::{Utf8Path, Utf8PathBuf}; use semver::Version; use serde::de::{Deserialize, Deserializer, Error as _}; -use crate::executor::{ColorConfig, OutputFormat}; +use crate::executor::ColorConfig; use crate::fatal; use crate::util::{Utf8PathBufExt, add_dylib_path, string_enum}; @@ -565,13 +565,6 @@ pub struct Config { /// FIXME: this is *way* too coarse; the user can't select *which* info to verbosely dump. pub verbose: bool, - /// (Useless) Adjust libtest output format. - /// - /// FIXME: the hand-rolled executor does not support non-JSON output, because `compiletest` need - /// to package test outcome as `libtest`-esque JSON that `bootstrap` can intercept *anyway*. - /// However, now that we don't use the `libtest` executor, this is useless. - pub format: OutputFormat, - /// Whether to use colors in test output. /// /// Note: the exact control mechanism is delegated to [`colored`]. @@ -768,7 +761,6 @@ impl Config { adb_device_status: Default::default(), lldb_python_dir: Default::default(), verbose: Default::default(), - format: Default::default(), color: Default::default(), remote_test_client: Default::default(), compare_mode: Default::default(), diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs index df64f12784f..fdd7155c21f 100644 --- a/src/tools/compiletest/src/executor.rs +++ b/src/tools/compiletest/src/executor.rs @@ -1,5 +1,9 @@ //! This module contains a reimplementation of the subset of libtest //! functionality needed by compiletest. +//! +//! FIXME(Zalathar): Much of this code was originally designed to mimic libtest +//! as closely as possible, for ease of migration. Now that libtest is no longer +//! used, we can potentially redesign things to be a better fit for compiletest. use std::borrow::Cow; use std::collections::HashMap; @@ -207,7 +211,7 @@ impl TestOutcome { /// /// Adapted from `filter_tests` in libtest. /// -/// FIXME(#139660): After the libtest dependency is removed, redesign the whole filtering system to +/// FIXME(#139660): Now that libtest has been removed, redesign the whole filtering system to /// do a better job of understanding and filtering _paths_, instead of being tied to libtest's /// substring/exact matching behaviour. fn filter_tests(opts: &Config, tests: Vec<CollectedTest>) -> Vec<CollectedTest> { @@ -249,7 +253,7 @@ fn get_concurrency() -> usize { } } -/// Information needed to create a `test::TestDescAndFn`. +/// Information that was historically needed to create a libtest `TestDescAndFn`. pub(crate) struct CollectedTest { pub(crate) desc: CollectedTestDesc, pub(crate) config: Arc<Config>, @@ -257,7 +261,7 @@ pub(crate) struct CollectedTest { pub(crate) revision: Option<String>, } -/// Information needed to create a `test::TestDesc`. +/// Information that was historically needed to create a libtest `TestDesc`. pub(crate) struct CollectedTestDesc { pub(crate) name: String, pub(crate) ignore: bool, @@ -274,18 +278,6 @@ pub enum ColorConfig { NeverColor, } -/// Format of the test results output. -#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] -pub enum OutputFormat { - /// Verbose output - Pretty, - /// Quiet output - #[default] - Terse, - /// JSON output - Json, -} - /// Whether test is expected to panic or not. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub(crate) enum ShouldPanic { diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 469dd68207e..8737fec80bb 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -9,7 +9,6 @@ mod tests; pub mod common; -pub mod compute_diff; mod debuggers; pub mod diagnostics; pub mod directives; @@ -43,8 +42,7 @@ use crate::common::{ expected_output_path, output_base_dir, output_relative_path, }; use crate::directives::DirectivesCache; -use crate::executor::{CollectedTest, ColorConfig, OutputFormat}; -use crate::util::logv; +use crate::executor::{CollectedTest, ColorConfig}; /// Creates the `Config` instance for this invocation of compiletest. /// @@ -137,9 +135,7 @@ pub fn parse_config(args: Vec<String>) -> Config { "overwrite stderr/stdout files instead of complaining about a mismatch", ) .optflag("", "fail-fast", "stop as soon as possible after any test fails") - .optflag("", "quiet", "print one character per test instead of one line") .optopt("", "color", "coloring: auto, always, never", "WHEN") - .optflag("", "json", "emit json output instead of plaintext output") .optopt("", "target", "the target to build for", "TARGET") .optopt("", "host", "the host to build for", "HOST") .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH") @@ -203,7 +199,6 @@ pub fn parse_config(args: Vec<String>) -> Config { "COMMAND", ) .reqopt("", "minicore-path", "path to minicore aux library", "PATH") - .optflag("N", "no-new-executor", "disables the new test executor, and uses libtest instead") .optopt( "", "debugger", @@ -436,12 +431,6 @@ pub fn parse_config(args: Vec<String>) -> Config { && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(), lldb_python_dir: matches.opt_str("lldb-python-dir"), verbose: matches.opt_present("verbose"), - format: match (matches.opt_present("quiet"), matches.opt_present("json")) { - (true, true) => panic!("--quiet and --json are incompatible"), - (true, false) => OutputFormat::Terse, - (false, true) => OutputFormat::Json, - (false, false) => OutputFormat::Pretty, - }, only_modified: matches.opt_present("only-modified"), color, remote_test_client: matches.opt_str("remote-test-client").map(Utf8PathBuf::from), @@ -486,52 +475,6 @@ pub fn parse_config(args: Vec<String>) -> Config { } } -pub fn log_config(config: &Config) { - let c = config; - logv(c, "configuration:".to_string()); - logv(c, format!("compile_lib_path: {}", config.compile_lib_path)); - logv(c, format!("run_lib_path: {}", config.run_lib_path)); - logv(c, format!("rustc_path: {}", config.rustc_path)); - logv(c, format!("cargo_path: {:?}", config.cargo_path)); - logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); - - logv(c, format!("src_root: {}", config.src_root)); - logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root)); - - logv(c, format!("build_root: {}", config.build_root)); - logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root)); - - logv(c, format!("sysroot_base: {}", config.sysroot_base)); - - logv(c, format!("stage: {}", config.stage)); - logv(c, format!("stage_id: {}", config.stage_id)); - logv(c, format!("mode: {}", config.mode)); - logv(c, format!("run_ignored: {}", config.run_ignored)); - logv(c, format!("filters: {:?}", config.filters)); - logv(c, format!("skip: {:?}", config.skip)); - logv(c, format!("filter_exact: {}", config.filter_exact)); - logv( - c, - format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),), - ); - logv(c, format!("runner: {}", opt_str(&config.runner))); - logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags)); - logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags)); - logv(c, format!("target: {}", config.target)); - logv(c, format!("host: {}", config.host)); - logv(c, format!("android-cross-path: {}", config.android_cross_path)); - logv(c, format!("adb_path: {}", config.adb_path)); - logv(c, format!("adb_test_dir: {}", config.adb_test_dir)); - logv(c, format!("adb_device_status: {}", config.adb_device_status)); - logv(c, format!("ar: {}", config.ar)); - logv(c, format!("target-linker: {:?}", config.target_linker)); - logv(c, format!("host-linker: {:?}", config.host_linker)); - logv(c, format!("verbose: {}", config.verbose)); - logv(c, format!("format: {:?}", config.format)); - logv(c, format!("minicore_path: {}", config.minicore_path)); - logv(c, "\n".to_string()); -} - pub fn opt_str(maybestr: &Option<String>) -> &str { match *maybestr { None => "(none)", @@ -548,6 +491,8 @@ pub fn opt_str2(maybestr: Option<String>) -> String { /// Called by `main` after the config has been parsed. pub fn run_tests(config: Arc<Config>) { + debug!(?config, "run_tests"); + // If we want to collect rustfix coverage information, // we first make sure that the coverage file does not exist. // It will be created later on. @@ -601,7 +546,7 @@ pub fn run_tests(config: Arc<Config>) { configs.push(config.clone()); }; - // Discover all of the tests in the test suite directory, and build a libtest + // Discover all of the tests in the test suite directory, and build a `CollectedTest` // structure for each test (or each revision of a multi-revision test). let mut tests = Vec::new(); for c in configs { @@ -613,50 +558,35 @@ pub fn run_tests(config: Arc<Config>) { // Delegate to the executor to filter and run the big list of test structures // created during test discovery. When the executor decides to run a test, // it will return control to the rest of compiletest by calling `runtest::run`. - // FIXME(Zalathar): Once we're confident that we won't need to revert the - // removal of the libtest-based executor, remove this Result and other - // remnants of the old executor. - let res: io::Result<bool> = Ok(executor::run_tests(&config, tests)); - - // Check the outcome reported by libtest. - match res { - Ok(true) => {} - Ok(false) => { - // We want to report that the tests failed, but we also want to give - // some indication of just what tests we were running. Especially on - // CI, where there can be cross-compiled tests for a lot of - // architectures, without this critical information it can be quite - // easy to miss which tests failed, and as such fail to reproduce - // the failure locally. - - let mut msg = String::from("Some tests failed in compiletest"); - write!(msg, " suite={}", config.suite).unwrap(); - - if let Some(compare_mode) = config.compare_mode.as_ref() { - write!(msg, " compare_mode={}", compare_mode).unwrap(); - } + let ok = executor::run_tests(&config, tests); + + // Check the outcome reported by the executor. + if !ok { + // We want to report that the tests failed, but we also want to give + // some indication of just what tests we were running. Especially on + // CI, where there can be cross-compiled tests for a lot of + // architectures, without this critical information it can be quite + // easy to miss which tests failed, and as such fail to reproduce + // the failure locally. + + let mut msg = String::from("Some tests failed in compiletest"); + write!(msg, " suite={}", config.suite).unwrap(); + + if let Some(compare_mode) = config.compare_mode.as_ref() { + write!(msg, " compare_mode={}", compare_mode).unwrap(); + } - if let Some(pass_mode) = config.force_pass_mode.as_ref() { - write!(msg, " pass_mode={}", pass_mode).unwrap(); - } + if let Some(pass_mode) = config.force_pass_mode.as_ref() { + write!(msg, " pass_mode={}", pass_mode).unwrap(); + } - write!(msg, " mode={}", config.mode).unwrap(); - write!(msg, " host={}", config.host).unwrap(); - write!(msg, " target={}", config.target).unwrap(); + write!(msg, " mode={}", config.mode).unwrap(); + write!(msg, " host={}", config.host).unwrap(); + write!(msg, " target={}", config.target).unwrap(); - println!("{msg}"); + println!("{msg}"); - std::process::exit(1); - } - Err(e) => { - // We don't know if tests passed or not, but if there was an error - // during testing we don't want to just succeed (we may not have - // tested something), so fail. - // - // This should realistically "never" happen, so don't try to make - // this a pretty error message. - panic!("I/O failure during tests: {:?}", e); - } + std::process::exit(1); } } @@ -691,7 +621,11 @@ impl TestCollector { /// /// This always inspects _all_ test files in the suite (e.g. all 17k+ ui tests), /// regardless of whether any filters/tests were specified on the command-line, -/// because filtering is handled later by libtest. +/// because filtering is handled later by code that was copied from libtest. +/// +/// FIXME(Zalathar): Now that we no longer rely on libtest, try to overhaul +/// test discovery to take into account the filters/tests specified on the +/// command-line, instead of having to enumerate everything. pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest> { debug!("making tests from {}", config.src_test_suite_root); let common_inputs_stamp = common_inputs_stamp(&config); @@ -805,7 +739,7 @@ fn modified_tests(config: &Config, dir: &Utf8Path) -> Result<Vec<Utf8PathBuf>, S } /// Recursively scans a directory to find test files and create test structures -/// that will be handed over to libtest. +/// that will be handed over to the executor. fn collect_tests_from_dir( cx: &TestCollectorCx, dir: &Utf8Path, @@ -871,7 +805,7 @@ fn collect_tests_from_dir( if is_test(file_name) && (!cx.config.only_modified || cx.modified_tests.contains(&file_path)) { - // We found a test file, so create the corresponding libtest structures. + // We found a test file, so create the corresponding test structures. debug!(%file_path, "found test file"); // Record the stem of the test file, to check for overlaps later. @@ -915,7 +849,7 @@ pub fn is_test(file_name: &str) -> bool { } /// For a single test file, creates one or more test structures (one per revision) that can be -/// handed over to libtest to run, possibly in parallel. +/// handed over to the executor to run, possibly in parallel. fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &TestPaths) { // For run-make tests, each "test file" is actually a _directory_ containing an `rmake.rs`. But // for the purposes of directive parsing, we want to look at that recipe file, not the directory @@ -929,7 +863,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te // Scan the test file to discover its revisions, if any. let early_props = EarlyProps::from_file(&cx.config, &test_path); - // Normally we create one libtest structure per revision, with two exceptions: + // Normally we create one structure per revision, with two exceptions: // - If a test doesn't use revisions, create a dummy revision (None) so that // the test can still run. // - Incremental tests inherently can't run their revisions in parallel, so @@ -944,12 +878,12 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te // For each revision (or the sole dummy revision), create and append a // `CollectedTest` that can be handed over to the test executor. collector.tests.extend(revisions.into_iter().map(|revision| { - // Create a test name and description to hand over to libtest. + // Create a test name and description to hand over to the executor. let src_file = fs::File::open(&test_path).expect("open test file to parse ignores"); let test_name = make_test_name(&cx.config, testpaths, revision); - // Create a libtest description for the test/revision. + // Create a description struct for the test/revision. // This is where `ignore-*`/`only-*`/`needs-*` directives are handled, - // because they need to set the libtest ignored flag. + // because they historically needed to set the libtest ignored flag. let mut desc = make_test_description( &cx.config, &cx.cache, @@ -961,10 +895,12 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te ); // If a test's inputs haven't changed since the last time it ran, - // mark it as ignored so that libtest will skip it. + // mark it as ignored so that the executor will skip it. if !cx.config.force_rerun && is_up_to_date(cx, testpaths, &early_props, revision) { desc.ignore = true; // Keep this in sync with the "up-to-date" message detected by bootstrap. + // FIXME(Zalathar): Now that we are no longer tied to libtest, we could + // find a less fragile way to communicate this status to bootstrap. desc.ignore_message = Some("up-to-date".into()); } @@ -1104,7 +1040,7 @@ impl Stamp { } } -/// Creates a name for this test/revision that can be handed over to libtest. +/// Creates a name for this test/revision that can be handed over to the executor. fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> String { // Print the name of the file, relative to the sources root. let path = testpaths.file.strip_prefix(&config.src_root).unwrap(); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c533293e791..867624cc8fa 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -7,7 +7,7 @@ use std::io::prelude::*; use std::io::{self, BufReader}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::sync::Arc; -use std::{env, iter, str}; +use std::{env, fmt, iter, str}; use build_helper::fs::remove_and_create_dir_all; use camino::{Utf8Path, Utf8PathBuf}; @@ -21,15 +21,13 @@ use crate::common::{ UI_WINDOWS_SVG, expected_output_path, incremental_dir, output_base_dir, output_base_name, output_testname_unique, }; -use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; use crate::directives::TestProps; use crate::errors::{Error, ErrorKind, load_errors}; use crate::read2::{Truncated, read2_abbreviated}; -use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex}; +use crate::runtest::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; +use crate::util::{Utf8PathBufExt, add_dylib_path, static_regex}; use crate::{ColorConfig, help, json, stamp_file_path, warning}; -mod debugger; - // Helper modules that implement test running logic for each test suite. // tidy-alphabetical-start mod assembly; @@ -48,6 +46,8 @@ mod rustdoc_json; mod ui; // tidy-alphabetical-end +mod compute_diff; +mod debugger; #[cfg(test)] mod tests; @@ -1459,7 +1459,7 @@ impl<'test> TestCx<'test> { ) -> ProcRes { let cmdline = { let cmdline = self.make_cmdline(&command, lib_path); - logv(self.config, format!("executing {}", cmdline)); + self.logv(format_args!("executing {cmdline}")); cmdline }; @@ -2006,6 +2006,18 @@ impl<'test> TestCx<'test> { output_base_name(self.config, self.testpaths, self.safe_revision()) } + /// Prints a message to (captured) stdout if `config.verbose` is true. + /// The message is also logged to `tracing::debug!` regardles of verbosity. + /// + /// Use `format_args!` as the argument to perform formatting if required. + fn logv(&self, message: impl fmt::Display) { + debug!("{message}"); + if self.config.verbose { + // Note: `./x test ... --verbose --no-capture` is needed to see this print. + println!("{message}"); + } + } + /// Prefix to print before error messages. Normally just `error`, but also /// includes the revision name for tests that use revisions. #[must_use] @@ -2222,7 +2234,7 @@ impl<'test> TestCx<'test> { .env("PAGER", "") .stdin(File::open(&diff_filename).unwrap()) // Capture output and print it explicitly so it will in turn be - // captured by libtest. + // captured by output-capture. .output() .unwrap(); assert!(output.status.success()); @@ -2666,8 +2678,8 @@ impl<'test> TestCx<'test> { // // It's not possible to detect paths in the error messages generally, but this is a // decent enough heuristic. - static_regex!( - r#"(?x) + let re = static_regex!( + r#"(?x) (?: # Match paths that don't include spaces. (?:\\[\pL\pN\.\-_']+)+\.\pL+ @@ -2675,11 +2687,8 @@ impl<'test> TestCx<'test> { # If the path starts with a well-known root, then allow spaces and no file extension. \$(?:DIR|SRC_DIR|TEST_BUILD_DIR|BUILD_DIR|LIB_DIR)(?:\\[\pL\pN\.\-_'\ ]+)+ )"# - ) - .replace_all(&output, |caps: &Captures<'_>| { - println!("{}", &caps[0]); - caps[0].replace(r"\", "/") - }) + ); + re.replace_all(&output, |caps: &Captures<'_>| caps[0].replace(r"\", "/")) .replace("\r\n", "\n") } diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/runtest/compute_diff.rs index 509e7e11703..509e7e11703 100644 --- a/src/tools/compiletest/src/compute_diff.rs +++ b/src/tools/compiletest/src/runtest/compute_diff.rs diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 6114afdc9df..88d022b8bba 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -10,7 +10,6 @@ use super::debugger::DebuggerCommands; use super::{Debugger, Emit, ProcRes, TestCx, Truncated, WillExecute}; use crate::common::Config; use crate::debuggers::{extract_gdb_version, is_android_gdb_target}; -use crate::util::logv; impl TestCx<'_> { pub(super) fn run_debuginfo_test(&self) { @@ -234,7 +233,7 @@ impl TestCx<'_> { gdb.args(debugger_opts); // FIXME(jieyouxu): don't pass an empty Path let cmdline = self.make_cmdline(&gdb, Utf8Path::new("")); - logv(self.config, format!("executing {}", cmdline)); + self.logv(format_args!("executing {cmdline}")); cmdline }; @@ -395,6 +394,35 @@ impl TestCx<'_> { // We don't want to hang when calling `quit` while the process is still running let mut script_str = String::from("settings set auto-confirm true\n"); + // macOS has a system for restricting access to files and peripherals + // called Transparency, Consent, and Control (TCC), which can be + // configured using the "Security & Privacy" tab in your settings. + // + // This system is provenance-based: if Terminal.app is given access to + // your Desktop, and you launch a binary within Terminal.app, the new + // binary also has access to the files on your Desktop. + // + // By default though, LLDB launches binaries in very isolated + // contexts. This includes resetting any TCC grants that might + // otherwise have been inherited. + // + // In effect, this means that if the developer has placed the rust + // repository under one of the system-protected folders, they will get + // a pop-up _for each binary_ asking for permissions to access the + // folder - quite annoying. + // + // To avoid this, we tell LLDB to spawn processes with TCC grants + // inherited from the parent process. + // + // Setting this also avoids unnecessary overhead from XprotectService + // when running with the Developer Tool grant. + // + // TIP: If you want to allow launching `lldb ~/Desktop/my_binary` + // without being prompted, you can put this in your `~/.lldbinit` too. + if self.config.host.contains("darwin") { + script_str.push_str("settings set target.inherit-tcc true\n"); + } + // Make LLDB emit its version, so we have it documented in the test output script_str.push_str("version\n"); diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs index efdb131bf14..55043bf4bc2 100644 --- a/src/tools/compiletest/src/runtest/mir_opt.rs +++ b/src/tools/compiletest/src/runtest/mir_opt.rs @@ -6,7 +6,7 @@ use miropt_test_tools::{MiroptTest, MiroptTestFile, files_for_miropt_test}; use tracing::debug; use super::{Emit, TestCx, WillExecute}; -use crate::compute_diff::write_diff; +use crate::runtest::compute_diff::write_diff; impl TestCx<'_> { pub(super) fn run_mir_opt_test(&self) { diff --git a/src/tools/compiletest/src/runtest/pretty.rs b/src/tools/compiletest/src/runtest/pretty.rs index e3b07f1d63d..26557727233 100644 --- a/src/tools/compiletest/src/runtest/pretty.rs +++ b/src/tools/compiletest/src/runtest/pretty.rs @@ -1,14 +1,13 @@ use std::fs; use super::{ProcRes, ReadFrom, TestCx}; -use crate::util::logv; impl TestCx<'_> { pub(super) fn run_pretty_test(&self) { if self.props.pp_exact.is_some() { - logv(self.config, "testing for exact pretty-printing".to_owned()); + self.logv("testing for exact pretty-printing"); } else { - logv(self.config, "testing for converging pretty-printing".to_owned()); + self.logv("testing for converging pretty-printing"); } let rounds = match self.props.pp_exact { @@ -21,10 +20,7 @@ impl TestCx<'_> { let mut round = 0; while round < rounds { - logv( - self.config, - format!("pretty-printing round {} revision {:?}", round, self.revision), - ); + self.logv(format_args!("pretty-printing round {round} revision {:?}", self.revision)); let read_from = if round == 0 { ReadFrom::Path } else { ReadFrom::Stdin(srcs[round].to_owned()) }; diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index c8d5190c039..8a0e45cf8ca 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -308,7 +308,7 @@ impl TestCx<'_> { let stdout = String::from_utf8_lossy(&stdout).into_owned(); let stderr = String::from_utf8_lossy(&stderr).into_owned(); // This conditions on `status.success()` so we don't print output twice on error. - // NOTE: this code is called from a libtest thread, so it's hidden by default unless --nocapture is passed. + // NOTE: this code is called from an executor thread, so it's hidden by default unless --no-capture is passed. self.dump_output(status.success(), &cmd.get_program().to_string_lossy(), &stdout, &stderr); if !status.success() { let res = ProcRes { status, stdout, stderr, truncated, cmdline: format!("{:?}", cmd) }; diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index fb047548c45..1f16a672a98 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -2,9 +2,6 @@ use std::env; use std::process::Command; use camino::{Utf8Path, Utf8PathBuf}; -use tracing::*; - -use crate::common::Config; #[cfg(test)] mod tests; @@ -26,14 +23,6 @@ fn path_div() -> &'static str { ";" } -pub fn logv(config: &Config, s: String) { - debug!("{}", s); - if config.verbose { - // Note: `./x test ... --verbose --no-capture` is needed to see this print. - println!("{}", s); - } -} - pub trait Utf8PathBufExt { /// Append an extension to the path, even if it already has one. fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf; diff --git a/src/tools/coverage-dump/Cargo.toml b/src/tools/coverage-dump/Cargo.toml index 36a66f16030..e491804c257 100644 --- a/src/tools/coverage-dump/Cargo.toml +++ b/src/tools/coverage-dump/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" [dependencies] anyhow = "1.0.71" -itertools = "0.12" +itertools.workspace = true leb128 = "0.2.5" md5 = { package = "md-5" , version = "0.10.5" } miniz_oxide = "0.8.8" regex = "1.8.4" -rustc-demangle = "0.1.23" +rustc-demangle.workspace = true diff --git a/src/tools/features-status-dump/Cargo.toml b/src/tools/features-status-dump/Cargo.toml index b2976f14a01..d72555da486 100644 --- a/src/tools/features-status-dump/Cargo.toml +++ b/src/tools/features-status-dump/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" anyhow = { version = "1" } clap = { version = "4", features = ["derive"] } serde = { version = "1.0.125", features = [ "derive" ] } -serde_json = "1.0.59" +serde_json.workspace = true tidy = { path = "../tidy", features = ["build-metrics"] } diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index bcb3165de45..5edf1f3d88b 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -11,5 +11,5 @@ anyhow = "1.0.65" askama = "0.14.0" cargo_metadata = "0.21" serde = { version = "1.0.147", features = ["derive"] } -serde_json = "1.0.85" +serde_json.workspace = true thiserror = "1" diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index 80fc26cbe66..92fde363882 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -8,5 +8,5 @@ jsonpath-rust = "1.0.0" getopts = "0.2" regex = "1.4" shlex = "1.0" -serde_json = "1.0" +serde_json.workspace = true fs-err = "2.5.0" diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml index cc8ecefd530..44beaf2ddfd 100644 --- a/src/tools/jsondoclint/Cargo.toml +++ b/src/tools/jsondoclint/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" anyhow = "1.0.62" clap = { version = "4.0.15", features = ["derive"] } fs-err = "2.8.1" -rustc-hash = "2.0.0" +rustc-hash.workspace = true rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.85" +serde_json.workspace = true diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index 51146831efa..e2738636a14 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -26,6 +26,7 @@ pub(crate) enum Kind { AssocType, Primitive, Keyword, + Attribute, // Not in ItemKind ProcMacro, } @@ -53,6 +54,7 @@ impl Kind { ExternType => true, // FIXME(adotinthevoid): I'm not sure if these are correct + Attribute => false, Keyword => false, ProcAttribute => false, ProcDerive => false, @@ -109,6 +111,7 @@ impl Kind { Kind::Primitive => false, Kind::Keyword => false, Kind::ProcMacro => false, + Kind::Attribute => false, } } @@ -163,6 +166,7 @@ impl Kind { match s.kind { ItemKind::AssocConst => AssocConst, ItemKind::AssocType => AssocType, + ItemKind::Attribute => Attribute, ItemKind::Constant => Constant, ItemKind::Enum => Enum, ItemKind::ExternCrate => ExternCrate, diff --git a/src/tools/lint-docs/Cargo.toml b/src/tools/lint-docs/Cargo.toml index 6e1ab84ed18..acafe17cb0c 100644 --- a/src/tools/lint-docs/Cargo.toml +++ b/src/tools/lint-docs/Cargo.toml @@ -8,6 +8,6 @@ description = "A script to extract the lint documentation for the rustc book." [dependencies] rustc-literal-escaper = "0.0.5" -serde_json = "1.0.57" -tempfile = "3.1.0" +serde_json.workspace = true +tempfile.workspace = true walkdir = "2.3.1" diff --git a/src/tools/llvm-bitcode-linker/Cargo.toml b/src/tools/llvm-bitcode-linker/Cargo.toml index a9210b562f3..f78f8b618d3 100644 --- a/src/tools/llvm-bitcode-linker/Cargo.toml +++ b/src/tools/llvm-bitcode-linker/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] anyhow = "1.0" -tracing = "0.1" -tracing-subscriber = {version = "0.3.0", features = ["std"] } +tracing.workspace = true +tracing-subscriber = { version = "0.3.0", features = ["std"] } clap = { version = "4.3", features = ["derive"] } thiserror = "1.0.24" diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 5e833540002..695959e2e68 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -269d5b56bcfdf2be82213e72ef9a2e4c592a8c6b +e004014d1bf4c29928a0f0f9f7d0964d43606cbd diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs index 3de34e570c7..d8ac5114f27 100644 --- a/src/tools/miri/tests/pass/atomic.rs +++ b/src/tools/miri/tests/pass/atomic.rs @@ -2,7 +2,6 @@ //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(strict_provenance_atomic_ptr)] // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml index f4051ae67d7..b2833a9d7f1 100644 --- a/src/tools/opt-dist/Cargo.toml +++ b/src/tools/opt-dist/Cargo.toml @@ -15,9 +15,9 @@ fs_extra = "1" camino = "1" tar = "0.4" xz = { version = "0.1", package = "xz2" } -serde_json = "1" +serde_json.workspace = true glob = "0.3" -tempfile = "3.5" +tempfile.workspace = true derive_builder = "0.20" clap = { version = "4", features = ["derive"] } tabled = { version = "0.15", default-features = false, features = ["std"] } diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 250e0f65a9f..86ac4b9d7b4 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -12,10 +12,10 @@ edition = "2024" # tidy-alphabetical-start bstr = "1.12" gimli = "0.32" -libc = "0.2" +libc.workspace = true object = "0.37" regex = "1.11" -serde_json = "1.0" +serde_json.workspace = true similar = "2.7" wasmparser = { version = "0.236", default-features = false, features = ["std", "features", "validate"] } # tidy-alphabetical-end diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index c1f27de7ed4..f43733665ed 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -14,7 +14,7 @@ ignore = "0.4.18" semver = "1.0" serde = { version = "1.0.125", features = ["derive"], optional = true } termcolor = "1.1.3" -rustc-hash = "2.0.0" +rustc-hash.workspace = true fluent-syntax = "0.12" similar = "2.5.0" toml = "0.7.8" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 18d97a748ba..6974ede624a 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -287,14 +287,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "gimli", "gsgdt", "hashbrown", + "icu_collections", "icu_list", - "icu_list_data", - "icu_locid", - "icu_locid_transform", - "icu_locid_transform_data", + "icu_locale", + "icu_locale_core", + "icu_locale_data", "icu_provider", - "icu_provider_adapters", - "icu_provider_macros", "ident_case", "indexmap", "intl-memoizer", @@ -332,6 +330,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "polonius-engine", "portable-atomic", // dependency for platforms doesn't support `AtomicU64` in std "portable-atomic-util", + "potential_utf", "ppv-lite86", "proc-macro-hack", "proc-macro2", @@ -447,6 +446,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "zerocopy-derive", "zerofrom", "zerofrom-derive", + "zerotrie", "zerovec", "zerovec-derive", // tidy-alphabetical-end diff --git a/src/tools/tidy/src/unit_tests.rs b/src/tools/tidy/src/unit_tests.rs index 3d14a467319..7396310ed37 100644 --- a/src/tools/tidy/src/unit_tests.rs +++ b/src/tools/tidy/src/unit_tests.rs @@ -61,6 +61,7 @@ pub fn check(root_path: &Path, stdlib: bool, bad: &mut bool) { || path.ends_with("library/alloc/src/collections/linked_list/tests.rs") || path.ends_with("library/alloc/src/collections/vec_deque/tests.rs") || path.ends_with("library/alloc/src/raw_vec/tests.rs") + || path.ends_with("library/alloc/src/wtf8/tests.rs") } }; diff --git a/tests/assembly-llvm/reg-struct-return.rs b/tests/assembly-llvm/reg-struct-return.rs new file mode 100644 index 00000000000..b251d791d51 --- /dev/null +++ b/tests/assembly-llvm/reg-struct-return.rs @@ -0,0 +1,143 @@ +//! Tests that -Zreg-struct-return changes ABI for small struct returns +//! from hidden-pointer convention to register-return on x86_32. +//! This test covers: +//! * Callee side, verifying that the structs are correctly loaded into registers when +//! `-Zreg-struct-return` is activated +//! * Caller side, verifying callers do receive returned structs in registers when +//! `-Zreg-struct-return` is activated +//@ add-core-stubs +//@ assembly-output: emit-asm +//@ compile-flags: -O --target=i686-unknown-linux-gnu -Crelocation-model=static +//@ revisions: WITH WITHOUT +//@[WITH] compile-flags: -Zreg-struct-return +//@ needs-llvm-components: x86 + +#![feature(no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +// Verifies ABI changes for small structs, where both fields fit into one register. +// WITH is expected to use register return, WITHOUT should use hidden pointer. +mod Small { + struct SmallStruct { + a: i8, + b: i8, + } + + unsafe extern "C" { + fn small() -> SmallStruct; + } + + #[unsafe(no_mangle)] + pub unsafe extern "C" fn small_callee() -> SmallStruct { + // (42 << 8) | 42 = 10794 + + // WITH-LABEL: small_callee + // WITH: movw $10794, %ax + // WITH: retl + + // WITHOUT-LABEL: small_callee + // WITHOUT: movl 4(%esp), %e{{.*}} + // WITHOUT: movw $10794, (%e{{.*}}) + // WITHOUT: retl $4 + SmallStruct { a: 42, b: 42 } + } + + #[unsafe(no_mangle)] + pub unsafe extern "C" fn small_caller(dst: &mut SmallStruct) { + // WITH-LABEL: small_caller + // WITH: calll small + // WITH: movw %ax, (%e{{.*}}) + + // WITHOUT-LABEL: small_caller + // WITHOUT: calll small + // WITHOUT: movzwl {{.*}}(%esp), %e[[TMP:..]] + // WITHOUT: movw %[[TMP]], (%e{{..}}) + *dst = small(); + } +} + +// Verifies ABI changes for a struct of size 8, which is the maximum size +// for reg-struct-return. +// WITH is expected to still use register return, WITHOUT should use hidden +// pointer. +mod Pivot { + struct PivotStruct { + a: i32, + b: i32, + } + + unsafe extern "C" { + fn pivot() -> PivotStruct; + } + + #[unsafe(no_mangle)] + pub unsafe extern "C" fn pivot_callee() -> PivotStruct { + // WITH-LABEL: pivot_callee + // WITH: movl $42, %e{{.*}} + // WITH: movl $42, %e{{.*}} + // WITH: retl + + // WITHOUT-LABEL: pivot_callee + // WITHOUT: movl 4(%esp), %e{{.*}} + // WITHOUT-DAG: movl $42, (%e{{.*}}) + // WITHOUT-DAG: movl $42, 4(%e{{.*}}) + // WITHOUT: retl $4 + PivotStruct { a: 42, b: 42 } + } + + #[unsafe(no_mangle)] + pub unsafe extern "C" fn pivot_caller(dst: &mut PivotStruct) { + // WITH-LABEL: pivot_caller + // WITH: calll pivot + // WITH-DAG: movl %e{{.*}}, 4(%e{{.*}}) + // WITH-DAG: movl %e{{.*}}, (%e{{.*}}) + + // WITHOUT-LABEL: pivot_caller + // WITHOUT: calll pivot + // WITHOUT: movsd {{.*}}(%esp), %[[TMP:xmm.]] + // WITHOUT: movsd %[[TMP]], (%e{{..}}) + *dst = pivot(); + } +} + +// Verifies ABI changes for a struct of size 12, which is larger than the +// maximum size for reg-struct-return (8 bytes). +// Here, the hidden pointer convention should be used even when `-Zreg-struct-return` is set. +mod Large { + struct LargeStruct { + a: i32, + b: i32, + c: i32, + } + + unsafe extern "C" { + fn large() -> LargeStruct; + } + + #[unsafe(no_mangle)] + pub unsafe extern "C" fn large_callee() -> LargeStruct { + // CHECK-LABEL: large_callee + // CHECK: movl 4(%esp), %e{{.*}} + // CHECK-DAG: movl $42, (%e{{.*}}) + // CHECK-DAG: movl $42, 4(%e{{.*}}) + // CHECK-DAG: movl $42, 8(%e{{.*}}) + // CHECK: retl $4 + LargeStruct { a: 42, b: 42, c: 42 } + } + + #[unsafe(no_mangle)] + pub unsafe extern "C" fn large_caller(dst: &mut LargeStruct) { + // CHECK-LABEL: large_caller + // CHECK: calll large + // CHECK-DAG: movl {{.*}}(%esp), %[[TMP1:e..]] + // CHECK-DAG: movl %[[TMP1]], {{.*}}(%e{{..}}) + // CHECK-DAG: movsd {{.*}}(%esp), %[[TMP2:xmm.]] + // CHECK-DAG: movsd %[[TMP2]], {{.*}}(%e{{..}}) + *dst = large(); + } +} diff --git a/tests/assembly-llvm/x86_64-mcount.rs b/tests/assembly-llvm/x86_64-mcount.rs new file mode 100644 index 00000000000..0428272cfc5 --- /dev/null +++ b/tests/assembly-llvm/x86_64-mcount.rs @@ -0,0 +1,24 @@ +//@ assembly-output: emit-asm +//@ compile-flags: -Zinstrument-mcount=y -Cllvm-args=-x86-asm-syntax=intel + +//@ revisions: x86_64-linux +//@[x86_64-linux] compile-flags: --target=x86_64-unknown-linux-gnu +//@[x86_64-linux] needs-llvm-components: x86 +//@[x86_64-linux] only-x86_64-unknown-linux-gnu + +//@ revisions: x86_64-darwin +//@[x86_64-darwin] compile-flags: --target=x86_64-apple-darwin +//@[x86_64-darwin] needs-llvm-components: x86 +//@[x86_64-darwin] only-x86_64-apple-darwin + +#![crate_type = "lib"] + +// CHECK-LABEL: mcount_func: +#[no_mangle] +pub fn mcount_func() { + // CHECK: call mcount + + std::hint::black_box(()); + + // CHECK: ret +} diff --git a/tests/codegen-llvm/addr-of-mutate.rs b/tests/codegen-llvm/addr-of-mutate.rs index 71669065289..36d6bf555d1 100644 --- a/tests/codegen-llvm/addr-of-mutate.rs +++ b/tests/codegen-llvm/addr-of-mutate.rs @@ -5,7 +5,7 @@ // Test for the absence of `readonly` on the argument when it is mutated via `&raw const`. // See <https://github.com/rust-lang/rust/issues/111502>. -// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 1{{( captures\(none\))?}} dereferenceable(128) %x) +// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias noundef align 1{{( captures\(address\))?}} dereferenceable(128) %x) #[no_mangle] pub fn foo(x: [u8; 128]) -> u8 { let ptr = core::ptr::addr_of!(x).cast_mut(); @@ -15,7 +15,7 @@ pub fn foo(x: [u8; 128]) -> u8 { x[0] } -// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) +// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias noundef align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) #[no_mangle] pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut(); @@ -24,7 +24,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { } // If going through a deref (and there are no other mutating accesses), then `readonly` is fine. -// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) +// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias noundef readonly align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) #[no_mangle] pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut(); diff --git a/tests/codegen-llvm/atomicptr.rs b/tests/codegen-llvm/atomicptr.rs index ce6c4aa0d2b..9d5e618fe76 100644 --- a/tests/codegen-llvm/atomicptr.rs +++ b/tests/codegen-llvm/atomicptr.rs @@ -6,7 +6,6 @@ //@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes #![crate_type = "lib"] -#![feature(strict_provenance_atomic_ptr)] use std::ptr::without_provenance_mut; use std::sync::atomic::AtomicPtr; diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index db508682862..a0744e44c61 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -134,7 +134,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {} #[no_mangle] pub fn notunpin_borrow(_: &NotUnpin) {} -// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align 4{{( captures\(none\))?}} dereferenceable(32) %_1) +// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias noundef readonly align 4{{( captures\(address\))?}} dereferenceable(32) %_1) #[no_mangle] pub fn indirect_struct(_: S) {} @@ -197,7 +197,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> { x } -// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(none\))?}} dereferenceable(32){{( %_0)?}}) +// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(address\))?}} dereferenceable(32){{( %_0)?}}) #[no_mangle] pub fn struct_return() -> S { S { _field: [0, 0, 0, 0, 0, 0, 0, 0] } diff --git a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs index 4666342a16a..7ea08a1a8f7 100644 --- a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs +++ b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs @@ -256,11 +256,11 @@ pub struct IntDoubleInt { c: i32, } -// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 8{{( captures\(none\))?}} dereferenceable(24) %a) +// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias noundef align 8{{( captures\(address\))?}} dereferenceable(24) %a) #[no_mangle] pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {} -// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(none\))?}} dereferenceable(24) %_0) +// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(address\))?}} dereferenceable(24) %_0) #[no_mangle] pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt { IntDoubleInt { a: 1, b: 2., c: 3 } diff --git a/tests/crashes/120175.rs b/tests/crashes/120175.rs index c6e7203ff98..e441454bed2 100644 --- a/tests/crashes/120175.rs +++ b/tests/crashes/120175.rs @@ -2,8 +2,9 @@ //@ needs-rustc-debug-assertions #![feature(extern_types)] +#![feature(raw_dylib_elf)] -#[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")] +#[link(name = "bar", kind = "raw-dylib")] extern "C" { pub type CrossCrate; } diff --git a/tests/crashes/137580.rs b/tests/crashes/137580.rs deleted file mode 100644 index 246c80ef556..00000000000 --- a/tests/crashes/137580.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #137580 -fn main() { - println!("%65536$", 1); -} diff --git a/tests/debuginfo/basic-stepping.rs b/tests/debuginfo/basic-stepping.rs index e7a70c8b087..f6399814a43 100644 --- a/tests/debuginfo/basic-stepping.rs +++ b/tests/debuginfo/basic-stepping.rs @@ -4,6 +4,7 @@ //@ ignore-aarch64: Doesn't work yet. //@ ignore-loongarch64: Doesn't work yet. +//@ ignore-riscv64: Doesn't work yet. //@ compile-flags: -g // gdb-command: run diff --git a/tests/mir-opt/building/async_await.rs b/tests/mir-opt/building/async_await.rs index 6c44570d109..2d14a1fb0c6 100644 --- a/tests/mir-opt/building/async_await.rs +++ b/tests/mir-opt/building/async_await.rs @@ -4,7 +4,7 @@ // related to `yield` are `&mut Context`, and its return type is `Poll`. //@ edition:2018 -//@ compile-flags: -C panic=abort +//@ compile-flags: -Zmir-opt-level=0 -C panic=abort #![crate_type = "lib"] diff --git a/tests/mir-opt/building/dump_mir_cycle.rs b/tests/mir-opt/building/dump_mir_cycle.rs index 8e13420aed7..ab0f2ea6db8 100644 --- a/tests/mir-opt/building/dump_mir_cycle.rs +++ b/tests/mir-opt/building/dump_mir_cycle.rs @@ -1,3 +1,5 @@ +//@ compile-flags: -Zmir-opt-level=0 + #[derive(Debug)] pub struct Thing { pub next: &'static Thing, diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs index eaf5537e0ab..07025f572ab 100644 --- a/tests/mir-opt/building/enum_cast.rs +++ b/tests/mir-opt/building/enum_cast.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 // skip-filecheck // EMIT_MIR enum_cast.foo.built.after.mir // EMIT_MIR enum_cast.bar.built.after.mir diff --git a/tests/mir-opt/building/eq_never_type.rs b/tests/mir-opt/building/eq_never_type.rs index 90e2e697535..486e2f9fb8d 100644 --- a/tests/mir-opt/building/eq_never_type.rs +++ b/tests/mir-opt/building/eq_never_type.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 // skip-filecheck #![feature(never_type)] #![allow(unreachable_code)] diff --git a/tests/mir-opt/building/index_array_and_slice.rs b/tests/mir-opt/building/index_array_and_slice.rs index 42ede66d92b..47d8255ef57 100644 --- a/tests/mir-opt/building/index_array_and_slice.rs +++ b/tests/mir-opt/building/index_array_and_slice.rs @@ -1,36 +1,42 @@ -//@ compile-flags: -C opt-level=0 +//@ compile-flags: -Zmir-opt-level=0 -C opt-level=0 // EMIT_MIR index_array_and_slice.index_array.built.after.mir fn index_array(array: &[i32; 7], index: usize) -> &i32 { // CHECK: bb0: - // CHECK: [[LT:_.+]] = Lt(copy _2, const 7_usize); - // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const 7_usize, copy _2) -> [success: bb1, unwind + // CHECK: _3 = copy _2; + // CHECK: [[LT:_.+]] = Lt(copy _3, const 7_usize); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const 7_usize, copy _3) -> [success: bb1, unwind // CHECK: bb1: - // CHECK: _0 = &(*_1)[_2]; + // CHECK: _5 = &(*_1)[_3]; + // CHECK: _0 = &(*_5); &array[index] } // EMIT_MIR index_array_and_slice.index_const_generic_array.built.after.mir fn index_const_generic_array<const N: usize>(array: &[i32; N], index: usize) -> &i32 { // CHECK: bb0: - // CHECK: [[LT:_.+]] = Lt(copy _2, const N); - // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const N, copy _2) -> [success: bb1, unwind + // CHECK: _3 = copy _2; + // CHECK: [[LT:_.+]] = Lt(copy _3, const N); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const N, copy _3) -> [success: bb1, unwind // CHECK: bb1: - // CHECK: _0 = &(*_1)[_2]; + // CHECK: _5 = &(*_1)[_3]; + // CHECK: _0 = &(*_5); &array[index] } // EMIT_MIR index_array_and_slice.index_slice.built.after.mir fn index_slice(slice: &[i32], index: usize) -> &i32 { // CHECK: bb0: + // CHECK: _3 = copy _2; // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1); - // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]); - // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1, + // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1, // CHECK: bb1: - // CHECK: _0 = &(*_1)[_2]; + // CHECK: _6 = &(*_1)[_3]; + // CHECK: _0 = &(*_6); &slice[index] } @@ -40,12 +46,15 @@ fn index_mut_slice(slice: &mut [i32], index: usize) -> &i32 { // This cannot `copy _1` in the *built* MIR, only in the *runtime* MIR. // CHECK: bb0: - // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1); - // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]); - // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1, + // CHECK: _3 = copy _2; + // CHECK: _4 = &raw const (fake) (*_1); + // CHECK: [[LEN:_.+]] = PtrMetadata(move _4); + // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1, // CHECK: bb1: - // CHECK: _0 = &(*_1)[_2]; + // CHECK: _7 = &(*_1)[_3]; + // CHECK: _0 = &(*_7); &slice[index] } @@ -54,13 +63,15 @@ struct WithSliceTail(f64, [i32]); // EMIT_MIR index_array_and_slice.index_custom.built.after.mir fn index_custom(custom: &WithSliceTail, index: usize) -> &i32 { // CHECK: bb0: + // CHECK: _3 = copy _2; // CHECK: [[PTR:_.+]] = &raw const (fake) ((*_1).1: [i32]); - // CHECK: [[LEN:_.+]] = PtrMetadata(copy [[PTR]]); - // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]); - // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1, + // CHECK: [[LEN:_.+]] = PtrMetadata(move [[PTR]]); + // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1, // CHECK: bb1: - // CHECK: _0 = &((*_1).1: [i32])[_2]; + // CHECK: _7 = &((*_1).1: [i32])[_3]; + // CHECK: _0 = &(*_7); &custom.1[index] } diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir index 8a36c901eed..fa35658a16d 100644 --- a/tests/mir-opt/building/issue_101867.main.built.after.mir +++ b/tests/mir-opt/building/issue_101867.main.built.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8> -| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8> +| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8> +| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8> | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/issue_101867.rs b/tests/mir-opt/building/issue_101867.rs index f8a531e8982..a00bc13b3fe 100644 --- a/tests/mir-opt/building/issue_101867.rs +++ b/tests/mir-opt/building/issue_101867.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 // skip-filecheck // EMIT_MIR issue_101867.main.built.after.mir fn main() { diff --git a/tests/mir-opt/building/issue_110508.rs b/tests/mir-opt/building/issue_110508.rs index e597cd5d06b..aa8a7b1d08f 100644 --- a/tests/mir-opt/building/issue_110508.rs +++ b/tests/mir-opt/building/issue_110508.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 // skip-filecheck // EMIT_MIR issue_110508.{impl#0}-BAR.built.after.mir // EMIT_MIR issue_110508.{impl#0}-SELF_BAR.built.after.mir diff --git a/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir b/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir index c3d28fae518..0cefb9c8fd1 100644 --- a/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir +++ b/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `<impl at $DIR/issue_110508.rs:9:1: 9:9>::BAR` after built +// MIR for `<impl at $DIR/issue_110508.rs:10:1: 10:9>::BAR` after built -const <impl at $DIR/issue_110508.rs:9:1: 9:9>::BAR: Foo = { +const <impl at $DIR/issue_110508.rs:10:1: 10:9>::BAR: Foo = { let mut _0: Foo; let mut _1: (); diff --git a/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir b/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir index 177518c30af..0e0e9149385 100644 --- a/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir +++ b/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `<impl at $DIR/issue_110508.rs:9:1: 9:9>::SELF_BAR` after built +// MIR for `<impl at $DIR/issue_110508.rs:10:1: 10:9>::SELF_BAR` after built -const <impl at $DIR/issue_110508.rs:9:1: 9:9>::SELF_BAR: Foo = { +const <impl at $DIR/issue_110508.rs:10:1: 10:9>::SELF_BAR: Foo = { let mut _0: Foo; let mut _1: (); diff --git a/tests/mir-opt/building/issue_49232.rs b/tests/mir-opt/building/issue_49232.rs index ac06e02778f..f17e3e955a4 100644 --- a/tests/mir-opt/building/issue_49232.rs +++ b/tests/mir-opt/building/issue_49232.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 // skip-filecheck // We must mark a variable whose initialization fails due to an // abort statement as StorageDead. diff --git a/tests/mir-opt/building/logical_or_in_conditional.rs b/tests/mir-opt/building/logical_or_in_conditional.rs index 249ccf72804..d1c1ea2896a 100644 --- a/tests/mir-opt/building/logical_or_in_conditional.rs +++ b/tests/mir-opt/building/logical_or_in_conditional.rs @@ -1,5 +1,5 @@ // skip-filecheck -//@ compile-flags: -Z validate-mir +//@ compile-flags: -Zmir-opt-level=0 -Z validate-mir //@ edition: 2024 struct Droppy(u8); impl Drop for Droppy { diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir index 744553c7cd2..5cf182c21c3 100644 --- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir +++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir @@ -1,10 +1,10 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test -| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test -| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test -| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test +| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:16:14: 16:23, inferred_ty: *mut Test +| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:16:14: 16:23, inferred_ty: *mut Test +| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:20:18: 20:31, inferred_ty: &&&&*mut Test +| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:20:18: 20:31, inferred_ty: &&&&*mut Test | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/receiver_ptr_mutability.rs b/tests/mir-opt/building/receiver_ptr_mutability.rs index 1ddb8b71a5a..37b142f1d8a 100644 --- a/tests/mir-opt/building/receiver_ptr_mutability.rs +++ b/tests/mir-opt/building/receiver_ptr_mutability.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 // skip-filecheck // EMIT_MIR receiver_ptr_mutability.main.built.after.mir diff --git a/tests/mir-opt/building/shifts.rs b/tests/mir-opt/building/shifts.rs index d7747bb2f78..165b388bc18 100644 --- a/tests/mir-opt/building/shifts.rs +++ b/tests/mir-opt/building/shifts.rs @@ -1,5 +1,5 @@ // skip-filecheck -//@ compile-flags: -C debug-assertions=yes +//@ compile-flags: -Zmir-opt-level=0 -C debug-assertions=yes // EMIT_MIR shifts.shift_signed.built.after.mir fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) { diff --git a/tests/mir-opt/building/storage_live_dead_in_statics.rs b/tests/mir-opt/building/storage_live_dead_in_statics.rs index 7cb74acbf06..868f4a8f559 100644 --- a/tests/mir-opt/building/storage_live_dead_in_statics.rs +++ b/tests/mir-opt/building/storage_live_dead_in_statics.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 // skip-filecheck // Check that when we compile the static `XXX` into MIR, we do not // generate `StorageStart` or `StorageEnd` statements. diff --git a/tests/mir-opt/building/uniform_array_move_out.rs b/tests/mir-opt/building/uniform_array_move_out.rs index aff5996d0b6..36245273fe1 100644 --- a/tests/mir-opt/building/uniform_array_move_out.rs +++ b/tests/mir-opt/building/uniform_array_move_out.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 // skip-filecheck #![feature(liballoc_internals, rustc_attrs)] diff --git a/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir index 3d26fe24ac9..bbf504d311f 100644 --- a/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir @@ -1,8 +1,8 @@ // MIR for `let_else` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char) -| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char) +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:36:20: 36:45, inferred_ty: (u32, u64, &char) +| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:36:20: 36:45, inferred_ty: (u32, u64, &char) | fn let_else() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir index b2a06ae53a8..7bf2551e99f 100644 --- a/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir @@ -1,8 +1,8 @@ // MIR for `let_else_bindless` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char) -| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char) +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:41:20: 41:45, inferred_ty: (u32, u64, &char) +| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:41:20: 41:45, inferred_ty: (u32, u64, &char) | fn let_else_bindless() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir index d1b8f823e9b..0cf681d8ab2 100644 --- a/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir @@ -1,8 +1,8 @@ // MIR for `let_init` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char) -| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char) +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:26:20: 26:45, inferred_ty: (u32, u64, &char) +| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:26:20: 26:45, inferred_ty: (u32, u64, &char) | fn let_init() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir index 6702f930060..968813c826e 100644 --- a/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir @@ -1,8 +1,8 @@ // MIR for `let_init_bindless` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char) -| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char) +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:31:20: 31:45, inferred_ty: (u32, u64, &char) +| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:31:20: 31:45, inferred_ty: (u32, u64, &char) | fn let_init_bindless() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir index 76b5938b87d..b6fdc4ff46d 100644 --- a/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir @@ -1,7 +1,7 @@ // MIR for `let_uninit` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:15:20: 15:45, inferred_ty: (u32, u64, &char) +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:16:20: 16:45, inferred_ty: (u32, u64, &char) | fn let_uninit() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir index 0cd12558771..472dbfb6304 100644 --- a/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir @@ -1,7 +1,7 @@ // MIR for `let_uninit_bindless` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:20:20: 20:45, inferred_ty: (u32, u64, &char) +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:21:20: 21:45, inferred_ty: (u32, u64, &char) | fn let_uninit_bindless() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir index c0ce6f1d06b..ff4b0bf7600 100644 --- a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir @@ -1,8 +1,8 @@ // MIR for `match_assoc_const` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32 -| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32 +| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32 +| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32 | fn match_assoc_const() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir index 3a6aa5b7c2c..4cc433f475f 100644 --- a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir @@ -1,10 +1,10 @@ // MIR for `match_assoc_const_range` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32 -| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32 -| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32 -| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32 +| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32 +| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32 +| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32 +| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32 | fn match_assoc_const_range() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.rs b/tests/mir-opt/building/user_type_annotations.rs index d55c678d5ae..527bf62f7dc 100644 --- a/tests/mir-opt/building/user_type_annotations.rs +++ b/tests/mir-opt/building/user_type_annotations.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -Zmir-opt-level=0 //@ edition: 2024 // skip-filecheck diff --git a/tests/rustdoc-gui/links-color.goml b/tests/rustdoc-gui/links-color.goml index f11920cdd8c..a363175c1dd 100644 --- a/tests/rustdoc-gui/links-color.goml +++ b/tests/rustdoc-gui/links-color.goml @@ -9,7 +9,7 @@ show-text: true define-function: ( "check-colors", [theme, mod, macro, struct, enum, trait, fn, type, union, keyword, - sidebar, sidebar_current, sidebar_current_background], + attribute, sidebar, sidebar_current, sidebar_current_background], block { call-function: ("switch-theme", {"theme": |theme|}) // Checking results colors. @@ -22,6 +22,7 @@ define-function: ( assert-css: (".item-table .type", {"color": |type|}, ALL) assert-css: (".item-table .union", {"color": |union|}, ALL) assert-css: (".item-table .keyword", {"color": |keyword|}, ALL) + assert-css: (".item-table .attribute", {"color": |attribute|}, ALL) // Checking sidebar elements. assert-css: ( ".sidebar-elems li:not(.current) a", @@ -58,6 +59,7 @@ call-function: ( "type": "#ffa0a5", "union": "#ffa0a5", "keyword": "#39afd7", + "attribute": "#39afd7", "sidebar": "#53b1db", "sidebar_current": "#ffb44c", "sidebar_current_background": "transparent", @@ -76,6 +78,7 @@ call-function: ( "type": "#2dbfb8", "union": "#2dbfb8", "keyword": "#d2991d", + "attribute": "#d2991d", "sidebar": "#fdbf35", "sidebar_current": "#fdbf35", "sidebar_current_background": "#444", @@ -94,6 +97,7 @@ call-function: ( "type": "#ad378a", "union": "#ad378a", "keyword": "#3873ad", + "attribute": "#3873ad", "sidebar": "#356da4", "sidebar_current": "#356da4", "sidebar_current_background": "#fff", diff --git a/tests/rustdoc-gui/module-items-font.goml b/tests/rustdoc-gui/module-items-font.goml index 0e6dd81c05b..bed95b378c6 100644 --- a/tests/rustdoc-gui/module-items-font.goml +++ b/tests/rustdoc-gui/module-items-font.goml @@ -65,3 +65,12 @@ assert-css: ( "#keywords + .item-table dd", {"font-family": '"Source Serif 4", NanumBarunGothic, serif'}, ) +// attributes +assert-css: ( + "#attributes + .item-table dt a", + {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'}, +) +assert-css: ( + "#attributes + .item-table dd", + {"font-family": '"Source Serif 4", NanumBarunGothic, serif'}, +) diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index e136eab6a7d..fe0f6401089 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -7,7 +7,8 @@ define-function: ( [ theme, count_color, desc_color, path_color, bottom_border_color, keyword_color, struct_color, associatedtype_color, tymethod_color, method_color, structfield_color, - structfield_hover_color, macro_color, fn_color, hover_path_color, hover_background, grey + structfield_hover_color, macro_color, fn_color, hover_path_color, hover_background, + attribute_color, grey ], block { call-function: ("switch-theme", {"theme": |theme|}) @@ -47,6 +48,11 @@ define-function: ( "hover_color": |keyword_color|, }) call-function: ("check-result-color", { + "result_kind": "attribute", + "color": |attribute_color|, + "hover_color": |attribute_color|, + }) + call-function: ("check-result-color", { "result_kind": "struct", "color": |struct_color|, "hover_color": |struct_color|, @@ -155,6 +161,7 @@ call-function: ("check-search-color", { "path_color": "#0096cf", "bottom_border_color": "#aaa3", "keyword_color": "#39afd7", + "attribute_color": "#39afd7", "struct_color": "#ffa0a5", "associatedtype_color": "#39afd7", "tymethod_color": "#fdd687", @@ -176,6 +183,7 @@ call-function: ("check-search-color", { "path_color": "#ddd", "bottom_border_color": "#aaa3", "keyword_color": "#d2991d", + "attribute_color": "#d2991d", "struct_color": "#2dbfb8", "associatedtype_color": "#d2991d", "tymethod_color": "#2bab63", @@ -197,6 +205,7 @@ call-function: ("check-search-color", { "path_color": "#000", "bottom_border_color": "#aaa3", "keyword_color": "#3873ad", + "attribute_color": "#3873ad", "struct_color": "#ad378a", "associatedtype_color": "#3873ad", "tymethod_color": "#ad7c37", diff --git a/tests/rustdoc-gui/sidebar-links-color.goml b/tests/rustdoc-gui/sidebar-links-color.goml index 57c45555a76..9a398655f8f 100644 --- a/tests/rustdoc-gui/sidebar-links-color.goml +++ b/tests/rustdoc-gui/sidebar-links-color.goml @@ -12,6 +12,7 @@ define-function: ( enum_hover_background, union, union_hover, union_hover_background, trait, trait_hover, trait_hover_background, fn, fn_hover, fn_hover_background, type, type_hover, type_hover_background, keyword, keyword_hover, keyword_hover_background, + attribute, attribute_hover, attribute_hover_background, ], block { call-function: ("switch-theme", {"theme": |theme|}) @@ -85,6 +86,16 @@ define-function: ( ".sidebar .block.keyword a:hover", {"color": |keyword_hover|, "background-color": |keyword_hover_background|}, ) + // Attribute + assert-css: ( + ".sidebar .block.attribute a", + {"color": |attribute|, "background-color": "rgba(0, 0, 0, 0)"}, + ) + move-cursor-to: ".sidebar .block.attribute a" + assert-css: ( + ".sidebar .block.attribute a:hover", + {"color": |attribute_hover|, "background-color": |attribute_hover_background|}, + ) } ) @@ -113,6 +124,9 @@ call-function: ( "keyword": "#53b1db", "keyword_hover": "#ffb44c", "keyword_hover_background": "transparent", + "attribute": "#53b1db", + "attribute_hover": "#ffb44c", + "attribute_hover_background": "transparent", } ) call-function: ( @@ -140,6 +154,9 @@ call-function: ( "keyword": "#fdbf35", "keyword_hover": "#fdbf35", "keyword_hover_background": "#444", + "attribute": "#fdbf35", + "attribute_hover": "#fdbf35", + "attribute_hover_background": "#444", } ) call-function: ( @@ -167,5 +184,8 @@ call-function: ( "keyword": "#356da4", "keyword_hover": "#356da4", "keyword_hover_background": "#fff", + "attribute": "#356da4", + "attribute_hover": "#356da4", + "attribute_hover_background": "#fff", } ) diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs index 623f5b33e9b..42f2fbd93b1 100644 --- a/tests/rustdoc-gui/src/test_docs/lib.rs +++ b/tests/rustdoc-gui/src/test_docs/lib.rs @@ -161,6 +161,10 @@ pub enum AnEnum { /// Some keyword. pub mod keyword {} +#[doc(attribute = "forbid")] +/// Some attribute. +pub mod repr {} + /// Just some type alias. pub type SomeType = u32; diff --git a/tests/rustdoc-json/doc_attribute.rs b/tests/rustdoc-json/doc_attribute.rs new file mode 100644 index 00000000000..9e1a711f0b7 --- /dev/null +++ b/tests/rustdoc-json/doc_attribute.rs @@ -0,0 +1,18 @@ +// Doc attributes (`#[doc(attribute = "...")]` should not be generated in rustdoc JSON output +// and this test ensures it. + +#![feature(rustdoc_internals)] +#![no_std] + +//@ !has "$.index[?(@.name=='repr')]" +//@ has "$.index[?(@.name=='foo')]" + +#[doc(attribute = "repr")] +/// this is a test! +pub mod foo {} + +//@ !has "$.index[?(@.name=='forbid')]" +//@ !has "$.index[?(@.name=='bar')]" +#[doc(attribute = "forbid")] +/// hello +mod bar {} diff --git a/tests/rustdoc-ui/doc-attribute-unsupported.rs b/tests/rustdoc-ui/doc-attribute-unsupported.rs new file mode 100644 index 00000000000..3bd153117a9 --- /dev/null +++ b/tests/rustdoc-ui/doc-attribute-unsupported.rs @@ -0,0 +1,7 @@ +// This is currently not supported but should be! + +#![feature(rustdoc_internals)] + +#[doc(attribute = "diagnostic::do_not_recommend")] //~ ERROR +/// bla +mod yup {} diff --git a/tests/rustdoc-ui/doc-attribute-unsupported.stderr b/tests/rustdoc-ui/doc-attribute-unsupported.stderr new file mode 100644 index 00000000000..e2480a548ac --- /dev/null +++ b/tests/rustdoc-ui/doc-attribute-unsupported.stderr @@ -0,0 +1,10 @@ +error: nonexistent builtin attribute `diagnostic::do_not_recommend` used in `#[doc(attribute = "...")]` + --> $DIR/doc-attribute-unsupported.rs:5:19 + | +LL | #[doc(attribute = "diagnostic::do_not_recommend")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: only existing builtin attributes are allowed in core/std + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc-ui/invalid-attribute.rs b/tests/rustdoc-ui/invalid-attribute.rs new file mode 100644 index 00000000000..2fc7be2cf34 --- /dev/null +++ b/tests/rustdoc-ui/invalid-attribute.rs @@ -0,0 +1,10 @@ +// Testing the output when an invalid builtin attribute is passed as value +// to `doc(attribute = "...")`. + +#![feature(rustdoc_internals)] + +#[doc(attribute = "foo df")] //~ ERROR +mod foo {} + +#[doc(attribute = "fooyi")] //~ ERROR +mod foo2 {} diff --git a/tests/rustdoc-ui/invalid-attribute.stderr b/tests/rustdoc-ui/invalid-attribute.stderr new file mode 100644 index 00000000000..66e68ce44b4 --- /dev/null +++ b/tests/rustdoc-ui/invalid-attribute.stderr @@ -0,0 +1,18 @@ +error: nonexistent builtin attribute `foo df` used in `#[doc(attribute = "...")]` + --> $DIR/invalid-attribute.rs:6:19 + | +LL | #[doc(attribute = "foo df")] + | ^^^^^^^^ + | + = help: only existing builtin attributes are allowed in core/std + +error: nonexistent builtin attribute `fooyi` used in `#[doc(attribute = "...")]` + --> $DIR/invalid-attribute.rs:9:19 + | +LL | #[doc(attribute = "fooyi")] + | ^^^^^^^ + | + = help: only existing builtin attributes are allowed in core/std + +error: aborting due to 2 previous errors + diff --git a/tests/rustdoc/doc-attribute.rs b/tests/rustdoc/doc-attribute.rs new file mode 100644 index 00000000000..92e603ae6e5 --- /dev/null +++ b/tests/rustdoc/doc-attribute.rs @@ -0,0 +1,24 @@ +// Test checking the `#[doc(attribute = "...")]` attribute. + +#![crate_name = "foo"] + +#![feature(rustdoc_internals)] + +//@ has foo/index.html '//h2[@id="attributes"]' 'Attributes' +//@ has foo/index.html '//a[@href="attribute.no_mangle.html"]' 'no_mangle' +//@ has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Attributes' +//@ has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#attributes' +//@ has foo/attribute.no_mangle.html '//h1' 'Attribute no_mangle' +//@ has foo/attribute.no_mangle.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' +//@ has foo/index.html '//a/@href' '../foo/index.html' +//@ !has foo/foo/index.html +//@ !has-dir foo/foo +//@ !has foo/index.html '//span' '🔒' +#[doc(attribute = "no_mangle")] +/// this is a test! +mod foo{} + +//@ has foo/attribute.repr.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'hello' +#[doc(attribute = "repr")] +/// hello +mod bar {} diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index b8d6c632b97..ec6b9b8f027 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some( diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index b8d6c632b97..ec6b9b8f027 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some( diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index b8d6c632b97..ec6b9b8f027 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some( diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index b8d6c632b97..ec6b9b8f027 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some( diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 0fec35dabdd..47341da221f 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -454,7 +454,7 @@ error: ABIs are not compatible }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(32 bytes), pointee_align: Some( @@ -527,7 +527,7 @@ error: ABIs are not compatible }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(128 bytes), pointee_align: Some( diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index ce8bd41f045..94a01a80873 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -454,7 +454,7 @@ error: ABIs are not compatible }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(32 bytes), pointee_align: Some( @@ -527,7 +527,7 @@ error: ABIs are not compatible }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(128 bytes), pointee_align: Some( diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index ce8bd41f045..94a01a80873 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -454,7 +454,7 @@ error: ABIs are not compatible }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(32 bytes), pointee_align: Some( @@ -527,7 +527,7 @@ error: ABIs are not compatible }, mode: Indirect { attrs: ArgAttributes { - regular: NoAlias | NoCapture | NonNull | NoUndef, + regular: NoAlias | CapturesAddress | NonNull | NoUndef, arg_ext: None, pointee_size: Size(128 bytes), pointee_align: Some( diff --git a/tests/ui/array-slice-vec/pattern-matching-fixed-length-vectors-7784.rs b/tests/ui/array-slice-vec/fixed-length-vector-pattern-matching-7784.rs index 7d987e92b63..7d987e92b63 100644 --- a/tests/ui/array-slice-vec/pattern-matching-fixed-length-vectors-7784.rs +++ b/tests/ui/array-slice-vec/fixed-length-vector-pattern-matching-7784.rs diff --git a/tests/ui/array-slice-vec/matching-on-vector-slice-option-8498.rs b/tests/ui/array-slice-vec/vector-slice-matching-8498.rs index e243a247ed5..e243a247ed5 100644 --- a/tests/ui/array-slice-vec/matching-on-vector-slice-option-8498.rs +++ b/tests/ui/array-slice-vec/vector-slice-matching-8498.rs diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr index ce49126c316..9a5b69497c0 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr @@ -32,12 +32,10 @@ LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:1 + --> $DIR/issue-111404-1.rs:10:8 | LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + | ^ error: aborting due to 5 previous errors diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr index 3d82f572a1a..823d8d5b92f 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr @@ -25,6 +25,7 @@ error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future<Outp | LL | match fut.as_mut().poll(ctx) { | ^^^^ method not found in `Pin<&mut impl Future<Output = ()>>` + | --> $SRC_DIR/core/src/future/future.rs:LL:COL | = note: the method is available for `Pin<&mut impl Future<Output = ()>>` here diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 90ca007451e..932aaf7a9e2 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -81,8 +81,7 @@ #[export_stable = 1] //~^ ERROR malformed #[link] -//~^ ERROR valid forms for the attribute are -//~| WARN this was previously accepted by the compiler +//~^ ERROR malformed #[link_name] //~^ ERROR malformed #[link_section] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 69f9a18c179..b85864b401e 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -1,5 +1,5 @@ error[E0539]: malformed `cfg` attribute input - --> $DIR/malformed-attrs.rs:102:1 + --> $DIR/malformed-attrs.rs:101:1 | LL | #[cfg] | ^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg] = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> error: malformed `cfg_attr` attribute input - --> $DIR/malformed-attrs.rs:104:1 + --> $DIR/malformed-attrs.rs:103:1 | LL | #[cfg_attr] | ^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | #[cfg_attr(condition, attribute, other_attribute, ...)] | ++++++++++++++++++++++++++++++++++++++++++++ error[E0463]: can't find crate for `wloop` - --> $DIR/malformed-attrs.rs:211:1 + --> $DIR/malformed-attrs.rs:210:1 | LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate @@ -42,7 +42,7 @@ LL | #![windows_subsystem = "windows"] | +++++++++++ error: malformed `instruction_set` attribute input - --> $DIR/malformed-attrs.rs:106:1 + --> $DIR/malformed-attrs.rs:105:1 | LL | #[instruction_set] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` @@ -50,13 +50,13 @@ LL | #[instruction_set] = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute> error: malformed `patchable_function_entry` attribute input - --> $DIR/malformed-attrs.rs:108:1 + --> $DIR/malformed-attrs.rs:107:1 | LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` error: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:132:1 + --> $DIR/malformed-attrs.rs:131:1 | LL | #[must_not_suspend()] | ^^^^^^^^^^^^^^^^^^^^^ @@ -71,13 +71,13 @@ LL + #[must_not_suspend] | error: malformed `cfi_encoding` attribute input - --> $DIR/malformed-attrs.rs:134:1 + --> $DIR/malformed-attrs.rs:133:1 | LL | #[cfi_encoding] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` error: malformed `allow` attribute input - --> $DIR/malformed-attrs.rs:178:1 + --> $DIR/malformed-attrs.rs:177:1 | LL | #[allow] | ^^^^^^^^ @@ -93,7 +93,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `expect` attribute input - --> $DIR/malformed-attrs.rs:180:1 + --> $DIR/malformed-attrs.rs:179:1 | LL | #[expect] | ^^^^^^^^^ @@ -109,7 +109,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `warn` attribute input - --> $DIR/malformed-attrs.rs:182:1 + --> $DIR/malformed-attrs.rs:181:1 | LL | #[warn] | ^^^^^^^ @@ -125,7 +125,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `deny` attribute input - --> $DIR/malformed-attrs.rs:184:1 + --> $DIR/malformed-attrs.rs:183:1 | LL | #[deny] | ^^^^^^^ @@ -141,7 +141,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `forbid` attribute input - --> $DIR/malformed-attrs.rs:186:1 + --> $DIR/malformed-attrs.rs:185:1 | LL | #[forbid] | ^^^^^^^^^ @@ -157,7 +157,7 @@ LL | #[forbid(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `debugger_visualizer` attribute input - --> $DIR/malformed-attrs.rs:188:1 + --> $DIR/malformed-attrs.rs:187:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]` @@ -165,13 +165,13 @@ LL | #[debugger_visualizer] = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute> error: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:203:1 + --> $DIR/malformed-attrs.rs:202:1 | LL | #[thread_local()] | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]` error: malformed `no_link` attribute input - --> $DIR/malformed-attrs.rs:207:1 + --> $DIR/malformed-attrs.rs:206:1 | LL | #[no_link()] | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]` @@ -179,7 +179,7 @@ LL | #[no_link()] = note: for more information, visit <https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute> error: malformed `macro_export` attribute input - --> $DIR/malformed-attrs.rs:214:1 + --> $DIR/malformed-attrs.rs:213:1 | LL | #[macro_export = 18] | ^^^^^^^^^^^^^^^^^^^^ @@ -195,25 +195,25 @@ LL + #[macro_export] | error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:99:1 + --> $DIR/malformed-attrs.rs:98:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:116:1 + --> $DIR/malformed-attrs.rs:115:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:123:1 + --> $DIR/malformed-attrs.rs:122:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/malformed-attrs.rs:216:1 + --> $DIR/malformed-attrs.rs:215:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -242,18 +242,8 @@ LL | #[doc] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-attrs.rs:83:1 - | -LL | #[link] - | ^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> - = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> - error: invalid argument - --> $DIR/malformed-attrs.rs:188:1 + --> $DIR/malformed-attrs.rs:187:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -494,8 +484,27 @@ LL | #[export_stable = 1] | | didn't expect any arguments here | help: must be of the form: `#[export_stable]` +error[E0539]: malformed `link` attribute input + --> $DIR/malformed-attrs.rs:83:1 + | +LL | #[link] + | ^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL | #[link(name = "...")] + | ++++++++++++++ +LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...")] + | +++++++++++++++++++++++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + = and 1 other candidate + error[E0539]: malformed `link_name` attribute input - --> $DIR/malformed-attrs.rs:86:1 + --> $DIR/malformed-attrs.rs:85:1 | LL | #[link_name] | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` @@ -503,7 +512,7 @@ LL | #[link_name] = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute> error[E0539]: malformed `link_section` attribute input - --> $DIR/malformed-attrs.rs:88:1 + --> $DIR/malformed-attrs.rs:87:1 | LL | #[link_section] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]` @@ -511,7 +520,7 @@ LL | #[link_section] = note: for more information, visit <https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute> error[E0539]: malformed `coverage` attribute input - --> $DIR/malformed-attrs.rs:90:1 + --> $DIR/malformed-attrs.rs:89:1 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -524,7 +533,7 @@ LL | #[coverage(on)] | ++++ error[E0539]: malformed `sanitize` attribute input - --> $DIR/malformed-attrs.rs:92:1 + --> $DIR/malformed-attrs.rs:91:1 | LL | #[sanitize] | ^^^^^^^^^^^ expected this to be a list @@ -542,7 +551,7 @@ LL | #[sanitize(kcfi = "on|off")] = and 5 other candidates error[E0565]: malformed `no_implicit_prelude` attribute input - --> $DIR/malformed-attrs.rs:97:1 + --> $DIR/malformed-attrs.rs:96:1 | LL | #[no_implicit_prelude = 23] | ^^^^^^^^^^^^^^^^^^^^^^----^ @@ -551,7 +560,7 @@ LL | #[no_implicit_prelude = 23] | help: must be of the form: `#[no_implicit_prelude]` error[E0565]: malformed `proc_macro` attribute input - --> $DIR/malformed-attrs.rs:99:1 + --> $DIR/malformed-attrs.rs:98:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^----^ @@ -560,7 +569,7 @@ LL | #[proc_macro = 18] | help: must be of the form: `#[proc_macro]` error[E0565]: malformed `coroutine` attribute input - --> $DIR/malformed-attrs.rs:111:5 + --> $DIR/malformed-attrs.rs:110:5 | LL | #[coroutine = 63] || {} | ^^^^^^^^^^^^----^ @@ -569,7 +578,7 @@ LL | #[coroutine = 63] || {} | help: must be of the form: `#[coroutine]` error[E0565]: malformed `proc_macro_attribute` attribute input - --> $DIR/malformed-attrs.rs:116:1 + --> $DIR/malformed-attrs.rs:115:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -578,7 +587,7 @@ LL | #[proc_macro_attribute = 19] | help: must be of the form: `#[proc_macro_attribute]` error[E0539]: malformed `must_use` attribute input - --> $DIR/malformed-attrs.rs:119:1 + --> $DIR/malformed-attrs.rs:118:1 | LL | #[must_use = 1] | ^^^^^^^^^^^^^-^ @@ -596,7 +605,7 @@ LL + #[must_use] | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/malformed-attrs.rs:123:1 + --> $DIR/malformed-attrs.rs:122:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -610,7 +619,7 @@ LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | ++++++++++++++++++++++++++++++++++++++++++ error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input - --> $DIR/malformed-attrs.rs:128:1 + --> $DIR/malformed-attrs.rs:127:1 | LL | #[rustc_layout_scalar_valid_range_start] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -619,7 +628,7 @@ LL | #[rustc_layout_scalar_valid_range_start] | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]` error[E0539]: malformed `rustc_layout_scalar_valid_range_end` attribute input - --> $DIR/malformed-attrs.rs:130:1 + --> $DIR/malformed-attrs.rs:129:1 | LL | #[rustc_layout_scalar_valid_range_end] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -628,7 +637,7 @@ LL | #[rustc_layout_scalar_valid_range_end] | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` error[E0565]: malformed `marker` attribute input - --> $DIR/malformed-attrs.rs:155:1 + --> $DIR/malformed-attrs.rs:154:1 | LL | #[marker = 3] | ^^^^^^^^^---^ @@ -637,7 +646,7 @@ LL | #[marker = 3] | help: must be of the form: `#[marker]` error[E0565]: malformed `fundamental` attribute input - --> $DIR/malformed-attrs.rs:157:1 + --> $DIR/malformed-attrs.rs:156:1 | LL | #[fundamental()] | ^^^^^^^^^^^^^--^ @@ -646,7 +655,7 @@ LL | #[fundamental()] | help: must be of the form: `#[fundamental]` error[E0565]: malformed `ffi_pure` attribute input - --> $DIR/malformed-attrs.rs:165:5 + --> $DIR/malformed-attrs.rs:164:5 | LL | #[unsafe(ffi_pure = 1)] | ^^^^^^^^^^^^^^^^^^---^^ @@ -655,7 +664,7 @@ LL | #[unsafe(ffi_pure = 1)] | help: must be of the form: `#[ffi_pure]` error[E0539]: malformed `link_ordinal` attribute input - --> $DIR/malformed-attrs.rs:167:5 + --> $DIR/malformed-attrs.rs:166:5 | LL | #[link_ordinal] | ^^^^^^^^^^^^^^^ @@ -666,7 +675,7 @@ LL | #[link_ordinal] = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error[E0565]: malformed `ffi_const` attribute input - --> $DIR/malformed-attrs.rs:171:5 + --> $DIR/malformed-attrs.rs:170:5 | LL | #[unsafe(ffi_const = 1)] | ^^^^^^^^^^^^^^^^^^^---^^ @@ -675,7 +684,7 @@ LL | #[unsafe(ffi_const = 1)] | help: must be of the form: `#[ffi_const]` error[E0539]: malformed `linkage` attribute input - --> $DIR/malformed-attrs.rs:173:5 + --> $DIR/malformed-attrs.rs:172:5 | LL | #[linkage] | ^^^^^^^^^^ expected this to be of the form `linkage = "..."` @@ -693,7 +702,7 @@ LL | #[linkage = "external"] = and 5 other candidates error[E0565]: malformed `automatically_derived` attribute input - --> $DIR/malformed-attrs.rs:191:1 + --> $DIR/malformed-attrs.rs:190:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -702,7 +711,7 @@ LL | #[automatically_derived = 18] | help: must be of the form: `#[automatically_derived]` error[E0565]: malformed `non_exhaustive` attribute input - --> $DIR/malformed-attrs.rs:197:1 + --> $DIR/malformed-attrs.rs:196:1 | LL | #[non_exhaustive = 1] | ^^^^^^^^^^^^^^^^^---^ @@ -711,13 +720,13 @@ LL | #[non_exhaustive = 1] | help: must be of the form: `#[non_exhaustive]` error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` - --> $DIR/malformed-attrs.rs:209:1 + --> $DIR/malformed-attrs.rs:208:1 | LL | #[macro_use = 1] | ^^^^^^^^^^^^^^^^ error[E0565]: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:216:1 + --> $DIR/malformed-attrs.rs:215:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^---^ @@ -726,7 +735,7 @@ LL | #[allow_internal_unsafe = 1] | help: must be of the form: `#[allow_internal_unsafe]` error[E0565]: malformed `type_const` attribute input - --> $DIR/malformed-attrs.rs:143:5 + --> $DIR/malformed-attrs.rs:142:5 | LL | #[type_const = 1] | ^^^^^^^^^^^^^---^ @@ -759,7 +768,7 @@ LL | #[repr] | ^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/malformed-attrs.rs:149:1 + --> $DIR/malformed-attrs.rs:148:1 | LL | #[diagnostic::do_not_recommend()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -767,7 +776,7 @@ LL | #[diagnostic::do_not_recommend()] = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: missing options for `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:138:1 + --> $DIR/malformed-attrs.rs:137:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -775,7 +784,7 @@ LL | #[diagnostic::on_unimplemented] = help: at least one of the `message`, `note` and `label` options are expected warning: malformed `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:140:1 + --> $DIR/malformed-attrs.rs:139:1 | LL | #[diagnostic::on_unimplemented = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -792,7 +801,7 @@ LL | #[inline = 5] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:94:1 + --> $DIR/malformed-attrs.rs:93:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -801,7 +810,7 @@ LL | #[ignore()] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:223:1 + --> $DIR/malformed-attrs.rs:222:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ @@ -810,7 +819,7 @@ LL | #[ignore = 1] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error[E0308]: mismatched types - --> $DIR/malformed-attrs.rs:111:23 + --> $DIR/malformed-attrs.rs:110:23 | LL | fn test() { | - help: a return type might be missing here: `-> _` @@ -818,7 +827,7 @@ LL | #[coroutine = 63] || {} | ^^^^^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{coroutine@$DIR/malformed-attrs.rs:111:23: 111:25}` + found coroutine `{coroutine@$DIR/malformed-attrs.rs:110:23: 110:25}` error: aborting due to 77 previous errors; 3 warnings emitted @@ -849,18 +858,6 @@ LL | #[doc] = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default Future breakage diagnostic: -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-attrs.rs:83:1 - | -LL | #[link] - | ^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> - = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default - -Future breakage diagnostic: error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/malformed-attrs.rs:52:1 | @@ -873,7 +870,7 @@ LL | #[inline = 5] Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:94:1 + --> $DIR/malformed-attrs.rs:93:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -884,7 +881,7 @@ LL | #[ignore()] Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:223:1 + --> $DIR/malformed-attrs.rs:222:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ diff --git a/tests/ui/pattern/match-with-at-binding-8391.rs b/tests/ui/binding/match-with-at-binding-8391.rs index bc4e7be7989..bc4e7be7989 100644 --- a/tests/ui/pattern/match-with-at-binding-8391.rs +++ b/tests/ui/binding/match-with-at-binding-8391.rs diff --git a/tests/ui/issues/issue-7092.rs b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.rs index fab18bd7cf7..4cb04cdf5be 100644 --- a/tests/ui/issues/issue-7092.rs +++ b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7092 enum Whatever { } diff --git a/tests/ui/issues/issue-7092.stderr b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.stderr index e2e57486746..1f8ff2d8df1 100644 --- a/tests/ui/issues/issue-7092.stderr +++ b/tests/ui/binding/method-call-nonsensical-pattern-binding-7092.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-7092.rs:6:9 + --> $DIR/method-call-nonsensical-pattern-binding-7092.rs:7:9 | LL | match x { | - this expression has type `Whatever` diff --git a/tests/ui/pattern/ref-in-function-parameter-patterns-8860.rs b/tests/ui/binding/ref-pattern-drop-behavior-8860.rs index 1a67caf021c..1a67caf021c 100644 --- a/tests/ui/pattern/ref-in-function-parameter-patterns-8860.rs +++ b/tests/ui/binding/ref-pattern-drop-behavior-8860.rs diff --git a/tests/ui/issues/issue-6738.rs b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.rs index a2f8dfe9c49..856caa2b297 100644 --- a/tests/ui/issues/issue-6738.rs +++ b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6738 struct Foo<T> { x: T, } diff --git a/tests/ui/issues/issue-6738.stderr b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.stderr index f22d6a2e468..060d33079d3 100644 --- a/tests/ui/issues/issue-6738.stderr +++ b/tests/ui/binop/struct-field-generic-type-binary-assignment-error-6738.stderr @@ -1,5 +1,5 @@ error[E0368]: binary assignment operation `+=` cannot be applied to type `T` - --> $DIR/issue-6738.rs:6:9 + --> $DIR/struct-field-generic-type-binary-assignment-error-6738.rs:7:9 | LL | self.x += v.x; | ------^^^^^^^ diff --git a/tests/ui/issues/auxiliary/issue-5518.rs b/tests/ui/borrowck/auxiliary/aux-5518.rs index bfe96552a5c..bfe96552a5c 100644 --- a/tests/ui/issues/auxiliary/issue-5518.rs +++ b/tests/ui/borrowck/auxiliary/aux-5518.rs diff --git a/tests/ui/issues/issue-5884.rs b/tests/ui/borrowck/borrowed-pointer-in-struct-5884.rs index 559b897395d..d2f17cf905d 100644 --- a/tests/ui/issues/issue-5884.rs +++ b/tests/ui/borrowck/borrowed-pointer-in-struct-5884.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5884 //@ build-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-5550.rs b/tests/ui/borrowck/incorrect-loan-error-on-local-update-5550.rs index 41de8ee5d32..2258d768657 100644 --- a/tests/ui/issues/issue-5550.rs +++ b/tests/ui/borrowck/incorrect-loan-error-on-local-update-5550.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5550 //@ run-pass #![allow(unused_assignments)] diff --git a/tests/ui/issues/issue-5708.rs b/tests/ui/borrowck/struct-with-reference-to-trait-5708.rs index 6fa3cfa4724..5157a3bf36b 100644 --- a/tests/ui/issues/issue-5708.rs +++ b/tests/ui/borrowck/struct-with-reference-to-trait-5708.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5708 //@ run-pass #![allow(unused_variables)] /* @@ -10,7 +11,6 @@ This does not occur with concrete types, only with references to traits. */ - // original trait Inner { fn print(&self); @@ -38,7 +38,6 @@ pub fn main() { outer.inner.print(); } - // minimal pub trait MyTrait<T> { fn dummy(&self, t: T) -> T { panic!() } diff --git a/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs b/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs new file mode 100644 index 00000000000..f254030a011 --- /dev/null +++ b/tests/ui/borrowck/trait-method-lifetime-substitution-5518.rs @@ -0,0 +1,7 @@ +// https://github.com/rust-lang/rust/issues/5518 +//@ run-pass +//@ aux-build:aux-5518.rs + +extern crate aux_5518 as other; + +fn main() {} diff --git a/tests/ui/issues/issue-6557.rs b/tests/ui/box/box-patterns-feature-usage-6557.rs index 64a025a294f..e0d9b25c366 100644 --- a/tests/ui/issues/issue-6557.rs +++ b/tests/ui/box/box-patterns-feature-usage-6557.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6557 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr index dc323f9a234..3bf8b7ba5d8 100644 --- a/tests/ui/c-variadic/issue-86053-1.stderr +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -57,10 +57,10 @@ error[E0412]: cannot find type `F` in this scope | LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { | ^ + | --> $SRC_DIR/core/src/ops/function.rs:LL:COL | = note: similarly named trait `Fn` defined here - | help: a trait with a similar name exists | LL | self , ... , self , self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) { diff --git a/tests/ui/issues/issue-54094.rs b/tests/ui/cast/associated-type-bounds-cast-54094.rs index 4ca7d1d81b6..c9f307e95b9 100644 --- a/tests/ui/issues/issue-54094.rs +++ b/tests/ui/cast/associated-type-bounds-cast-54094.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/54094 //@ check-pass trait Zoo { type X; diff --git a/tests/ui/issues/issue-6318.rs b/tests/ui/cast/owned-struct-to-trait-cast-6318.rs index d3f08285a93..8cfc77c4274 100644 --- a/tests/ui/issues/issue-6318.rs +++ b/tests/ui/cast/owned-struct-to-trait-cast-6318.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6318 //@ run-pass pub enum Thing { diff --git a/tests/ui/issues/issue-6153.rs b/tests/ui/closures/closure-mut-argument-6153.rs index cd78c85d94b..ac19c2bd15f 100644 --- a/tests/ui/issues/issue-6153.rs +++ b/tests/ui/closures/closure-mut-argument-6153.rs @@ -1,6 +1,6 @@ +// https://github.com/rust-lang/rust/issues/6153 //@ run-pass - fn swap<F>(f: F) -> Vec<isize> where F: FnOnce(Vec<isize>) -> Vec<isize> { let x = vec![1, 2, 3]; f(x) diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr index 3e95fab441a..987625d22c9 100644 --- a/tests/ui/closures/issue-78720.stderr +++ b/tests/ui/closures/issue-78720.stderr @@ -9,10 +9,10 @@ error[E0412]: cannot find type `F` in this scope | LL | _func: F, | ^ + | --> $SRC_DIR/core/src/ops/function.rs:LL:COL | = note: similarly named trait `Fn` defined here - | help: a trait with a similar name exists | LL | _func: Fn, diff --git a/tests/ui/closures/issue-90871.stderr b/tests/ui/closures/issue-90871.stderr index ef1cb213f73..12020226680 100644 --- a/tests/ui/closures/issue-90871.stderr +++ b/tests/ui/closures/issue-90871.stderr @@ -3,6 +3,7 @@ error[E0412]: cannot find type `n` in this scope | LL | type_ascribe!(2, n([u8; || 1])) | ^ help: a trait with a similar name exists: `Fn` + | --> $SRC_DIR/core/src/ops/function.rs:LL:COL | = note: similarly named trait `Fn` defined here diff --git a/tests/ui/codegen/indirect-nocapture.rs b/tests/ui/codegen/indirect-nocapture.rs new file mode 100644 index 00000000000..78024a94c0d --- /dev/null +++ b/tests/ui/codegen/indirect-nocapture.rs @@ -0,0 +1,15 @@ +// Regression test for issue #137668 where an indirect argument have been marked as nocapture +// despite the fact that callee did in fact capture the address. +// +//@ run-pass +//@ compile-flags: -Copt-level=2 + +#[inline(never)] +pub fn f(a: [u32; 64], b: [u32; 64]) -> bool { + &a as *const _ as usize != &b as *const _ as usize +} + +fn main() { + static S: [u32; 64] = [0; 64]; + assert!(f(S, S)); +} diff --git a/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs b/tests/ui/codegen/matrix-row-swap-54462.rs index 70d0bee7332..6bfc600399a 100644 --- a/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs +++ b/tests/ui/codegen/matrix-row-swap-54462.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/54462 //@ run-pass // //@ compile-flags: -Ccodegen-units=1 -O diff --git a/tests/ui/issues/issue-7012.rs b/tests/ui/codegen/static-array-comparison-7012.rs index 69b881e2a43..c08b1c0059b 100644 --- a/tests/ui/issues/issue-7012.rs +++ b/tests/ui/codegen/static-array-comparison-7012.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7012 //@ run-pass #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] diff --git a/tests/ui/coercion/mut-trait-coercion-8248.rs b/tests/ui/coercion/coerce-mut-trait-object-8248.rs index a45a4d94315..a45a4d94315 100644 --- a/tests/ui/coercion/mut-trait-coercion-8248.rs +++ b/tests/ui/coercion/coerce-mut-trait-object-8248.rs diff --git a/tests/ui/coercion/mut-trait-coercion-8248.stderr b/tests/ui/coercion/coerce-mut-trait-object-8248.stderr index 0c7d5f9dc45..c3b35a7063c 100644 --- a/tests/ui/coercion/mut-trait-coercion-8248.stderr +++ b/tests/ui/coercion/coerce-mut-trait-object-8248.stderr @@ -1,5 +1,5 @@ warning: method `dummy` is never used - --> $DIR/mut-trait-coercion-8248.rs:5:8 + --> $DIR/coerce-mut-trait-object-8248.rs:5:8 | LL | trait A { | - method in this trait diff --git a/tests/ui/issues/issue-54477-reduced-2.rs b/tests/ui/collections/vecdeque-append-operation-54477.rs index 5f65e545182..7680fd0bb01 100644 --- a/tests/ui/issues/issue-54477-reduced-2.rs +++ b/tests/ui/collections/vecdeque-append-operation-54477.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/54477 //@ run-pass // rust-lang/rust#54477: runtime bug in the VecDeque library that was // exposed by this test case, derived from test suite of crates.io diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr index b9db7461699..c9c8115660f 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr @@ -3,10 +3,10 @@ error[E0412]: cannot find type `F` in this scope | LL | let f: F = async { 1 }; | ^ + | --> $SRC_DIR/core/src/ops/function.rs:LL:COL | = note: similarly named trait `Fn` defined here - | help: a trait with a similar name exists | LL | let f: Fn = async { 1 }; diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr index 56025e0d9b2..5008a2eada8 100644 --- a/tests/ui/consts/issue-89088.stderr +++ b/tests/ui/consts/issue-89088.stderr @@ -6,6 +6,7 @@ LL | const FOO: &A = &A::Field(Cow::Borrowed("foo")); ... LL | FOO => todo!(), | ^^^ constant of non-structural type + | --> $SRC_DIR/alloc/src/borrow.rs:LL:COL | = note: `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns diff --git a/tests/ui/issues/auxiliary/issue-7178.rs b/tests/ui/cross-crate/auxiliary/aux-7178.rs index 56ae5139af4..56ae5139af4 100644 --- a/tests/ui/issues/auxiliary/issue-7178.rs +++ b/tests/ui/cross-crate/auxiliary/aux-7178.rs diff --git a/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs b/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs new file mode 100644 index 00000000000..3888d3bdaa9 --- /dev/null +++ b/tests/ui/cross-crate/static-method-returning-self-with-generics-7178.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/7178 +//@ run-pass +//@ aux-build:aux-7178.rs + +extern crate aux_7178 as cross_crate_self; + +pub fn main() { + let _ = cross_crate_self::Foo::new(&1); +} diff --git a/tests/ui/cross-crate/static-regions-in-cross-crate-8259.rs b/tests/ui/cross-crate/static-with-cross-crate-regions-8259.rs index 347cfa2aee1..347cfa2aee1 100644 --- a/tests/ui/cross-crate/static-regions-in-cross-crate-8259.rs +++ b/tests/ui/cross-crate/static-with-cross-crate-regions-8259.rs diff --git a/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs b/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs new file mode 100644 index 00000000000..ce3ea7dd579 --- /dev/null +++ b/tests/ui/cross-crate/tuple-struct-cross-crate-7899.rs @@ -0,0 +1,10 @@ +// https://github.com/rust-lang/rust/issues/7899 +//@ run-pass +#![allow(unused_variables)] +//@ aux-build:aux-7899.rs + +extern crate aux_7899 as testcrate; + +fn main() { + let f = testcrate::V2(1.0f32, 2.0f32); +} diff --git a/tests/ui/derives/deriving-meta-unknown-trait.stderr b/tests/ui/derives/deriving-meta-unknown-trait.stderr index 28753b8f9f2..7ee90ae9eb0 100644 --- a/tests/ui/derives/deriving-meta-unknown-trait.stderr +++ b/tests/ui/derives/deriving-meta-unknown-trait.stderr @@ -3,6 +3,7 @@ error: cannot find derive macro `Eqr` in this scope | LL | #[derive(Eqr)] | ^^^ help: a derive macro with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named derive macro `Eq` defined here @@ -12,6 +13,7 @@ error: cannot find derive macro `Eqr` in this scope | LL | #[derive(Eqr)] | ^^^ help: a derive macro with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named derive macro `Eq` defined here diff --git a/tests/ui/did_you_mean/println-typo.stderr b/tests/ui/did_you_mean/println-typo.stderr index a1e0b1f1ba4..7dd6fbba620 100644 --- a/tests/ui/did_you_mean/println-typo.stderr +++ b/tests/ui/did_you_mean/println-typo.stderr @@ -3,6 +3,7 @@ error: cannot find macro `prinltn` in this scope | LL | prinltn!(); | ^^^^^^^ help: a macro with a similar name exists: `println` + | --> $SRC_DIR/std/src/macros.rs:LL:COL | = note: similarly named macro `println` defined here diff --git a/tests/ui/issues/issue-5900.rs b/tests/ui/enum/enum-referred-by-submodule-5900.rs index 14b7b8f815a..4ed092670a8 100644 --- a/tests/ui/issues/issue-5900.rs +++ b/tests/ui/enum/enum-referred-by-submodule-5900.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5900 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs b/tests/ui/enum/enum-with-generic-parameter-5997.rs index 7ed8819f322..fab7ebbbbdc 100644 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs +++ b/tests/ui/enum/enum-with-generic-parameter-5997.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5997 //@ run-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-6117.rs b/tests/ui/enum/match-either-enum-variants-6117.rs index 3ccf67b0319..7b395066166 100644 --- a/tests/ui/issues/issue-6117.rs +++ b/tests/ui/enum/match-either-enum-variants-6117.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6117 //@ run-pass #![allow(dead_code)] diff --git a/tests/ui/error-codes/E0458.rs b/tests/ui/error-codes/E0458.rs index 35e7e84d479..0e35ba43bfb 100644 --- a/tests/ui/error-codes/E0458.rs +++ b/tests/ui/error-codes/E0458.rs @@ -1,4 +1,4 @@ -#[link(kind = "wonderful_unicorn")] extern "C" {} //~ ERROR E0458 +#[link(kind = "wonderful_unicorn")] extern "C" {} //~ ERROR malformed `link` attribute input [E0539] //~| ERROR E0459 fn main() { diff --git a/tests/ui/error-codes/E0458.stderr b/tests/ui/error-codes/E0458.stderr index c13ae4e7862..524765ea12a 100644 --- a/tests/ui/error-codes/E0458.stderr +++ b/tests/ui/error-codes/E0458.stderr @@ -1,8 +1,27 @@ -error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib, link-arg - --> $DIR/E0458.rs:1:15 +error[E0539]: malformed `link` attribute input + --> $DIR/E0458.rs:1:1 | LL | #[link(kind = "wonderful_unicorn")] extern "C" {} - | ^^^^^^^^^^^^^^^^^^^ unknown link kind + | ^^^^^^^^^^^^^^-------------------^^ + | | + | valid arguments are "static", "dylib", "framework", "raw-dylib" or "link-arg" + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(kind = "wonderful_unicorn")] extern "C" {} +LL + #[link(name = "...")] extern "C" {} + | +LL - #[link(kind = "wonderful_unicorn")] extern "C" {} +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] extern "C" {} + | +LL - #[link(kind = "wonderful_unicorn")] extern "C" {} +LL + #[link(name = "...", kind = "dylib|static|...")] extern "C" {} + | +LL - #[link(kind = "wonderful_unicorn")] extern "C" {} +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] extern "C" {} + | + = and 1 other candidate error[E0459]: `#[link]` attribute requires a `name = "string"` argument --> $DIR/E0458.rs:1:1 @@ -12,5 +31,5 @@ LL | #[link(kind = "wonderful_unicorn")] extern "C" {} error: aborting due to 2 previous errors -Some errors have detailed explanations: E0458, E0459. -For more information about an error, try `rustc --explain E0458`. +Some errors have detailed explanations: E0459, E0539. +For more information about an error, try `rustc --explain E0459`. diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs index 57d6b591287..0ad3b2aead4 100644 --- a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs +++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs @@ -2,6 +2,10 @@ /// wonderful mod foo {} +#[doc(attribute = "repr")] //~ ERROR: `#[doc(attribute)]` is meant for internal use only +/// wonderful +mod foo2 {} + trait Mine {} #[doc(fake_variadic)] //~ ERROR: `#[doc(fake_variadic)]` is meant for internal use only diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr index f3c00a2156b..5a6d4d3b45e 100644 --- a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr +++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr @@ -8,8 +8,18 @@ LL | #[doc(keyword = "match")] = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: `#[doc(attribute)]` is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:5:1 + | +LL | #[doc(attribute = "repr")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information + = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: `#[doc(fake_variadic)]` is meant for internal use only - --> $DIR/feature-gate-rustdoc_internals.rs:7:1 + --> $DIR/feature-gate-rustdoc_internals.rs:11:1 | LL | #[doc(fake_variadic)] | ^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +29,7 @@ LL | #[doc(fake_variadic)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `#[doc(search_unbox)]` is meant for internal use only - --> $DIR/feature-gate-rustdoc_internals.rs:10:1 + --> $DIR/feature-gate-rustdoc_internals.rs:14:1 | LL | #[doc(search_unbox)] | ^^^^^^^^^^^^^^^^^^^^ @@ -28,6 +38,6 @@ LL | #[doc(search_unbox)] = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 3d814700d98..e5dae4c0069 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -69,7 +69,7 @@ //~| WARN previously accepted //~| HELP can only be applied to //~| HELP remove the attribute -#![link()] //~ WARN attribute should be applied to an `extern` block +#![link(name = "x")] //~ WARN attribute should be applied to an `extern` block //~^ WARN this was previously accepted #![link_name = "1900"] //~^ WARN attribute cannot be used on @@ -692,38 +692,38 @@ mod link_section { // Note that this is a `check-pass` test, so it will never invoke the linker. -#[link()] +#[link(name = "x")] //~^ WARN attribute should be applied to an `extern` block //~| WARN this was previously accepted mod link { //~^ NOTE not an `extern` block - mod inner { #![link()] } + mod inner { #![link(name = "x")] } //~^ WARN attribute should be applied to an `extern` block //~| WARN this was previously accepted //~| NOTE not an `extern` block - #[link()] fn f() { } + #[link(name = "x")] fn f() { } //~^ WARN attribute should be applied to an `extern` block //~| WARN this was previously accepted //~| NOTE not an `extern` block - #[link()] struct S; + #[link(name = "x")] struct S; //~^ WARN attribute should be applied to an `extern` block //~| WARN this was previously accepted //~| NOTE not an `extern` block - #[link()] type T = S; + #[link(name = "x")] type T = S; //~^ WARN attribute should be applied to an `extern` block //~| WARN this was previously accepted //~| NOTE not an `extern` block - #[link()] impl S { } + #[link(name = "x")] impl S { } //~^ WARN attribute should be applied to an `extern` block //~| WARN this was previously accepted //~| NOTE not an `extern` block - #[link()] extern "Rust" {} + #[link(name = "x")] extern "Rust" {} //~^ WARN attribute should be applied to an `extern` block //~| WARN this was previously accepted } diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 65e3d29e269..ef74a00e5a1 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -223,13 +223,13 @@ LL | #![no_std] warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:1 | -LL | #[link()] - | ^^^^^^^^^ +LL | #[link(name = "x")] + | ^^^^^^^^^^^^^^^^^^^ ... LL | / mod link { LL | | LL | | -LL | | mod inner { #![link()] } +LL | | mod inner { #![link(name = "x")] } ... | LL | | } | |_- not an `extern` block @@ -316,8 +316,8 @@ LL | #![type_length_limit="0100"] warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1 | -LL | #![link()] - | ^^^^^^^^^^ not an `extern` block +LL | #![link(name = "x")] + | ^^^^^^^^^^^^^^^^^^^^ not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -462,48 +462,48 @@ LL | #![no_std] impl S { } warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:17 | -LL | mod inner { #![link()] } - | ------------^^^^^^^^^^-- not an `extern` block +LL | mod inner { #![link(name = "x")] } + | ------------^^^^^^^^^^^^^^^^^^^^-- not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5 | -LL | #[link()] fn f() { } - | ^^^^^^^^^ ---------- not an `extern` block +LL | #[link(name = "x")] fn f() { } + | ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5 | -LL | #[link()] struct S; - | ^^^^^^^^^ --------- not an `extern` block +LL | #[link(name = "x")] struct S; + | ^^^^^^^^^^^^^^^^^^^ --------- not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5 | -LL | #[link()] type T = S; - | ^^^^^^^^^ ----------- not an `extern` block +LL | #[link(name = "x")] type T = S; + | ^^^^^^^^^^^^^^^^^^^ ----------- not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 | -LL | #[link()] impl S { } - | ^^^^^^^^^ ---------- not an `extern` block +LL | #[link(name = "x")] impl S { } + | ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 | -LL | #[link()] extern "Rust" {} - | ^^^^^^^^^ +LL | #[link(name = "x")] extern "Rust" {} + | ^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/tests/ui/issues/issue-54696.rs b/tests/ui/function-pointer/function-pointer-comparison-54696.rs index 63ffbe42bcc..2e28dfeaaf8 100644 --- a/tests/ui/issues/issue-54696.rs +++ b/tests/ui/function-pointer/function-pointer-comparison-54696.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/54696 //@ run-pass #![allow(unpredictable_function_pointer_comparisons)] diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.rs index 0b1857ae3df..00bf66dd4e0 100644 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs +++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5997 fn f<Z>() -> bool { enum E { V(Z) } //~^ ERROR can't use generic parameters from outer item diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr index c0b3cd6de66..aea0f049b07 100644 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.stderr +++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/issue-5997-enum.rs:2:16 + --> $DIR/enum-definition-with-outer-generic-parameter-5997.rs:3:16 | LL | fn f<Z>() -> bool { | - type parameter from outer item diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr index d7add865aa0..2e3fd612334 100644 --- a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr +++ b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr @@ -2,7 +2,7 @@ error: implementation of `FnMut` is not general enough --> $DIR/higher-ranked-lifetime-error.rs:12:5 | LL | assert_all::<_, &String>(id); - | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnMut` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnMut` is not general enough | = note: `for<'a> fn(&'a String) -> &'a String {id}` must implement `FnMut<(&String,)>` = note: ...but it actually implements `FnMut<(&'0 String,)>`, for some specific lifetime `'0` diff --git a/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr index 916854e07af..6c17b1f4874 100644 --- a/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr +++ b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr @@ -2,7 +2,7 @@ error: implementation of `Foo` is not general enough --> $DIR/due-to-where-clause.rs:2:5 | LL | test::<FooS>(&mut 42); - | ^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`... = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1` diff --git a/tests/ui/impl-trait/call_method_without_import.no_import.stderr b/tests/ui/impl-trait/call_method_without_import.no_import.stderr index dbac74b2247..2ca79aa7c10 100644 --- a/tests/ui/impl-trait/call_method_without_import.no_import.stderr +++ b/tests/ui/impl-trait/call_method_without_import.no_import.stderr @@ -3,6 +3,7 @@ error[E0599]: no method named `fmt` found for opaque type `impl Debug` in the cu | LL | x.fmt(f); | ^^^ method not found in `impl Debug` + | --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL | = note: the method is available for `impl Debug` here diff --git a/tests/ui/impl-trait/impl-generic-mismatch.stderr b/tests/ui/impl-trait/impl-generic-mismatch.stderr index 18347bd0f97..d7fff4c445d 100644 --- a/tests/ui/impl-trait/impl-generic-mismatch.stderr +++ b/tests/ui/impl-trait/impl-generic-mismatch.stderr @@ -48,6 +48,7 @@ error[E0643]: method `hash` has incompatible signature for trait | LL | fn hash(&self, hasher: &mut impl Hasher) {} | ^^^^^^^^^^^ expected generic parameter, found `impl Trait` + | --> $SRC_DIR/core/src/hash/mod.rs:LL:COL | = note: declaration in trait here diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr index 5d0bf9bea6a..c91ea8a8793 100644 --- a/tests/ui/imports/suggest-remove-issue-121315.stderr +++ b/tests/ui/imports/suggest-remove-issue-121315.stderr @@ -3,10 +3,10 @@ error: the item `TryFrom` is imported redundantly | LL | use std::convert::TryFrom; | ^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `TryFrom` is already defined here - | note: the lint level is defined here --> $DIR/suggest-remove-issue-121315.rs:2:25 | @@ -18,6 +18,7 @@ error: the item `TryFrom` is imported redundantly | LL | use std::convert::{TryFrom, TryInto}; | ^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `TryFrom` is already defined here @@ -27,6 +28,7 @@ error: the item `TryInto` is imported redundantly | LL | use std::convert::{TryFrom, TryInto}; | ^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `TryInto` is already defined here @@ -48,6 +50,7 @@ error: the item `Into` is imported redundantly | LL | use std::convert::{AsMut, Into}; | ^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `Into` is already defined here diff --git a/tests/ui/issues/issue-17546.stderr b/tests/ui/issues/issue-17546.stderr index 25a94dd9723..5bae738d3ec 100644 --- a/tests/ui/issues/issue-17546.stderr +++ b/tests/ui/issues/issue-17546.stderr @@ -3,10 +3,10 @@ error[E0573]: expected type, found variant `NoResult` | LL | fn new() -> NoResult<MyEnum, String> { | ^^^^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/core/src/result.rs:LL:COL | = note: similarly named enum `Result` defined here - | help: try using the variant's enum | LL - fn new() -> NoResult<MyEnum, String> { @@ -57,10 +57,10 @@ error[E0573]: expected type, found variant `NoResult` | LL | fn newer() -> NoResult<foo::MyEnum, String> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/core/src/result.rs:LL:COL | = note: similarly named enum `Result` defined here - | help: try using the variant's enum | LL - fn newer() -> NoResult<foo::MyEnum, String> { diff --git a/tests/ui/issues/issue-27033.stderr b/tests/ui/issues/issue-27033.stderr index 7a0ca888d74..129870f8c40 100644 --- a/tests/ui/issues/issue-27033.stderr +++ b/tests/ui/issues/issue-27033.stderr @@ -3,6 +3,7 @@ error[E0530]: match bindings cannot shadow unit variants | LL | None @ _ => {} | ^^^^ cannot be named the same as a unit variant + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the unit variant `None` is defined here diff --git a/tests/ui/issues/issue-54410.rs b/tests/ui/issues/issue-54410.rs deleted file mode 100644 index e3e8ca985b9..00000000000 --- a/tests/ui/issues/issue-54410.rs +++ /dev/null @@ -1,8 +0,0 @@ -extern "C" { - pub static mut symbol: [i8]; - //~^ ERROR the size for values of type `[i8]` cannot be known at compilation time -} - -fn main() { - println!("{:p}", unsafe { &symbol }); -} diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr deleted file mode 100644 index cb68ada7e13..00000000000 --- a/tests/ui/issues/issue-54410.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0277]: the size for values of type `[i8]` cannot be known at compilation time - --> $DIR/issue-54410.rs:2:5 - | -LL | pub static mut symbol: [i8]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[i8]` - = note: statics and constants must have a statically known size - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-5518.rs b/tests/ui/issues/issue-5518.rs deleted file mode 100644 index 333185c482f..00000000000 --- a/tests/ui/issues/issue-5518.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -//@ aux-build:issue-5518.rs - - -extern crate issue_5518 as other; - -fn main() {} diff --git a/tests/ui/issues/issue-5844.rs b/tests/ui/issues/issue-5844.rs deleted file mode 100644 index 23021207ae1..00000000000 --- a/tests/ui/issues/issue-5844.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@aux-build:issue-5844-aux.rs - -extern crate issue_5844_aux; - -fn main() { - issue_5844_aux::rand(); //~ ERROR: requires unsafe -} diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs deleted file mode 100644 index 19d994b0dfb..00000000000 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn f<T>() -> bool { - struct S(T); //~ ERROR can't use generic parameters from outer item - - true -} - -fn main() { - let b = f::<isize>(); - assert!(b); -} diff --git a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr b/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr deleted file mode 100644 index 670a54894b5..00000000000 --- a/tests/ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0401]: can't use generic parameters from outer item - --> $DIR/issue-5997-struct.rs:2:14 - | -LL | fn f<T>() -> bool { - | - type parameter from outer item -LL | struct S(T); - | -^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `<T>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/issues/issue-6344-match.rs b/tests/ui/issues/issue-6344-match.rs deleted file mode 100644 index 9251e274383..00000000000 --- a/tests/ui/issues/issue-6344-match.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ run-pass -#![allow(non_shorthand_field_patterns)] - -struct A { x: usize } - -impl Drop for A { - fn drop(&mut self) {} -} - -pub fn main() { - let a = A { x: 0 }; - - match a { - A { x : ref x } => { - println!("{}", x) - } - } -} diff --git a/tests/ui/issues/issue-7178.rs b/tests/ui/issues/issue-7178.rs deleted file mode 100644 index 408ce0b03eb..00000000000 --- a/tests/ui/issues/issue-7178.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass -//@ aux-build:issue-7178.rs - - -extern crate issue_7178 as cross_crate_self; - -pub fn main() { - let _ = cross_crate_self::Foo::new(&1); -} diff --git a/tests/ui/issues/issue-53419.rs b/tests/ui/lifetimes/dyn-trait-function-pointer-53419.rs index 55d41f2005d..b1017b104ac 100644 --- a/tests/ui/issues/issue-53419.rs +++ b/tests/ui/lifetimes/dyn-trait-function-pointer-53419.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/53419 //@ check-pass struct Foo { diff --git a/tests/ui/issues/issue-7268.rs b/tests/ui/lifetimes/static-bound-fulfillment-with-pointer-7268.rs index a3bc1bc3446..8ec58e6cd80 100644 --- a/tests/ui/issues/issue-7268.rs +++ b/tests/ui/lifetimes/static-bound-fulfillment-with-pointer-7268.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7268 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.full-debuginfo.stderr index 5b97a2104a3..4b179d59e5f 100644 --- a/tests/ui/limits/huge-enum.stderr +++ b/tests/ui/limits/huge-enum.full-debuginfo.stderr @@ -1,5 +1,5 @@ error: values of the type `Option<TYPE>` are too big for the target architecture - --> $DIR/huge-enum.rs:15:9 + --> $DIR/huge-enum.rs:17:9 | LL | let big: BIG = None; | ^^^ diff --git a/tests/ui/limits/huge-enum.no-debuginfo.stderr b/tests/ui/limits/huge-enum.no-debuginfo.stderr new file mode 100644 index 00000000000..4b179d59e5f --- /dev/null +++ b/tests/ui/limits/huge-enum.no-debuginfo.stderr @@ -0,0 +1,8 @@ +error: values of the type `Option<TYPE>` are too big for the target architecture + --> $DIR/huge-enum.rs:17:9 + | +LL | let big: BIG = None; + | ^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs index 6d5b86411f3..9395bee9765 100644 --- a/tests/ui/limits/huge-enum.rs +++ b/tests/ui/limits/huge-enum.rs @@ -1,9 +1,11 @@ +// FIXME(#61117): Remove revisions once x86_64-gnu-debug CI job sets rust.debuginfo-level-tests=2 +// NOTE: The .stderr for both revisions shall be identical. +//@ revisions: no-debuginfo full-debuginfo //@ build-fail //@ normalize-stderr: "std::option::Option<\[u32; \d+\]>" -> "TYPE" //@ normalize-stderr: "\[u32; \d+\]" -> "TYPE" - -// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0 -//@ compile-flags: -Cdebuginfo=0 +//@[no-debuginfo] compile-flags: -Cdebuginfo=0 +//@[full-debuginfo] compile-flags: -Cdebuginfo=2 #[cfg(target_pointer_width = "32")] type BIG = Option<[u32; (1<<29)-1]>; diff --git a/tests/ui/link-native-libs/issue-43925.rs b/tests/ui/link-native-libs/issue-43925.rs index 1a210887154..e3ce71352c0 100644 --- a/tests/ui/link-native-libs/issue-43925.rs +++ b/tests/ui/link-native-libs/issue-43925.rs @@ -1,4 +1,6 @@ -#[link(name = "foo", cfg("rlib"))] //~ ERROR link cfg must have a single predicate argument +#[link(name = "foo", cfg("rlib"))] +//~^ ERROR link cfg is unstable +//~| ERROR `cfg` predicate key must be an identifier extern "C" {} fn main() {} diff --git a/tests/ui/link-native-libs/issue-43925.stderr b/tests/ui/link-native-libs/issue-43925.stderr index 7cc347c6163..82d204222df 100644 --- a/tests/ui/link-native-libs/issue-43925.stderr +++ b/tests/ui/link-native-libs/issue-43925.stderr @@ -1,8 +1,18 @@ -error: link cfg must have a single predicate argument +error[E0658]: link cfg is unstable --> $DIR/issue-43925.rs:1:22 | LL | #[link(name = "foo", cfg("rlib"))] | ^^^^^^^^^^^ + | + = help: add `#![feature(link_cfg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: `cfg` predicate key must be an identifier + --> $DIR/issue-43925.rs:1:26 + | +LL | #[link(name = "foo", cfg("rlib"))] + | ^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/link-native-libs/issue-43926.rs b/tests/ui/link-native-libs/issue-43926.rs index 6d3003552dc..293ad3f4ec1 100644 --- a/tests/ui/link-native-libs/issue-43926.rs +++ b/tests/ui/link-native-libs/issue-43926.rs @@ -1,4 +1,4 @@ -#[link(name = "foo", cfg())] //~ ERROR link cfg must have a single predicate argument +#[link(name = "foo", cfg())] //~ ERROR malformed `link` attribute input extern "C" {} fn main() {} diff --git a/tests/ui/link-native-libs/issue-43926.stderr b/tests/ui/link-native-libs/issue-43926.stderr index 7c5c50a38a9..9e3ec21cc94 100644 --- a/tests/ui/link-native-libs/issue-43926.stderr +++ b/tests/ui/link-native-libs/issue-43926.stderr @@ -1,8 +1,28 @@ -error: link cfg must have a single predicate argument - --> $DIR/issue-43926.rs:1:22 +error[E0805]: malformed `link` attribute input + --> $DIR/issue-43926.rs:1:1 | LL | #[link(name = "foo", cfg())] - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^-----^^ + | | + | expected a single argument here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "foo", cfg())] +LL + #[link(name = "...")] + | +LL - #[link(name = "foo", cfg())] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "foo", cfg())] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "foo", cfg())] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0805`. diff --git a/tests/ui/link-native-libs/link-attr-validation-early.rs b/tests/ui/link-native-libs/link-attr-validation-early.rs index a7dd80f8920..89a34ac6ca1 100644 --- a/tests/ui/link-native-libs/link-attr-validation-early.rs +++ b/tests/ui/link-native-libs/link-attr-validation-early.rs @@ -1,8 +1,6 @@ // Top-level ill-formed -#[link] //~ ERROR valid forms for the attribute are - //~| WARN this was previously accepted -#[link = "foo"] //~ ERROR valid forms for the attribute are - //~| WARN this was previously accepted +#[link] //~ ERROR malformed +#[link = "foo"] //~ ERROR malformed extern "C" {} fn main() {} diff --git a/tests/ui/link-native-libs/link-attr-validation-early.stderr b/tests/ui/link-native-libs/link-attr-validation-early.stderr index d4fc2e272f8..e4799b1a161 100644 --- a/tests/ui/link-native-libs/link-attr-validation-early.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-early.stderr @@ -1,47 +1,45 @@ -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` +error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-early.rs:2:1 | LL | #[link] - | ^^^^^^^ + | ^^^^^^^ expected this to be a list | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default +help: try changing it to one of the following valid forms of the attribute + | +LL | #[link(name = "...")] + | ++++++++++++++ +LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...")] + | +++++++++++++++++++++++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + = and 1 other candidate -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/link-attr-validation-early.rs:4:1 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-early.rs:3:1 | LL | #[link = "foo"] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ expected this to be a list | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> - -error: aborting due to 2 previous errors - -Future incompatibility report: Future breakage diagnostic: -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/link-attr-validation-early.rs:2:1 +help: try changing it to one of the following valid forms of the attribute | -LL | #[link] - | ^^^^^^^ +LL - #[link = "foo"] +LL + #[link(name = "...")] | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> - = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default - -Future breakage diagnostic: -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/link-attr-validation-early.rs:4:1 +LL - #[link = "foo"] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] | -LL | #[link = "foo"] - | ^^^^^^^^^^^^^^^ +LL - #[link = "foo"] +LL + #[link(name = "...", kind = "dylib|static|...")] | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> - = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default +LL - #[link = "foo"] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/link-native-libs/link-attr-validation-late.rs b/tests/ui/link-native-libs/link-attr-validation-late.rs index 4eeb8ba4884..d2947b5f61a 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.rs +++ b/tests/ui/link-native-libs/link-attr-validation-late.rs @@ -1,38 +1,36 @@ #![feature(link_cfg)] // Top-level ill-formed -#[link(name = "...", "literal")] //~ ERROR unexpected `#[link]` argument -#[link(name = "...", unknown)] //~ ERROR unexpected `#[link]` argument +#[link(name = "...", "literal")] //~ ERROR malformed `link` attribute input +#[link(name = "...", unknown)] //~ ERROR malformed `link` attribute input extern "C" {} // Duplicate arguments -#[link(name = "foo", name = "bar")] //~ ERROR multiple `name` arguments -#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR multiple `kind` arguments -#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR multiple `modifiers` arguments -#[link(name = "...", cfg(false), cfg(false))] //~ ERROR multiple `cfg` arguments -#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR multiple `wasm_import_module` arguments +#[link(name = "foo", name = "bar")] //~ ERROR malformed `link` attribute input +#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR malformed `link` attribute input +#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR malformed `link` attribute input +#[link(name = "...", cfg(false), cfg(false))] //~ ERROR malformed `link` attribute input +#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR malformed `link` attribute input extern "C" {} // Ill-formed arguments -#[link(name)] //~ ERROR link name must be of the form `name = "string"` - //~| ERROR `#[link]` attribute requires a `name = "string"` argument -#[link(name())] //~ ERROR link name must be of the form `name = "string"` - //~| ERROR `#[link]` attribute requires a `name = "string"` argument -#[link(name = "...", kind)] //~ ERROR link kind must be of the form `kind = "string"` -#[link(name = "...", kind())] //~ ERROR link kind must be of the form `kind = "string"` -#[link(name = "...", modifiers)] //~ ERROR link modifiers must be of the form `modifiers = "string"` -#[link(name = "...", modifiers())] //~ ERROR link modifiers must be of the form `modifiers = "string"` -#[link(name = "...", cfg)] //~ ERROR link cfg must be of the form `cfg(/* predicate */)` -#[link(name = "...", cfg = "literal")] //~ ERROR link cfg must be of the form `cfg(/* predicate */)` -#[link(name = "...", cfg("literal"))] //~ ERROR link cfg must have a single predicate argument -#[link(name = "...", wasm_import_module)] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"` -#[link(name = "...", wasm_import_module())] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"` +#[link(name)] //~ ERROR malformed `link` attribute input +#[link(name())] //~ ERROR malformed `link` attribute input +#[link(name = "...", kind)] //~ ERROR malformed `link` attribute input +#[link(name = "...", kind())] //~ ERROR malformed `link` attribute input +#[link(name = "...", modifiers)] //~ ERROR malformed `link` attribute input +#[link(name = "...", modifiers())] //~ ERROR malformed `link` attribute input +#[link(name = "...", cfg)] //~ ERROR malformed `link` attribute input +#[link(name = "...", cfg = "literal")] //~ ERROR malformed `link` attribute input +#[link(name = "...", cfg("literal"))] //~ ERROR `cfg` predicate key must be an identifier +#[link(name = "...", wasm_import_module)] //~ ERROR malformed `link` attribute input +#[link(name = "...", wasm_import_module())] //~ ERROR malformed `link` attribute input extern "C" {} // Basic modifier validation #[link(name = "...", modifiers = "")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix #[link(name = "...", modifiers = "no-plus-minus")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix -#[link(name = "...", modifiers = "+unknown")] //~ ERROR unknown linking modifier `unknown` +#[link(name = "...", modifiers = "+unknown")] //~ ERROR malformed `link` attribute input #[link(name = "...", modifiers = "+verbatim,+verbatim")] //~ ERROR multiple `verbatim` modifiers extern "C" {} diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr index f3989c09360..834dca0bc0b 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr @@ -1,147 +1,472 @@ -error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type - --> $DIR/link-attr-validation-late.rs:4:22 +error[E0565]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:4:1 | LL | #[link(name = "...", "literal")] - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^---------^^ + | | + | didn't expect a literal here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", "literal")] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", "literal")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", "literal")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", "literal")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type - --> $DIR/link-attr-validation-late.rs:5:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:5:1 | LL | #[link(name = "...", unknown)] - | ^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^-------^^ + | | + | valid arguments are "name", "kind", "modifiers", "cfg", "wasm_import_module" or "import_name_type" + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", unknown)] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", unknown)] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", unknown)] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", unknown)] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: multiple `name` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:9:22 +error[E0538]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:9:1 | LL | #[link(name = "foo", name = "bar")] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^------------^^ + | | + | found `name` used as a key more than once + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "foo", name = "bar")] +LL + #[link(name = "...")] + | +LL - #[link(name = "foo", name = "bar")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "foo", name = "bar")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "foo", name = "bar")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: multiple `kind` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:10:38 +error[E0538]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:10:1 | LL | #[link(name = "...", kind = "dylib", kind = "bar")] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------^^ + | | + | found `kind` used as a key more than once + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", kind = "dylib", kind = "bar")] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", kind = "dylib", kind = "bar")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", kind = "dylib", kind = "bar")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", kind = "dylib", kind = "bar")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: multiple `modifiers` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:11:47 +error[E0538]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:11:1 | LL | #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^ + | | + | found `modifiers` used as a key more than once + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: multiple `cfg` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:12:34 +error[E0538]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:12:1 | LL | #[link(name = "...", cfg(false), cfg(false))] - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------^^ + | | + | found `cfg` used as a key more than once + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", cfg(false), cfg(false))] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", cfg(false), cfg(false))] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", cfg(false), cfg(false))] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", cfg(false), cfg(false))] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: multiple `wasm_import_module` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:13:36 +error[E0538]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:13:1 | LL | #[link(wasm_import_module = "foo", wasm_import_module = "bar")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: link name must be of the form `name = "string"` - --> $DIR/link-attr-validation-late.rs:17:8 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------^^ + | | + | found `wasm_import_module` used as a key more than once | -LL | #[link(name)] - | ^^^^ + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")] +LL + #[link(name = "...")] + | +LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error[E0459]: `#[link]` attribute requires a `name = "string"` argument +error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:17:1 | LL | #[link(name)] - | ^^^^^^^^^^^^^ missing `name` argument - -error: link name must be of the form `name = "string"` - --> $DIR/link-attr-validation-late.rs:19:8 + | ^^^^^^^----^^ + | | + | expected this to be of the form `name = "..."` | -LL | #[link(name())] - | ^^^^^^ + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL | #[link(name = "...")] + | +++++++ +LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...")] + | ++++++++++++++++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + = and 1 other candidate -error[E0459]: `#[link]` attribute requires a `name = "string"` argument - --> $DIR/link-attr-validation-late.rs:19:1 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:18:1 | LL | #[link(name())] - | ^^^^^^^^^^^^^^^ missing `name` argument + | ^^^^^^^------^^ + | | + | expected this to be of the form `name = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name())] +LL + #[link(name = "...")] + | +LL - #[link(name())] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name())] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name())] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: link kind must be of the form `kind = "string"` - --> $DIR/link-attr-validation-late.rs:21:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:19:1 | LL | #[link(name = "...", kind)] - | ^^^^ + | ^^^^^^^^^^^^^^^^^^^^^----^^ + | | + | expected this to be of the form `kind = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", kind)] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", kind)] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL | #[link(name = "...", kind = "dylib|static|...")] + | ++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + = and 1 other candidate -error: link kind must be of the form `kind = "string"` - --> $DIR/link-attr-validation-late.rs:22:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:20:1 | LL | #[link(name = "...", kind())] - | ^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^------^^ + | | + | expected this to be of the form `kind = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", kind())] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", kind())] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", kind())] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", kind())] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: link modifiers must be of the form `modifiers = "string"` - --> $DIR/link-attr-validation-late.rs:23:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:21:1 | LL | #[link(name = "...", modifiers)] - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^---------^^ + | | + | expected this to be of the form `modifiers = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", modifiers)] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", modifiers)] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", modifiers)] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", modifiers)] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: link modifiers must be of the form `modifiers = "string"` - --> $DIR/link-attr-validation-late.rs:24:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:22:1 | LL | #[link(name = "...", modifiers())] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^-----------^^ + | | + | expected this to be of the form `modifiers = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", modifiers())] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", modifiers())] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", modifiers())] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", modifiers())] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: link cfg must be of the form `cfg(/* predicate */)` - --> $DIR/link-attr-validation-late.rs:25:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:23:1 | LL | #[link(name = "...", cfg)] - | ^^^ + | ^^^^^^^^^^^^^^^^^^^^^---^^ + | | + | expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", cfg)] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", cfg)] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", cfg)] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", cfg)] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: link cfg must be of the form `cfg(/* predicate */)` - --> $DIR/link-attr-validation-late.rs:26:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:24:1 | LL | #[link(name = "...", cfg = "literal")] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^---------------^^ + | | + | expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", cfg = "literal")] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", cfg = "literal")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", cfg = "literal")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", cfg = "literal")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: link cfg must have a single predicate argument - --> $DIR/link-attr-validation-late.rs:27:22 +error: `cfg` predicate key must be an identifier + --> $DIR/link-attr-validation-late.rs:25:26 | LL | #[link(name = "...", cfg("literal"))] - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^ -error: wasm import module must be of the form `wasm_import_module = "string"` - --> $DIR/link-attr-validation-late.rs:28:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:26:1 | LL | #[link(name = "...", wasm_import_module)] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^------------------^^ + | | + | expected this to be of the form `wasm_import_module = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", wasm_import_module)] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", wasm_import_module)] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", wasm_import_module)] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", wasm_import_module)] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: wasm import module must be of the form `wasm_import_module = "string"` - --> $DIR/link-attr-validation-late.rs:29:22 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:27:1 | LL | #[link(name = "...", wasm_import_module())] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^--------------------^^ + | | + | expected this to be of the form `wasm_import_module = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", wasm_import_module())] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", wasm_import_module())] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", wasm_import_module())] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", wasm_import_module())] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed - --> $DIR/link-attr-validation-late.rs:33:34 + --> $DIR/link-attr-validation-late.rs:31:34 | LL | #[link(name = "...", modifiers = "")] | ^^ error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed - --> $DIR/link-attr-validation-late.rs:34:34 + --> $DIR/link-attr-validation-late.rs:32:34 | LL | #[link(name = "...", modifiers = "no-plus-minus")] | ^^^^^^^^^^^^^^^ -error: unknown linking modifier `unknown`, expected one of: bundle, verbatim, whole-archive, as-needed - --> $DIR/link-attr-validation-late.rs:35:34 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:33:1 | LL | #[link(name = "...", modifiers = "+unknown")] - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------^^ + | | + | valid arguments are "bundle", "verbatim", "whole-archive" or "as-needed" + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", modifiers = "+unknown")] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", modifiers = "+unknown")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", modifiers = "+unknown")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", modifiers = "+unknown")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: multiple `verbatim` modifiers in a single `modifiers` argument - --> $DIR/link-attr-validation-late.rs:36:34 + --> $DIR/link-attr-validation-late.rs:34:34 | LL | #[link(name = "...", modifiers = "+verbatim,+verbatim")] | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 24 previous errors +error: aborting due to 22 previous errors -For more information about this error, try `rustc --explain E0459`. +Some errors have detailed explanations: E0538, E0539, E0565. +For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/link-native-libs/modifiers-override-4.rs b/tests/ui/link-native-libs/modifiers-override-4.rs new file mode 100644 index 00000000000..cc5b07e20cc --- /dev/null +++ b/tests/ui/link-native-libs/modifiers-override-4.rs @@ -0,0 +1,12 @@ +#[link(name = "foo")] +#[link( +//~^ ERROR malformed `link` attribute input + name = "bar", + kind = "static", + modifiers = "+whole-archive,-whole-archive", + //~^ ERROR multiple `whole-archive` modifiers in a single `modifiers` argument + modifiers = "+bundle" +)] +extern "C" {} + +fn main() {} diff --git a/tests/ui/link-native-libs/modifiers-override-4.stderr b/tests/ui/link-native-libs/modifiers-override-4.stderr new file mode 100644 index 00000000000..317e89cb39c --- /dev/null +++ b/tests/ui/link-native-libs/modifiers-override-4.stderr @@ -0,0 +1,67 @@ +error[E0538]: malformed `link` attribute input + --> $DIR/modifiers-override-4.rs:2:1 + | +LL | / #[link( +LL | | +LL | | name = "bar", +LL | | kind = "static", +... | +LL | | modifiers = "+bundle" + | | --------------------- found `modifiers` used as a key more than once +LL | | )] + | |__^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link( +LL - +LL - name = "bar", +LL - kind = "static", +LL - modifiers = "+whole-archive,-whole-archive", +LL - +LL - modifiers = "+bundle" +LL - )] +LL + #[link(name = "...")] + | +LL - #[link( +LL - +LL - name = "bar", +LL - kind = "static", +LL - modifiers = "+whole-archive,-whole-archive", +LL - +LL - modifiers = "+bundle" +LL - )] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link( +LL - +LL - name = "bar", +LL - kind = "static", +LL - modifiers = "+whole-archive,-whole-archive", +LL - +LL - modifiers = "+bundle" +LL - )] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link( +LL - +LL - name = "bar", +LL - kind = "static", +LL - modifiers = "+whole-archive,-whole-archive", +LL - +LL - modifiers = "+bundle" +LL - )] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate + +error: multiple `whole-archive` modifiers in a single `modifiers` argument + --> $DIR/modifiers-override-4.rs:6:17 + | +LL | modifiers = "+whole-archive,-whole-archive", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0538`. diff --git a/tests/ui/link-native-libs/modifiers-override.rs b/tests/ui/link-native-libs/modifiers-override.rs index cd2d003664a..a44b7d37ed8 100644 --- a/tests/ui/link-native-libs/modifiers-override.rs +++ b/tests/ui/link-native-libs/modifiers-override.rs @@ -4,13 +4,8 @@ #[link( name = "bar", kind = "static", - modifiers = "+whole-archive,-whole-archive", - //~^ ERROR multiple `whole-archive` modifiers in a single `modifiers` argument - modifiers = "+bundle" - //~^ ERROR multiple `modifiers` arguments in a single `#[link]` attribute )] extern "C" {} //~^ ERROR overriding linking modifiers from command line is not supported -//~| ERROR overriding linking modifiers from command line is not supported fn main() {} diff --git a/tests/ui/link-native-libs/modifiers-override.stderr b/tests/ui/link-native-libs/modifiers-override.stderr index 64427651e9f..3cc99c96c7c 100644 --- a/tests/ui/link-native-libs/modifiers-override.stderr +++ b/tests/ui/link-native-libs/modifiers-override.stderr @@ -1,28 +1,8 @@ -error: multiple `modifiers` arguments in a single `#[link]` attribute - --> $DIR/modifiers-override.rs:9:5 - | -LL | modifiers = "+bundle" - | ^^^^^^^^^^^^^^^^^^^^^ - -error: multiple `whole-archive` modifiers in a single `modifiers` argument - --> $DIR/modifiers-override.rs:7:17 - | -LL | modifiers = "+whole-archive,-whole-archive", - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: overriding linking modifiers from command line is not supported - --> $DIR/modifiers-override.rs:12:1 - | -LL | extern "C" {} - | ^^^^^^^^^^^^^ - error: overriding linking modifiers from command line is not supported - --> $DIR/modifiers-override.rs:12:1 + --> $DIR/modifiers-override.rs:8:1 | LL | extern "C" {} | ^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs index 50ad8a173ad..542f34b3eb1 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs @@ -1,7 +1,10 @@ -//@ only-windows -//@ only-x86 +//@ add-core-stubs +//@ compile-flags: --target i686-pc-windows-msvc +//@ needs-llvm-components: x86 +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] +#![crate_type = "lib"] + #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] -//~^ ERROR import name type must be of the form `import_name_type = "string"` +//~^ ERROR malformed extern "C" { } - -fn main() {} diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr index d2cf7a0ba1f..6121762fb03 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr @@ -1,8 +1,28 @@ -error: import name type must be of the form `import_name_type = "string"` - --> $DIR/import-name-type-invalid-format.rs:3:42 +error[E0539]: malformed `link` attribute input + --> $DIR/import-name-type-invalid-format.rs:8:1 | LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------^^ + | | + | expected this to be of the form `import_name_type = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] +LL + #[link(name = "...")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs index cf456b9b261..e2418642aea 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs @@ -1,8 +1,11 @@ // ignore-tidy-linelength -//@ only-windows -//@ only-x86 +//@ add-core-stubs +//@ compile-flags: --target i686-pc-windows-msvc +//@ needs-llvm-components: x86 +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] +#![crate_type = "lib"] + #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] -//~^ ERROR multiple `import_name_type` arguments in a single `#[link]` attribute +//~^ ERROR malformed extern "C" { } - -fn main() {} diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr index 8e65baf65df..adfe915b464 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr @@ -1,8 +1,28 @@ -error: multiple `import_name_type` arguments in a single `#[link]` attribute - --> $DIR/import-name-type-multiple.rs:4:74 +error[E0538]: malformed `link` attribute input + --> $DIR/import-name-type-multiple.rs:9:1 | LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------^^ + | | + | found `import_name_type` used as a key more than once + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] +LL + #[link(name = "...")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0538`. diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs index b3859ba1ce6..174e8682f29 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs @@ -1,7 +1,10 @@ -//@ only-windows -//@ only-x86 +//@ add-core-stubs +//@ compile-flags: --target i686-pc-windows-msvc +//@ needs-llvm-components: x86 +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] +#![crate_type = "lib"] + #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] -//~^ ERROR unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated +//~^ ERROR malformed extern "C" { } - -fn main() {} diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr index 4b8b90eb6e2..fc24a6bed17 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr @@ -1,8 +1,28 @@ -error: unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated - --> $DIR/import-name-type-unknown-value.rs:3:42 +error[E0539]: malformed `link` attribute input + --> $DIR/import-name-type-unknown-value.rs:8:1 | LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------^^ + | | + | valid arguments are "decorated", "noprefix" or "undecorated" + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] +LL + #[link(name = "...")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs index 3ead5cb1fd7..ca6aef79c95 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs @@ -1,5 +1,10 @@ -//@ only-windows -//@ only-x86 +//@ add-core-stubs +//@ compile-flags: --target i686-pc-windows-msvc +//@ needs-llvm-components: x86 +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] +#![crate_type = "lib"] + #[link(name = "foo", import_name_type = "decorated")] //~^ ERROR import name type can only be used with link kind `raw-dylib` extern "C" { } @@ -11,5 +16,3 @@ extern "C" { } // Specifying `import_name_type` before `kind` shouldn't raise an error. #[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")] extern "C" { } - -fn main() {} diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr index 75cadc471c4..075e4ffffb8 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr @@ -1,11 +1,11 @@ error: import name type can only be used with link kind `raw-dylib` - --> $DIR/import-name-type-unsupported-link-kind.rs:3:22 + --> $DIR/import-name-type-unsupported-link-kind.rs:8:22 | LL | #[link(name = "foo", import_name_type = "decorated")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: import name type can only be used with link kind `raw-dylib` - --> $DIR/import-name-type-unsupported-link-kind.rs:7:39 + --> $DIR/import-name-type-unsupported-link-kind.rs:12:39 | LL | #[link(name = "bar", kind = "static", import_name_type = "decorated")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs index ab0dcda64e6..5f1410f7d2a 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs @@ -1,7 +1,10 @@ -//@ only-windows -//@ ignore-x86 +//@ add-core-stubs +//@ compile-flags: --target aarch64-pc-windows-msvc +//@ needs-llvm-components: aarch64 +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] +#![crate_type = "lib"] + #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")] //~^ ERROR import name type is only supported on x86 extern "C" { } - -fn main() {} diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr index 757f1f7994e..ad3b9f79c84 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr @@ -1,5 +1,5 @@ error: import name type is only supported on x86 - --> $DIR/import-name-type-x86-only.rs:3:42 + --> $DIR/import-name-type-x86-only.rs:8:42 | LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs index 301e690be38..8651a4e7175 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs @@ -10,7 +10,7 @@ fn test() {} //~^ ERROR attribute cannot be used on static mut imported_val: i32 = 123; -#[link(name = "exporter", kind = "raw-dylib")] +#[link(name = "exporter")] extern "C" { #[link_ordinal(13)] fn imported_function(); diff --git a/tests/ui/lint/int_to_ptr-unsized.rs b/tests/ui/lint/int_to_ptr-unsized.rs new file mode 100644 index 00000000000..bbdc2474561 --- /dev/null +++ b/tests/ui/lint/int_to_ptr-unsized.rs @@ -0,0 +1,23 @@ +// Checks for the `integer_to_pointer_transmutes` lint with unsized types +// +// Related to https://github.com/rust-lang/rust/issues/145935 + +//@ check-pass + +#![allow(non_camel_case_types)] +#![allow(unused_unsafe)] + +#[cfg(target_pointer_width = "64")] +type usizemetadata = i128; + +#[cfg(target_pointer_width = "32")] +type usizemetadata = i64; + +unsafe fn unsized_type(a: usize) { + let _ref = unsafe { std::mem::transmute::<usizemetadata, &'static str>(0xff) }; + //~^ WARN transmuting an integer to a pointer + let _ptr = unsafe { std::mem::transmute::<usizemetadata, *const [u8]>(0xff) }; + //~^ WARN transmuting an integer to a pointer +} + +fn main() {} diff --git a/tests/ui/lint/int_to_ptr-unsized.stderr b/tests/ui/lint/int_to_ptr-unsized.stderr new file mode 100644 index 00000000000..9799af8b12c --- /dev/null +++ b/tests/ui/lint/int_to_ptr-unsized.stderr @@ -0,0 +1,27 @@ +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr-unsized.rs:17:25 + | +LL | let _ref = unsafe { std::mem::transmute::<usizemetadata, &'static str>(0xff) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers> + = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance> + = note: `#[warn(integer_to_ptr_transmutes)]` on by default + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr-unsized.rs:19:25 + | +LL | let _ptr = unsafe { std::mem::transmute::<usizemetadata, *const [u8]>(0xff) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers> + = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance> + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr index c14ab9e11e0..8a5c243ddf8 100644 --- a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr +++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr @@ -3,10 +3,10 @@ warning: the item `String` is imported redundantly | LL | use std::string::String; | ^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `String` is already defined here - | note: the lint level is defined here --> $DIR/use-redundant-issue-71450.rs:3:9 | diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr index 48d5c275055..71bc7d3b371 100644 --- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr @@ -3,10 +3,10 @@ warning: the item `Some` is imported redundantly | LL | use std::option::Option::Some; | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `Some` is already defined here - | note: the lint level is defined here --> $DIR/use-redundant-prelude-rust-2015.rs:3:9 | @@ -18,6 +18,7 @@ warning: the item `None` is imported redundantly | LL | use std::option::Option::None; | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `None` is already defined here @@ -27,6 +28,7 @@ warning: the item `Ok` is imported redundantly | LL | use std::result::Result::Ok; | ^^^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `Ok` is already defined here @@ -36,6 +38,7 @@ warning: the item `Err` is imported redundantly | LL | use std::result::Result::Err; | ^^^^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `Err` is already defined here diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr index 526771c597a..f9b7af2105c 100644 --- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr @@ -3,10 +3,10 @@ warning: the item `TryFrom` is imported redundantly | LL | use std::convert::TryFrom; | ^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `TryFrom` is already defined here - | note: the lint level is defined here --> $DIR/use-redundant-prelude-rust-2021.rs:3:9 | @@ -18,6 +18,7 @@ warning: the item `TryInto` is imported redundantly | LL | use std::convert::TryInto; | ^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | = note: the item `TryInto` is already defined here diff --git a/tests/ui/issues/issue-5741.rs b/tests/ui/loops/unreachable-while-loop-5741.rs index af4702ec22c..bc69df0f675 100644 --- a/tests/ui/issues/issue-5741.rs +++ b/tests/ui/loops/unreachable-while-loop-5741.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5741 //@ run-pass #![allow(while_true)] #![allow(unreachable_code)] diff --git a/tests/ui/macros/format-foreign-dollar-without-spec.rs b/tests/ui/macros/format-foreign-dollar-without-spec.rs new file mode 100644 index 00000000000..c57c1382c8d --- /dev/null +++ b/tests/ui/macros/format-foreign-dollar-without-spec.rs @@ -0,0 +1,5 @@ +// https://github.com/rust-lang/rust/issues/137580 +fn main() { + println!("%65536$", 1); + //~^ ERROR never used +} diff --git a/tests/ui/macros/format-foreign-dollar-without-spec.stderr b/tests/ui/macros/format-foreign-dollar-without-spec.stderr new file mode 100644 index 00000000000..d5a07c50f00 --- /dev/null +++ b/tests/ui/macros/format-foreign-dollar-without-spec.stderr @@ -0,0 +1,16 @@ +error: argument never used + --> $DIR/format-foreign-dollar-without-spec.rs:3:25 + | +LL | println!("%65536$", 1); + | ^ argument never used + | +note: format specifiers use curly braces, and the conversion specifier ` + ` is unknown or unsupported + --> $DIR/format-foreign-dollar-without-spec.rs:3:15 + | +LL | println!("%65536$", 1); + | ^^^^^^^^ + = note: printf formatting is not supported; see the documentation for `std::fmt` + +error: aborting due to 1 previous error + diff --git a/tests/ui/macros/macro-name-typo.stderr b/tests/ui/macros/macro-name-typo.stderr index 9059b10faaa..1cc7ea6ec1b 100644 --- a/tests/ui/macros/macro-name-typo.stderr +++ b/tests/ui/macros/macro-name-typo.stderr @@ -3,6 +3,7 @@ error: cannot find macro `printlx` in this scope | LL | printlx!("oh noes!"); | ^^^^^^^ help: a macro with a similar name exists: `println` + | --> $SRC_DIR/std/src/macros.rs:LL:COL | = note: similarly named macro `println` defined here diff --git a/tests/ui/macros/macro-path-prelude-fail-3.stderr b/tests/ui/macros/macro-path-prelude-fail-3.stderr index 485d7b7869a..3d0a074deeb 100644 --- a/tests/ui/macros/macro-path-prelude-fail-3.stderr +++ b/tests/ui/macros/macro-path-prelude-fail-3.stderr @@ -3,6 +3,7 @@ error: cannot find macro `inline` in this scope | LL | inline!(); | ^^^^^^ help: a macro with a similar name exists: `line` + | --> $SRC_DIR/core/src/macros/mod.rs:LL:COL | = note: similarly named macro `line` defined here diff --git a/tests/ui/issues/issue-5554.rs b/tests/ui/macros/macro-variable-declaration-with-bounds-5554.rs index 7d219a0df70..8ccf8e80131 100644 --- a/tests/ui/issues/issue-5554.rs +++ b/tests/ui/macros/macro-variable-declaration-with-bounds-5554.rs @@ -1,7 +1,7 @@ +// https://github.com/rust-lang/rust/issues/5554 //@ run-pass #![allow(dead_code)] - pub struct X<T> { a: T, } diff --git a/tests/ui/issues/issue-5718.rs b/tests/ui/macros/macro-variable-unused-reporting-5718.rs index 234fb2e2222..55da925461d 100644 --- a/tests/ui/issues/issue-5718.rs +++ b/tests/ui/macros/macro-variable-unused-reporting-5718.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5718 //@ run-pass struct Element; diff --git a/tests/ui/macros/missing-writer-issue-139830.stderr b/tests/ui/macros/missing-writer-issue-139830.stderr index 34dd61328e0..0a1c6f6f3ea 100644 --- a/tests/ui/macros/missing-writer-issue-139830.stderr +++ b/tests/ui/macros/missing-writer-issue-139830.stderr @@ -3,10 +3,10 @@ error[E0599]: cannot write into `String` | LL | let _ = write!(buf, "foo"); | ^^^ + | --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL | = note: the method is available for `String` here - | note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method --> $DIR/missing-writer-issue-139830.rs:7:20 | diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs index 99f0fc904a9..407920c4e4e 100644 --- a/tests/ui/malformed/malformed-regressions.rs +++ b/tests/ui/malformed/malformed-regressions.rs @@ -4,9 +4,7 @@ //~^ WARN this was previously accepted #[inline = ""] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted -#[link] //~ ERROR valid forms for the attribute are -//~^ WARN this was previously accepted -#[link = ""] //~ ERROR valid forms for the attribute are -//~^ WARN this was previously accepted +#[link] //~ ERROR malformed +#[link = ""] //~ ERROR malformed fn main() {} diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index cab347a8062..850bcb6cbc2 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -9,25 +9,47 @@ LL | #[doc] = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` +error[E0539]: malformed `link` attribute input --> $DIR/malformed-regressions.rs:7:1 | LL | #[link] - | ^^^^^^^ + | ^^^^^^^ expected this to be a list | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL | #[link(name = "...")] + | ++++++++++++++ +LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...")] + | +++++++++++++++++++++++++++++++++++++++++ +LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + = and 1 other candidate -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-regressions.rs:9:1 +error[E0539]: malformed `link` attribute input + --> $DIR/malformed-regressions.rs:8:1 | LL | #[link = ""] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ expected this to be a list | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link = ""] +LL + #[link(name = "...")] + | +LL - #[link = ""] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link = ""] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link = ""] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` --> $DIR/malformed-regressions.rs:3:1 @@ -49,6 +71,7 @@ LL | #[inline = ""] error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0539`. Future incompatibility report: Future breakage diagnostic: error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` --> $DIR/malformed-regressions.rs:1:1 @@ -62,30 +85,6 @@ LL | #[doc] = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default Future breakage diagnostic: -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-regressions.rs:7:1 - | -LL | #[link] - | ^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> - = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default - -Future breakage diagnostic: -error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-regressions.rs:9:1 - | -LL | #[link = ""] - | ^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> - = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default - -Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` --> $DIR/malformed-regressions.rs:3:1 | diff --git a/tests/ui/issues/issue-5358-1.rs b/tests/ui/match/mismatched-types-in-match-5358.rs index 281f219c039..d096bf3a493 100644 --- a/tests/ui/issues/issue-5358-1.rs +++ b/tests/ui/match/mismatched-types-in-match-5358.rs @@ -1,8 +1,13 @@ -enum Either<T, U> { Left(T), Right(U) } +// https://github.com/rust-lang/rust/issues/5358 +enum Either<T, U> { + Left(T), + Right(U), +} struct S(Either<usize, usize>); fn main() { - match S(Either::Left(5)) { //~ NOTE this expression has type `S` + match S(Either::Left(5)) { + //~^ NOTE this expression has type `S` Either::Right(_) => {} //~^ ERROR mismatched types //~| NOTE expected `S`, found `Either<_, _>` diff --git a/tests/ui/issues/issue-5358-1.stderr b/tests/ui/match/mismatched-types-in-match-5358.stderr index e68db865dc4..6a6cf3ee269 100644 --- a/tests/ui/issues/issue-5358-1.stderr +++ b/tests/ui/match/mismatched-types-in-match-5358.stderr @@ -1,8 +1,9 @@ error[E0308]: mismatched types - --> $DIR/issue-5358-1.rs:6:9 + --> $DIR/mismatched-types-in-match-5358.rs:11:9 | LL | match S(Either::Left(5)) { | ------------------ this expression has type `S` +LL | LL | Either::Right(_) => {} | ^^^^^^^^^^^^^^^^ expected `S`, found `Either<_, _>` | diff --git a/tests/ui/match/mismatched-types-in-match-pattern-7867.rs b/tests/ui/match/mismatched-types-in-match-7867.rs index 9ff8755c819..9ff8755c819 100644 --- a/tests/ui/match/mismatched-types-in-match-pattern-7867.rs +++ b/tests/ui/match/mismatched-types-in-match-7867.rs diff --git a/tests/ui/match/mismatched-types-in-match-pattern-7867.stderr b/tests/ui/match/mismatched-types-in-match-7867.stderr index 8997f36114a..e41a61e42f4 100644 --- a/tests/ui/match/mismatched-types-in-match-pattern-7867.stderr +++ b/tests/ui/match/mismatched-types-in-match-7867.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/mismatched-types-in-match-pattern-7867.rs:10:9 + --> $DIR/mismatched-types-in-match-7867.rs:10:9 | LL | enum A { B, C } | - unit variant defined here diff --git a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr index a87c47a9f12..cc8bd18449a 100644 --- a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr +++ b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr @@ -14,6 +14,7 @@ warning: cannot specify lifetime arguments explicitly if late bound lifetime par | LL | 0.clone::<'a>(); | ^^ + | --> $SRC_DIR/core/src/clone.rs:LL:COL | = note: the late bound lifetime parameter is introduced here diff --git a/tests/ui/methods/trait-method-self-param-error-7575.rs b/tests/ui/methods/trait-method-resolution-7575.rs index 9793d43cc24..9793d43cc24 100644 --- a/tests/ui/methods/trait-method-self-param-error-7575.rs +++ b/tests/ui/methods/trait-method-resolution-7575.rs diff --git a/tests/ui/methods/trait-method-self-param-error-7575.stderr b/tests/ui/methods/trait-method-resolution-7575.stderr index 656db30352d..8bbc360de57 100644 --- a/tests/ui/methods/trait-method-self-param-error-7575.stderr +++ b/tests/ui/methods/trait-method-resolution-7575.stderr @@ -1,5 +1,5 @@ warning: trait `Foo` is never used - --> $DIR/trait-method-self-param-error-7575.rs:4:7 + --> $DIR/trait-method-resolution-7575.rs:4:7 | LL | trait Foo { | ^^^ diff --git a/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr b/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr index a2cec972e4a..6bda7840f7b 100644 --- a/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr +++ b/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-projection-mismatch.rs:20:5 | LL | wrap::<_, Thing>(); - | ^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected reference `&'a _` found reference `&_` diff --git a/tests/ui/issues/issue-5950.rs b/tests/ui/modules/pub-use-module-alias-5950.rs index 6015560fcf8..91d3f9b16ff 100644 --- a/tests/ui/issues/issue-5950.rs +++ b/tests/ui/modules/pub-use-module-alias-5950.rs @@ -1,6 +1,6 @@ +// https://github.com/rust-lang/rust/issues/5950 //@ check-pass - pub use local as local_alias; pub mod local { } diff --git a/tests/ui/resolve/module-import-resolution-7663.rs b/tests/ui/modules/use-statement-duplicate-check-7663.rs index 872806594fc..872806594fc 100644 --- a/tests/ui/resolve/module-import-resolution-7663.rs +++ b/tests/ui/modules/use-statement-duplicate-check-7663.rs diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr index ead4d490a62..0edbd7b44ef 100644 --- a/tests/ui/nll/ice-106874.stderr +++ b/tests/ui/nll/ice-106874.stderr @@ -17,6 +17,15 @@ LL | A(B(C::new(D::new(move |st| f(st))))) = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: implementation of `FnOnce` is not general enough + --> $DIR/ice-106874.rs:8:7 + | +LL | A(B(C::new(D::new(move |st| f(st))))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + error: implementation of `Fn` is not general enough --> $DIR/ice-106874.rs:8:7 | @@ -34,6 +43,7 @@ LL | A(B(C::new(D::new(move |st| f(st))))) | = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Fn` is not general enough --> $DIR/ice-106874.rs:8:7 @@ -46,45 +56,36 @@ LL | A(B(C::new(D::new(move |st| f(st))))) = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough - --> $DIR/ice-106874.rs:8:9 + --> $DIR/ice-106874.rs:8:7 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Fn` is not general enough - --> $DIR/ice-106874.rs:8:9 + --> $DIR/ice-106874.rs:8:7 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough | = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` - -error: implementation of `FnOnce` is not general enough - --> $DIR/ice-106874.rs:8:9 - | -LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error - --> $DIR/ice-106874.rs:8:41 + --> $DIR/ice-106874.rs:8:7 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: higher-ranked subtype error --> $DIR/ice-106874.rs:8:41 | LL | A(B(C::new(D::new(move |st| f(st))))) | ^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 10 previous errors diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index 26ad1efec05..c2e91edd138 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -38,18 +38,16 @@ LL | accept(callback); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error - --> $DIR/missing-universe-cause-issue-114907.rs:33:21 + --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | LL | accept(callback); - | ^ + | ^^^^^^^^^^^^^^^^ error: higher-ranked subtype error --> $DIR/missing-universe-cause-issue-114907.rs:33:21 | LL | accept(callback); | ^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/issues/issue-6130.rs b/tests/ui/numeric/type-limit-comparisons-6130.rs index c675a8a41dd..54b3f631e67 100644 --- a/tests/ui/issues/issue-6130.rs +++ b/tests/ui/numeric/type-limit-comparisons-6130.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6130 //@ run-pass pub fn main() { diff --git a/tests/ui/parser/bad-lit-suffixes.rs b/tests/ui/parser/bad-lit-suffixes.rs index 0a01bb84f01..0a1ee120730 100644 --- a/tests/ui/parser/bad-lit-suffixes.rs +++ b/tests/ui/parser/bad-lit-suffixes.rs @@ -42,5 +42,10 @@ extern "C" {} #[rustc_layout_scalar_valid_range_start(0suffix)] //~^ ERROR invalid suffix `suffix` for number literal -//~| ERROR malformed `rustc_layout_scalar_valid_range_start` attribute input struct S; + +impl S { + #[rustc_confusables("blah"suffix)] + //~^ ERROR suffixes on string literals are invalid + fn woof() { } +} diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr index e1a8a6834f4..6c3dbbcec64 100644 --- a/tests/ui/parser/bad-lit-suffixes.stderr +++ b/tests/ui/parser/bad-lit-suffixes.stderr @@ -10,12 +10,6 @@ error: suffixes on string literals are invalid LL | "C"suffix | ^^^^^^^^^ invalid suffix `suffix` -error: suffixes on string literals are invalid - --> $DIR/bad-lit-suffixes.rs:39:15 - | -LL | #[link(name = "string"suffix)] - | ^^^^^^^^^^^^^^ invalid suffix `suffix` - warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/bad-lit-suffixes.rs:3:1 | @@ -160,6 +154,12 @@ LL - #[must_use = "string"suffix] LL + #[must_use] | +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:39:15 + | +LL | #[link(name = "string"suffix)] + | ^^^^^^^^^^^^^^ invalid suffix `suffix` + error: invalid suffix `suffix` for number literal --> $DIR/bad-lit-suffixes.rs:43:41 | @@ -168,14 +168,11 @@ LL | #[rustc_layout_scalar_valid_range_start(0suffix)] | = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) -error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input - --> $DIR/bad-lit-suffixes.rs:43:1 +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:48:25 | -LL | #[rustc_layout_scalar_valid_range_start(0suffix)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^ - | | | - | | expected an integer literal here - | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]` +LL | #[rustc_confusables("blah"suffix)] + | ^^^^^^^^^^^^ invalid suffix `suffix` error: aborting due to 22 previous errors; 2 warnings emitted diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr index 21b99d6e663..dd33fdb21ba 100644 --- a/tests/ui/parser/misspelled-keywords/ref.stderr +++ b/tests/ui/parser/misspelled-keywords/ref.stderr @@ -15,6 +15,7 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has | LL | Some(refe list) => println!("{list:?}"), | ^^^^ ^^^^ expected 1 field, found 2 + | --> $SRC_DIR/core/src/option.rs:LL:COL | = note: tuple variant has 1 field diff --git a/tests/ui/issues/issue-5572.rs b/tests/ui/parser/partial-eq-trait-bound-5572.rs index f27744ef0ac..7ee0cdc43ee 100644 --- a/tests/ui/issues/issue-5572.rs +++ b/tests/ui/parser/partial-eq-trait-bound-5572.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5572 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr index 33000022b8f..a99f7e16fca 100644 --- a/tests/ui/parser/recover/recover-pat-exprs.stderr +++ b/tests/ui/parser/recover/recover-pat-exprs.stderr @@ -690,6 +690,7 @@ error: expected one of `)`, `,`, `@`, `if`, or `|`, found `*` | LL | let b = matches!(x, (x * x | x.f()) | x[0]); | ^ expected one of `)`, `,`, `@`, `if`, or `|` + | --> $SRC_DIR/core/src/macros/mod.rs:LL:COL | = note: while parsing argument for this `pat` macro fragment diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr index 21d09ec44c4..6d430184628 100644 --- a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr +++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr @@ -6,6 +6,7 @@ LL | const EMPTY: Vec<()> = Vec::new(); ... LL | EMPTY => {} | ^^^^^ constant of non-structural type + | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr index 69d10728ccd..ed465ea0bba 100644 --- a/tests/ui/pattern/issue-115599.stderr +++ b/tests/ui/pattern/issue-115599.stderr @@ -6,6 +6,7 @@ LL | const CONST_STRING: String = String::new(); ... LL | if let CONST_STRING = empty_str {} | ^^^^^^^^^^^^ constant of non-structural type + | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<u8>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns diff --git a/tests/ui/issues/auxiliary/iss.rs b/tests/ui/privacy/auxiliary/iss-6919.rs index cf32f6c2d5d..cf32f6c2d5d 100644 --- a/tests/ui/issues/auxiliary/iss.rs +++ b/tests/ui/privacy/auxiliary/iss-6919.rs diff --git a/tests/ui/issues/issue-6919.rs b/tests/ui/privacy/deref-separate-compile-unit-6919.rs index 7fb8a2f33bc..5d8934987e5 100644 --- a/tests/ui/issues/issue-6919.rs +++ b/tests/ui/privacy/deref-separate-compile-unit-6919.rs @@ -1,7 +1,7 @@ +// https://github.com/rust-lang/rust/issues/6919 //@ run-pass #![allow(unused_attributes)] -//@ aux-build:iss.rs - +//@ aux-build:iss-6919.rs extern crate issue6919_3; diff --git a/tests/ui/issues/issue-55376.rs b/tests/ui/privacy/pub-restricted-path-usage-55376.rs index 5a6862b6530..ca4e27c30a8 100644 --- a/tests/ui/issues/issue-55376.rs +++ b/tests/ui/privacy/pub-restricted-path-usage-55376.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/55376 //@ run-pass // Tests that paths in `pub(...)` don't fail HIR verification. diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr index 6c47b52c9de..2b48e9046bf 100644 --- a/tests/ui/privacy/suggest-box-new.stderr +++ b/tests/ui/privacy/suggest-box-new.stderr @@ -3,10 +3,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found struct `st | LL | let _ = std::collections::HashMap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL | = note: `std::collections::HashMap` defined here - | help: you might have meant to use an associated function to build this type | LL | let _ = std::collections::HashMap::new(); diff --git a/tests/ui/proc-macro/parent-source-spans.stderr b/tests/ui/proc-macro/parent-source-spans.stderr index a3b27fd7bcc..db1eed5e458 100644 --- a/tests/ui/proc-macro/parent-source-spans.stderr +++ b/tests/ui/proc-macro/parent-source-spans.stderr @@ -144,6 +144,7 @@ LL | parent_source_spans!($($tokens)*); ... LL | one!("hello", "world"); | ---------------------- in this macro invocation + | --> $SRC_DIR/core/src/result.rs:LL:COL | = note: similarly named tuple variant `Ok` defined here @@ -158,6 +159,7 @@ LL | parent_source_spans!($($tokens)*); ... LL | two!("yay", "rust"); | ------------------- in this macro invocation + | --> $SRC_DIR/core/src/result.rs:LL:COL | = note: similarly named tuple variant `Ok` defined here @@ -172,6 +174,7 @@ LL | parent_source_spans!($($tokens)*); ... LL | three!("hip", "hop"); | -------------------- in this macro invocation + | --> $SRC_DIR/core/src/result.rs:LL:COL | = note: similarly named tuple variant `Ok` defined here diff --git a/tests/ui/proc-macro/resolve-error.stderr b/tests/ui/proc-macro/resolve-error.stderr index 963298311ef..45b71a3e7b3 100644 --- a/tests/ui/proc-macro/resolve-error.stderr +++ b/tests/ui/proc-macro/resolve-error.stderr @@ -76,6 +76,7 @@ error: cannot find derive macro `Dlone` in this scope | LL | #[derive(Dlone)] | ^^^^^ help: a derive macro with a similar name exists: `Clone` + | --> $SRC_DIR/core/src/clone.rs:LL:COL | = note: similarly named derive macro `Clone` defined here @@ -85,6 +86,7 @@ error: cannot find derive macro `Dlone` in this scope | LL | #[derive(Dlone)] | ^^^^^ help: a derive macro with a similar name exists: `Clone` + | --> $SRC_DIR/core/src/clone.rs:LL:COL | = note: similarly named derive macro `Clone` defined here diff --git a/tests/ui/issues/issue-53728.rs b/tests/ui/repr/packed-struct-with-enum-53728.rs index 364965228c6..6ce65ed634f 100644 --- a/tests/ui/issues/issue-53728.rs +++ b/tests/ui/repr/packed-struct-with-enum-53728.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/53728 //@ run-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-6936.rs b/tests/ui/resolve/duplicate-name-in-module-6936.rs index e9aa80b4eb3..ae9282c0c24 100644 --- a/tests/ui/issues/issue-6936.rs +++ b/tests/ui/resolve/duplicate-name-in-module-6936.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6936 struct T; mod t1 { @@ -30,5 +31,4 @@ mod t6 { impl Foo {} // ok } - fn main() {} diff --git a/tests/ui/issues/issue-6936.stderr b/tests/ui/resolve/duplicate-name-in-module-6936.stderr index 03cc50636b4..76bb8f57386 100644 --- a/tests/ui/issues/issue-6936.stderr +++ b/tests/ui/resolve/duplicate-name-in-module-6936.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-6936.rs:5:5 + --> $DIR/duplicate-name-in-module-6936.rs:6:5 | LL | type Foo = crate::T; | -------------------- previous definition of the type `Foo` here @@ -9,7 +9,7 @@ LL | mod Foo {} = note: `Foo` must be defined only once in the type namespace of this module error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-6936.rs:10:5 + --> $DIR/duplicate-name-in-module-6936.rs:11:5 | LL | type Foo = crate::T; | -------------------- previous definition of the type `Foo` here @@ -19,7 +19,7 @@ LL | struct Foo; = note: `Foo` must be defined only once in the type namespace of this module error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-6936.rs:15:5 + --> $DIR/duplicate-name-in-module-6936.rs:16:5 | LL | type Foo = crate::T; | -------------------- previous definition of the type `Foo` here @@ -29,7 +29,7 @@ LL | enum Foo {} = note: `Foo` must be defined only once in the type namespace of this module error[E0428]: the name `Bar` is defined multiple times - --> $DIR/issue-6936.rs:25:5 + --> $DIR/duplicate-name-in-module-6936.rs:26:5 | LL | type Bar<T> = T; | ---------------- previous definition of the type `Bar` here diff --git a/tests/ui/resolve/levenshtein.stderr b/tests/ui/resolve/levenshtein.stderr index cf478210132..7fc5710c35e 100644 --- a/tests/ui/resolve/levenshtein.stderr +++ b/tests/ui/resolve/levenshtein.stderr @@ -18,6 +18,7 @@ error[E0412]: cannot find type `Opiton` in this scope | LL | type B = Opiton<u8>; // Misspelled type name from the prelude. | ^^^^^^ help: an enum with a similar name exists: `Option` + | --> $SRC_DIR/core/src/option.rs:LL:COL | = note: similarly named enum `Option` defined here diff --git a/tests/ui/issues/issue-7044.rs b/tests/ui/resolve/unit-like-struct-masks-constant-7044.rs index a6e22bc5237..f48dd695f01 100644 --- a/tests/ui/issues/issue-7044.rs +++ b/tests/ui/resolve/unit-like-struct-masks-constant-7044.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7044 static X: isize = 0; struct X; //~ ERROR the name `X` is defined multiple times diff --git a/tests/ui/issues/issue-7044.stderr b/tests/ui/resolve/unit-like-struct-masks-constant-7044.stderr index 9d1fb3a10dd..48aa6fce455 100644 --- a/tests/ui/issues/issue-7044.stderr +++ b/tests/ui/resolve/unit-like-struct-masks-constant-7044.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `X` is defined multiple times - --> $DIR/issue-7044.rs:2:1 + --> $DIR/unit-like-struct-masks-constant-7044.rs:3:1 | LL | static X: isize = 0; | -------------------- previous definition of the value `X` here diff --git a/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs b/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs index 65e61a21f1a..7902f40b09b 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs @@ -5,12 +5,12 @@ const fn assert_file_has_trailing_zero() { let caller = core::panic::Location::caller(); let file_str = caller.file(); - let file_with_nul = caller.file_with_nul(); - if file_str.len() != file_with_nul.count_bytes() { + let file_cstr = caller.file_as_c_str(); + if file_str.len() != file_cstr.count_bytes() { panic!("mismatched lengths"); } let trailing_byte: core::ffi::c_char = unsafe { - *file_with_nul.as_ptr().offset(file_with_nul.count_bytes() as _) + *file_cstr.as_ptr().offset(file_cstr.count_bytes() as _) }; if trailing_byte != 0 { panic!("trailing byte was nonzero") diff --git a/tests/ui/sanitizer/cfi/no_builtins.rs b/tests/ui/sanitizer/cfi/no_builtins.rs new file mode 100644 index 00000000000..949057689ab --- /dev/null +++ b/tests/ui/sanitizer/cfi/no_builtins.rs @@ -0,0 +1,22 @@ +// Verifies that `#![no_builtins]` crates can be built with linker-plugin-lto and CFI. +// See Issue #142284 +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Clinker-plugin-lto -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +//@ compile-flags: --crate-type rlib +//@ build-pass + +#![no_builtins] +#![no_std] + +pub static FUNC: fn() = initializer; + +pub fn initializer() { + call(fma_with_fma); +} + +pub fn call(fn_ptr: fn()) { + fn_ptr(); +} + +pub fn fma_with_fma() {} diff --git a/tests/ui/issues/issue-55380.rs b/tests/ui/specialization/trait-specialization-default-methods-55380.rs index 54894cdede0..b3d79fb5ffb 100644 --- a/tests/ui/issues/issue-55380.rs +++ b/tests/ui/specialization/trait-specialization-default-methods-55380.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/55380 //@ run-pass #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete diff --git a/tests/ui/issues/issue-55380.stderr b/tests/ui/specialization/trait-specialization-default-methods-55380.stderr index 403844c726f..f7c1903da62 100644 --- a/tests/ui/issues/issue-55380.stderr +++ b/tests/ui/specialization/trait-specialization-default-methods-55380.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-55380.rs:2:12 + --> $DIR/trait-specialization-default-methods-55380.rs:3:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-7364.rs b/tests/ui/static/global-variable-promotion-error-7364.rs index 4ce9beb68cd..dba4a484d61 100644 --- a/tests/ui/issues/issue-7364.rs +++ b/tests/ui/static/global-variable-promotion-error-7364.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7364 use std::cell::RefCell; // Regression test for issue 7364 diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/static/global-variable-promotion-error-7364.stderr index a47a90c90ce..b9d75676bef 100644 --- a/tests/ui/issues/issue-7364.stderr +++ b/tests/ui/static/global-variable-promotion-error-7364.stderr @@ -1,5 +1,5 @@ error[E0277]: `RefCell<isize>` cannot be shared between threads safely - --> $DIR/issue-7364.rs:4:15 + --> $DIR/global-variable-promotion-error-7364.rs:5:15 | LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0)); | ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely @@ -12,7 +12,7 @@ note: required because it appears within the type `Box<RefCell<isize>>` = note: shared static variables must have a type that implements `Sync` error[E0015]: cannot call non-const associated function `Box::<RefCell<isize>>::new` in statics - --> $DIR/issue-7364.rs:4:37 + --> $DIR/global-variable-promotion-error-7364.rs:5:37 | LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-5917.rs b/tests/ui/static/static-list-initialization-5917.rs index 8e91b1052a2..c6c32f7582e 100644 --- a/tests/ui/issues/issue-5917.rs +++ b/tests/ui/static/static-list-initialization-5917.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5917 //@ run-pass #![allow(non_upper_case_globals)] diff --git a/tests/ui/issues/issue-5688.rs b/tests/ui/static/static-struct-initialization-5688.rs index a7db1dfb15f..6a4c2f45b6b 100644 --- a/tests/ui/issues/issue-5688.rs +++ b/tests/ui/static/static-struct-initialization-5688.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5688 //@ run-pass /* # Corrupted initialization in the static struct diff --git a/tests/ui/structs-enums/auxiliary/aux-8044.rs b/tests/ui/structs/auxiliary/aux-8044.rs index 2ec25f51cde..2ec25f51cde 100644 --- a/tests/ui/structs-enums/auxiliary/aux-8044.rs +++ b/tests/ui/structs/auxiliary/aux-8044.rs diff --git a/tests/ui/structs-enums/struct-and-enum-usage-8044.rs b/tests/ui/structs/btree-struct-usage-8044.rs index 9b544f33f1c..9b544f33f1c 100644 --- a/tests/ui/structs-enums/struct-and-enum-usage-8044.rs +++ b/tests/ui/structs/btree-struct-usage-8044.rs diff --git a/tests/ui/issues/issue-6344-let.rs b/tests/ui/structs/destructuring-struct-with-dtor-6344.rs index 1e1bdfa17be..b107a99e89f 100644 --- a/tests/ui/issues/issue-6344-let.rs +++ b/tests/ui/structs/destructuring-struct-with-dtor-6344.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6344 //@ run-pass #![allow(non_shorthand_field_patterns)] diff --git a/tests/ui/issues/issue-5439.rs b/tests/ui/structs/nonexistent-struct-field-error-5439.rs index 852b264dc5d..b2b3293ac91 100644 --- a/tests/ui/issues/issue-5439.rs +++ b/tests/ui/structs/nonexistent-struct-field-error-5439.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5439 struct Foo { foo: isize, } diff --git a/tests/ui/issues/issue-5439.stderr b/tests/ui/structs/nonexistent-struct-field-error-5439.stderr index 6d1d74e3045..b560772fbf0 100644 --- a/tests/ui/issues/issue-5439.stderr +++ b/tests/ui/structs/nonexistent-struct-field-error-5439.stderr @@ -1,5 +1,5 @@ error[E0560]: struct `Foo` has no field named `nonexistent` - --> $DIR/issue-5439.rs:11:31 + --> $DIR/nonexistent-struct-field-error-5439.rs:12:31 | LL | return Box::new(Foo { nonexistent: self, foo: i }); | ^^^^^^^^^^^ `Foo` does not have this field diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr index a1a01c0abd6..1816a27dcdc 100644 --- a/tests/ui/suggestions/attribute-typos.stderr +++ b/tests/ui/suggestions/attribute-typos.stderr @@ -15,6 +15,7 @@ error: cannot find attribute `tests` in this scope | LL | #[tests] | ^^^^^ help: an attribute macro with a similar name exists: `test` + | --> $SRC_DIR/core/src/macros/mod.rs:LL:COL | = note: similarly named attribute macro `test` defined here diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr index 0cd6267b3b3..c81ac34aaf4 100644 --- a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr +++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr @@ -3,6 +3,7 @@ error[E0573]: expected type, found module `result` | LL | impl result { | ^^^^^^ help: an enum with a similar name exists: `Result` + | --> $SRC_DIR/core/src/result.rs:LL:COL | = note: similarly named enum `Result` defined here diff --git a/tests/ui/suggestions/enum-method-probe.stderr b/tests/ui/suggestions/enum-method-probe.stderr index 5aa0fc44c7b..7d97495af82 100644 --- a/tests/ui/suggestions/enum-method-probe.stderr +++ b/tests/ui/suggestions/enum-method-probe.stderr @@ -99,10 +99,10 @@ error[E0624]: method `len` is private | LL | res.len(); | ^^^ private method + | --> $SRC_DIR/core/src/option.rs:LL:COL | = note: private method defined here - | note: the method `len` exists on the type `Vec<{integer}>` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: consider using `Option::expect` to unwrap the `Vec<{integer}>` value, panicking if the value is an `Option::None` diff --git a/tests/ui/suggestions/import-trait-for-method-call.stderr b/tests/ui/suggestions/import-trait-for-method-call.stderr index 58b07fe7a42..177ab76cd1f 100644 --- a/tests/ui/suggestions/import-trait-for-method-call.stderr +++ b/tests/ui/suggestions/import-trait-for-method-call.stderr @@ -3,6 +3,7 @@ error[E0599]: no method named `finish` found for struct `DefaultHasher` in the c | LL | h.finish() | ^^^^^^ method not found in `DefaultHasher` + | --> $SRC_DIR/core/src/hash/mod.rs:LL:COL | = note: the method is available for `DefaultHasher` here diff --git a/tests/ui/suggestions/multi-suggestion.ascii.stderr b/tests/ui/suggestions/multi-suggestion.ascii.stderr index f2a146fbd52..1744162e6ce 100644 --- a/tests/ui/suggestions/multi-suggestion.ascii.stderr +++ b/tests/ui/suggestions/multi-suggestion.ascii.stderr @@ -3,10 +3,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found struct `st | LL | let _ = std::collections::HashMap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL | = note: `std::collections::HashMap` defined here - | help: you might have meant to use an associated function to build this type | LL | let _ = std::collections::HashMap::new(); diff --git a/tests/ui/suggestions/multi-suggestion.unicode.stderr b/tests/ui/suggestions/multi-suggestion.unicode.stderr index 69df481579b..4835c263f19 100644 --- a/tests/ui/suggestions/multi-suggestion.unicode.stderr +++ b/tests/ui/suggestions/multi-suggestion.unicode.stderr @@ -3,10 +3,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found struct `st │ LL │ let _ = std::collections::HashMap(); │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ╰╴ ╭▸ $SRC_DIR/std/src/collections/hash/map.rs:LL:COL │ ╰ note: `std::collections::HashMap` defined here - ╰╴ help: you might have meant to use an associated function to build this type ╭╴ LL │ let _ = std::collections::HashMap::new(); @@ -34,7 +34,7 @@ LL │ wtf: Some(Box(U { note: constructor is not visible here due to private fields ╭▸ $SRC_DIR/alloc/src/boxed.rs:LL:COL │ - ╰ note: private field + ├ note: private field │ ╰ note: private field help: you might have meant to use an associated function to build this type diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr index 0008b4fb5ed..8ab8a1716b1 100644 --- a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr +++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr @@ -44,6 +44,7 @@ error[E0599]: no method named `try_into` found for type `i32` in the current sco | LL | let _i: i16 = 0_i32.try_into().unwrap(); | ^^^^^^^^ + | --> $SRC_DIR/core/src/convert/mod.rs:LL:COL | = note: the method is available for `i32` here diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr index 2288bd1129c..40936ce1ec3 100644 --- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr @@ -3,10 +3,10 @@ error[E0404]: expected trait, found struct `String` | LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String { | ^^^^^^ not a trait + | --> $SRC_DIR/alloc/src/string.rs:LL:COL | = note: similarly named trait `ToString` defined here - | help: constrain the associated type to `String` | LL - struct Foo<T> where T: Bar, <T as Bar>::Baz: String { @@ -22,10 +22,10 @@ error[E0404]: expected trait, found struct `String` | LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { | ^^^^^^ not a trait + | --> $SRC_DIR/alloc/src/string.rs:LL:COL | = note: similarly named trait `ToString` defined here - | help: constrain the associated type to `String` | LL - struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { @@ -41,10 +41,10 @@ error[E0404]: expected trait, found struct `String` | LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { | ^^^^^^ not a trait + | --> $SRC_DIR/alloc/src/string.rs:LL:COL | = note: similarly named trait `ToString` defined here - | help: constrain the associated type to `String` | LL - fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { @@ -60,10 +60,10 @@ error[E0404]: expected trait, found struct `String` | LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { | ^^^^^^ not a trait + | --> $SRC_DIR/alloc/src/string.rs:LL:COL | = note: similarly named trait `ToString` defined here - | help: constrain the associated type to `String` | LL - fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { @@ -85,6 +85,7 @@ error[E0404]: expected trait, found struct `String` | LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {} | ^^^^^^ help: a trait with a similar name exists: `ToString` + | --> $SRC_DIR/alloc/src/string.rs:LL:COL | = note: similarly named trait `ToString` defined here diff --git a/tests/ui/issues/issue-5666.rs b/tests/ui/traits/dynamic-dispatch-trait-objects-5666.rs index 76e2f8229a0..e335949d832 100644 --- a/tests/ui/issues/issue-5666.rs +++ b/tests/ui/traits/dynamic-dispatch-trait-objects-5666.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5666 //@ run-pass struct Dog { @@ -14,7 +15,6 @@ impl Barks for Dog { } } - pub fn main() { let snoopy = Box::new(Dog{name: "snoopy".to_string()}); let bubbles = Box::new(Dog{name: "bubbles".to_string()}); diff --git a/tests/ui/issues/issue-53568.rs b/tests/ui/traits/nll-ice-custom-type-ops-53568.rs index 9862d4ced12..9b240cdc190 100644 --- a/tests/ui/issues/issue-53568.rs +++ b/tests/ui/traits/nll-ice-custom-type-ops-53568.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/53568 // Regression test for an NLL-related ICE (#53568) -- we failed to // resolve inference variables in "custom type-ops". // diff --git a/tests/ui/issues/issue-5883.rs b/tests/ui/traits/opaque-trait-size-error-5883.rs index dd4753e0344..e39e24e7342 100644 --- a/tests/ui/issues/issue-5883.rs +++ b/tests/ui/traits/opaque-trait-size-error-5883.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5883 trait A {} struct Struct { diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/traits/opaque-trait-size-error-5883.stderr index 2ca437b8c47..78de250b19a 100644 --- a/tests/ui/issues/issue-5883.stderr +++ b/tests/ui/traits/opaque-trait-size-error-5883.stderr @@ -1,19 +1,19 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:9:6 + --> $DIR/opaque-trait-size-error-5883.rs:10:6 | LL | ) -> Struct { | ^^^^^^ doesn't have a size known at compile-time | = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)` note: required because it appears within the type `Struct` - --> $DIR/issue-5883.rs:3:8 + --> $DIR/opaque-trait-size-error-5883.rs:4:8 | LL | struct Struct { | ^^^^^^ = note: the return type of a function must have a statically known size error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:8:8 + --> $DIR/opaque-trait-size-error-5883.rs:9:8 | LL | r: dyn A + 'static | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/traits/self-implements-kinds-in-default-methods-8171.rs b/tests/ui/traits/self-not-send-in-default-method-8171.rs index 59ea62c7690..59ea62c7690 100644 --- a/tests/ui/traits/self-implements-kinds-in-default-methods-8171.rs +++ b/tests/ui/traits/self-not-send-in-default-method-8171.rs diff --git a/tests/ui/issues/issue-6898.rs b/tests/ui/traits/trait-implementation-generic-access-6898.rs index c810acaf61b..e9437b1c522 100644 --- a/tests/ui/issues/issue-6898.rs +++ b/tests/ui/traits/trait-implementation-generic-access-6898.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/6898 //@ check-pass use std::mem; diff --git a/tests/ui/issues/issue-5988.rs b/tests/ui/traits/trait-implementation-restriction-5988.rs index b7527d9bea8..d3a5b10569b 100644 --- a/tests/ui/issues/issue-5988.rs +++ b/tests/ui/traits/trait-implementation-restriction-5988.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/5988 //@ run-pass trait B { diff --git a/tests/ui/traits/trait-implementation-and-usage-7563.rs b/tests/ui/traits/trait-object-lifetime-bounds-7563.rs index 8cfc7a14ffe..8cfc7a14ffe 100644 --- a/tests/ui/traits/trait-implementation-and-usage-7563.rs +++ b/tests/ui/traits/trait-object-lifetime-bounds-7563.rs diff --git a/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr new file mode 100644 index 00000000000..d90a786498e --- /dev/null +++ b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.dump.stderr @@ -0,0 +1,16 @@ +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<dyn OneTwo as One>::one - shim(reify)), + Method(<dyn OneTwo as Two>::two - shim(reify)), + TraitVPtr(<dyn OneTwo as Two>), + TraitVPtr(<dyn OneTwo as TwoAgain>), + ] + --> $DIR/empty-supertrait-with-nonempty-supersupertrait.rs:40:1 + | +LL | type T = dyn OneTwo; + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs new file mode 100644 index 00000000000..507cda63868 --- /dev/null +++ b/tests/ui/traits/vtable/empty-supertrait-with-nonempty-supersupertrait.rs @@ -0,0 +1,49 @@ +//@ revisions: run dump +//@[run] run-pass +//@[dump] check-fail +//! Regression test for #145752 +//! Ensure that `OneTwo` contains a vptr for `TwoAgain` +#![allow(unused)] +#![cfg_attr(dump, feature(rustc_attrs))] + +trait One { + fn one(&self) { + panic!("don't call this"); + } +} +impl One for () {} + +trait Two { + fn two(&self) { + println!("good"); + } +} +impl Two for () {} + +trait TwoAgain: Two {} +impl<T: Two> TwoAgain for T {} + +trait OneTwo: One + TwoAgain {} +impl<T: One + Two> OneTwo for T {} + +fn main() { + (&()).two(); + (&() as &dyn OneTwo).two(); + (&() as &dyn OneTwo as &dyn Two).two(); + + // these two used to panic because they called `one` due to #145752 + (&() as &dyn OneTwo as &dyn TwoAgain).two(); + (&() as &dyn OneTwo as &dyn TwoAgain as &dyn Two).two(); +} + +#[cfg_attr(dump, rustc_dump_vtable)] +type T = dyn OneTwo; +//[dump]~^ ERROR vtable entries: [ +//[dump]~| ERROR MetadataDropInPlace, +//[dump]~| ERROR MetadataSize, +//[dump]~| ERROR MetadataAlign, +//[dump]~| ERROR Method(<dyn OneTwo as One>::one - shim(reify)), +//[dump]~| ERROR Method(<dyn OneTwo as Two>::two - shim(reify)), +//[dump]~| ERROR TraitVPtr(<dyn OneTwo as Two>), +//[dump]~| ERROR TraitVPtr(<dyn OneTwo as TwoAgain>), +//[dump]~| ERROR ] diff --git a/tests/ui/traits/vtable/multiple-auto.rs b/tests/ui/traits/vtable/multiple-auto.rs new file mode 100644 index 00000000000..87ee865868b --- /dev/null +++ b/tests/ui/traits/vtable/multiple-auto.rs @@ -0,0 +1,50 @@ +// Related to <https://github.com/rust-lang/rust/issues/113840> +// +// This test makes sure that multiple auto traits can reuse the +// same pointer for upcasting (e.g. `Send`/`Sync`) + +#![crate_type = "lib"] +#![feature(rustc_attrs, auto_traits)] + +// Markers +auto trait M0 {} +auto trait M1 {} +auto trait M2 {} + +// Just a trait with a method +trait T { + fn method(&self) {} +} + +trait A: M0 + M1 + M2 + T {} + +trait B: M0 + M1 + T + M2 {} + +trait C: M0 + T + M1 + M2 {} + +trait D: T + M0 + M1 + M2 {} + +struct S; + +impl M0 for S {} +impl M1 for S {} +impl M2 for S {} +impl T for S {} + +#[rustc_dump_vtable] +impl A for S {} +//~^ ERROR vtable entries + +#[rustc_dump_vtable] +impl B for S {} +//~^ ERROR vtable entries + +#[rustc_dump_vtable] +impl C for S {} +//~^ ERROR vtable entries + +#[rustc_dump_vtable] +impl D for S {} +//~^ ERROR vtable entries + +fn main() {} diff --git a/tests/ui/traits/vtable/multiple-auto.stderr b/tests/ui/traits/vtable/multiple-auto.stderr new file mode 100644 index 00000000000..0a7c3ebd36d --- /dev/null +++ b/tests/ui/traits/vtable/multiple-auto.stderr @@ -0,0 +1,46 @@ +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as T>::method), + ] + --> $DIR/multiple-auto.rs:35:1 + | +LL | impl A for S {} + | ^^^^^^^^^^^^ + +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as T>::method), + ] + --> $DIR/multiple-auto.rs:39:1 + | +LL | impl B for S {} + | ^^^^^^^^^^^^ + +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as T>::method), + ] + --> $DIR/multiple-auto.rs:43:1 + | +LL | impl C for S {} + | ^^^^^^^^^^^^ + +error: vtable entries: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as T>::method), + ] + --> $DIR/multiple-auto.rs:47:1 + | +LL | impl D for S {} + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/type/issue-7607-1.stderr b/tests/ui/type/issue-7607-1.stderr index db4c8f25dbc..69b6d62e987 100644 --- a/tests/ui/type/issue-7607-1.stderr +++ b/tests/ui/type/issue-7607-1.stderr @@ -3,6 +3,7 @@ error[E0412]: cannot find type `Fo` in this scope | LL | impl Fo { | ^^ help: a trait with a similar name exists: `Fn` + | --> $SRC_DIR/core/src/ops/function.rs:LL:COL | = note: similarly named trait `Fn` defined here diff --git a/tests/ui/typeck/issue-83693.stderr b/tests/ui/typeck/issue-83693.stderr index 34bca426116..0359b8af93a 100644 --- a/tests/ui/typeck/issue-83693.stderr +++ b/tests/ui/typeck/issue-83693.stderr @@ -3,6 +3,7 @@ error[E0412]: cannot find type `F` in this scope | LL | impl F { | ^ help: a trait with a similar name exists: `Fn` + | --> $SRC_DIR/core/src/ops/function.rs:LL:COL | = note: similarly named trait `Fn` defined here diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr index 69d6bd74a73..a854ecb0622 100644 --- a/tests/ui/ufcs/ufcs-partially-resolved.stderr +++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr @@ -12,6 +12,7 @@ error[E0404]: expected trait, found enum `E` | LL | let _: <u8 as E>::N; | ^ help: a trait with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named trait `Eq` defined here @@ -42,6 +43,7 @@ error[E0404]: expected trait, found enum `E` | LL | <u8 as E>::N; | ^ help: a trait with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named trait `Eq` defined here @@ -63,6 +65,7 @@ error[E0404]: expected trait, found enum `E` | LL | let _: <u8 as E>::Y; | ^ help: a trait with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named trait `Eq` defined here @@ -72,6 +75,7 @@ error[E0404]: expected trait, found enum `E` | LL | <u8 as E>::Y; | ^ help: a trait with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named trait `Eq` defined here @@ -90,6 +94,7 @@ error[E0404]: expected trait, found enum `E` | LL | let _: <u8 as E>::N::NN; | ^ help: a trait with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named trait `Eq` defined here @@ -120,6 +125,7 @@ error[E0404]: expected trait, found enum `E` | LL | <u8 as E>::N::NN; | ^ help: a trait with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named trait `Eq` defined here @@ -141,6 +147,7 @@ error[E0404]: expected trait, found enum `E` | LL | let _: <u8 as E>::Y::NN; | ^ help: a trait with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named trait `Eq` defined here @@ -150,6 +157,7 @@ error[E0404]: expected trait, found enum `E` | LL | <u8 as E>::Y::NN; | ^ help: a trait with a similar name exists: `Eq` + | --> $SRC_DIR/core/src/cmp.rs:LL:COL | = note: similarly named trait `Eq` defined here diff --git a/tests/ui/issues/issue-7344.rs b/tests/ui/unreachable-code/boolean-negation-in-unreachable-code-7344.rs index 406b24634f5..8fd091872c3 100644 --- a/tests/ui/issues/issue-7344.rs +++ b/tests/ui/unreachable-code/boolean-negation-in-unreachable-code-7344.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/7344 //@ run-pass #![allow(unused_must_use)] diff --git a/tests/ui/issues/auxiliary/issue-5844-aux.rs b/tests/ui/unsafe/auxiliary/aux-5844.rs index ea83378cad6..ea83378cad6 100644 --- a/tests/ui/issues/auxiliary/issue-5844-aux.rs +++ b/tests/ui/unsafe/auxiliary/aux-5844.rs diff --git a/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs b/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs new file mode 100644 index 00000000000..11863ce647a --- /dev/null +++ b/tests/ui/unsafe/extern-function-requires-unsafe-5844.rs @@ -0,0 +1,8 @@ +// https://github.com/rust-lang/rust/issues/5844 +//@aux-build:aux-5844.rs + +extern crate aux_5844; + +fn main() { + aux_5844::rand(); //~ ERROR: requires unsafe +} diff --git a/tests/ui/issues/issue-5844.stderr b/tests/ui/unsafe/extern-function-requires-unsafe-5844.stderr index bae917fa72c..44dee178991 100644 --- a/tests/ui/issues/issue-5844.stderr +++ b/tests/ui/unsafe/extern-function-requires-unsafe-5844.stderr @@ -1,8 +1,8 @@ error[E0133]: call to unsafe function `rand` is unsafe and requires unsafe function or block - --> $DIR/issue-5844.rs:6:5 + --> $DIR/extern-function-requires-unsafe-5844.rs:7:5 | -LL | issue_5844_aux::rand(); - | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function +LL | aux_5844::rand(); + | ^^^^^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior diff --git a/tests/ui/wasm/wasm-import-module.rs b/tests/ui/wasm/wasm-import-module.rs index 2b3bca9a411..c38fcb1a000 100644 --- a/tests/ui/wasm/wasm-import-module.rs +++ b/tests/ui/wasm/wasm-import-module.rs @@ -1,12 +1,12 @@ #![feature(link_cfg)] -#[link(name = "...", wasm_import_module)] //~ ERROR: must be of the form +#[link(name = "...", wasm_import_module)] //~ ERROR: malformed `link` attribute input extern "C" {} -#[link(name = "...", wasm_import_module(x))] //~ ERROR: must be of the form +#[link(name = "...", wasm_import_module(x))] //~ ERROR: malformed `link` attribute input extern "C" {} -#[link(name = "...", wasm_import_module())] //~ ERROR: must be of the form +#[link(name = "...", wasm_import_module())] //~ ERROR: malformed `link` attribute input extern "C" {} #[link(wasm_import_module = "foo", name = "bar")] //~ ERROR: `wasm_import_module` is incompatible with other arguments diff --git a/tests/ui/wasm/wasm-import-module.stderr b/tests/ui/wasm/wasm-import-module.stderr index 84f437941a7..f5ea449839b 100644 --- a/tests/ui/wasm/wasm-import-module.stderr +++ b/tests/ui/wasm/wasm-import-module.stderr @@ -1,20 +1,77 @@ -error: wasm import module must be of the form `wasm_import_module = "string"` - --> $DIR/wasm-import-module.rs:3:22 +error[E0539]: malformed `link` attribute input + --> $DIR/wasm-import-module.rs:3:1 | LL | #[link(name = "...", wasm_import_module)] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^------------------^^ + | | + | expected this to be of the form `wasm_import_module = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", wasm_import_module)] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", wasm_import_module)] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", wasm_import_module)] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", wasm_import_module)] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: wasm import module must be of the form `wasm_import_module = "string"` - --> $DIR/wasm-import-module.rs:6:22 +error[E0539]: malformed `link` attribute input + --> $DIR/wasm-import-module.rs:6:1 | LL | #[link(name = "...", wasm_import_module(x))] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^---------------------^^ + | | + | expected this to be of the form `wasm_import_module = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", wasm_import_module(x))] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", wasm_import_module(x))] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", wasm_import_module(x))] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", wasm_import_module(x))] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate -error: wasm import module must be of the form `wasm_import_module = "string"` - --> $DIR/wasm-import-module.rs:9:22 +error[E0539]: malformed `link` attribute input + --> $DIR/wasm-import-module.rs:9:1 | LL | #[link(name = "...", wasm_import_module())] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^--------------------^^ + | | + | expected this to be of the form `wasm_import_module = "..."` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", wasm_import_module())] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", wasm_import_module())] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", wasm_import_module())] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", wasm_import_module())] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes --> $DIR/wasm-import-module.rs:12:8 @@ -36,3 +93,4 @@ LL | #[link(wasm_import_module = "foo", cfg(false))] error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0539`. |
